rbbt-util 5.30.1 → 5.30.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rbbt/hpc/orchestrate.rb +23 -3
- data/lib/rbbt/hpc/slurm.rb +21 -11
- data/lib/rbbt/persist.rb +1 -1
- data/lib/rbbt/resource/path.rb +8 -2
- data/lib/rbbt/tsv.rb +1 -4
- data/lib/rbbt/util/open.rb +3 -1
- data/lib/rbbt/workflow.rb +1 -1
- data/lib/rbbt/workflow/accessor.rb +4 -4
- data/lib/rbbt/workflow/examples.rb +5 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +5 -0
- data/lib/rbbt/workflow/step.rb +6 -3
- data/lib/rbbt/workflow/step/accessor.rb +7 -1
- data/lib/rbbt/workflow/step/run.rb +11 -6
- data/lib/rbbt/workflow/usage.rb +1 -1
- data/lib/rbbt/workflow/util/archive.rb +1 -1
- data/lib/rbbt/workflow/util/provenance.rb +9 -1
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/slurm/list +33 -6
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a9ed1ed74562cdb81e14bb2b2213398646f76e532bdee48e67f9ff2f5330aad
|
|
4
|
+
data.tar.gz: e54ecf83a0b4323ffe98f8968f4a65acc2aae2ee5437330f44f14dc17c450ec5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4d2eb887a184e24d78e8c565cefc25f09246d14e0f22d9a9037447806489cb4148fb2d9d3aad4cfe9bca1f256c0ec43afcc343047f20f974e6facea3214f40c0
|
|
7
|
+
data.tar.gz: 7f593e22911a501e353b6eb49830291a29b038474fd7bfc182e402f255219fc1eaf07311ad334118b43c275abc9ab2a5198d68ccbcdce7f3b4636c38dc698afd
|
data/lib/rbbt/hpc/orchestrate.rb
CHANGED
|
@@ -5,7 +5,10 @@ module HPC
|
|
|
5
5
|
def self.job_rules(rules, job)
|
|
6
6
|
workflow = job.workflow.to_s
|
|
7
7
|
task_name = job.task_name.to_s
|
|
8
|
+
task_name = job.overriden.to_s if Symbol === job.overriden
|
|
9
|
+
|
|
8
10
|
defaults = rules["defaults"] || {}
|
|
11
|
+
defaults.merge(rules[workflow]["defaults"] || {}) if rules[workflow]
|
|
9
12
|
|
|
10
13
|
job_rules = IndiferentHash.setup(defaults.dup)
|
|
11
14
|
|
|
@@ -56,7 +59,7 @@ module HPC
|
|
|
56
59
|
deps
|
|
57
60
|
end
|
|
58
61
|
|
|
59
|
-
def self.orchestrate_job(job, options, skip = false, seen = {})
|
|
62
|
+
def self.orchestrate_job(job, options, skip = false, seen = {}, chains = {})
|
|
60
63
|
return if job.done?
|
|
61
64
|
return unless job.path.split("/")[-4] == "jobs"
|
|
62
65
|
seen[:orchestration_target_job] ||= job
|
|
@@ -76,12 +79,15 @@ module HPC
|
|
|
76
79
|
|
|
77
80
|
deps = get_job_dependencies(job, job_rules)
|
|
78
81
|
|
|
82
|
+
chains[job.path] ||= []
|
|
79
83
|
dep_ids = deps.collect do |dep|
|
|
80
84
|
skip_dep = job_rules["chain_tasks"] &&
|
|
81
85
|
job_rules["chain_tasks"][job.workflow.to_s] && job_rules["chain_tasks"][job.workflow.to_s].include?(job.task_name.to_s) &&
|
|
82
86
|
job_rules["chain_tasks"][dep.workflow.to_s] && job_rules["chain_tasks"][dep.workflow.to_s].include?(dep.task_name.to_s)
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
chains[job.path] << dep if skip_dep
|
|
89
|
+
|
|
90
|
+
deps = seen[dep.path] ||= self.orchestrate_job(dep, options, skip_dep, seen, chains)
|
|
85
91
|
if job.canfail_paths.include? dep.path
|
|
86
92
|
[deps].flatten.compact.collect{|id| ['canfail', id] * ":"}
|
|
87
93
|
else
|
|
@@ -105,7 +111,21 @@ module HPC
|
|
|
105
111
|
job_options[:config_keys] = job_options[:config_keys] ? config_keys + "," + job_options[:config_keys] : config_keys
|
|
106
112
|
end
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
manifest = []
|
|
115
|
+
stack = [job]
|
|
116
|
+
while dep = stack.pop
|
|
117
|
+
manifest << dep
|
|
118
|
+
stack += chains[dep.path] if chains[dep.path]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
job_options[:manifest] = manifest.uniq.collect{|dep| dep.workflow_short_path}
|
|
122
|
+
|
|
123
|
+
if options[:dry_run]
|
|
124
|
+
puts Log.color(:yellow, "Manifest: ") + Log.color(:blue, job_options[:manifest] * ", ") + " - tasks: #{job_options[:task_cpus] || 1} - time: #{job_options[:time]} - config: #{job_options[:config_keys]}"
|
|
125
|
+
[]
|
|
126
|
+
else
|
|
127
|
+
run_job(job, job_options)
|
|
128
|
+
end
|
|
109
129
|
end
|
|
110
130
|
end
|
|
111
131
|
end
|
data/lib/rbbt/hpc/slurm.rb
CHANGED
|
@@ -21,10 +21,12 @@ module HPC
|
|
|
21
21
|
exclusive = options.delete :exclusive
|
|
22
22
|
highmem = options.delete :highmem
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
manifest = options.delete :manifest
|
|
25
|
+
|
|
26
|
+
queue = options.delete(:queue) || Rbbt::Config.get('queue', :slurm_queue, :slurm, :SLURM, :default => 'bsc_ls')
|
|
25
27
|
task_cpus = options.delete(:task_cpus) || 1
|
|
26
28
|
nodes = options.delete(:nodes) || 1
|
|
27
|
-
time = options.delete(:time) || "0:00
|
|
29
|
+
time = options.delete(:time) || "0:02:00"
|
|
28
30
|
|
|
29
31
|
inputs_dir = options.delete :inputs_dir
|
|
30
32
|
config_keys = options.delete :config_keys
|
|
@@ -258,6 +260,10 @@ EOF
|
|
|
258
260
|
workflow write_info --recursive --force=false --check_pid "$step_path" slurm_job $SLURM_JOB_ID
|
|
259
261
|
EOF
|
|
260
262
|
|
|
263
|
+
header +=<<-EOF if manifest
|
|
264
|
+
#MANIFEST: #{manifest * ", "}
|
|
265
|
+
EOF
|
|
266
|
+
|
|
261
267
|
header +=<<-EOF
|
|
262
268
|
#CMD: #{rbbt_cmd}
|
|
263
269
|
EOF
|
|
@@ -301,11 +307,15 @@ EOF
|
|
|
301
307
|
coda +=<<-EOF
|
|
302
308
|
|
|
303
309
|
# Sync data to target location
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
if [ $exit_status == '0' ]; then
|
|
311
|
+
mkdir -p "$(dirname '#{target}')"
|
|
312
|
+
rsync -avztAXHP --copy-unsafe-links "#{source}/" "#{target}/" &>> #{fsync}
|
|
313
|
+
sync_es="$?"
|
|
314
|
+
echo $sync_es > #{fsyncexit}
|
|
315
|
+
find '#{target}' -type l -ls | awk '$13 ~ /^#{target.gsub('/','\/')}/ { sub("#{source}", "#{target}", $13); print $11, $13 }' | while read A B; do rm $A; ln -s $B $A; done
|
|
316
|
+
else
|
|
317
|
+
sync_es="$exit_status"
|
|
318
|
+
fi
|
|
309
319
|
EOF
|
|
310
320
|
|
|
311
321
|
if contain && (wipe_container == "post" || wipe_container == "both")
|
|
@@ -331,11 +341,11 @@ EOF
|
|
|
331
341
|
else
|
|
332
342
|
coda +=<<-EOF
|
|
333
343
|
##{exec_cmd} system clean
|
|
334
|
-
if [ $exit_status == '0' -a $sync_es == '0' ]; then
|
|
344
|
+
#if [ $exit_status == '0' -a $sync_es == '0' ]; then
|
|
335
345
|
rm -Rfv #{contain} &>> #{fsync}
|
|
336
|
-
else
|
|
337
|
-
echo "ERROR: Process failed or results could not sync correctly. Contain directory not purged" &>> #{fsync}
|
|
338
|
-
fi
|
|
346
|
+
#else
|
|
347
|
+
# echo "ERROR: Process failed or results could not sync correctly. Contain directory not purged" &>> #{fsync}
|
|
348
|
+
#fi
|
|
339
349
|
EOF
|
|
340
350
|
|
|
341
351
|
end
|
data/lib/rbbt/persist.rb
CHANGED
data/lib/rbbt/resource/path.rb
CHANGED
|
@@ -218,7 +218,14 @@ module Path
|
|
|
218
218
|
|
|
219
219
|
else
|
|
220
220
|
where = where.to_sym
|
|
221
|
-
|
|
221
|
+
|
|
222
|
+
if paths.include? where
|
|
223
|
+
path = paths[where]
|
|
224
|
+
elsif where.to_s.include?("/")
|
|
225
|
+
path = where.to_s
|
|
226
|
+
else
|
|
227
|
+
raise "Did not recognize the 'where' tag: #{where}. Options: #{paths.keys}" unless paths.include? where
|
|
228
|
+
end
|
|
222
229
|
|
|
223
230
|
if where == :lib
|
|
224
231
|
libdir = @libdir || Path.caller_lib_dir(caller_lib) || "NOLIBDIR"
|
|
@@ -227,7 +234,6 @@ module Path
|
|
|
227
234
|
end
|
|
228
235
|
|
|
229
236
|
pwd = FileUtils.pwd
|
|
230
|
-
path = paths[where]
|
|
231
237
|
path = File.join(path, "{PATH}") unless path.include? "PATH}" or path.include? "{BASENAME}"
|
|
232
238
|
path = path.
|
|
233
239
|
sub('{PKGDIR}', pkgdir).
|
data/lib/rbbt/tsv.rb
CHANGED
|
@@ -118,16 +118,13 @@ module TSV
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
if data.respond_to? :persistence_path
|
|
121
|
+
data.read
|
|
121
122
|
data
|
|
122
123
|
else
|
|
123
124
|
h = data.dup
|
|
124
125
|
data.clear
|
|
125
126
|
data.annotate h
|
|
126
127
|
end
|
|
127
|
-
|
|
128
|
-
data.read
|
|
129
|
-
|
|
130
|
-
data
|
|
131
128
|
end
|
|
132
129
|
|
|
133
130
|
def self.parse_header(stream, options = {})
|
data/lib/rbbt/util/open.rb
CHANGED
|
@@ -748,7 +748,9 @@ module Open
|
|
|
748
748
|
if (dir_sub_path = find_repo_dir(path))
|
|
749
749
|
writable_repo?(*dir_sub_path)
|
|
750
750
|
else
|
|
751
|
-
if File.
|
|
751
|
+
if File.symlink?(path)
|
|
752
|
+
File.writable?(File.dirname(path))
|
|
753
|
+
elsif File.exist?(path)
|
|
752
754
|
File.writable?(path)
|
|
753
755
|
else
|
|
754
756
|
File.writable?(File.dirname(File.expand_path(path)))
|
data/lib/rbbt/workflow.rb
CHANGED
|
@@ -190,7 +190,7 @@ module Workflow
|
|
|
190
190
|
return Misc.string2const Misc.camel_case(wf_name)
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
-
Log.
|
|
193
|
+
Log.high{"Loading workflow #{wf_name}"}
|
|
194
194
|
require_local_workflow(wf_name) or
|
|
195
195
|
(Workflow.autoinstall and `rbbt workflow install #{Misc.snake_case(wf_name)} || rbbt workflow install #{wf_name}` and require_local_workflow(wf_name)) or raise("Workflow not found or could not be loaded: #{ wf_name }")
|
|
196
196
|
begin
|
|
@@ -382,8 +382,8 @@ module Workflow
|
|
|
382
382
|
else
|
|
383
383
|
task_info = d[:workflow].task_info(d[:task])
|
|
384
384
|
|
|
385
|
-
|
|
386
|
-
d[:workflow]._job(d[:task], d[:jobname],
|
|
385
|
+
_inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
|
|
386
|
+
d[:workflow]._job(d[:task], d[:jobname], _inputs)
|
|
387
387
|
end
|
|
388
388
|
end
|
|
389
389
|
ComputeDependency.setup(d, compute) if compute
|
|
@@ -400,8 +400,8 @@ module Workflow
|
|
|
400
400
|
setup_override_dependency(value, dep[:workflow], dep[:task])
|
|
401
401
|
else
|
|
402
402
|
task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
|
|
403
|
-
|
|
404
|
-
dep = dep[:workflow]._job(dep[:task], dep[:jobname],
|
|
403
|
+
_inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
|
|
404
|
+
dep = dep[:workflow]._job(dep[:task], dep[:jobname], _inputs)
|
|
405
405
|
end
|
|
406
406
|
end
|
|
407
407
|
end
|
|
@@ -53,7 +53,11 @@ module Workflow
|
|
|
53
53
|
if file =~ /\.yaml/
|
|
54
54
|
inputs[input.to_sym] = YAML.load(Open.read(file))
|
|
55
55
|
else
|
|
56
|
-
|
|
56
|
+
if File.symlink?(file)
|
|
57
|
+
inputs[input.to_sym] = File.readlink(file)
|
|
58
|
+
else
|
|
59
|
+
inputs[input.to_sym] = Open.realpath(file)
|
|
60
|
+
end
|
|
57
61
|
end
|
|
58
62
|
when :text
|
|
59
63
|
Log.debug "Reading #{ input } from #{file}"
|
data/lib/rbbt/workflow/step.rb
CHANGED
|
@@ -465,7 +465,10 @@ class Step
|
|
|
465
465
|
self
|
|
466
466
|
end
|
|
467
467
|
|
|
468
|
-
|
|
468
|
+
#connected = true means that dependency searching ends when a result is done
|
|
469
|
+
#but dependencies are absent, meanining that the file could have been dropped
|
|
470
|
+
#in
|
|
471
|
+
def rec_dependencies(connected = false, seen = [])
|
|
469
472
|
|
|
470
473
|
# A step result with no info_file means that it was manually
|
|
471
474
|
# placed. In that case, do not consider its dependencies
|
|
@@ -480,9 +483,9 @@ class Step
|
|
|
480
483
|
#next if self.done? && Open.exists?(info_file) && info[:dependencies] && info[:dependencies].select{|task,name,path| path == step.path }.empty?
|
|
481
484
|
next if archived_deps.include? step.path
|
|
482
485
|
next if seen.include? step.path
|
|
483
|
-
next if self.done? &&
|
|
486
|
+
next if self.done? && connected && ! updatable?
|
|
484
487
|
|
|
485
|
-
r = step.rec_dependencies(
|
|
488
|
+
r = step.rec_dependencies(connected, new_dependencies.collect{|d| d.path})
|
|
486
489
|
new_dependencies.concat r
|
|
487
490
|
new_dependencies << step
|
|
488
491
|
}
|
|
@@ -154,10 +154,16 @@ class Step
|
|
|
154
154
|
@name ||= path.sub(/.*\/#{Regexp.quote task_name.to_s}\/(.*)/, '\1')
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
|
|
157
158
|
def short_path
|
|
158
159
|
[task_name, name] * "/"
|
|
159
160
|
end
|
|
160
161
|
|
|
162
|
+
def workflow_short_path
|
|
163
|
+
return short_path unless workflow
|
|
164
|
+
workflow.to_s + "#" + short_path
|
|
165
|
+
end
|
|
166
|
+
|
|
161
167
|
def task_name
|
|
162
168
|
@task_name ||= task.name
|
|
163
169
|
end
|
|
@@ -456,7 +462,7 @@ class Step
|
|
|
456
462
|
end
|
|
457
463
|
|
|
458
464
|
def dirty_files
|
|
459
|
-
rec_dependencies = self.rec_dependencies
|
|
465
|
+
rec_dependencies = self.rec_dependencies(true)
|
|
460
466
|
return [] if rec_dependencies.empty?
|
|
461
467
|
canfail_paths = self.canfail_paths
|
|
462
468
|
|
|
@@ -112,23 +112,27 @@ class Step
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def updatable?
|
|
115
|
-
|
|
115
|
+
return true if ENV["RBBT_UPDATE_ALL_JOBS"] == 'true'
|
|
116
|
+
return false unless ENV["RBBT_UPDATE"] == "true"
|
|
117
|
+
return false unless Open.exists?(info_file)
|
|
118
|
+
return true if status != :noinfo && ! (relocated? && done?)
|
|
119
|
+
false
|
|
116
120
|
end
|
|
117
121
|
|
|
118
122
|
def dependency_checks
|
|
119
123
|
return [] if ENV["RBBT_UPDATE"] != "true"
|
|
120
124
|
|
|
121
|
-
rec_dependencies.
|
|
125
|
+
rec_dependencies(true).
|
|
122
126
|
reject{|dependency| (defined?(WorkflowRemoteClient) && WorkflowRemoteClient::RemoteStep === dependency) || Open.remote?(dependency.path) }.
|
|
123
127
|
reject{|dependency| dependency.error? }.
|
|
124
128
|
#select{|dependency| Open.exists?(dependency.path) || ((Open.exists?(dependency.info_file) && (dependency.status == :cleaned) || dependency.status == :waiting)) }.
|
|
125
|
-
select{|dependency| dependency.updatable? }.
|
|
129
|
+
#select{|dependency| dependency.updatable? }.
|
|
126
130
|
collect{|dependency| Workflow.relocate_dependency(self, dependency)}
|
|
127
131
|
end
|
|
128
132
|
|
|
129
133
|
def input_checks
|
|
130
|
-
(inputs.select{|i| Step === i } + inputs.select{|i| Path === i && Step === i.resource}.collect{|i| i.resource})
|
|
131
|
-
select{|dependency| dependency.updatable? }
|
|
134
|
+
(inputs.select{|i| Step === i } + inputs.select{|i| Path === i && Step === i.resource}.collect{|i| i.resource})
|
|
135
|
+
#select{|dependency| dependency.updatable? }
|
|
132
136
|
end
|
|
133
137
|
|
|
134
138
|
def checks
|
|
@@ -153,7 +157,8 @@ class Step
|
|
|
153
157
|
canfail_paths = self.canfail_paths
|
|
154
158
|
this_mtime = Open.mtime(self.path) if Open.exists?(self.path)
|
|
155
159
|
|
|
156
|
-
outdated_time = checks.select{|dep| dep.updatable? && dep.done? && Persist.newer?(path, dep.path) }
|
|
160
|
+
#outdated_time = checks.select{|dep| dep.updatable? && dep.done? && Persist.newer?(path, dep.path) }
|
|
161
|
+
outdated_time = checks.select{|dep| dep.done? && Persist.newer?(path, dep.path) }
|
|
157
162
|
outdated_dep = checks.reject{|dep| dep.done? || (dep.error? && ! dep.recoverable_error? && canfail_paths.include?(dep.path)) }
|
|
158
163
|
|
|
159
164
|
#checks.each do |dep|
|
data/lib/rbbt/workflow/usage.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Task
|
|
|
21
21
|
|
|
22
22
|
selects = []
|
|
23
23
|
if inputs.any?
|
|
24
|
-
inputs.zip(input_types.values_at(*inputs)).select{|i,t| t.to_sym == :select
|
|
24
|
+
inputs.zip(input_types.values_at(*inputs)).select{|i,t| t.to_sym == :select && input_options[i] && input_options[i][:select_options] }.each{|i,t| selects << [i, input_options[i][:select_options]] }
|
|
25
25
|
puts SOPT.input_doc(inputs, input_types, input_descriptions, input_defaults, true)
|
|
26
26
|
puts
|
|
27
27
|
end
|
|
@@ -78,6 +78,7 @@ class Step
|
|
|
78
78
|
name = info[:name] || File.basename(path)
|
|
79
79
|
status = :unsync if status == :done and not Open.exist?(path)
|
|
80
80
|
status = :notfound if status == :noinfo and not Open.exist?(path)
|
|
81
|
+
|
|
81
82
|
str = " " * offset
|
|
82
83
|
str << prov_report_msg(status, name, path, info)
|
|
83
84
|
step.dependencies.reverse.each do |dep|
|
|
@@ -90,7 +91,14 @@ class Step
|
|
|
90
91
|
if expand_repeats
|
|
91
92
|
str << Log.color(:green, Log.uncolor(prov_report(dep, offset+1, task)))
|
|
92
93
|
else
|
|
93
|
-
|
|
94
|
+
info = dep.info || {}
|
|
95
|
+
status = info[:status] || :missing
|
|
96
|
+
status = "remote" if Open.remote?(path) || Open.ssh?(path)
|
|
97
|
+
name = info[:name] || File.basename(path)
|
|
98
|
+
status = :unsync if status == :done and not Open.exist?(path)
|
|
99
|
+
status = :notfound if status == :noinfo and not Open.exist?(path)
|
|
100
|
+
|
|
101
|
+
str << Log.color(status == :notfound ? :blue : :green, " " * (offset + 1) + Log.uncolor(prov_report_msg(status, name, path, info)))
|
|
94
102
|
end
|
|
95
103
|
end
|
|
96
104
|
end if step.dependencies
|
data/share/rbbt_commands/migrate
CHANGED
|
@@ -70,6 +70,13 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
70
70
|
cmd = nil
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
+
if m = Open.read(fcmd).match(/#MANIFEST: (.*)/)
|
|
74
|
+
manifest = m[1]
|
|
75
|
+
else
|
|
76
|
+
manifest = nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
|
|
73
80
|
if m = Open.read(fcmd).match(/# Run command\n(.*?)\n/im)
|
|
74
81
|
exe = m[1].sub('step_path=$(','')
|
|
75
82
|
else
|
|
@@ -98,15 +105,24 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
98
105
|
if File.exists?(fstatus = File.join(dir, 'job.status'))
|
|
99
106
|
nodes = Open.read(fstatus).split("\n").last.split(/\s+/).last.split(",")
|
|
100
107
|
elsif job_nodes[id]
|
|
101
|
-
nodes = job_nodes[id]
|
|
108
|
+
nodes = job_nodes[id].reject{|n| n.include? "("}
|
|
102
109
|
else
|
|
103
110
|
nodes = []
|
|
104
111
|
end
|
|
105
112
|
|
|
113
|
+
if File.exists?(File.join(dir, 'exit.status'))
|
|
114
|
+
now = File.ctime(File.join(dir, 'exit.status'))
|
|
115
|
+
else
|
|
116
|
+
now = Time.now
|
|
117
|
+
end
|
|
118
|
+
|
|
106
119
|
if File.exists?(File.join(dir, 'std.out'))
|
|
120
|
+
cerrt = File.ctime File.join(dir, 'std.err')
|
|
121
|
+
coutt = File.ctime File.join(dir, 'std.out')
|
|
107
122
|
outt = File.mtime File.join(dir, 'std.out')
|
|
108
123
|
errt = File.mtime File.join(dir, 'std.err')
|
|
109
|
-
time_diff =
|
|
124
|
+
time_diff = now - [outt, errt].max
|
|
125
|
+
time_elapsed = now - [cerrt, coutt].min
|
|
110
126
|
end
|
|
111
127
|
|
|
112
128
|
fdep = File.join(dir, 'dependencies.list')
|
|
@@ -115,14 +131,19 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
115
131
|
fcadep = File.join(dir, 'canfail_dependencies.list')
|
|
116
132
|
cadeps = Open.read(fcadep).split("\n") if File.exists?(fcadep)
|
|
117
133
|
|
|
118
|
-
if done || error || aborted || running || queued || jobid
|
|
134
|
+
if done || error || aborted || running || queued || jobid
|
|
119
135
|
select = false
|
|
120
136
|
select = true if done && exit_status == 0
|
|
121
137
|
select = true if error && exit_status && exit_status != 0
|
|
122
138
|
select = true if aborted && (exit_status.nil? && ! running_jobs.include?(id))
|
|
123
|
-
|
|
124
|
-
select = true if
|
|
139
|
+
is_running = exit_status.nil? && running_jobs.include?(id) && (!deps || (running_jobs & deps).empty?)
|
|
140
|
+
select = true if queued && deps && (running_jobs & deps).any? || queued && is_running && nodes.empty?
|
|
141
|
+
select = true if running && nodes.any? && (exit_status.nil? && running_jobs.include?(id)) && (!deps || (running_jobs & deps).empty?)
|
|
125
142
|
select = true if jobid && jobid.split(",").include?(id)
|
|
143
|
+
select = select && cmd.match(/#{search}/) if search
|
|
144
|
+
next unless select
|
|
145
|
+
elsif search
|
|
146
|
+
select = false
|
|
126
147
|
select = true if search && cmd.match(/#{search}/)
|
|
127
148
|
next unless select
|
|
128
149
|
end
|
|
@@ -130,6 +151,8 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
130
151
|
|
|
131
152
|
puts Log.color :blue, dir
|
|
132
153
|
puts Log.color(:magenta, "Creation: ") << File.mtime(File.join(dir, 'command.slurm')).to_s
|
|
154
|
+
puts Log.color(:magenta, "Started: ") << File.ctime(File.join(dir, 'std.err')).to_s if File.exist?(File.join(dir, 'std.err'))
|
|
155
|
+
puts Log.color(:magenta, "Manifest: ") << Log.color(:yellow, manifest)
|
|
133
156
|
puts Log.color(:magenta, "Done: ") << File.mtime(File.join(dir, 'exit.status')).to_s if File.exist?(File.join(dir, 'exit.status'))
|
|
134
157
|
puts Log.color(:magenta, "Exec: ") << (exe || "Missing")
|
|
135
158
|
puts Log.color(:magenta, "CMD: ") << (Log.color(:yellow, cmd) || "Missing")
|
|
@@ -138,7 +161,8 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
138
161
|
puts Log.color(:magenta, "Dependencies: ") << deps * ", " if deps
|
|
139
162
|
puts Log.color(:magenta, "Dependencies (can fail): ") << cadeps * ", " if cadeps
|
|
140
163
|
puts Log.color(:magenta, "Nodes: ") << nodes * ", "
|
|
141
|
-
puts Log.color(:magenta, "
|
|
164
|
+
puts Log.color(:magenta, "Time elapsed: ") << Misc.format_seconds(time_elapsed) if time_elapsed
|
|
165
|
+
puts Log.color(:magenta, "Output: ") << File.exists?(File.join(dir, 'std.out')).to_s << (id.nil? || File.exists?(File.join(dir, 'exit.status')) ? "" : " (last update " + Misc.format_seconds(time_diff) + " ago)")
|
|
142
166
|
|
|
143
167
|
if options[:sbatch_parameters]
|
|
144
168
|
puts Log.color(:magenta, "SBATCH parameters: ")
|
|
@@ -180,8 +204,11 @@ workdir.glob("**/command.slurm").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
180
204
|
start = rss_average.keys.sort.first
|
|
181
205
|
eend = rss_average.keys.sort.last
|
|
182
206
|
time_elapsed = eend - start
|
|
207
|
+
ticks = 1 if ticks == 0
|
|
208
|
+
time_elapsed = 1 if time_elapsed == 0
|
|
183
209
|
puts Log.color(:yellow, "CPU average: ") + "%.2f" % ( ticks / clock_ticks / time_elapsed * 100).to_s
|
|
184
210
|
puts Log.color(:yellow, "RSS average: ") + "%.2f GB" % Misc.mean(rss_average.collect{|t,l| Misc.sum(l) / (1024 * 1024 * 1024)}).to_s
|
|
211
|
+
puts Log.color(:yellow, "Time: ") + Misc.format_seconds((eend - start))
|
|
185
212
|
|
|
186
213
|
end
|
|
187
214
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbbt-util
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.30.
|
|
4
|
+
version: 5.30.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miguel Vazquez
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-02-
|
|
11
|
+
date: 2021-02-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|