require 'date' require 'nera_db_folders' require 'nera_simulator_records' require 'nera_parameter_records' require 'nera_run_records' require 'nera_job_records' require 'nera_job_script' require 'fileutils' module NERA class RunLayerController # instance of NERA::DbFolders @db_folders # instance of NERA::Simulator class @sim_instance # id of the parameter set @param_id # instance of NERA::RunRecords @run_records def initialize( path_db_folder, sim_name, param_id) raise ArgumentError unless path_db_folder.is_a?(String) @db_folders = NERA::DbFolders.new( path_db_folder) sim_records = NERA::SimulatorRecords.new( @db_folders.path_to_simulators_table) found = sim_records.list.find do |rec| rec[:name] == sim_name.to_s end raise "No such simulator : #{sim_name.to_s}" unless found sim_class = NERA::Simulator.inherited_simulators.find do |sim| sim.to_s == sim_name.to_s end raise "No such simulator : #{sim_name.to_s}" unless sim_class @sim_instance = sim_class.new @param_id = param_id param_records = NERA::ParameterRecords.new( @db_folders.path_to_parameters_table( sim_class), sim_class) found = param_records.find_by_id( @param_id) raise "No such parameter : #{param_id}." unless found @sim_instance.class::Parameters.each do |pa| key = pa[0] if found[key] @sim_instance.param[key] = found[key] else @sim_instance.param[key] = pa[2] end end @run_records = NERA::RunRecords.new( @db_folders.path_to_runs_table( sim_class, @param_id) ) end def path_to_run_layer return @db_folders.path_to_run_layer( @sim_instance.class, @param_id) end def all_runs_list_in_csv list = @run_records.list_all header = @run_records.keys.dup csv_list = [] list.each do |r_hash| strings = [] header.each do |key| if r_hash[key].is_a?(DateTime) strings << r_hash[key].to_s.split('T')[0] else strings << r_hash[key].to_s end end csv_list << strings.join(", ") end return header.join(", "), csv_list end def create_jobs( num_jobs, num_runs_per_job = 1) unless num_jobs.is_a?(Integer) and num_jobs >= 0 raise ArgumentError, "num_jobs must be equal to or larger than zero." end job_ids = [] job_recs = NERA::JobRecords.new( @db_folders.path_to_jobs_table) js = NERA::JobScript.new( @db_folders) job_recs.transaction { @run_records.transaction { num_jobs.times do |j_idx| run_stat = @run_records.add( num_runs_per_job) rid = run_stat[0][:id] jid = job_recs.add( @sim_instance.class, @param_id, rid, num_runs_per_job) @run_records.set_job_id( rid, num_runs_per_job, jid) sim_records = NERA::SimulatorRecords.new( @db_folders.path_to_simulators_table) found = sim_records.list.find do |rec| rec[:name] == @sim_instance.class.to_s end path_script = js.create_script( jid, found[:id], @param_id, @sim_instance, run_stat) job_ids << jid end } } dump_in_yaml( job_recs) return job_ids end def not_finished_jobs_list_in_csv list = @run_records.list_all_not_finished header = "job_id, created_at, run_id, num_runs, omp_threads, mpi_processes" jobids = list.map do |rec| rec[:job_id] end jobids = jobids.sort.uniq csv_list = [] jobids.each do |jid| strings = [ jid] found = list.find_all do |r| r[:job_id] == jid end found_first = found.first strings << found_first[:created_at].to_s.split('T')[0] strings << found_first[:id] strings << found.size strings << found_first[:omp_threads] strings << found_first[:mpi_processes] csv_list << strings.join(", ") end return header, csv_list end def cancel_jobs( job_ids) unless job_ids.is_a?(Array) raise ArgumentError, "job_ids must be an Array." end job_ids.each do |x| raise ArgumentError, "each element of job_ids must be an Integer" unless x.is_a?(Integer) end job_recs = NERA::JobRecords.new( @db_folders.path_to_jobs_table) destroyed_jobids = [] job_recs.transaction { @run_records.transaction { job_ids.each do |jid| d = job_recs.destroy(jid) next unless d a = @run_records.destroy_job_id( jid) raise "must not happen" unless a FileUtils.rm( @db_folders.path_to_job_script(jid) ) destroyed_jobids << jid end } } dump_in_yaml( job_recs) destroyed_jobids = nil if destroyed_jobids.size == 0 return destroyed_jobids end def analysis_methods found = @sim_instance.public_methods.find_all do |meth| meth =~ /^analyze_/ end return found end def analyze( method_str) unless method_str.is_a?(String) or method_str.is_a?(Symbol) raise ArgumentError, "method_str must be a String or Symbol" end return nil unless method_str.to_s =~ /^analyze_/ found = @sim_instance.public_methods.find do |m| m == method_str.to_s end return nil unless found FileUtils.cd( @db_folders.path_to_run_layer(@sim_instance.class, @param_id) ) { @sim_instance.__send__( method_str) } end def analyze_all found = @sim_instance.public_methods.find_all do |m| m =~ /^analyze_/ end return nil unless found FileUtils.cd( @db_folders.path_to_run_layer(@sim_instance.class, @param_id) ) { found.each do |meth| @sim_instance.__send__( meth) end } end private def dump_in_yaml( job_recs) File.open( @db_folders.path_to_runs_yaml( @sim_instance.class, @param_id), 'w') do |io| YAML.dump( @run_records.list_all, io) io.flush end File.open( @db_folders.path_to_jobs_yaml, 'w') do |io| YAML.dump( job_recs.list_all, io) io.flush end end end end