class BaseChip::Project

Constants

DEFINED_SUBCOMMANDS

Attributes

registered_modes[R]
workload[RW]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/base_chip/project.rb, line 48
def initialize()
  super
  @project   = self
  @pwd       = Dir.pwd
end

Public Instance Methods

banner() click to toggle source
banner_line(str) click to toggle source
block_dereference(name,names,passive) click to toggle source
# File lib/base_chip/project.rb, line 166
def block_dereference(name,names,passive)
  if block = @blocks[name.to_sym]
    block.configure
    block.dereference_workload(names,passive)
  else
    fault "Could not find block #{name} in project #{@name}" # FIXME say who wanted it, and if shortcut occurred
  end
end
block_names() click to toggle source
# File lib/base_chip/project.rb, line 79
def block_names
  return @block_names if @block_names
  # \@block_names = Dir.glob("#\{@directory}/*")
  # \@block_names.map!{|path| path.split(/\//).pop}
  # \@block_names.delete 'settings.yaml'
  # \@block_names
end
configure() click to toggle source
Calls superclass method
# File lib/base_chip/project.rb, line 385
def configure
  return if @configured
  @directory          = BaseChip.root
  @modes             += BaseChip.options.modes.split(/,/) if BaseChip.options.modes
  super
  @modes.each do |name|
    fault "Attempted to call mode '#{name}', which isn't registered with the project.  Call register_mode(#{name}) in project.rb to allow.  Valid modes are #{project.registered_modes}" unless project.registered_modes.include? name.to_s
  end
  if self.blocks
    @directory_prefix = figure_directory_prefix
    @block_names      = self.blocks.keys
  end
end
default_modes() click to toggle source
# File lib/base_chip/project.rb, line 382
def default_modes
  %w{ coverage gates fast debug profiling }.each { |m| register_mode m }
end
dereference_clusters() click to toggle source
# File lib/base_chip/project.rb, line 398
def dereference_clusters
  return nil unless cluster_names = BaseChip.options.jobs
  configure
  fault "Cluster submission attempted, but no cluster types are configured." unless @cluster_types
  @dereferenced = []
  cluster_names = cluster_names.split(/,/)
  cluster_names.each do |cn|
    type     = nil
    cluster  = nil
    jobs     = nil
    cn_orig  = cn
    clusters = []

    if cn.sub!(/^(\d+)(?::|$)/,'')
      jobs = $1.to_i
    end
    if cn.sub!(/:(\d+)$/,'')
      fault "Multiple counts found in '#{cn_orig}'.  Separate multiple cluster specifiers with commas." if jobs
      jobs = $1.to_i
    end

    case cn
    when /^([^:]+):([^:]+)$/
      cluster = $2
      if $1 == 'all' || $1 == ''
        cluster_types.each_value do |cluster_type|
          clusters += cluster_type.dereference(cluster,jobs,true)
        end
      elsif cluster_type = @cluster_types[$1.to_sym]
        clusters += cluster_type.dereference(cluster,jobs,false)
      else
        fault "Could not find cluster type '#{$1}' in cluster specifier '#{cn_orig}'." if jobs
      end
    when /^([^:]+)$/
      if cluster_type = @cluster_types[$1.to_sym]
        clusters += cluster_type.dereference('all',jobs,true)
      else
        cluster_types.each_value do |cluster_type|
          clusters += cluster_type.dereference('all',jobs,true)
        end
      end
    when ''
      cluster_types.each_value do |cluster_type|
        clusters += cluster_type.dereference('all',jobs,true)
      end
    else
      fault "Could not parse the cluster specifier '#{cn_orig}'." if jobs
    end
    fault "No clusters could be determined for the cluster specifier '#{cn_orig}'." if clusters.empty?

    if cluster_order
      cluster_order.each do |name|
        tmp = clusters.delete_if {|c| c.full_name == "#{@name}:#{name}"}
        try_add_clusters tmp, jobs
      end
    end
    try_add_clusters clusters, jobs
  end
  @dereferenced
end
dereference_workload(targets) click to toggle source
# File lib/base_chip/project.rb, line 174
def dereference_workload(targets)
  configure
  fault "project '#{name}' has no blocks defined" unless @blocks
  targets ||= ['all']
  out = []

  workload_hash = Hash.new

  targets.each do |t|
    case t 
    when 'gate', 'diffgate', 'all'
      self.block_names.each do |b|
        out += block_dereference(b,[t],true)
      end
    when /^all:(.*)$/
      self.block_names.each do |b|
        out += block_dereference(b,[$1],true)
      end
    when /:/
      tmp = t.split(/:/)
      b = tmp.shift
      out += block_dereference(b,[tmp.join(':')],true)
    else
      fault "Cannot determine block in order to run #{t}."
    end
  end
  out.uniq!
  out
end
diffgate(targets) click to toggle source
# File lib/base_chip/project.rb, line 118
def diffgate(targets)
  targets.each do |t|
    return false unless t =~ /\bdiffgate$/
  end
  true
end
discover_blocks() click to toggle source
# File lib/base_chip/project.rb, line 368
def discover_blocks         ; file_glob("#{@directory}/*/base_chip/block.rb"         , /(\w+)\/base_chip\/block\.rb$/                , :block         )
                              file_glob("#{@directory}/base_chip/block/*.rb"         ,        /base_chip\/blocks\/(\w+)\.rb$/        , :block         ) end
discover_cluster_types() click to toggle source
# File lib/base_chip/project.rb, line 371
def discover_cluster_types  ; file_glob("#{@directory}/base_chip/cluster_types/*.rb" ,        /base_chip\/cluster_types\/(\w+)\.rb$/ , :cluster_type  ) end
discover_configurations() click to toggle source
# File lib/base_chip/project.rb, line 370
def discover_configurations ; file_glob("#{@directory}/base_chip/configurations/*.rb",        /base_chip\/configurations\/(\w+)\.rb$/, :configuration ) end
discover_subprojects() click to toggle source
# File lib/base_chip/project.rb, line 366
def discover_subprojects    ; file_glob("#{@directory}/*/base_chip/project.rb"       , /(\w+)\/base_chip\/project\.rb$/              , :subproject    )
                              file_glob("#{@directory}/base_chip/subprojects/*.rb"   ,        /base_chip\/subprojects\/(\w+)\.rb$/   , :subproject    ) end
figure_directory_prefix() click to toggle source

def configure_blocks(block_names)

block_names.each do |name|
  self.blocks[name.to_sym].configure
end

end

# File lib/base_chip/project.rb, line 58
def figure_directory_prefix
  # if @directory == @pwd
  #   return nil
  # elsif @pwd.length > @directory.length
    configure
    if @blocks
      @blocks.each do |bname,block|
        block.configure
        if @pwd =~ /^#{block.directory}\b/
          block.configurations.each do |cname,configuration|
            configuration.configure
            return "#{bname}:#{cname}" if @pwd =~ /^#{configuration.directory}\b/
          end
          return bname.to_s
        end
      end
    end
  # end
  nil
  # fault "'base_chip' should be run from a block's work directory or the top level of the project."
end
find_action(t_name) click to toggle source
# File lib/base_chip/project.rb, line 245
def find_action(t_name)
  address     = t_name.split(/:/)

  block_name  = address.shift.to_sym
  block       = self.blocks[block_name]           or fault("Couldn't find block '#{block_name}'")

  config_name = address.shift.to_sym
  config      = block.configurations[config_name] or fault("Couldn't find configuration '#{config_name}' in block '#{block_name}")

  thing       = address.shift.to_sym
  action      = config.actions[thing]
  return action if action

  test_list   = config.test_lists[thing]          or fault("Could not find action or test list '#{thing}' in block:configuration '#{block_name}:#{config_name}'")
  test_name   = address.shift.to_sym
  test        = test_list.tests[test_name]        or fault("Could not find test '#{test_name}' in block:configuration:list '#{block_name}:#{config_name}:#{thing}'")
  return test
end
ready(targets=nil) click to toggle source
# File lib/base_chip/project.rb, line 87
def ready(targets=nil) #,available_only=false)
  configure
  @orig_targets = targets
  if @directory_prefix
    # no map! here because @orig_targets needs to stay true to the original command
    targets = targets.map { |t| "#{@directory_prefix}:#{t}" }
  end
  @workload = dereference_workload targets
  @workload.delete_if {|w|w.nil?}
  if @workload.empty?
    if diffgate(targets)
      puts  "diffgate returned no targets needing to run"
      exit
    else
      fault "Could not determine anything to run based on the targets #{targets}.  Did you mean to run this from another directory?"
    end
  end

  w_names = @workload.map{|w|w.name}
  @workload.each do |w|
    w.configure
    if w.depends
      w.deep_depends.each do |d|
        if @workload.include? d
          w.wait_count += 1
          d.next_tasks << w
        end
      end
    end
  end
end
register_mode(name) click to toggle source
# File lib/base_chip/project.rb, line 378
def register_mode(name)
  @registered_modes ||= []
  @registered_modes << name.to_s
end
results_line(type,block,total) click to toggle source
# File lib/base_chip/project.rb, line 223
def results_line(type,block,total)
  blocks = block == 'all' ? @results[type].keys : [block]
  if total
    pass_fail_cancel = [0,0,0,0,0,0,0]
    blocks.each do |b|
      res_hash = @results[type][b]
      pass_fail_cancel[0] += res_hash['pass'].size
      pass_fail_cancel[2] += res_hash['fail'].size
      pass_fail_cancel[4] += res_hash[:cancel].size
    end
    pass_fail_cancel[6] = pass_fail_cancel[0] + pass_fail_cancel[2] + pass_fail_cancel[4]
    pass_fail_cancel[1] = (100 * pass_fail_cancel[0]/pass_fail_cancel[6]).round
    pass_fail_cancel[3] = (100 * pass_fail_cancel[2]/pass_fail_cancel[6]).round
    pass_fail_cancel[5] = (100 * pass_fail_cancel[4]/pass_fail_cancel[6]).round
    str  = pass_fail_cancel[0] > 0 ? ' %6d %3d |' : ' %6d %3d |'
    str += pass_fail_cancel[3] > 0 ? ' %6d %3d |' : ' %6d %3d |'
    str += pass_fail_cancel[5] > 0 ? ' %6d %3d |' : ' %6d %3d |'
    return "#{str} %6d" % pass_fail_cancel
  else
    fault 'Internal error: detailed result reporting not yet supported'
  end
end
run_all_readied() click to toggle source
# File lib/base_chip/project.rb, line 124
def run_all_readied
  # @report_hash = {}
  FileUtils.mkdir_p "#{@directory}/reports"
  @report_name    = "#{@directory}/reports/workload.#{BaseChip.random_string}"
  @report_file    = File.new(@report_name,'w')
  if @tasker.clusters
    @tasker.ready
  else
    @foreground = @workload.size == 1
  end
  begin
    @tasker.submit_workload_chain workload_chain
    @tasker.run
  rescue Interrupt
    @tasker.finish
  end
end
shortcut(name, array) click to toggle source

def enable_tracking(opc,opi)

# puts "enabled tracking(#{opc},#{opi})"
init_results_sockets(:client)
@opc = opc
@opi = opi

end def track_complete(state,first_error = nil)

return unless @opc
msg = Message.new
msg.project = 'gandalf'
msg.type    = 'complete'
msg.state   = state
msg.data = {
  'opc'         => @opc  ,
  'opi'         => @opi  ,
  'first_error' => first_error
}
send_work_message(msg)

end def track_results(test_action,state,problem,totals)

return unless @opc
msg = Message.new
msg.project = 'gandalf'
msg.type    = 'test_action'
msg.state   = state
msg.data = {
  'name'        => test_action.bundle_name,
  'block'       => test_action.block.name,
  'opc'         => @opc,
  'opi'         => @opi,
  'first_error' => problem && problem.signature,
  'file'        => problem && problem.file,
  'bundle'      => problem && problem.bundle,
  'totals'      => totals
}
# puts "sending totals #{test_action.totals.inspect}"
puts "sending message #{msg.data.inspect}"
if test_action.class_string == 'Action'
  msg.data['action'   ] = test_action.name
else
  msg.data['test'     ] = test_action.name
  msg.data['test_list'] = test_action.test_list.name
end
send_work_message(msg)

end

# File lib/base_chip/project.rb, line 361
def shortcut(name, array)
  @shortcuts ||= {}
  @shortcuts[name] = array
end
tasker_finish() click to toggle source
# File lib/base_chip/project.rb, line 295
def tasker_finish
  banner
end
tasker_handle_results(task, result, problem_or_directory=nil, totals={}) click to toggle source
# File lib/base_chip/project.rb, line 203
def tasker_handle_results(task, result, problem_or_directory=nil, totals={})
  action = @workload.select{|w|w.full_name == task.task_name}.first
  # track_results(action, result, problem, totals)
  if result == 'fail'
    message = (problem_or_directory || "#{action.class_string} '#{action.name}' failed without an error signature").to_s
    begin
      error message
    rescue
    end
    @failing ||= 0
    @failing  += 1
    @first_error = {}
    @first_error[action.class_string] ||= message
  end
  @results                                         ||= {}
  @results[action.class_string]                    ||= {}
  @results[action.class_string][action.block.name] ||= {'pass' => [], 'fail' => [], :cancel =>[]}
  @results[action.class_string][action.block.name][result] << action
  @report_file.puts "#{result} #{action.class_string} #{task.task_name} #{problem_or_directory}"
end
tasker_run_task(t_obj) click to toggle source
# File lib/base_chip/project.rb, line 298
def tasker_run_task(t_obj)
  t = find_action(t_obj.task_name)
  begin
    t.foreground = @foreground
    t.run
  rescue ReportingError => e
    # FIXME reuse test error states here
    t.state = 'fail'
  rescue Exception => e
    t.problem = Problem.new
    t.problem.signature = "#{t.full_name} #{e.class} --- #{e.message}"
    puts e.backtrace
    # FIXME reuse test error states here
    t.state = 'fail'
  end
            #track_results(t    ,t.state,t.problem               ,t.totals)
  @tasker.register_results(t_obj,t.state,t.problem || t.directory,t.totals)
end
try_add_clusters(clusters, jobs) click to toggle source
# File lib/base_chip/project.rb, line 458
def try_add_clusters(clusters, jobs)
  clusters.each do |c|
    next if @dereferenced.include? c
    c.configure
    fault "could not determine number of jobs to run in cluster '#{c.full_name}'.  Consider setting a default for this cluster." unless (c.default_jobs || c.maximum_jobs || jobs)    
    if    (c.default_jobs || c.maximum_jobs) == nil; c.slots = jobs
    elsif jobs.nil?                                ; c.slots = c.default_jobs || c.maximum_jobs
    elsif jobs > c.maximum_jobs                    ; c.slots = c.maximum_jobs
    else                                             c.slots = jobs
    end
    @dereferenced << c
  end
end
use_tool(name,version) click to toggle source
# File lib/base_chip/project.rb, line 372
def use_tool(name,version)
  tool :name do |t|
    t.select_version version
  end
end
workload_chain() click to toggle source
# File lib/base_chip/project.rb, line 141
def workload_chain
  @workload.each do |w|
    w.task           = t = Task.new
    t.task_name      = w.full_name
    t.foreground     = @foreground
    t.worker_command = if @tasker.clusters
                         lambda { |client_id|
                           # The "@drb_uri ||=" is necessary because Drb.uri can change for some reason, and a command compare happens later
                           "#{$0} #{@orig_targets.join(' ')} --client-of #{@drb_uri ||= DRb.uri} --client-id #{client_id} --work-dir #{@pwd} #{
                             '--modes ' + BaseChip.options.modes                        if BaseChip.options.modes             } #{
                             (['--' ]   + BaseChip.options. append_arguments).join(' ') if BaseChip.options. append_arguments } #{
                             (['---']   + BaseChip.options.replace_arguments).join(' ') if BaseChip.options.replace_arguments }" }
                       else
                         nil
                       end
  end
  @workload.map do |w|
    t = w.task
    t.next_tasks = w.next_tasks.map { |nt| nt.task }
    t.wait_count = w.wait_count
    w.next_tasks.uniq!
    t
  end
end