rbbt-util 5.32.16 → 5.32.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -77,14 +77,15 @@ module Workflow
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,15 +93,17 @@ 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
98
100
  when 'recursive'
99
- dep.rec_dependencies.each do |d|
101
+ (dep.dependencies + dep.rec_dependencies).uniq.each do |d|
102
+ next if d.overriden
100
103
  d.clean unless config(:remove_dep, d.task_signature, d.task_name, d.workflow.to_s, :default => true).to_s == 'false'
101
104
  end
102
105
  dep.clean unless config(:remove_dep, dep.task_signature, dep.task_name, dep.workflow.to_s, :default => true).to_s == 'false'
103
- end
106
+ end unless dep.overriden
104
107
  else
105
108
  if Open.exists?(dep.files_dir)
106
109
  Open.rm_rf self.files_dir
@@ -0,0 +1,196 @@
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.dup : 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
+
87
+ dep.task_name = task_name
88
+ dep.overriden = dep.original_task_name.to_sym if dep.original_task_name
89
+
90
+ dep.extend step_module
91
+
92
+ dep
93
+ end
94
+
95
+ def real_dependencies(task, orig_jobname, inputs, dependencies)
96
+ real_dependencies = []
97
+ path_deps = {}
98
+
99
+ override_dependencies = override_dependencies(inputs)
100
+
101
+ dependencies.each do |dependency|
102
+ _inputs = IndiferentHash.setup(inputs.dup)
103
+ jobname = orig_jobname
104
+ jobname = _inputs[:jobname] if _inputs.include? :jobname
105
+
106
+ real_dep = case dependency
107
+ when Array
108
+ workflow, dep_task, options = dependency
109
+
110
+ if override_dependencies[workflow.to_s] && value = override_dependencies[workflow.to_s][dep_task]
111
+ setup_override_dependency(value, workflow, dep_task)
112
+ else
113
+
114
+ compute = options[:compute] if options
115
+
116
+ all_d = (real_dependencies + real_dependencies.flatten.collect{|d| d.rec_dependencies} ).flatten.compact.uniq
117
+
118
+ _inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
119
+ jobname = _inputs.delete :jobname if _inputs.include? :jobname
120
+
121
+ job = workflow._job(dep_task, jobname, _inputs)
122
+ ComputeDependency.setup(job, compute) if compute
123
+ job
124
+ end
125
+ when Step
126
+ dependency
127
+ when Symbol
128
+ if override_dependencies[self.to_s] && value = override_dependencies[self.to_s][dependency]
129
+ setup_override_dependency(value, self, dependency)
130
+ else
131
+ _job(dependency, jobname, _inputs)
132
+ end
133
+ when Proc
134
+ if DependencyBlock === dependency
135
+ orig_dep = dependency.dependency
136
+ wf, task_name, options = orig_dep
137
+
138
+ if override_dependencies[wf.to_s] && value = override_dependencies[wf.to_s][task_name]
139
+ dep = setup_override_dependency(value, wf, task_name)
140
+ else
141
+
142
+ options = {} if options.nil?
143
+ compute = options[:compute]
144
+
145
+ options = IndiferentHash.setup(options.dup)
146
+ dep = dependency.call jobname, _inputs.merge(options), real_dependencies
147
+
148
+ dep = [dep] unless Array === dep
149
+
150
+ new_=[]
151
+ dep.each{|d|
152
+ next if d.nil?
153
+ if Hash === d
154
+ d[:workflow] ||= wf
155
+ d[:task] ||= task_name
156
+ _override_dependencies = override_dependencies.merge(override_dependencies(d[:inputs] || {}))
157
+ d = if _override_dependencies[d[:workflow].to_s] && value = _override_dependencies[d[:workflow].to_s][d[:task]]
158
+ setup_override_dependency(value, d[:workflow], d[:task])
159
+ else
160
+ task_info = d[:workflow].task_info(d[:task])
161
+
162
+ _inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
163
+ d[:workflow]._job(d[:task], d[:jobname], _inputs)
164
+ end
165
+ end
166
+ ComputeDependency.setup(d, compute) if compute
167
+ new_ << d
168
+ }
169
+ dep = new_
170
+ end
171
+ else
172
+ _inputs = IndiferentHash.setup(_inputs.dup)
173
+ dep = dependency.call jobname, _inputs, real_dependencies
174
+ if Hash === dep
175
+ dep[:workflow] ||= wf || self
176
+ _override_dependencies = override_dependencies.merge(override_dependencies(dep[:inputs] || {}))
177
+ if _override_dependencies[dep[:workflow].to_s] && value = _override_dependencies[dep[:workflow].to_s][dep[:task]]
178
+ setup_override_dependency(value, dep[:workflow], dep[:task])
179
+ else
180
+ task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
181
+ _inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
182
+ dep = dep[:workflow]._job(dep[:task], dep[:jobname], _inputs)
183
+ end
184
+ end
185
+ end
186
+
187
+ dep
188
+ else
189
+ raise "Dependency for #{task.name} not understood: #{Misc.fingerprint dependency}"
190
+ end
191
+
192
+ real_dependencies << real_dep
193
+ end
194
+ real_dependencies.flatten.compact
195
+ end
196
+ 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,49 +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
- #connected = true means that dependency searching ends when a result is done
508
- #but dependencies are absent, meanining that the file could have been dropped
509
- #in
510
- def rec_dependencies(connected = false, seen = [])
511
-
512
- # A step result with no info_file means that it was manually
513
- # placed. In that case, do not consider its dependencies
514
- return [] if ! (defined? WorkflowRemoteClient && WorkflowRemoteClient::RemoteStep === self) && ! Open.exists?(self.info_file) && Open.exists?(self.path.to_s)
515
-
516
- return [] if dependencies.nil? or dependencies.empty?
517
-
518
- new_dependencies = []
519
- archived_deps = self.info[:archived_info] ? self.info[:archived_info].keys : []
520
-
521
- dependencies.each{|step|
522
- #next if self.done? && Open.exists?(info_file) && info[:dependencies] && info[:dependencies].select{|task,name,path| path == step.path }.empty?
523
- next if archived_deps.include? step.path
524
- next if seen.include? step.path
525
- next if self.done? && connected && ! updatable?
526
-
527
- r = step.rec_dependencies(connected, new_dependencies.collect{|d| d.path})
528
- new_dependencies.concat r
529
- new_dependencies << step
530
- }
531
- new_dependencies.uniq
532
- end
533
-
534
354
  def writable?
535
355
  Open.writable?(self.path) && Open.writable?(self.info_file)
536
356
  end