require 'fileutils' require 'nera_simulator_records' require 'nera_job_records' require 'logger' module NERA # This class contains the information of the folder structure class DbFolders # ------------------------------------- # instance variables ------------------ # ------------------------------------- @db_folder # path to db_folder @logger # logger instance attr_reader :logger #-------------------------------------- #-class methods ----------------------- #-------------------------------------- def initialize( db_folder) if db_folder =~ /\/$/ @db_folder = db_folder else @db_folder = db_folder + '/' end unless valid_db?( @db_folder) raise RuntimeError, "Database #{@db_folder} is not a valid database folder." end # load simulator classes Dir.glob( "#{@db_folder}/Simulator_classes/*.rb").each do |lib| require lib end # logger instance @logger = Logger.new( path_to_log_file, 8) @logger.level = Logger::INFO end def valid_db?( fold) return false unless FileTest.directory?( fold) return false unless FileTest.directory?( fold + "Jobs/") return false unless FileTest.directory?( fold + "Jobs/Include/") return false unless FileTest.directory?( fold + "Tables/") return false unless FileTest.directory?( fold + "Simulator_classes/") return false unless FileTest.exist?( fold + "Tables/simulators.pstore") return false unless FileTest.exist?( fold + "Tables/jobs.pstore") return true end private :valid_db? def self.create_db( db_folder) if FileTest.directory?( db_folder) raise RuntimeError, "Folder #{db_folder} already exists." end if db_folder =~ /\/$/ db = db_folder else db = db_folder + '/' end FileUtils.mkdir( db, :verbose => true) FileUtils.mkdir( db + "Jobs/", :verbose => true) FileUtils.mkdir( db + "Jobs/Include/", :verbose => true) FileUtils.mkdir( db + "Tables/", :verbose => true) FileUtils.mkdir( db + "Simulator_classes/", :verbose => true) f = NERA::SimulatorRecords.create_table( db + "Tables/simulators.pstore") raise "must not happen" unless f f = NERA::JobRecords.create_table( db + "Tables/jobs.pstore") raise "must not happen" unless f File.open( db + 'simulators.yml', 'w') do |io| YAML.dump( [], io ) io.flush end File.open( db + 'Jobs/jobs.yml', 'w') do |io| YAML.dump( [], io ) io.flush end return true end #-------------------------------------- #-public instance methods-------------- #-------------------------------------- public def path_to_simulator_layer return @db_folder end def path_to_simulators_table return "#{@db_folder}Tables/simulators.pstore" end def path_to_simulators_yaml return "#{@db_folder}simulators.yml" end def create_new_simulator_folder( sim_class) unless sim_class.superclass == NERA::Simulator raise ArgumentError, "must be a subclass of NERA::Simulator" end name = sim_class.to_s name += '/' if FileTest.directory?( @db_folder + name) or FileTest.directory?( @db_folder + "Tables/" + name) return nil end FileUtils.mkdir( @db_folder + name, :verbose => true) FileUtils.mkdir( @db_folder + "Tables/" + name, :verbose => true) File.open( path_to_parameters_yaml( sim_class) , 'w') do |io| YAML.dump( [], io ) io.flush end return true end def path_to_parameter_layer( sim_class) unless sim_class.superclass == NERA::Simulator raise ArgumentError, "must be a subclass of NERA::Simulator" end name = sim_class.to_s name += '/' path = @db_folder + name if FileTest.directory?(path) return path else return nil end end def path_to_parameters_table( sim_class) unless sim_class.superclass == NERA::Simulator raise ArgumentError, "must be a subclass of NERA::Simulator" end name = sim_class.to_s name += '/' path = @db_folder + 'Tables/' + name + 'parameters.pstore' unless FileTest.directory?( @db_folder + 'Tables/' + name) return nil end return path end def path_to_parameters_yaml( sim_class) return path_to_parameter_layer( sim_class) + 'parameters.yml' end def create_new_parameter_folder( sim_class, param_id) p = path_to_parameter_layer( sim_class) return nil unless p if param_id.to_i > 99999 or param_id.to_i <= 0 raise RuntimeError, "The specified parameter id #{param_id} is out of range." end fold_name = sprintf("%05d/", param_id.to_i) if FileTest.directory?( p + fold_name) return nil end FileUtils.mkdir( p + fold_name) p = path_to_parameters_table( sim_class) p.sub!(/parameters.pstore$/, fold_name) FileUtils.mkdir( p) File.open( path_to_runs_yaml( sim_class, param_id) , 'w') do |io| YAML.dump( [], io ) io.flush end return true end def path_to_run_layer( sim_class, param_id) p = path_to_parameter_layer( sim_class) return nil unless p if param_id.to_i > 99999 or param_id.to_i <= 0 return nil end fold_name = sprintf("%05d/", param_id.to_i) path = p + fold_name return path end def path_to_runs_table( sim_class, param_id) ppt = path_to_parameters_table( sim_class) return nil unless ppt if param_id.to_i > 99999 or param_id.to_i <= 0 return nil end fold_name = sprintf("%05d/", param_id.to_i) path = ppt.sub(/parameters.pstore$/, fold_name) raise "must not happen" unless path return path + 'runs.pstore' end def path_to_runs_yaml( sim_class, param_id) return path_to_run_layer( sim_class, param_id) + 'runs.yml' end def path_to_job_layer return @db_folder + "Jobs/" end def path_to_jobs_table return @db_folder + "Tables/jobs.pstore" end def path_to_jobs_yaml return path_to_job_layer + "jobs.yml" end def path_to_job_script(job_id) filename = sprintf("j%06d.sh", job_id) return path_to_job_layer + filename end def path_to_include_layer return @db_folder + "Jobs/Include/" end def search_include_files return Dir.glob( path_to_include_layer + "j[0-9][0-9][0-9][0-9][0-9][0-9]*.tar.bz2") end def path_to_finished_jobs_file return @db_folder + "Tables/finished_jobs.yml" end def path_to_hosts_yaml return @db_folder + "Tables/hosts.yml" end def path_to_log_file return @db_folder + "Tables/logfile.txt" end end end