rbbt-util 5.28.9 → 5.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/entity.rb +1 -1
- data/lib/rbbt/fix_width_table.rb +5 -4
- data/lib/rbbt/hpc.rb +1 -549
- data/lib/rbbt/hpc/orchestrate.rb +23 -0
- data/lib/rbbt/hpc/slurm.rb +570 -0
- data/lib/rbbt/persist.rb +9 -4
- data/lib/rbbt/persist/tsv/adapter.rb +0 -1
- data/lib/rbbt/persist/tsv/fix_width_table.rb +5 -3
- data/lib/rbbt/resource.rb +12 -6
- data/lib/rbbt/resource/path.rb +1 -1
- data/lib/rbbt/tsv/attach.rb +7 -4
- data/lib/rbbt/tsv/dumper.rb +6 -2
- data/lib/rbbt/tsv/parallel.rb +0 -3
- data/lib/rbbt/util/R.rb +2 -2
- data/lib/rbbt/util/cmd.rb +10 -0
- data/lib/rbbt/util/misc/bgzf.rb +1 -1
- data/lib/rbbt/util/misc/indiferent_hash.rb +8 -0
- data/lib/rbbt/util/misc/inspect.rb +11 -7
- data/lib/rbbt/util/named_array.rb +1 -1
- data/lib/rbbt/util/open.rb +17 -16
- data/lib/rbbt/workflow.rb +2 -1
- data/lib/rbbt/workflow/accessor.rb +3 -2
- data/lib/rbbt/workflow/definition.rb +3 -1
- data/lib/rbbt/workflow/examples.rb +2 -2
- data/lib/rbbt/workflow/integration/ansible.rb +53 -0
- data/lib/rbbt/workflow/integration/ansible/workflow.rb +60 -0
- data/lib/rbbt/workflow/step.rb +16 -5
- data/lib/rbbt/workflow/step/accessor.rb +36 -24
- data/lib/rbbt/workflow/step/dependencies.rb +8 -2
- data/lib/rbbt/workflow/step/run.rb +22 -19
- data/lib/rbbt/workflow/util/archive.rb +2 -0
- data/lib/rbbt/workflow/util/orchestrator.rb +30 -12
- data/lib/rbbt/workflow/util/provenance.rb +7 -3
- data/share/rbbt_commands/ansible +55 -0
- data/share/rbbt_commands/purge_job +0 -1
- data/share/rbbt_commands/slurm/list +141 -0
- data/share/rbbt_commands/slurm/orchestrate +47 -0
- data/share/rbbt_commands/{workflow/slurm → slurm/task} +10 -3
- data/share/rbbt_commands/system/status +22 -22
- data/share/rbbt_commands/workflow/forget_deps +9 -0
- data/share/rbbt_commands/workflow/info +12 -9
- data/share/rbbt_commands/workflow/prov +2 -1
- data/test/rbbt/association/test_index.rb +6 -6
- data/test/rbbt/knowledge_base/test_query.rb +3 -3
- data/test/rbbt/knowledge_base/test_registry.rb +1 -1
- data/test/rbbt/persist/tsv/test_cdb.rb +0 -7
- data/test/rbbt/persist/tsv/test_kyotocabinet.rb +2 -8
- data/test/rbbt/persist/tsv/test_leveldb.rb +0 -6
- data/test/rbbt/persist/tsv/test_lmdb.rb +0 -6
- data/test/rbbt/persist/tsv/test_tokyocabinet.rb +15 -14
- data/test/rbbt/test_entity.rb +0 -1
- data/test/rbbt/test_knowledge_base.rb +3 -4
- data/test/rbbt/test_persist.rb +10 -6
- data/test/rbbt/test_workflow.rb +49 -16
- data/test/rbbt/tsv/test_accessor.rb +11 -0
- data/test/rbbt/tsv/test_attach.rb +86 -8
- data/test/rbbt/tsv/test_index.rb +6 -7
- data/test/rbbt/tsv/test_manipulate.rb +2 -3
- data/test/rbbt/util/R/test_model.rb +2 -1
- data/test/rbbt/util/R/test_plot.rb +0 -2
- data/test/rbbt/util/concurrency/test_processes.rb +1 -1
- data/test/rbbt/util/misc/test_bgzf.rb +11 -7
- data/test/rbbt/util/misc/test_lock.rb +0 -1
- data/test/rbbt/util/misc/test_multipart_payload.rb +1 -1
- data/test/rbbt/util/misc/test_pipes.rb +0 -5
- data/test/rbbt/util/test_R.rb +1 -0
- data/test/rbbt/util/test_log.rb +4 -6
- data/test/rbbt/util/test_misc.rb +0 -2
- data/test/rbbt/util/test_open.rb +0 -1
- data/test/rbbt/util/test_python.rb +17 -1
- data/test/rbbt/workflow/test_remote_workflow.rb +1 -1
- data/test/rbbt/workflow/test_step.rb +8 -3
- data/test/rbbt/workflow/util/test_orchestrator.rb +50 -0
- metadata +10 -5
- data/test/rbbt/workflow/remote/test_client.rb +0 -56
@@ -50,8 +50,8 @@ module Workflow
|
|
50
50
|
case input_types[input]
|
51
51
|
when :file
|
52
52
|
Log.debug "Pointing #{ input } to #{file}"
|
53
|
-
if file =~ /\.
|
54
|
-
inputs[input.to_sym] = Open.read(file)
|
53
|
+
if file =~ /\.yaml/
|
54
|
+
inputs[input.to_sym] = YAML.load(Open.read(file))
|
55
55
|
else
|
56
56
|
inputs[input.to_sym] = Open.realpath(file)
|
57
57
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative 'ansible/workflow'
|
2
|
+
require 'rbbt/workflow/usage'
|
3
|
+
|
4
|
+
module Ansible
|
5
|
+
def self.play(playbook, inventory = nil)
|
6
|
+
inventory = Rbbt.etc.ansible_inventory.find
|
7
|
+
Log.with_severity 0 do
|
8
|
+
TmpFile.with_file do |tmp|
|
9
|
+
if Hash === playbook
|
10
|
+
Open.write(tmp, [playbook].to_yaml)
|
11
|
+
playbook = tmp
|
12
|
+
end
|
13
|
+
CMD.cmd_log("ansible-playbook -i #{inventory} #{playbook}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.clean_symbols(hash)
|
19
|
+
new = {}
|
20
|
+
hash.each do |key,value|
|
21
|
+
key = key.to_s
|
22
|
+
value = case value
|
23
|
+
when Symbol
|
24
|
+
value.to_s
|
25
|
+
when Hash
|
26
|
+
self.clean_symbols(value)
|
27
|
+
else
|
28
|
+
value
|
29
|
+
end
|
30
|
+
new[key] = value
|
31
|
+
end
|
32
|
+
new
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.workflow2playbook(workflow, task, options = {})
|
36
|
+
job_options = workflow.get_SOPT(workflow.tasks[task])
|
37
|
+
|
38
|
+
tasks = workflow.job(task, nil, job_options).exec
|
39
|
+
|
40
|
+
hosts = options[:hosts] || 'localhost'
|
41
|
+
|
42
|
+
clean_tasks = tasks.collect{|task| self.clean_symbols task }
|
43
|
+
{"hosts" => hosts, "tasks" => clean_tasks}
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.playbook(file, task = nil, options = {})
|
47
|
+
task = 'default' if task.nil?
|
48
|
+
|
49
|
+
workflow = Workflow.require_workflow file
|
50
|
+
task = workflow.tasks.keys.last if workflow.tasks[task].nil?
|
51
|
+
workflow2playbook workflow, task, options
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rbbt/workflow'
|
2
|
+
|
3
|
+
module Ansible
|
4
|
+
module AnsibleWorkflow
|
5
|
+
def self.extended(object)
|
6
|
+
class << object
|
7
|
+
attr_accessor :ans_tasks
|
8
|
+
end
|
9
|
+
|
10
|
+
object.helper :register do |task_info|
|
11
|
+
desc = task.description if task
|
12
|
+
name ||= desc || short_path
|
13
|
+
task_info = {"name" => name}.merge(task_info)
|
14
|
+
@ans_tasks ||= []
|
15
|
+
@ans_tasks << task_info
|
16
|
+
task
|
17
|
+
end
|
18
|
+
|
19
|
+
object.helper :ans do |name, info|
|
20
|
+
register({ name => info})
|
21
|
+
end
|
22
|
+
|
23
|
+
object.helper :add do |name, info|
|
24
|
+
@ans_tasks.last[name.to_s] = info
|
25
|
+
end
|
26
|
+
|
27
|
+
object.helper :shell do |cmd|
|
28
|
+
register({"shell" => cmd.strip})
|
29
|
+
end
|
30
|
+
|
31
|
+
object.helper :sudo do |cmd|
|
32
|
+
register({"shell" => cmd.strip, "become" => 'yes'})
|
33
|
+
end
|
34
|
+
|
35
|
+
object.helper :singularity do |scmd|
|
36
|
+
img = config :singularity_img, :build, :test, :small, :default => '/data/img/singularity/rbbt/rbbt.simg'
|
37
|
+
container = config :singularity_container, :build, :test, :small, :default => '/data/img/sandbox/mvazque2/'
|
38
|
+
cmd = <<-EOF
|
39
|
+
singularity exec -C -H '#{container}' '#{img}' #{scmd}
|
40
|
+
EOF
|
41
|
+
register({"shell" => cmd.strip, "name" => short_path})
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
object.helper :produce_task do
|
46
|
+
@ans_tasks
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def play(name = nil, &block)
|
51
|
+
name = Misc.snake_case(@description) if name.nil?
|
52
|
+
task name => :yaml do |*args|
|
53
|
+
self.instance_exec *args, &block
|
54
|
+
dependencies.inject([]){|acc,dep| acc += dep.load } + produce_task
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -12,6 +12,9 @@ class Step
|
|
12
12
|
attr_accessor :exec
|
13
13
|
attr_accessor :relocated
|
14
14
|
attr_accessor :result, :mutex, :seen
|
15
|
+
attr_accessor :real_inputs, :original_task_name
|
16
|
+
|
17
|
+
RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
|
15
18
|
|
16
19
|
class << self
|
17
20
|
attr_accessor :lock_dir
|
@@ -143,17 +146,24 @@ class Step
|
|
143
146
|
seen = []
|
144
147
|
while path = deps.pop
|
145
148
|
dep_info = archived_info[path]
|
146
|
-
dep_info
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
149
|
+
if dep_info
|
150
|
+
dep_info[:inputs].each do |k,v|
|
151
|
+
all_inputs[k] = v unless all_inputs.include?(k)
|
152
|
+
end if dep_info[:inputs]
|
153
|
+
deps.concat(dep_info[:dependencies].collect{|p| p.last } - seen) if dep_info[:dependencies]
|
154
|
+
deps.concat(dep_info[:archived_dependencies].collect{|p| p.last } - seen) if dep_info[:archived_dependencies]
|
155
|
+
end
|
151
156
|
seen << path
|
152
157
|
end
|
153
158
|
|
154
159
|
all_inputs
|
155
160
|
end
|
156
161
|
|
162
|
+
def dependencies=(dependencies)
|
163
|
+
@dependencies = dependencies
|
164
|
+
set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
|
165
|
+
end
|
166
|
+
|
157
167
|
def recursive_inputs
|
158
168
|
if NamedArray === inputs
|
159
169
|
i = {}
|
@@ -449,6 +459,7 @@ class Step
|
|
449
459
|
status << "not running" if ! done? && ! running?
|
450
460
|
status.unshift " " if status.any?
|
451
461
|
Log.high "Cleaning step: #{path}#{status * " "}"
|
462
|
+
Log.stack caller if RBBT_DEBUG_CLEAN
|
452
463
|
abort if ! done? && running?
|
453
464
|
Step.clean(path)
|
454
465
|
self
|
@@ -8,6 +8,16 @@ class Step
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
def self.serialize_info(info)
|
12
|
+
info = info.clean_version if IndiferentHash === info
|
13
|
+
INFO_SERIALIZER.dump(info)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load_serialized_info(io)
|
17
|
+
IndiferentHash.setup(INFO_SERIALIZER.load(io))
|
18
|
+
end
|
19
|
+
|
20
|
+
|
11
21
|
def self.wait_for_jobs(jobs)
|
12
22
|
jobs = [jobs] if Step === jobs
|
13
23
|
begin
|
@@ -59,7 +69,7 @@ class Step
|
|
59
69
|
def self.step_info(path)
|
60
70
|
begin
|
61
71
|
Open.open(info_file(path), :mode => 'rb') do |f|
|
62
|
-
|
72
|
+
self.load_serialized_info(f)
|
63
73
|
end
|
64
74
|
rescue Exception
|
65
75
|
Log.exception $!
|
@@ -83,18 +93,18 @@ class Step
|
|
83
93
|
|
84
94
|
Log.debug "Saving job input #{name} (#{type}) into #{path}"
|
85
95
|
case
|
86
|
-
when
|
87
|
-
Open.
|
88
|
-
when
|
89
|
-
Open.write(path, value)
|
90
|
-
when type == "file"
|
96
|
+
when Step === value
|
97
|
+
Open.link(value.path, path)
|
98
|
+
when type.to_s == "file"
|
91
99
|
if String === value && File.exists?(value)
|
92
100
|
Open.link(value, path)
|
93
101
|
else
|
94
|
-
Open.write(path + '.
|
102
|
+
Open.write(path + '.yaml', value.to_yaml)
|
95
103
|
end
|
96
|
-
when
|
97
|
-
value
|
104
|
+
when Array === value
|
105
|
+
Open.write(path, value * "\n")
|
106
|
+
when IO === value
|
107
|
+
Open.write(path, value)
|
98
108
|
else
|
99
109
|
Open.write(path, value.to_s)
|
100
110
|
end
|
@@ -104,7 +114,7 @@ class Step
|
|
104
114
|
def self.save_job_inputs(job, dir, options = nil)
|
105
115
|
options = IndiferentHash.setup options.dup if options
|
106
116
|
|
107
|
-
task_name = job.task_name
|
117
|
+
task_name = Symbol === job.overriden ? job.overriden : job.task_name
|
108
118
|
workflow = job.workflow
|
109
119
|
workflow = Kernel.const_get workflow if String === workflow
|
110
120
|
task_info = workflow.task_info(task_name)
|
@@ -113,15 +123,17 @@ class Step
|
|
113
123
|
input_defaults = task_info[:input_defaults]
|
114
124
|
|
115
125
|
inputs = {}
|
126
|
+
real_inputs = job.real_inputs || job.info[:real_inputs]
|
116
127
|
job.recursive_inputs.zip(job.recursive_inputs.fields).each do |value,name|
|
117
128
|
next unless task_inputs.include? name.to_sym
|
118
|
-
next
|
129
|
+
next unless real_inputs.include? name.to_sym
|
130
|
+
next if options && ! options.include?(name)
|
119
131
|
next if value.nil?
|
120
132
|
next if input_defaults[name] == value
|
121
133
|
inputs[name] = value
|
122
134
|
end
|
123
135
|
|
124
|
-
if options.include?
|
136
|
+
if options && options.include?('override_dependencies')
|
125
137
|
inputs.merge!(:override_dependencies => open[:override_dependencies])
|
126
138
|
input_types = IndiferentHash.setup(input_types.merge(:override_dependencies => :array))
|
127
139
|
end
|
@@ -188,7 +200,7 @@ class Step
|
|
188
200
|
info_lock.lock if check_lock and false
|
189
201
|
begin
|
190
202
|
Open.open(info_file, :mode => 'rb') do |file|
|
191
|
-
|
203
|
+
Step.load_serialized_info(file)
|
192
204
|
end
|
193
205
|
ensure
|
194
206
|
info_lock.unlock if check_lock and false
|
@@ -204,7 +216,7 @@ class Step
|
|
204
216
|
Log.debug{"Error loading info file: " + info_file}
|
205
217
|
Log.exception $!
|
206
218
|
Open.rm info_file
|
207
|
-
Misc.sensiblewrite(info_file,
|
219
|
+
Misc.sensiblewrite(info_file, Step.serialize_info({:status => :error, :messages => ["Info file lost"]}))
|
208
220
|
raise $!
|
209
221
|
end
|
210
222
|
end
|
@@ -212,10 +224,10 @@ class Step
|
|
212
224
|
def init_info(force = false)
|
213
225
|
return nil if @exec || info_file.nil? || (Open.exists?(info_file) && ! force)
|
214
226
|
Open.lock(info_file, :lock => info_lock) do
|
215
|
-
i = {:status => :waiting, :pid => Process.pid, :path => path}
|
227
|
+
i = {:status => :waiting, :pid => Process.pid, :path => path, :real_inputs => real_inputs}
|
216
228
|
i[:dependencies] = dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
|
217
|
-
|
218
|
-
|
229
|
+
Misc.sensiblewrite(info_file, Step.serialize_info(i), :force => true, :lock => false)
|
230
|
+
@info_cache = IndiferentHash.setup(i)
|
219
231
|
@info_cache_time = Time.now
|
220
232
|
end
|
221
233
|
end
|
@@ -227,9 +239,9 @@ class Step
|
|
227
239
|
Open.lock(info_file, :lock => info_lock) do
|
228
240
|
i = info(false).dup
|
229
241
|
i[key] = value
|
230
|
-
|
231
|
-
|
232
|
-
Misc.sensiblewrite(info_file, dump, :force => true, :lock => false)
|
242
|
+
dump = Step.serialize_info(i)
|
243
|
+
@info_cache = IndiferentHash.setup(i)
|
244
|
+
Misc.sensiblewrite(info_file, dump, :force => true, :lock => false) if Open.exists?(info_file)
|
233
245
|
@info_cache_time = Time.now
|
234
246
|
value
|
235
247
|
end
|
@@ -242,9 +254,9 @@ class Step
|
|
242
254
|
Open.lock(info_file, :lock => info_lock) do
|
243
255
|
i = info(false)
|
244
256
|
i.merge! hash
|
245
|
-
|
246
|
-
|
247
|
-
Misc.sensiblewrite(info_file, dump, :force => true, :lock => false)
|
257
|
+
dump = Step.serialize_info(i)
|
258
|
+
@info_cache = IndiferentHash.setup(i)
|
259
|
+
Misc.sensiblewrite(info_file, dump, :force => true, :lock => false) if Open.exists?(info_file)
|
248
260
|
@info_cache_time = Time.now
|
249
261
|
value
|
250
262
|
end
|
@@ -537,7 +549,7 @@ class Step
|
|
537
549
|
end
|
538
550
|
|
539
551
|
def file(name)
|
540
|
-
Path.setup(File.join(files_dir, name.to_s))
|
552
|
+
Path.setup(File.join(files_dir, name.to_s), workflow, self)
|
541
553
|
end
|
542
554
|
|
543
555
|
def save_file(name, content)
|
@@ -92,7 +92,13 @@ class Step
|
|
92
92
|
(job.done? && job.dirty?) || (job.error? && job.dirty?) ||
|
93
93
|
(!(job.noinfo? || job.done? || job.error? || job.aborted? || job.running?))
|
94
94
|
|
95
|
-
|
95
|
+
if ! (job.resumable? && (job.updated? && ! job.dirty?))
|
96
|
+
Log.high "About to clean -- status: #{status}, present #{File.exists?(job.path)}, " +
|
97
|
+
%w(done? error? recoverable_error? noinfo? updated? dirty? aborted? running? resumable?).
|
98
|
+
collect{|v| [v, job.send(v)]*": "} * ", " if RBBT_DEBUG_CLEAN
|
99
|
+
|
100
|
+
job.clean
|
101
|
+
end
|
96
102
|
job.set_info :status, :cleaned
|
97
103
|
end
|
98
104
|
|
@@ -121,7 +127,7 @@ class Step
|
|
121
127
|
end
|
122
128
|
|
123
129
|
def input_dependencies
|
124
|
-
inputs.flatten.select{|i| Step === i}
|
130
|
+
(inputs.flatten.select{|i| Step === i} + inputs.flatten.select{|dep| Path === dep && Step === dep.resource}.collect{|dep| dep.resource})
|
125
131
|
end
|
126
132
|
|
127
133
|
|
@@ -112,7 +112,7 @@ class Step
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def updatable?
|
115
|
-
(ENV["RBBT_UPDATE_ALL_JOBS"] == 'true' || ( ENV["RBBT_UPDATE"] == "true" && Open.exists?(info_file)) && status != :noinfo && ! (relocated? && done?))
|
115
|
+
(ENV["RBBT_UPDATE_ALL_JOBS"] == 'true' || ( ENV["RBBT_UPDATE"] == "true" && Open.exists?(info_file)) && status != :noinfo && ! (relocated? && done?)) || (ENV["RBBT_UPDATE"] && ! (done? && ! Open.exists?(info_file)))
|
116
116
|
end
|
117
117
|
|
118
118
|
def dependency_checks
|
@@ -128,7 +128,7 @@ class Step
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def input_checks
|
131
|
-
inputs.select{|i| Step === i }.
|
131
|
+
(inputs.select{|i| Step === i } + inputs.select{|i| Path === i && Step === i.resource}.collect{|i| i.resource}).
|
132
132
|
select{|dependency| dependency.updatable? }
|
133
133
|
end
|
134
134
|
|
@@ -154,25 +154,28 @@ class Step
|
|
154
154
|
canfail_paths = self.canfail_paths
|
155
155
|
this_mtime = Open.mtime(self.path) if Open.exists?(self.path)
|
156
156
|
|
157
|
-
checks.
|
158
|
-
|
159
|
-
dep_done = dep.done?
|
157
|
+
outdated_time = checks.select{|dep| dep.updatable? && dep.done? && Persist.newer?(path, dep.path) }
|
158
|
+
outdated_dep = checks.reject{|dep| dep.done? || (dep.error? && ! dep.recoverable_error? && canfail_paths.include?(dep.path)) }
|
160
159
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
rescue
|
166
|
-
end
|
160
|
+
#checks.each do |dep|
|
161
|
+
# next unless dep.updatable?
|
162
|
+
# dep_done = dep.done?
|
167
163
|
|
168
|
-
|
169
|
-
|
170
|
-
|
164
|
+
# begin
|
165
|
+
# if this_mtime && dep_done && Open.exists?(dep.path) && (Open.mtime(dep.path) > this_mtime + 1)
|
166
|
+
# outdated_time << dep
|
167
|
+
# end
|
168
|
+
# rescue
|
169
|
+
# end
|
171
170
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
171
|
+
# # Is this pointless? this would mean some dep got updated after a later
|
172
|
+
# # dep but but before this one.
|
173
|
+
# #if (! dep.done? && ! canfail_paths.include?(dep.path)) || ! dep.updated?
|
174
|
+
|
175
|
+
# if (! dep_done && ! canfail_paths.include?(dep.path))
|
176
|
+
# outdated_dep << dep
|
177
|
+
# end
|
178
|
+
#end
|
176
179
|
|
177
180
|
Log.high "Some newer files found: #{Misc.fingerprint outdated_time}" if outdated_time.any?
|
178
181
|
Log.high "Some outdated files found: #{Misc.fingerprint outdated_dep}" if outdated_dep.any?
|
@@ -215,7 +218,7 @@ class Step
|
|
215
218
|
no_load = :stream if no_load
|
216
219
|
|
217
220
|
Open.write(pid_file, Process.pid.to_s) unless Open.exists?(path) or Open.exists?(pid_file)
|
218
|
-
result_type = @task.result_type
|
221
|
+
result_type = @task.result_type if @task
|
219
222
|
result_type = info[:result_type] if result_type.nil?
|
220
223
|
result = Persist.persist "Job", result_type, :file => path, :check => persist_checks, :no_load => no_load do
|
221
224
|
if Step === Step.log_relay_step and not self == Step.log_relay_step
|
@@ -67,8 +67,10 @@ class Step
|
|
67
67
|
next unless File.exists?(step.path)
|
68
68
|
job_files << step.path
|
69
69
|
job_files << step.info_file if File.exists?(step.info_file)
|
70
|
+
job_files << Step.md5_file(step.path) if File.exists?(Step.md5_file step.path)
|
70
71
|
job_file_dir_content = Dir.glob(step.files_dir + '/**/*')
|
71
72
|
job_files += job_file_dir_content
|
73
|
+
job_files << step.files_dir if File.exists?(step.files_dir)
|
72
74
|
rec_dependencies = Set.new
|
73
75
|
|
74
76
|
next unless recursive
|
@@ -26,15 +26,25 @@ module Workflow
|
|
26
26
|
workload
|
27
27
|
end
|
28
28
|
|
29
|
+
def self.workload(jobs)
|
30
|
+
jobs.inject({}) do |acc,job|
|
31
|
+
Orchestrator.job_workload(job).each do |j,d|
|
32
|
+
acc[j] = d unless acc.keys.collect{|k| k.path }.include? j.path
|
33
|
+
end
|
34
|
+
acc
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
29
38
|
def self.job_rules(rules, job)
|
30
39
|
workflow = job.workflow.to_s
|
31
40
|
task_name = job.task_name.to_s
|
41
|
+
defaults = rules["defaults"] || {}
|
32
42
|
|
33
|
-
return IndiferentHash.setup(
|
34
|
-
return IndiferentHash.setup(
|
43
|
+
return IndiferentHash.setup(defaults) unless rules[workflow]
|
44
|
+
return IndiferentHash.setup(defaults) unless rules[workflow][task_name]
|
35
45
|
|
36
46
|
job_rules = IndiferentHash.setup(rules[workflow][task_name])
|
37
|
-
|
47
|
+
defaults.each{|k,v| job_rules[k] = v if job_rules[k].nil? } if defaults
|
38
48
|
job_rules
|
39
49
|
end
|
40
50
|
|
@@ -143,18 +153,25 @@ module Workflow
|
|
143
153
|
end
|
144
154
|
end
|
145
155
|
|
146
|
-
def erase_job_dependencies(job, rules,
|
156
|
+
def erase_job_dependencies(job, rules, all_jobs, top_level_jobs)
|
147
157
|
job.dependencies.each do |dep|
|
148
158
|
next if top_level_jobs.include? dep.path
|
149
159
|
next unless Orchestrator.job_rules(rules, dep)["erase"].to_s == 'true'
|
150
160
|
|
151
|
-
|
152
|
-
|
161
|
+
dep_path = dep.path
|
162
|
+
parents = all_jobs.select do |parent|
|
163
|
+
paths = parent.info[:dependencies].nil? ? parent.dependencies.collect{|d| d.path } : parent.info[:dependencies].collect{|d| d.last }
|
164
|
+
paths.include? dep_path
|
165
|
+
end
|
166
|
+
|
167
|
+
next unless parents.reject{|parent| parent.done? }.empty?
|
153
168
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
169
|
+
parents.each do |parent|
|
170
|
+
Log.high "Erasing #{dep.path} from #{parent.path}"
|
171
|
+
parent.archive_deps
|
172
|
+
parent.copy_files_dir
|
173
|
+
parent.dependencies = parent.dependencies - [dep]
|
174
|
+
end
|
158
175
|
dep.clean
|
159
176
|
end
|
160
177
|
end
|
@@ -162,7 +179,8 @@ module Workflow
|
|
162
179
|
def process(rules, jobs)
|
163
180
|
begin
|
164
181
|
|
165
|
-
workload =
|
182
|
+
workload = Orchestrator.workload(jobs)
|
183
|
+
all_jobs = workload.keys
|
166
184
|
|
167
185
|
top_level_jobs = jobs.collect{|job| job.path }
|
168
186
|
while workload.any?
|
@@ -187,7 +205,7 @@ module Workflow
|
|
187
205
|
when job.done?
|
188
206
|
Log.debug "Orchestrator done #{job.path}"
|
189
207
|
release_resources(job)
|
190
|
-
erase_job_dependencies(job, rules,
|
208
|
+
erase_job_dependencies(job, rules, all_jobs, top_level_jobs)
|
191
209
|
|
192
210
|
when job.running?
|
193
211
|
next
|