rbbt-util 5.33.7 → 5.33.11
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/batch.rb +4 -4
- data/lib/rbbt/hpc/orchestrate/batches.rb +7 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +44 -38
- data/lib/rbbt/hpc/orchestrate.rb +9 -4
- data/lib/rbbt/hpc/slurm.rb +2 -2
- data/lib/rbbt/resource/path.rb +1 -2
- data/lib/rbbt/resource/util.rb +20 -7
- data/lib/rbbt/util/misc/inspect.rb +9 -8
- data/lib/rbbt/util/misc/system.rb +2 -1
- data/lib/rbbt/workflow/dependencies.rb +4 -1
- data/lib/rbbt/workflow/step/accessor.rb +4 -0
- data/lib/rbbt/workflow/step/dependencies.rb +1 -1
- data/lib/rbbt/workflow/step/save_load_inputs.rb +228 -44
- data/lib/rbbt/workflow/step.rb +3 -3
- data/share/install/software/lib/install_helpers +4 -0
- data/share/rbbt_commands/hpc/list +54 -16
- data/share/rbbt_commands/hpc/orchestrate +2 -1
- data/share/rbbt_commands/hpc/tail +1 -0
- data/share/rbbt_commands/lsf/list +54 -16
- data/share/rbbt_commands/lsf/orchestrate +2 -1
- data/share/rbbt_commands/lsf/tail +1 -0
- data/share/rbbt_commands/slurm/list +54 -16
- data/share/rbbt_commands/slurm/orchestrate +2 -1
- data/share/rbbt_commands/slurm/tail +1 -0
- data/share/rbbt_commands/workflow/task +11 -0
- data/test/rbbt/workflow/step/test_save_load_inputs.rb +91 -1
- 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: e5c26a161d8529f19d32ace8b5565042b4baa6fef3d69580f46aadc523e8cc51
|
|
4
|
+
data.tar.gz: 8ee1305d3a66a55273474da60e84cec3385391ad99c8c87e764fd72eaaf29285
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b9ddf9ff821584ef21f7c30be381965ea9a8cf1cce7e9913cc11c118fa1d31211fe321d72c5d8daabcb14aac5b20df45c527fefa1d142c7a08633c3818b79dd
|
|
7
|
+
data.tar.gz: c0ab742b23fe87fd7f52bfdfe75690a02566547a34a484912c74766cff70c83634434d5a67a9e665bfdffb28be143afdb20028356befe045e19b14bcc83a21ff
|
data/lib/rbbt/hpc/batch.rb
CHANGED
|
@@ -88,8 +88,8 @@ module HPC
|
|
|
88
88
|
def rbbt_job_exec_cmd(job, options)
|
|
89
89
|
|
|
90
90
|
jobname = job.clean_name
|
|
91
|
-
workflow = job.workflow
|
|
92
|
-
task = job.task_name
|
|
91
|
+
workflow = job.original_workflow || job.workflow
|
|
92
|
+
task = job.original_task_name || job.task_name
|
|
93
93
|
|
|
94
94
|
Misc.add_defaults options, :jobname => jobname
|
|
95
95
|
|
|
@@ -535,8 +535,8 @@ env > #{batch_options[:fenv]}
|
|
|
535
535
|
:batch_base_dir, :clean_batch_job, :remove_batch_dir, :batch_procpath, :tail, :batch_dependencies, :dry_run,
|
|
536
536
|
:batch_base_dir => File.expand_path(File.join('~/rbbt-batch'))
|
|
537
537
|
|
|
538
|
-
workflow = job.workflow
|
|
539
|
-
task_name = job.task_name
|
|
538
|
+
workflow = job.original_workflow ||job.workflow
|
|
539
|
+
task_name = job.original_task_name || job.task_name
|
|
540
540
|
|
|
541
541
|
workflows_to_load = job.rec_dependencies.select{|d| Step === d}.collect{|d| d.workflow }.compact.collect(&:to_s) - [workflow.to_s]
|
|
542
542
|
|
|
@@ -101,7 +101,9 @@ module HPC
|
|
|
101
101
|
|
|
102
102
|
batches.each do |batch|
|
|
103
103
|
job_rules = batch[:jobs].inject(nil) do |acc,job|
|
|
104
|
-
|
|
104
|
+
workflow = job.original_workflow || job.workflow
|
|
105
|
+
task_name = job.original_task_name || job.task_name
|
|
106
|
+
task_rules = task_specific_rules(rules, workflow, task_name)
|
|
105
107
|
acc = accumulate_rules(acc, task_rules.dup)
|
|
106
108
|
end
|
|
107
109
|
|
|
@@ -120,13 +122,16 @@ module HPC
|
|
|
120
122
|
end
|
|
121
123
|
|
|
122
124
|
batches.each do |batch|
|
|
125
|
+
next if batch[:top_level].overriden?
|
|
123
126
|
next unless batch[:rules][:skip]
|
|
124
127
|
batch[:rules].delete :skip
|
|
125
128
|
next if batch[:deps].nil?
|
|
126
129
|
|
|
127
130
|
if batch[:deps].any?
|
|
131
|
+
batch_dep_jobs = batch[:top_level].rec_dependencies
|
|
128
132
|
target = batch[:deps].select do |target|
|
|
129
|
-
(
|
|
133
|
+
batch_dep_jobs.include?(target[:top_level]) && # Don't piggyback batches that are an input dependency, only real dependencies
|
|
134
|
+
(batch[:deps] - [target] - target[:deps]).empty?
|
|
130
135
|
end.first
|
|
131
136
|
next if target.nil?
|
|
132
137
|
target[:jobs] = batch[:jobs] + target[:jobs]
|
|
@@ -4,8 +4,10 @@ module HPC
|
|
|
4
4
|
return [] if Symbol === job.overriden
|
|
5
5
|
matches = []
|
|
6
6
|
chains.each do |name, chain|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
workflow = job.original_workflow || job.workflow
|
|
8
|
+
task_name = job.original_task_name || job.task_name
|
|
9
|
+
next unless chain[:tasks].include?(workflow.to_s)
|
|
10
|
+
next unless chain[:tasks][workflow.to_s].include?(task_name.to_s)
|
|
9
11
|
matches << name
|
|
10
12
|
end
|
|
11
13
|
matches
|
|
@@ -38,46 +40,50 @@ module HPC
|
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
def self.job_chains(rules, job)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
found
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
43
|
+
@@job_chains ||= {}
|
|
44
|
+
@@job_chains[Misc.digest([rules, job.path].inspect)] ||=
|
|
45
|
+
begin
|
|
46
|
+
chains = self.parse_chains(rules)
|
|
47
|
+
|
|
48
|
+
matches = check_chains(chains, job)
|
|
49
|
+
|
|
50
|
+
dependencies = job_dependencies(job)
|
|
51
|
+
|
|
52
|
+
job_chains = []
|
|
53
|
+
new_job_chains = {}
|
|
54
|
+
dependencies.each do |dep|
|
|
55
|
+
dep_matches = check_chains(chains, dep)
|
|
56
|
+
common = matches & dep_matches
|
|
57
|
+
|
|
58
|
+
dep_chains = job_chains(rules, dep)
|
|
59
|
+
found = []
|
|
60
|
+
dep_chains.each do |match,info|
|
|
61
|
+
if common.include?(match)
|
|
62
|
+
found << match
|
|
63
|
+
new_info = new_job_chains[match] ||= {}
|
|
64
|
+
new_info[:jobs] ||= []
|
|
65
|
+
new_info[:jobs].concat info[:jobs]
|
|
66
|
+
new_info[:top_level] = job
|
|
67
|
+
else
|
|
68
|
+
job_chains << [match, info]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
(common - found).each do |match|
|
|
73
|
+
info = {}
|
|
74
|
+
info[:jobs] = [job, dep]
|
|
75
|
+
info[:top_level] = job
|
|
76
|
+
job_chains << [match, info]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
new_job_chains.each do |match,info|
|
|
81
|
+
info[:jobs].prepend job
|
|
63
82
|
job_chains << [match, info]
|
|
64
83
|
end
|
|
65
|
-
end
|
|
66
84
|
|
|
67
|
-
|
|
68
|
-
info = {}
|
|
69
|
-
info[:jobs] = [job, dep]
|
|
70
|
-
info[:top_level] = job
|
|
71
|
-
job_chains << [match, info]
|
|
85
|
+
job_chains
|
|
72
86
|
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
new_job_chains.each do |match,info|
|
|
76
|
-
info[:jobs].prepend job
|
|
77
|
-
job_chains << [match, info]
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
job_chains
|
|
81
87
|
end
|
|
82
88
|
|
|
83
89
|
end
|
data/lib/rbbt/hpc/orchestrate.rb
CHANGED
|
@@ -13,7 +13,11 @@ module HPC
|
|
|
13
13
|
all_deps = rec_dependencies + [job]
|
|
14
14
|
|
|
15
15
|
all_deps.each do |dep|
|
|
16
|
-
|
|
16
|
+
begin
|
|
17
|
+
Step.prepare_for_execution(dep)
|
|
18
|
+
rescue RbbtException
|
|
19
|
+
next
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
end
|
|
@@ -26,6 +30,7 @@ module HPC
|
|
|
26
30
|
options.delete "printpath"
|
|
27
31
|
options.delete "detach"
|
|
28
32
|
options.delete "jobname"
|
|
33
|
+
options.delete "load_inputs"
|
|
29
34
|
|
|
30
35
|
Log.high "Prepare for exec"
|
|
31
36
|
prepare_for_execution(job)
|
|
@@ -40,8 +45,8 @@ module HPC
|
|
|
40
45
|
|
|
41
46
|
IndiferentHash.setup(rules)
|
|
42
47
|
|
|
43
|
-
Log.high "Compute batches"
|
|
44
48
|
batches = HPC::Orchestration.job_batches(rules, job)
|
|
49
|
+
Log.high "Compute #{batches.length} batches"
|
|
45
50
|
|
|
46
51
|
batch_ids = {}
|
|
47
52
|
while batches.any?
|
|
@@ -77,9 +82,9 @@ module HPC
|
|
|
77
82
|
|
|
78
83
|
if options[:dry_run]
|
|
79
84
|
puts Log.color(:magenta, "Manifest: ") + Log.color(:blue, job_options[:manifest] * ", ") + " - tasks: #{job_options[:task_cpus] || 1} - time: #{job_options[:time]} - config: #{job_options[:config_keys]}"
|
|
80
|
-
puts Log.color(:
|
|
85
|
+
puts Log.color(:yellow, "Deps: ") + Log.color(:blue, job_options[:batch_dependencies]*", ")
|
|
81
86
|
puts Log.color(:yellow, "Path: ") + top[:top_level].path
|
|
82
|
-
puts Log.color(:yellow, "Options: ") +
|
|
87
|
+
puts Log.color(:yellow, "Options: ") + job_options.inspect
|
|
83
88
|
batch_ids[top] = top[:top_level].task_signature
|
|
84
89
|
else
|
|
85
90
|
id = run_job(top[:top_level], job_options)
|
data/lib/rbbt/hpc/slurm.rb
CHANGED
|
@@ -94,8 +94,8 @@ export BATCH_SYSTEM=SLURM
|
|
|
94
94
|
|
|
95
95
|
return if Open.exists?(fexit)
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
Log.info "Issuing SLURM file: #{fcmd}"
|
|
98
|
+
Log.debug Open.read(fcmd)
|
|
99
99
|
|
|
100
100
|
if File.exists?(fjob)
|
|
101
101
|
job = Open.read(fjob).to_i
|
data/lib/rbbt/resource/path.rb
CHANGED
|
@@ -167,8 +167,7 @@ module Path
|
|
|
167
167
|
|
|
168
168
|
@path ||= {}
|
|
169
169
|
rsearch_paths = (resource and resource.respond_to?(:search_paths)) ? resource.search_paths : nil
|
|
170
|
-
|
|
171
|
-
key = Misc.obj2digest(key_elems.inspect)
|
|
170
|
+
key = [where, caller_lib, rsearch_paths, paths].inspect
|
|
172
171
|
self.sub!('~/', Etc.getpwuid.dir + '/') if self.include? "~"
|
|
173
172
|
|
|
174
173
|
return @path[key] if @path[key]
|
data/lib/rbbt/resource/util.rb
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
module Path
|
|
2
2
|
|
|
3
3
|
def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])
|
|
4
|
-
file = caller.reject{|l|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}.first.sub(/\.rb[^\w].*/,'.rb') if file.nil?
|
|
4
|
+
#file = caller.reject{|l|
|
|
5
|
+
# l =~ /rbbt\/(?:resource\.rb|workflow\.rb)/ or
|
|
6
|
+
# l =~ /rbbt\/resource\/path\.rb/ or
|
|
7
|
+
# l =~ /rbbt\/persist.rb/ or
|
|
8
|
+
# l =~ /rbbt\/util\/misc\.rb/ or
|
|
9
|
+
# l =~ /progress-monitor\.rb/
|
|
10
|
+
#}.first.sub(/\.rb[^\w].*/,'.rb') if file.nil?
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if file.nil?
|
|
14
|
+
caller_dup = caller.dup
|
|
15
|
+
while file = caller_dup.shift
|
|
16
|
+
break unless file =~ /rbbt\/(?:resource\.rb|workflow\.rb)/ or
|
|
17
|
+
file =~ /rbbt\/resource\/path\.rb/ or
|
|
18
|
+
file =~ /rbbt\/persist.rb/ or
|
|
19
|
+
file =~ /rbbt\/util\/misc\.rb/ or
|
|
20
|
+
file =~ /progress-monitor\.rb/
|
|
21
|
+
end
|
|
22
|
+
file = file.sub(/\.rb[^\w].*/,'.rb')
|
|
23
|
+
end
|
|
11
24
|
|
|
12
25
|
relative_to = [relative_to] unless Array === relative_to
|
|
13
26
|
file = File.expand_path(file)
|
|
@@ -80,7 +80,7 @@ module Misc
|
|
|
80
80
|
end
|
|
81
81
|
when (defined? TSV and TSV)
|
|
82
82
|
obj.with_unnamed do
|
|
83
|
-
"TSV:{"<< fingerprint(obj.all_fields|| [])
|
|
83
|
+
"TSV:{"<< fingerprint(obj.all_fields|| []) << ";" << fingerprint(obj.keys) << "}"
|
|
84
84
|
end
|
|
85
85
|
when Hash
|
|
86
86
|
if obj.length > 10
|
|
@@ -297,14 +297,14 @@ module Misc
|
|
|
297
297
|
str = case obj
|
|
298
298
|
when nil
|
|
299
299
|
'nil'
|
|
300
|
+
when Symbol
|
|
301
|
+
obj.to_s
|
|
300
302
|
when TrueClass
|
|
301
303
|
'true'
|
|
302
304
|
when FalseClass
|
|
303
305
|
'false'
|
|
304
306
|
when Hash
|
|
305
307
|
"{"<< obj.collect{|k,v| obj2str(k) + '=>' << obj2str(v)}*"," << "}"
|
|
306
|
-
when Symbol
|
|
307
|
-
obj.to_s
|
|
308
308
|
when (defined?(Path) and Path)
|
|
309
309
|
if defined?(Step) && Open.exists?(Step.info_file(obj))
|
|
310
310
|
obj2str(Workflow.load_step(obj))
|
|
@@ -324,9 +324,10 @@ module Misc
|
|
|
324
324
|
end
|
|
325
325
|
when String
|
|
326
326
|
good_filename = Misc.is_filename?(obj, false) && ! %w(. ..).include?(obj) && %w(. /).include?(obj[0])
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
327
|
+
if good_filename
|
|
328
|
+
obj = obj.dup
|
|
329
|
+
obj.extend Path
|
|
330
|
+
obj2str obj
|
|
330
331
|
else
|
|
331
332
|
obj = obj.chomp if String === obj
|
|
332
333
|
if obj.length > HASH2MD5_MAX_STRING_LENGTH
|
|
@@ -339,7 +340,7 @@ module Misc
|
|
|
339
340
|
if obj.length > HASH2MD5_MAX_ARRAY_LENGTH
|
|
340
341
|
"[" << sample_large_obj(obj, HASH2MD5_MAX_ARRAY_LENGTH).collect{|v| obj2str(v)} * "," << "]"
|
|
341
342
|
else
|
|
342
|
-
"[" << obj.collect{|v| obj2str(v)} * "," << "]"
|
|
343
|
+
"[" << obj.collect{|v| obj2str(v) } * "," << "]"
|
|
343
344
|
end
|
|
344
345
|
when TSV::Parser
|
|
345
346
|
remove_long_items(obj)
|
|
@@ -354,7 +355,7 @@ module Misc
|
|
|
354
355
|
"<IO:" << obj.path << "--" << mtime_str(obj.path) << ">"
|
|
355
356
|
end
|
|
356
357
|
when (defined? Step and Step)
|
|
357
|
-
"<IO:" << obj.
|
|
358
|
+
"<IO:" << obj.short_path_real << ">"
|
|
358
359
|
when IO
|
|
359
360
|
if obj.respond_to? :filename and obj.filename
|
|
360
361
|
if defined?(Step) && Open.exists?(Step.info_file(obj.filename))
|
|
@@ -113,9 +113,10 @@ end
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def self.is_filename?(string, need_to_exists = true)
|
|
116
|
+
return false if string.nil?
|
|
116
117
|
return true if defined? Path and Path === string
|
|
117
118
|
return true if string.respond_to? :exists
|
|
118
|
-
return true if String === string and string.length
|
|
119
|
+
return true if String === string and string.split("/").select{|p| p.length > 265}.empty? and (! need_to_exists || File.exist?(string))
|
|
119
120
|
return false
|
|
120
121
|
end
|
|
121
122
|
|
|
@@ -72,9 +72,12 @@ module Workflow
|
|
|
72
72
|
def setup_override_dependency(dep, workflow, task_name)
|
|
73
73
|
return [] if dep == :skip || dep == 'skip'
|
|
74
74
|
dep = Step === dep ? dep.dup : Workflow.load_step(dep)
|
|
75
|
+
|
|
76
|
+
dep.original_workflow ||= dep.workflow if dep.workflow
|
|
77
|
+
dep.original_task_name ||= dep.task_name if dep.workflow
|
|
78
|
+
|
|
75
79
|
dep.workflow = workflow
|
|
76
80
|
dep.info[:name] = dep.name
|
|
77
|
-
dep.original_task_name ||= dep.task_name if dep.workflow
|
|
78
81
|
|
|
79
82
|
|
|
80
83
|
begin
|
|
@@ -96,6 +96,10 @@ class Step
|
|
|
96
96
|
[task_name, name] * "/"
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
+
def short_path_real
|
|
100
|
+
[(Symbol === overriden ? overriden : task_name).to_s, name] * "/"
|
|
101
|
+
end
|
|
102
|
+
|
|
99
103
|
def workflow_short_path
|
|
100
104
|
return short_path unless workflow
|
|
101
105
|
workflow.to_s + "#" + short_path
|
|
@@ -510,7 +510,7 @@ class Step
|
|
|
510
510
|
|
|
511
511
|
def overriden?
|
|
512
512
|
return true if @overriden
|
|
513
|
-
return true if dependencies.select{|dep| dep.overriden? }.any?
|
|
513
|
+
return true if dependencies && dependencies.select{|dep| dep.overriden? }.any?
|
|
514
514
|
info[:archived_info].each do |f,i|
|
|
515
515
|
next if Symbol === i
|
|
516
516
|
return true if i[:overriden] || i["overriden"]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
module Workflow
|
|
2
|
+
|
|
2
3
|
def self.load_inputs(dir, input_names, input_types)
|
|
3
4
|
inputs = {}
|
|
4
5
|
if File.exists?(dir) && ! File.directory?(dir)
|
|
@@ -20,21 +21,59 @@ module Workflow
|
|
|
20
21
|
Log.debug "Trying #{ input }: #{file}"
|
|
21
22
|
next unless file and (File.symlink?(file) || file.exists?)
|
|
22
23
|
|
|
23
|
-
type = input_types[input]
|
|
24
|
+
type = orig_type = input_types[input]
|
|
24
25
|
|
|
25
26
|
type = :io if file.split(".").last == 'as_io'
|
|
26
27
|
|
|
28
|
+
type = :io_array if file.split(".").last == 'as_io_array'
|
|
29
|
+
|
|
30
|
+
type = :step if file.split(".").last == 'as_step'
|
|
31
|
+
|
|
32
|
+
type = :step_array if file.split(".").last == 'as_step_array'
|
|
33
|
+
|
|
34
|
+
type = :step_file if file.split(".").last == 'as_step_file'
|
|
35
|
+
|
|
36
|
+
type = :step_file_array if file.split(".").last == 'as_step_file_array'
|
|
37
|
+
|
|
27
38
|
type = :path if file.split(".").last == 'as_path'
|
|
28
39
|
|
|
40
|
+
type = :path_array if file.split(".").last == 'as_path_array'
|
|
41
|
+
|
|
42
|
+
type = :filename if file.split(".").last == 'as_filename'
|
|
43
|
+
|
|
29
44
|
type = :nofile if file.split(".").last == 'nofile'
|
|
30
45
|
|
|
31
46
|
case type
|
|
32
47
|
when :nofile
|
|
33
48
|
inputs[input.to_sym] = Open.realpath(file)
|
|
49
|
+
when :path_array
|
|
50
|
+
inputs[input.to_sym] = Open.read(file).strip.split("\n")
|
|
34
51
|
when :path
|
|
35
|
-
inputs[input.to_sym] = Open.
|
|
52
|
+
inputs[input.to_sym] = Open.read(file).strip.split("\n").first
|
|
53
|
+
when :io
|
|
54
|
+
inputs[input.to_sym] = Open.open(Open.realpath(file)).split("\n")
|
|
36
55
|
when :io
|
|
37
|
-
inputs[input.to_sym] = Open.
|
|
56
|
+
inputs[input.to_sym] = Open.realpath(file).split("\n").collect{|f| Open.open(f)}
|
|
57
|
+
when :step_array
|
|
58
|
+
steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
|
|
59
|
+
inputs[input.to_sym] = steps
|
|
60
|
+
when :step
|
|
61
|
+
steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
|
|
62
|
+
inputs[input.to_sym] = steps.first
|
|
63
|
+
when :step_file
|
|
64
|
+
path = Open.read(file).strip
|
|
65
|
+
path.extend Path
|
|
66
|
+
step_path = path.match(/(.*)\.files/)[1]
|
|
67
|
+
path.resource = Step.new step_path
|
|
68
|
+
inputs[input.to_sym] = path
|
|
69
|
+
when :step_file_array
|
|
70
|
+
paths = Open.read(file).split("\n")
|
|
71
|
+
paths.each do |path|
|
|
72
|
+
path.extend Path
|
|
73
|
+
step_path = path.match(/(.*)\.files/)[1]
|
|
74
|
+
path.resource = Step.new step_path
|
|
75
|
+
end
|
|
76
|
+
inputs[input.to_sym] = paths
|
|
38
77
|
when :file, :binary
|
|
39
78
|
Log.debug "Pointing #{ input } to #{file}"
|
|
40
79
|
if file =~ /\.yaml/
|
|
@@ -87,60 +126,149 @@ module Workflow
|
|
|
87
126
|
job(task_name, jobname, inputs)
|
|
88
127
|
end
|
|
89
128
|
|
|
129
|
+
#def self.load_inputs_old(dir, input_names, input_types)
|
|
130
|
+
# inputs = {}
|
|
131
|
+
# if File.exists?(dir) && ! File.directory?(dir)
|
|
132
|
+
# Log.debug "Loading inputs from #{dir}, not a directory trying as tar.gz"
|
|
133
|
+
# tarfile = dir
|
|
134
|
+
# digest = CMD.cmd("md5sum '#{tarfile}'").read.split(" ").first
|
|
135
|
+
# tmpdir = Rbbt.tmp.input_bundle[digest].find
|
|
136
|
+
# Misc.untar(tarfile, tmpdir) unless File.exists? tmpdir
|
|
137
|
+
# files = tmpdir.glob("*")
|
|
138
|
+
# if files.length == 1 && File.directory?(files.first)
|
|
139
|
+
# tmpdir = files.first
|
|
140
|
+
# end
|
|
141
|
+
# load_inputs(tmpdir, input_names, input_types)
|
|
142
|
+
# else
|
|
143
|
+
# dir = Path.setup(dir.dup)
|
|
144
|
+
# input_names.each do |input|
|
|
145
|
+
# file = dir[input].find
|
|
146
|
+
# file = dir.glob(input.to_s + ".*").reject{|f| f =~ /\.md5$/}.first if file.nil? or not (File.symlink?(file) || file.exists?)
|
|
147
|
+
# Log.debug "Trying #{ input }: #{file}"
|
|
148
|
+
# next unless file and (File.symlink?(file) || file.exists?)
|
|
149
|
+
|
|
150
|
+
# type = input_types[input]
|
|
151
|
+
|
|
152
|
+
# type = :io if file.split(".").last == 'as_io'
|
|
153
|
+
|
|
154
|
+
# type = :path if file.split(".").last == 'as_path'
|
|
155
|
+
|
|
156
|
+
# type = :filename if file.split(".").last == 'as_filename'
|
|
157
|
+
|
|
158
|
+
# type = :nofile if file.split(".").last == 'nofile'
|
|
159
|
+
|
|
160
|
+
# case type
|
|
161
|
+
# when :nofile
|
|
162
|
+
# inputs[input.to_sym] = Open.realpath(file)
|
|
163
|
+
# when :path
|
|
164
|
+
# inputs[input.to_sym] = Open.realpath(Open.read(file).strip)
|
|
165
|
+
# when :io
|
|
166
|
+
# inputs[input.to_sym] = Open.open(Open.realpath(file))
|
|
167
|
+
# when :file, :binary
|
|
168
|
+
# Log.debug "Pointing #{ input } to #{file}"
|
|
169
|
+
# if file =~ /\.yaml/
|
|
170
|
+
# inputs[input.to_sym] = YAML.load(Open.read(file))
|
|
171
|
+
# else
|
|
172
|
+
# if File.symlink?(file)
|
|
173
|
+
# link_target = File.expand_path(File.readlink(file), File.dirname(file))
|
|
174
|
+
# inputs[input.to_sym] = link_target
|
|
175
|
+
# else
|
|
176
|
+
# inputs[input.to_sym] = Open.realpath(file)
|
|
177
|
+
# end
|
|
178
|
+
# end
|
|
179
|
+
# when :text
|
|
180
|
+
# Log.debug "Reading #{ input } from #{file}"
|
|
181
|
+
# inputs[input.to_sym] = Open.read(file)
|
|
182
|
+
# when :array
|
|
183
|
+
# Log.debug "Reading array #{ input } from #{file}"
|
|
184
|
+
# inputs[input.to_sym] = Open.read(file).split("\n")
|
|
185
|
+
# when :tsv
|
|
186
|
+
# Log.debug "Opening tsv #{ input } from #{file}"
|
|
187
|
+
# inputs[input.to_sym] = TSV.open(file)
|
|
188
|
+
# when :boolean
|
|
189
|
+
# inputs[input.to_sym] = (file.read.strip == 'true')
|
|
190
|
+
# else
|
|
191
|
+
# Log.debug "Loading #{ input } from #{file}"
|
|
192
|
+
# inputs[input.to_sym] = file.read.strip
|
|
193
|
+
# end
|
|
194
|
+
|
|
195
|
+
# end
|
|
196
|
+
# inputs = IndiferentHash.setup(inputs)
|
|
197
|
+
|
|
198
|
+
# dir.glob("*#*").each do |od|
|
|
199
|
+
# name = File.basename(od)
|
|
200
|
+
# value = Open.read(od)
|
|
201
|
+
# Log.debug "Loading override dependency #{ name } as #{value}"
|
|
202
|
+
# inputs[name] = value.chomp
|
|
203
|
+
# end
|
|
204
|
+
|
|
205
|
+
# inputs
|
|
206
|
+
# end
|
|
207
|
+
#end
|
|
90
208
|
end
|
|
91
209
|
|
|
92
210
|
class Step
|
|
93
|
-
def self.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
when
|
|
117
|
-
if
|
|
118
|
-
|
|
119
|
-
Open.ln_s(value, path)
|
|
211
|
+
def self.save_input(name, value, type, dir)
|
|
212
|
+
path = File.join(dir, name.to_s)
|
|
213
|
+
|
|
214
|
+
case value
|
|
215
|
+
when Path
|
|
216
|
+
if Step === value.resource
|
|
217
|
+
path = path + '.as_step_file'
|
|
218
|
+
else
|
|
219
|
+
path = path + '.as_path'
|
|
220
|
+
end
|
|
221
|
+
when String
|
|
222
|
+
if Misc.is_filename?(value, false)
|
|
223
|
+
value = value.dup
|
|
224
|
+
value.extend Path
|
|
225
|
+
return save_input(name, value, type, dir)
|
|
226
|
+
end
|
|
227
|
+
when IO
|
|
228
|
+
path = path + '.as_io'
|
|
229
|
+
when Step
|
|
230
|
+
value = value.path
|
|
231
|
+
path = path + '.as_step'
|
|
232
|
+
when Array
|
|
233
|
+
case value.first
|
|
234
|
+
when Path
|
|
235
|
+
if Step === value.first.resource
|
|
236
|
+
path = path + '.as_step_file_array'
|
|
120
237
|
else
|
|
121
|
-
|
|
122
|
-
value = "#{value}" if Path === value
|
|
123
|
-
Open.write(path + '.yaml', value.to_yaml)
|
|
238
|
+
path = path + '.as_path_array'
|
|
124
239
|
end
|
|
125
|
-
when
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if value.filename && String === value.filename && File.exists?(value.filename)
|
|
129
|
-
Open.ln_s(value.filename, path)
|
|
130
|
-
else
|
|
131
|
-
Open.write(path, value)
|
|
240
|
+
when String
|
|
241
|
+
if Misc.is_filename?(value.first, false)
|
|
242
|
+
path = path + '.as_path_array'
|
|
132
243
|
end
|
|
133
|
-
|
|
134
|
-
|
|
244
|
+
when IO
|
|
245
|
+
path = path + '.as_io_array'
|
|
246
|
+
when Step
|
|
247
|
+
path = path + '.as_step_array'
|
|
248
|
+
value = value.collect{|s| s.path }
|
|
135
249
|
end
|
|
250
|
+
|
|
251
|
+
value = value * "\n"
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
Log.debug "Saving job input #{name} (#{type}) into #{path}"
|
|
255
|
+
Open.write(path, value.to_s)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def self.save_inputs(inputs, input_types, input_options, dir)
|
|
259
|
+
inputs.each do |name,value|
|
|
260
|
+
type = input_types[name]
|
|
261
|
+
type = type.to_s if type
|
|
262
|
+
|
|
263
|
+
save_input(name, value, type, dir)
|
|
136
264
|
end.any?
|
|
137
265
|
end
|
|
138
266
|
|
|
139
267
|
def self.save_job_inputs(job, dir, options = nil)
|
|
140
268
|
options = IndiferentHash.setup options.dup if options
|
|
141
269
|
|
|
142
|
-
task_name =
|
|
143
|
-
workflow = job.workflow
|
|
270
|
+
task_name = job.original_task_name || job.task_name
|
|
271
|
+
workflow = job.original_workflow || job.workflow
|
|
144
272
|
workflow = Kernel.const_get workflow if String === workflow
|
|
145
273
|
if workflow
|
|
146
274
|
task_info = IndiferentHash.setup(workflow.task_info(task_name))
|
|
@@ -176,4 +304,60 @@ class Step
|
|
|
176
304
|
|
|
177
305
|
inputs.keys
|
|
178
306
|
end
|
|
307
|
+
|
|
308
|
+
#def self.save_inputs_old(inputs, input_types, input_options, dir)
|
|
309
|
+
# inputs.each do |name,value|
|
|
310
|
+
# type = input_types[name]
|
|
311
|
+
# type = type.to_s if type
|
|
312
|
+
# path = File.join(dir, name.to_s)
|
|
313
|
+
|
|
314
|
+
# if (IO === value || Step === value) && ! (input_options[name] && input_options[name][:nofile])
|
|
315
|
+
# path = path + '.as_io'
|
|
316
|
+
# elsif Misc.is_filename?(value, false)
|
|
317
|
+
# path = path + '.as_filename'
|
|
318
|
+
# end
|
|
319
|
+
|
|
320
|
+
# Log.debug "Saving job input #{name} (#{type}) into #{path}"
|
|
321
|
+
|
|
322
|
+
# case
|
|
323
|
+
# when IO === value
|
|
324
|
+
# Open.write(path, value.to_s)
|
|
325
|
+
# when Step === value
|
|
326
|
+
# Open.ln_s(value.path, path)
|
|
327
|
+
# when type.to_s == "binary"
|
|
328
|
+
# if String === value && File.exists?(value)
|
|
329
|
+
# value = File.expand_path(value)
|
|
330
|
+
# Open.ln_s(value, path)
|
|
331
|
+
# elsif String === value && Misc.is_filename?(value, false)
|
|
332
|
+
# Open.write(path + '.as_path' , value)
|
|
333
|
+
# else
|
|
334
|
+
# Open.write(path, value, :mode => 'wb')
|
|
335
|
+
# end
|
|
336
|
+
# when TSV === value
|
|
337
|
+
# Open.write(path, value.to_s)
|
|
338
|
+
# when Array === value
|
|
339
|
+
# Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
|
|
340
|
+
# when %w(file tsv array).include?(type.to_s)
|
|
341
|
+
# if String === value && File.exists?(value)
|
|
342
|
+
# value = File.expand_path(value)
|
|
343
|
+
# Open.ln_s(value, path)
|
|
344
|
+
# elsif String === value && Misc.is_filename?(value, false)
|
|
345
|
+
# Open.write(path + '.as_path' , value)
|
|
346
|
+
# else
|
|
347
|
+
# value = value.collect{|v| v = "#{v}" if Path === v; v } if Array === value
|
|
348
|
+
# value = "#{value}" if Path === value
|
|
349
|
+
# Open.write(path + '.yaml', value.to_yaml)
|
|
350
|
+
# end
|
|
351
|
+
# when IO === value
|
|
352
|
+
# if value.filename && String === value.filename && File.exists?(value.filename)
|
|
353
|
+
# Open.ln_s(value.filename, path)
|
|
354
|
+
# else
|
|
355
|
+
# Open.write(path, value)
|
|
356
|
+
# end
|
|
357
|
+
# else
|
|
358
|
+
# Open.write(path, value.to_s)
|
|
359
|
+
# end
|
|
360
|
+
# end.any?
|
|
361
|
+
#end
|
|
362
|
+
|
|
179
363
|
end
|
data/lib/rbbt/workflow/step.rb
CHANGED
|
@@ -15,7 +15,7 @@ class Step
|
|
|
15
15
|
attr_accessor :exec
|
|
16
16
|
attr_accessor :relocated
|
|
17
17
|
attr_accessor :result, :mutex, :seen
|
|
18
|
-
attr_accessor :real_inputs, :original_task_name
|
|
18
|
+
attr_accessor :real_inputs, :original_task_name, :original_workflow
|
|
19
19
|
|
|
20
20
|
RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
|
|
21
21
|
|
|
@@ -376,9 +376,9 @@ class Step
|
|
|
376
376
|
}
|
|
377
377
|
raise "Dependency step not found: #{ name }" if deps.empty?
|
|
378
378
|
if (deps & self.dependencies).any?
|
|
379
|
-
(deps & self.dependencies).
|
|
379
|
+
(deps & self.dependencies).last
|
|
380
380
|
else
|
|
381
|
-
deps.
|
|
381
|
+
deps.last
|
|
382
382
|
end
|
|
383
383
|
end
|
|
384
384
|
end
|
|
@@ -22,6 +22,7 @@ $ rbbt slurm list [options]
|
|
|
22
22
|
-s--search* Regular expression
|
|
23
23
|
-t--tail* Show the last lines of the STDERR
|
|
24
24
|
-l--long Show more entries
|
|
25
|
+
-c--compressed Show compressed information about entries
|
|
25
26
|
-p--progress Report progress of job and the dependencies
|
|
26
27
|
-BP--batch_parameters show batch parameters
|
|
27
28
|
-BPP--batch_procpath show Procpath performance summary
|
|
@@ -140,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
140
141
|
rescue
|
|
141
142
|
nodes = []
|
|
142
143
|
end
|
|
143
|
-
elsif job_nodes[id]
|
|
144
|
+
elsif job_nodes && job_nodes[id]
|
|
144
145
|
nodes = job_nodes[id].reject{|n| n.include? "("}
|
|
145
146
|
else
|
|
146
147
|
nodes = []
|
|
@@ -185,6 +186,42 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
185
186
|
end
|
|
186
187
|
|
|
187
188
|
|
|
189
|
+
count += 1
|
|
190
|
+
|
|
191
|
+
if options[:compressed]
|
|
192
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) : Log.color(:green, id)
|
|
193
|
+
if different_system
|
|
194
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : Log.color(:green, id)
|
|
195
|
+
else
|
|
196
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : (running_jobs.include?(id) || $norunningjobs ? Log.color(:green, id) : Log.color(:red, id) )
|
|
197
|
+
end
|
|
198
|
+
prog_rep = []
|
|
199
|
+
if options[:progress]
|
|
200
|
+
step_line = Open.read(fcmd).split("\n").select{|line| line =~ /^#STEP_PATH:/}.first
|
|
201
|
+
if step_line
|
|
202
|
+
require 'rbbt/workflow'
|
|
203
|
+
step_path = step_line.split(": ").last.strip
|
|
204
|
+
step = Step.new step_path
|
|
205
|
+
step.load_dependencies_from_info
|
|
206
|
+
has_bar = false
|
|
207
|
+
(step.rec_dependencies + [step]).reverse.each do |j|
|
|
208
|
+
next if j.done?
|
|
209
|
+
if j.file(:progress).exists?
|
|
210
|
+
bar = Log::ProgressBar.new
|
|
211
|
+
bar.load(j.file(:progress).yaml)
|
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
|
214
|
+
prog_rep << [rep]
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
workflow, task, name = step_path.split("/")[-3..-1]
|
|
220
|
+
job_str = [Log.color(:yellow, workflow), Log.color(:magenta, task), name] * "/"
|
|
221
|
+
puts [job_str, status, prog_rep ].flatten * " "
|
|
222
|
+
next
|
|
223
|
+
end
|
|
224
|
+
|
|
188
225
|
puts Log.color :blue, dir
|
|
189
226
|
puts Log.color(:magenta, "Creation: ") << File.mtime(File.join(dir, 'command.batch')).to_s if long
|
|
190
227
|
puts Log.color(:magenta, "Started: ") << File.ctime(File.join(dir, 'std.err')).to_s if File.exist?(File.join(dir, 'std.err')) && long
|
|
@@ -232,22 +269,22 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
232
269
|
cpu_average = {}
|
|
233
270
|
rss_average = {}
|
|
234
271
|
perf.through :key, ["ts", 'stat_pid', "stat_utime", "stat_stime", "stat_cutime", "stat_cstime", "stat_rss"] do |k, values|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
272
|
+
time, stat_pid, ucpu, scpu, ccpu, cscpu, rss = values
|
|
273
|
+
time = time.to_f
|
|
274
|
+
|
|
275
|
+
cpu = Misc.sum([ucpu, scpu].collect{|v| v.to_f})
|
|
276
|
+
cpu_average[stat_pid] ||= {}
|
|
277
|
+
cpu_average[stat_pid][time] ||= []
|
|
278
|
+
cpu_average[stat_pid][time] << cpu.to_f
|
|
279
|
+
rss_average[time] ||= []
|
|
280
|
+
rss_average[time] << rss.to_f * page_size
|
|
244
281
|
end
|
|
245
282
|
|
|
246
283
|
ticks = 0
|
|
247
284
|
cpu_average.each do |stat_pid, cpu_average_pid|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
285
|
+
start = cpu_average_pid.keys.sort.first
|
|
286
|
+
eend = cpu_average_pid.keys.sort.last
|
|
287
|
+
ticks += Misc.sum(cpu_average_pid[eend]) - Misc.sum(cpu_average_pid[start])
|
|
251
288
|
end
|
|
252
289
|
start = rss_average.keys.sort.first
|
|
253
290
|
eend = rss_average.keys.sort.last
|
|
@@ -305,12 +342,13 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
305
342
|
has_bar = true
|
|
306
343
|
end
|
|
307
344
|
end
|
|
308
|
-
|
|
345
|
+
step_status = step.status
|
|
346
|
+
step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
|
|
347
|
+
step_status = Log.color :green, step_status if step_status.to_s == 'done'
|
|
348
|
+
puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
|
|
309
349
|
end
|
|
310
350
|
end
|
|
311
351
|
|
|
312
|
-
count += 1
|
|
313
|
-
|
|
314
352
|
end
|
|
315
353
|
|
|
316
354
|
puts
|
|
@@ -60,5 +60,6 @@ class Step
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
ARGV.concat [
|
|
63
|
+
ARGV.concat ['--detach']
|
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
|
@@ -22,6 +22,7 @@ $ rbbt slurm list [options]
|
|
|
22
22
|
-s--search* Regular expression
|
|
23
23
|
-t--tail* Show the last lines of the STDERR
|
|
24
24
|
-l--long Show more entries
|
|
25
|
+
-c--compressed Show compressed information about entries
|
|
25
26
|
-p--progress Report progress of job and the dependencies
|
|
26
27
|
-BP--batch_parameters show batch parameters
|
|
27
28
|
-BPP--batch_procpath show Procpath performance summary
|
|
@@ -140,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
140
141
|
rescue
|
|
141
142
|
nodes = []
|
|
142
143
|
end
|
|
143
|
-
elsif job_nodes[id]
|
|
144
|
+
elsif job_nodes && job_nodes[id]
|
|
144
145
|
nodes = job_nodes[id].reject{|n| n.include? "("}
|
|
145
146
|
else
|
|
146
147
|
nodes = []
|
|
@@ -185,6 +186,42 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
185
186
|
end
|
|
186
187
|
|
|
187
188
|
|
|
189
|
+
count += 1
|
|
190
|
+
|
|
191
|
+
if options[:compressed]
|
|
192
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) : Log.color(:green, id)
|
|
193
|
+
if different_system
|
|
194
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : Log.color(:green, id)
|
|
195
|
+
else
|
|
196
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : (running_jobs.include?(id) || $norunningjobs ? Log.color(:green, id) : Log.color(:red, id) )
|
|
197
|
+
end
|
|
198
|
+
prog_rep = []
|
|
199
|
+
if options[:progress]
|
|
200
|
+
step_line = Open.read(fcmd).split("\n").select{|line| line =~ /^#STEP_PATH:/}.first
|
|
201
|
+
if step_line
|
|
202
|
+
require 'rbbt/workflow'
|
|
203
|
+
step_path = step_line.split(": ").last.strip
|
|
204
|
+
step = Step.new step_path
|
|
205
|
+
step.load_dependencies_from_info
|
|
206
|
+
has_bar = false
|
|
207
|
+
(step.rec_dependencies + [step]).reverse.each do |j|
|
|
208
|
+
next if j.done?
|
|
209
|
+
if j.file(:progress).exists?
|
|
210
|
+
bar = Log::ProgressBar.new
|
|
211
|
+
bar.load(j.file(:progress).yaml)
|
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
|
214
|
+
prog_rep << [rep]
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
workflow, task, name = step_path.split("/")[-3..-1]
|
|
220
|
+
job_str = [Log.color(:yellow, workflow), Log.color(:magenta, task), name] * "/"
|
|
221
|
+
puts [job_str, status, prog_rep ].flatten * " "
|
|
222
|
+
next
|
|
223
|
+
end
|
|
224
|
+
|
|
188
225
|
puts Log.color :blue, dir
|
|
189
226
|
puts Log.color(:magenta, "Creation: ") << File.mtime(File.join(dir, 'command.batch')).to_s if long
|
|
190
227
|
puts Log.color(:magenta, "Started: ") << File.ctime(File.join(dir, 'std.err')).to_s if File.exist?(File.join(dir, 'std.err')) && long
|
|
@@ -232,22 +269,22 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
232
269
|
cpu_average = {}
|
|
233
270
|
rss_average = {}
|
|
234
271
|
perf.through :key, ["ts", 'stat_pid', "stat_utime", "stat_stime", "stat_cutime", "stat_cstime", "stat_rss"] do |k, values|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
272
|
+
time, stat_pid, ucpu, scpu, ccpu, cscpu, rss = values
|
|
273
|
+
time = time.to_f
|
|
274
|
+
|
|
275
|
+
cpu = Misc.sum([ucpu, scpu].collect{|v| v.to_f})
|
|
276
|
+
cpu_average[stat_pid] ||= {}
|
|
277
|
+
cpu_average[stat_pid][time] ||= []
|
|
278
|
+
cpu_average[stat_pid][time] << cpu.to_f
|
|
279
|
+
rss_average[time] ||= []
|
|
280
|
+
rss_average[time] << rss.to_f * page_size
|
|
244
281
|
end
|
|
245
282
|
|
|
246
283
|
ticks = 0
|
|
247
284
|
cpu_average.each do |stat_pid, cpu_average_pid|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
285
|
+
start = cpu_average_pid.keys.sort.first
|
|
286
|
+
eend = cpu_average_pid.keys.sort.last
|
|
287
|
+
ticks += Misc.sum(cpu_average_pid[eend]) - Misc.sum(cpu_average_pid[start])
|
|
251
288
|
end
|
|
252
289
|
start = rss_average.keys.sort.first
|
|
253
290
|
eend = rss_average.keys.sort.last
|
|
@@ -305,12 +342,13 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
305
342
|
has_bar = true
|
|
306
343
|
end
|
|
307
344
|
end
|
|
308
|
-
|
|
345
|
+
step_status = step.status
|
|
346
|
+
step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
|
|
347
|
+
step_status = Log.color :green, step_status if step_status.to_s == 'done'
|
|
348
|
+
puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
|
|
309
349
|
end
|
|
310
350
|
end
|
|
311
351
|
|
|
312
|
-
count += 1
|
|
313
|
-
|
|
314
352
|
end
|
|
315
353
|
|
|
316
354
|
puts
|
|
@@ -60,5 +60,6 @@ class Step
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
ARGV.concat [
|
|
63
|
+
ARGV.concat ['--detach']
|
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
|
@@ -22,6 +22,7 @@ $ rbbt slurm list [options]
|
|
|
22
22
|
-s--search* Regular expression
|
|
23
23
|
-t--tail* Show the last lines of the STDERR
|
|
24
24
|
-l--long Show more entries
|
|
25
|
+
-c--compressed Show compressed information about entries
|
|
25
26
|
-p--progress Report progress of job and the dependencies
|
|
26
27
|
-BP--batch_parameters show batch parameters
|
|
27
28
|
-BPP--batch_procpath show Procpath performance summary
|
|
@@ -140,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
140
141
|
rescue
|
|
141
142
|
nodes = []
|
|
142
143
|
end
|
|
143
|
-
elsif job_nodes[id]
|
|
144
|
+
elsif job_nodes && job_nodes[id]
|
|
144
145
|
nodes = job_nodes[id].reject{|n| n.include? "("}
|
|
145
146
|
else
|
|
146
147
|
nodes = []
|
|
@@ -185,6 +186,42 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
185
186
|
end
|
|
186
187
|
|
|
187
188
|
|
|
189
|
+
count += 1
|
|
190
|
+
|
|
191
|
+
if options[:compressed]
|
|
192
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) : Log.color(:green, id)
|
|
193
|
+
if different_system
|
|
194
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : Log.color(:green, id)
|
|
195
|
+
else
|
|
196
|
+
status = exit_status ? (exit_status == 0 ? Log.color(:green, "Done") : Log.color(:red, "Error")) + " (#{ id })" : (running_jobs.include?(id) || $norunningjobs ? Log.color(:green, id) : Log.color(:red, id) )
|
|
197
|
+
end
|
|
198
|
+
prog_rep = []
|
|
199
|
+
if options[:progress]
|
|
200
|
+
step_line = Open.read(fcmd).split("\n").select{|line| line =~ /^#STEP_PATH:/}.first
|
|
201
|
+
if step_line
|
|
202
|
+
require 'rbbt/workflow'
|
|
203
|
+
step_path = step_line.split(": ").last.strip
|
|
204
|
+
step = Step.new step_path
|
|
205
|
+
step.load_dependencies_from_info
|
|
206
|
+
has_bar = false
|
|
207
|
+
(step.rec_dependencies + [step]).reverse.each do |j|
|
|
208
|
+
next if j.done?
|
|
209
|
+
if j.file(:progress).exists?
|
|
210
|
+
bar = Log::ProgressBar.new
|
|
211
|
+
bar.load(j.file(:progress).yaml)
|
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
|
214
|
+
prog_rep << [rep]
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
workflow, task, name = step_path.split("/")[-3..-1]
|
|
220
|
+
job_str = [Log.color(:yellow, workflow), Log.color(:magenta, task), name] * "/"
|
|
221
|
+
puts [job_str, status, prog_rep ].flatten * " "
|
|
222
|
+
next
|
|
223
|
+
end
|
|
224
|
+
|
|
188
225
|
puts Log.color :blue, dir
|
|
189
226
|
puts Log.color(:magenta, "Creation: ") << File.mtime(File.join(dir, 'command.batch')).to_s if long
|
|
190
227
|
puts Log.color(:magenta, "Started: ") << File.ctime(File.join(dir, 'std.err')).to_s if File.exist?(File.join(dir, 'std.err')) && long
|
|
@@ -232,22 +269,22 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
232
269
|
cpu_average = {}
|
|
233
270
|
rss_average = {}
|
|
234
271
|
perf.through :key, ["ts", 'stat_pid', "stat_utime", "stat_stime", "stat_cutime", "stat_cstime", "stat_rss"] do |k, values|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
272
|
+
time, stat_pid, ucpu, scpu, ccpu, cscpu, rss = values
|
|
273
|
+
time = time.to_f
|
|
274
|
+
|
|
275
|
+
cpu = Misc.sum([ucpu, scpu].collect{|v| v.to_f})
|
|
276
|
+
cpu_average[stat_pid] ||= {}
|
|
277
|
+
cpu_average[stat_pid][time] ||= []
|
|
278
|
+
cpu_average[stat_pid][time] << cpu.to_f
|
|
279
|
+
rss_average[time] ||= []
|
|
280
|
+
rss_average[time] << rss.to_f * page_size
|
|
244
281
|
end
|
|
245
282
|
|
|
246
283
|
ticks = 0
|
|
247
284
|
cpu_average.each do |stat_pid, cpu_average_pid|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
285
|
+
start = cpu_average_pid.keys.sort.first
|
|
286
|
+
eend = cpu_average_pid.keys.sort.last
|
|
287
|
+
ticks += Misc.sum(cpu_average_pid[eend]) - Misc.sum(cpu_average_pid[start])
|
|
251
288
|
end
|
|
252
289
|
start = rss_average.keys.sort.first
|
|
253
290
|
eend = rss_average.keys.sort.last
|
|
@@ -305,12 +342,13 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
305
342
|
has_bar = true
|
|
306
343
|
end
|
|
307
344
|
end
|
|
308
|
-
|
|
345
|
+
step_status = step.status
|
|
346
|
+
step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
|
|
347
|
+
step_status = Log.color :green, step_status if step_status.to_s == 'done'
|
|
348
|
+
puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
|
|
309
349
|
end
|
|
310
350
|
end
|
|
311
351
|
|
|
312
|
-
count += 1
|
|
313
|
-
|
|
314
352
|
end
|
|
315
353
|
|
|
316
354
|
puts
|
|
@@ -60,5 +60,6 @@ class Step
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
ARGV.concat [
|
|
63
|
+
ARGV.concat ['--detach']
|
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
|
@@ -76,6 +76,16 @@ def fix_options(workflow, task, job_options)
|
|
|
76
76
|
type = input_types[name]
|
|
77
77
|
type = type.to_sym if type
|
|
78
78
|
|
|
79
|
+
if Step === value
|
|
80
|
+
job_options_cleaned[name] = value
|
|
81
|
+
next
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if Path === value && Step === value.resource
|
|
85
|
+
job_options_cleaned[name] = value
|
|
86
|
+
next
|
|
87
|
+
end
|
|
88
|
+
|
|
79
89
|
value = case type
|
|
80
90
|
when nil
|
|
81
91
|
value
|
|
@@ -148,6 +158,7 @@ def fix_options(workflow, task, job_options)
|
|
|
148
158
|
else
|
|
149
159
|
value
|
|
150
160
|
end
|
|
161
|
+
|
|
151
162
|
job_options_cleaned[name] = value
|
|
152
163
|
end
|
|
153
164
|
|
|
@@ -26,11 +26,26 @@ module TestSaveLoadWF
|
|
|
26
26
|
task :prefix => :array do
|
|
27
27
|
step(:reverse).run.collect{|e| "A-#{e}" }
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
input :integer, :integer
|
|
31
|
+
input :float, :float
|
|
32
|
+
input :file, :file
|
|
33
|
+
input :file_no_file, :file, "", nil, :nofile => true
|
|
34
|
+
input :string, :string
|
|
35
|
+
input :select, :select
|
|
36
|
+
input :array, :array
|
|
37
|
+
input :array_no_file, :array, "", nil, :nofile => true
|
|
38
|
+
input :tsv, :tsv, "", nil, :nofile => true
|
|
39
|
+
input :tsv_no_file, :tsv, "", nil, :nofile => true
|
|
40
|
+
input :binary, :binary, "", nil, :nofile => true
|
|
41
|
+
input :binary_no_file, :tsv, "", nil, :nofile => true
|
|
42
|
+
task :save_test => :string do
|
|
43
|
+
"DONE"
|
|
44
|
+
end
|
|
29
45
|
end
|
|
30
46
|
|
|
31
47
|
class TestSaveLoad < Test::Unit::TestCase
|
|
32
48
|
def test_save
|
|
33
|
-
Log.with_severity 0 do
|
|
34
49
|
job = TestSaveLoadWF.job(:prefix)
|
|
35
50
|
job.recursive_clean
|
|
36
51
|
job = TestSaveLoadWF.job(:prefix)
|
|
@@ -40,6 +55,81 @@ class TestSaveLoad < Test::Unit::TestCase
|
|
|
40
55
|
newjob = TestSaveLoadWF.job_for_directory_inputs(:reverse, directory)
|
|
41
56
|
assert_equal job.rec_dependencies.last.path, newjob.path
|
|
42
57
|
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_save_all_normal
|
|
61
|
+
tsv = TSV.setup({}, "Key~Value#:type=:single")
|
|
62
|
+
tsv["key"] = "value"
|
|
63
|
+
options = {
|
|
64
|
+
:float => 0.5,
|
|
65
|
+
:integer => 15,
|
|
66
|
+
:string => "STRING",
|
|
67
|
+
:select => "option",
|
|
68
|
+
:array => [0,1,2,3],
|
|
69
|
+
:tsv => tsv,
|
|
70
|
+
}
|
|
71
|
+
Log.with_severity 0 do
|
|
72
|
+
Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
|
|
73
|
+
job = TestSaveLoadWF.job(:save_test, nil, options)
|
|
74
|
+
TmpFile.with_file do |directory|
|
|
75
|
+
Step.save_job_inputs(job, directory)
|
|
76
|
+
newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
|
|
77
|
+
assert_equal job.path, newjob.path
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_save_all_file
|
|
84
|
+
tsv = TSV.setup({}, "Key~Value#:type=:single")
|
|
85
|
+
tsv["key"] = "value"
|
|
86
|
+
Log.with_severity 0 do
|
|
87
|
+
Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
|
|
88
|
+
TmpFile.with_file do |input_file|
|
|
89
|
+
Path.setup(input_file)
|
|
90
|
+
options = {
|
|
91
|
+
:float => input_file.float,
|
|
92
|
+
:integer => input_file.integer,
|
|
93
|
+
:string => input_file.string,
|
|
94
|
+
:select => input_file.select,
|
|
95
|
+
:array => input_file.array,
|
|
96
|
+
:tsv => input_file.tsv_file,
|
|
97
|
+
}
|
|
98
|
+
job = TestSaveLoadWF.job(:save_test, nil, options)
|
|
99
|
+
TmpFile.with_file do |directory|
|
|
100
|
+
Step.save_job_inputs(job, directory)
|
|
101
|
+
newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
|
|
102
|
+
assert_equal job.path, newjob.path
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_save_all_job_file
|
|
110
|
+
tsv = TSV.setup({}, "Key~Value#:type=:single")
|
|
111
|
+
tsv["key"] = "value"
|
|
112
|
+
Log.with_severity 0 do
|
|
113
|
+
Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
|
|
114
|
+
TmpFile.with_file do |input_file|
|
|
115
|
+
Path.setup(input_file)
|
|
116
|
+
options = {
|
|
117
|
+
:float => input_file.float,
|
|
118
|
+
:integer => input_file.integer,
|
|
119
|
+
:string => input_file.string,
|
|
120
|
+
:select => input_file.select,
|
|
121
|
+
:array => TestSaveLoadWF.job(:list),
|
|
122
|
+
:binary => TestSaveLoadWF.job(:list).file('binary'),
|
|
123
|
+
:tsv => input_file.tsv_file,
|
|
124
|
+
}
|
|
125
|
+
job = TestSaveLoadWF.job(:save_test, nil, options)
|
|
126
|
+
TmpFile.with_file do |directory|
|
|
127
|
+
Step.save_job_inputs(job, directory)
|
|
128
|
+
newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
|
|
129
|
+
assert_equal job.path, newjob.path
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
43
133
|
end
|
|
44
134
|
end
|
|
45
135
|
end
|
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.33.
|
|
4
|
+
version: 5.33.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miguel Vazquez
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-04-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|