rbbt-util 5.32.15 → 5.32.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -73,18 +73,19 @@ module Workflow
73
73
  REMOVE_DEP_TASKS = ENV["RBBT_REMOVE_DEP_TASKS"] == "true"
74
74
  def dep_task(name, workflow, oname, *rest, &block)
75
75
  dep(workflow, oname, *rest, &block)
76
- extension workflow.tasks[oname].extension if workflow.tasks.include?(oname) unless @extension
76
+ extension :dep_task unless @extension
77
77
  returns workflow.tasks[oname].result_description if workflow.tasks.include?(oname) unless @result_description
78
78
  task name do
79
79
  raise RbbtException, "dependency not found in dep_task" if dependencies.empty?
80
+ Step.wait_for_jobs dependencies.select{|d| d.streaming? }
80
81
  dep = dependencies.last
81
82
  dep.join
82
83
  raise dep.get_exception if dep.error?
83
84
  raise Aborted, "Aborted dependency #{dep.path}" if dep.aborted?
84
85
  set_info :result_type, dep.info[:result_type]
85
- forget = config :forget_dep_tasks, "forget_dep_tasks", "key:forget_dep_tasks", :default => FORGET_DEP_TASKS
86
+ forget = config :forget_dep_tasks, "forget_dep_tasks", :default => FORGET_DEP_TASKS
86
87
  if forget
87
- remove = config :remove_dep_tasks, "remove_dep_tasks", "key:remove_dep_tasks", :default => REMOVE_DEP_TASKS
88
+ remove = config :remove_dep_tasks, "remove_dep_tasks", :default => REMOVE_DEP_TASKS
88
89
 
89
90
  self.archive_deps
90
91
  self.copy_files_dir
@@ -92,6 +93,7 @@ module Workflow
92
93
  Open.rm_rf self.files_dir if Open.exist? self.files_dir
93
94
  FileUtils.cp_r dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
94
95
  Open.ln_h dep.path, self.tmp_path
96
+
95
97
  case remove.to_s
96
98
  when 'true'
97
99
  dep.clean
@@ -0,0 +1,195 @@
1
+ module Workflow
2
+ def rec_dependencies(taskname, seen = [])
3
+ @rec_dependencies ||= {}
4
+ @rec_dependencies[taskname] ||= [] unless task_dependencies.include?(taskname)
5
+ @rec_dependencies[taskname] ||= begin
6
+
7
+ deps = task_dependencies[taskname]
8
+
9
+ all_deps = []
10
+ deps.each do |dep|
11
+ next if seen.include?(dep)
12
+ if DependencyBlock === dep
13
+ all_deps << dep.dependency if dep.dependency
14
+ else
15
+ all_deps << dep unless Proc === dep
16
+ end
17
+
18
+ begin
19
+ case dep
20
+ when Array
21
+ wf, t, o = dep
22
+
23
+ wf.rec_dependencies(t.to_sym, seen + [dep]).each do |d|
24
+ if Array === d
25
+ new = d.dup
26
+ else
27
+ new = [dep.first, d]
28
+ end
29
+
30
+ if Hash === o and not o.empty?
31
+ if Hash === new.last
32
+ hash = new.last.dup
33
+ o.each{|k,v| hash[k] ||= v}
34
+ new[new.length-1] = hash
35
+ else
36
+ new.push o.dup
37
+ end
38
+ end
39
+
40
+ all_deps << new
41
+ end if wf && t
42
+
43
+ when String, Symbol
44
+ rec_deps = rec_dependencies(dep.to_sym, seen + [dep])
45
+ all_deps.concat rec_deps
46
+ when DependencyBlock
47
+ dep = dep.dependency
48
+ raise TryAgain
49
+ end
50
+ rescue TryAgain
51
+ retry
52
+ end
53
+ end
54
+ all_deps.uniq
55
+ end
56
+ end
57
+
58
+ def override_dependencies(inputs)
59
+ override_dependencies = IndiferentHash.setup({})
60
+ return override_dependencies if inputs.nil?
61
+ inputs.each do |key,value|
62
+ if String === key && m = key.match(/(.*)#(.*)/)
63
+ workflow, task = m.values_at 1, 2
64
+ workflow = self.to_s if workflow.empty?
65
+ override_dependencies[workflow] ||= IndiferentHash.setup({})
66
+ override_dependencies[workflow][task] = value
67
+ end
68
+ end
69
+ override_dependencies
70
+ end
71
+
72
+ def setup_override_dependency(dep, workflow, task_name)
73
+ return [] if dep == :skip || dep == 'skip'
74
+ dep = Step === dep ? dep : Workflow.load_step(dep)
75
+ dep.workflow = workflow
76
+ dep.info[:name] = dep.name
77
+ dep.original_task_name ||= dep.task_name if dep.workflow
78
+
79
+
80
+ begin
81
+ workflow = Kernel.const_get workflow if String === workflow
82
+ dep.task = workflow.tasks[task_name] if dep.task.nil? && workflow.tasks.include?(task_name)
83
+ rescue
84
+ Log.exception $!
85
+ end
86
+ dep.task_name = task_name
87
+ dep.overriden = dep.original_task_name.to_sym
88
+
89
+ dep.extend step_module
90
+
91
+ dep
92
+ end
93
+
94
+ def real_dependencies(task, orig_jobname, inputs, dependencies)
95
+ real_dependencies = []
96
+ path_deps = {}
97
+
98
+ override_dependencies = override_dependencies(inputs)
99
+
100
+ dependencies.each do |dependency|
101
+ _inputs = IndiferentHash.setup(inputs.dup)
102
+ jobname = orig_jobname
103
+ jobname = _inputs[:jobname] if _inputs.include? :jobname
104
+
105
+ real_dep = case dependency
106
+ when Array
107
+ workflow, dep_task, options = dependency
108
+
109
+ if override_dependencies[workflow.to_s] && value = override_dependencies[workflow.to_s][dep_task]
110
+ setup_override_dependency(value, workflow, dep_task)
111
+ else
112
+
113
+ compute = options[:compute] if options
114
+
115
+ all_d = (real_dependencies + real_dependencies.flatten.collect{|d| d.rec_dependencies} ).flatten.compact.uniq
116
+
117
+ _inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
118
+ jobname = _inputs.delete :jobname if _inputs.include? :jobname
119
+
120
+ job = workflow._job(dep_task, jobname, _inputs)
121
+ ComputeDependency.setup(job, compute) if compute
122
+ job
123
+ end
124
+ when Step
125
+ dependency
126
+ when Symbol
127
+ if override_dependencies[self.to_s] && value = override_dependencies[self.to_s][dependency]
128
+ setup_override_dependency(value, self, dependency)
129
+ else
130
+ _job(dependency, jobname, _inputs)
131
+ end
132
+ when Proc
133
+ if DependencyBlock === dependency
134
+ orig_dep = dependency.dependency
135
+ wf, task_name, options = orig_dep
136
+
137
+ if override_dependencies[wf.to_s] && value = override_dependencies[wf.to_s][task_name]
138
+ dep = setup_override_dependency(value, wf, task_name)
139
+ else
140
+
141
+ options = {} if options.nil?
142
+ compute = options[:compute]
143
+
144
+ options = IndiferentHash.setup(options.dup)
145
+ dep = dependency.call jobname, _inputs.merge(options), real_dependencies
146
+
147
+ dep = [dep] unless Array === dep
148
+
149
+ new_=[]
150
+ dep.each{|d|
151
+ next if d.nil?
152
+ if Hash === d
153
+ d[:workflow] ||= wf
154
+ d[:task] ||= task_name
155
+ _override_dependencies = override_dependencies.merge(override_dependencies(d[:inputs] || {}))
156
+ d = if _override_dependencies[d[:workflow].to_s] && value = _override_dependencies[d[:workflow].to_s][d[:task]]
157
+ setup_override_dependency(value, d[:workflow], d[:task])
158
+ else
159
+ task_info = d[:workflow].task_info(d[:task])
160
+
161
+ _inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
162
+ d[:workflow]._job(d[:task], d[:jobname], _inputs)
163
+ end
164
+ end
165
+ ComputeDependency.setup(d, compute) if compute
166
+ new_ << d
167
+ }
168
+ dep = new_
169
+ end
170
+ else
171
+ _inputs = IndiferentHash.setup(_inputs.dup)
172
+ dep = dependency.call jobname, _inputs, real_dependencies
173
+ if Hash === dep
174
+ dep[:workflow] ||= wf || self
175
+ _override_dependencies = override_dependencies.merge(override_dependencies(dep[:inputs] || {}))
176
+ if _override_dependencies[dep[:workflow].to_s] && value = _override_dependencies[dep[:workflow].to_s][dep[:task]]
177
+ setup_override_dependency(value, dep[:workflow], dep[:task])
178
+ else
179
+ task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
180
+ _inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
181
+ dep = dep[:workflow]._job(dep[:task], dep[:jobname], _inputs)
182
+ end
183
+ end
184
+ end
185
+
186
+ dep
187
+ else
188
+ raise "Dependency for #{task.name} not understood: #{Misc.fingerprint dependency}"
189
+ end
190
+
191
+ real_dependencies << real_dep
192
+ end
193
+ real_dependencies.flatten.compact
194
+ end
195
+ end
@@ -4,6 +4,8 @@ require 'rbbt/util/log'
4
4
  require 'rbbt/util/semaphore'
5
5
  require 'rbbt/workflow/step/accessor'
6
6
  require 'rbbt/workflow/step/prepare'
7
+ require 'rbbt/workflow/step/status'
8
+ require 'rbbt/workflow/step/info'
7
9
 
8
10
  class Step
9
11
  attr_accessor :clean_name, :path, :task, :workflow, :inputs, :dependencies, :bindings
@@ -35,41 +37,6 @@ class Step
35
37
  end
36
38
 
37
39
 
38
- def overriden?
39
- return true if @overriden
40
- return true if dependencies.select{|dep| dep.overriden? }.any?
41
- info[:archived_info].each do |f,i|
42
- return true if i[:overriden] || i["overriden"]
43
- end if info[:archived_info]
44
- return false
45
- end
46
-
47
- def overriden
48
- @overriden
49
- #if @overriden.nil?
50
- # return false if dependencies.nil?
51
- # dependencies.select{|dep| dep.overriden? }.any?
52
- #else
53
- # @overriden
54
- #end
55
- end
56
-
57
- def overriden_deps
58
- ord = []
59
- deps = dependencies.dup
60
- while dep = deps.shift
61
- case dep.overriden
62
- when FalseClass
63
- next
64
- when Symbol
65
- ord << dep
66
- else
67
- deps += dep.dependencies
68
- end
69
- end
70
- ord
71
- end
72
-
73
40
  def initialize(path, task = nil, inputs = nil, dependencies = nil, bindings = nil, clean_name = nil)
74
41
  path = Path.setup(Misc.sanitize_filename(path)) if String === path
75
42
  path = path.call if Proc === path
@@ -99,35 +66,6 @@ class Step
99
66
  end
100
67
 
101
68
 
102
- def load_inputs_from_info
103
- if info[:inputs]
104
- info_inputs = info[:inputs]
105
- if task && task.respond_to?(:inputs) && task.inputs
106
- IndiferentHash.setup info_inputs
107
- @inputs = NamedArray.setup info_inputs.values_at(*task.inputs.collect{|name| name.to_s}), task.inputs
108
- else
109
- @inputs = NamedArray.setup info_inputs.values, info_inputs.keys
110
- end
111
- else
112
- nil
113
- end
114
- end
115
-
116
- def load_dependencies_from_info
117
- relocated = nil
118
- @dependencies = (self.info[:dependencies] || []).collect do |task,name,dep_path|
119
- if Open.exists?(dep_path) || Open.exists?(dep_path + '.info')
120
- Workflow._load_step dep_path
121
- else
122
- next if FalseClass === relocated
123
- new_path = Workflow.relocate(path, dep_path)
124
- relocated = true if Open.exists?(new_path) || Open.exists?(new_path + '.info')
125
- Workflow._load_step new_path
126
- end
127
- end.compact
128
- @relocated = relocated
129
- end
130
-
131
69
 
132
70
  def inputs
133
71
  return @inputs if NamedArray === @inputs
@@ -151,54 +89,6 @@ class Step
151
89
  end
152
90
  end
153
91
 
154
- def archive_deps
155
- self.set_info :archived_info, archived_info
156
- self.set_info :archived_dependencies, info[:dependencies]
157
- end
158
-
159
- def archived_info
160
- return info[:archived_info] if info[:archived_info]
161
-
162
- archived_info = {}
163
- dependencies.each do |dep|
164
- if Symbol === dep.overriden && ! Open.exists?(dep.info_file)
165
- archived_info[dep.path] = dep.overriden
166
- else
167
- archived_info[dep.path] = dep.info
168
- end
169
- archived_info.merge!(dep.archived_info)
170
- end if dependencies
171
-
172
- archived_info
173
- end
174
-
175
- def archived_inputs
176
- return {} unless info[:archived_dependencies]
177
- archived_info = self.archived_info
178
-
179
- all_inputs = IndiferentHash.setup({})
180
- deps = info[:archived_dependencies].collect{|p| p.last}
181
- seen = []
182
- while path = deps.pop
183
- dep_info = archived_info[path]
184
- if dep_info
185
- dep_info[:inputs].each do |k,v|
186
- all_inputs[k] = v unless all_inputs.include?(k)
187
- end if dep_info[:inputs]
188
- deps.concat(dep_info[:dependencies].collect{|p| p.last } - seen) if dep_info[:dependencies]
189
- deps.concat(dep_info[:archived_dependencies].collect{|p| p.last } - seen) if dep_info[:archived_dependencies]
190
- end
191
- seen << path
192
- end
193
-
194
- all_inputs
195
- end
196
-
197
- def dependencies=(dependencies)
198
- @dependencies = dependencies
199
- set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
200
- end
201
-
202
92
  def recursive_inputs
203
93
  if NamedArray === inputs
204
94
  i = {}
@@ -213,7 +103,8 @@ class Step
213
103
 
214
104
  dep.inputs.zip(dep.inputs.fields).each do |v,f|
215
105
  if i.include?(f) && i[f] != v
216
- Log.debug "Conflict in #{ f }: #{[Misc.fingerprint(i[f]), Misc.fingerprint(v)] * " <-> "}"
106
+ next
107
+ #Log.debug "Variable '#{f}' reused with different values: #{[Misc.fingerprint(i[f]), Misc.fingerprint(v)] * " <-> "}"
217
108
  else
218
109
  i[f] = v
219
110
  end
@@ -453,34 +344,6 @@ class Step
453
344
  res
454
345
  end
455
346
 
456
- def self.clean(path)
457
- info_file = Step.info_file path
458
- pid_file = Step.pid_file path
459
- md5_file = Step.md5_file path
460
- files_dir = Step.files_dir path
461
- tmp_path = Step.tmp_path path
462
-
463
- if ! (Open.writable?(path) && Open.writable?(info_file))
464
- Log.warn "Could not clean #{path}: not writable"
465
- return
466
- end
467
-
468
- if (Open.exists?(path) or Open.broken_link?(path)) or Open.exists?(pid_file) or Open.exists?(info_file) or Open.exists?(files_dir) or Open.broken_link?(files_dir)
469
-
470
- @result = nil
471
- @pid = nil
472
-
473
- Misc.insist do
474
- Open.rm info_file if Open.exists?(info_file)
475
- Open.rm md5_file if Open.exists?(md5_file)
476
- Open.rm path if (Open.exists?(path) || Open.broken_link?(path))
477
- Open.rm_rf files_dir if Open.exists?(files_dir) || Open.broken_link?(files_dir)
478
- Open.rm pid_file if Open.exists?(pid_file)
479
- Open.rm tmp_path if Open.exists?(tmp_path)
480
- end
481
- end
482
- end
483
-
484
347
  def update
485
348
  if dirty?
486
349
  dependencies.collect{|d| d.update } if dependencies
@@ -488,22 +351,6 @@ class Step
488
351
  end
489
352
  end
490
353
 
491
- def clean
492
- if ! Open.exists?(info_file)
493
- Log.high "Refusing to clean step with no .info file: #{path}"
494
- return self
495
- end
496
- status = []
497
- status << "dirty" if done? && dirty?
498
- status << "not running" if ! done? && ! running?
499
- status.unshift " " if status.any?
500
- Log.high "Cleaning step: #{path}#{status * " "}"
501
- Log.stack caller if RBBT_DEBUG_CLEAN
502
- abort if ! done? && running?
503
- Step.clean(path)
504
- self
505
- end
506
-
507
354
  #connected = true means that dependency searching ends when a result is done
508
355
  #but dependencies are absent, meanining that the file could have been dropped
509
356
  #in
@@ -516,7 +363,11 @@ class Step
516
363
  return [] if dependencies.nil? or dependencies.empty?
517
364
 
518
365
  new_dependencies = []
519
- archived_deps = self.info[:archived_info] ? self.info[:archived_info].keys : []
366
+ if self.overriden?
367
+ archived_deps = []
368
+ else
369
+ archived_deps = self.info[:archived_info] ? self.info[:archived_info].keys : []
370
+ end
520
371
 
521
372
  dependencies.each{|step|
522
373
  #next if self.done? && Open.exists?(info_file) && info[:dependencies] && info[:dependencies].select{|task,name,path| path == step.path }.empty?
@@ -528,6 +379,7 @@ class Step
528
379
  new_dependencies.concat r
529
380
  new_dependencies << step
530
381
  }
382
+
531
383
  new_dependencies.uniq
532
384
  end
533
385