rbbt-util 5.32.16 → 5.32.21

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.
@@ -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