rbbt-util 5.44.1 → 6.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rbbt +67 -90
- data/etc/app.d/base.rb +2 -2
- data/etc/app.d/semaphores.rb +3 -3
- data/lib/rbbt/annotations/annotated_array.rb +207 -207
- data/lib/rbbt/annotations/refactor.rb +27 -0
- data/lib/rbbt/annotations/util.rb +282 -282
- data/lib/rbbt/annotations.rb +343 -320
- data/lib/rbbt/association/database.rb +200 -225
- data/lib/rbbt/association/index.rb +294 -291
- data/lib/rbbt/association/item.rb +227 -227
- data/lib/rbbt/association/open.rb +35 -34
- data/lib/rbbt/association/util.rb +0 -169
- data/lib/rbbt/association.rb +2 -4
- data/lib/rbbt/entity/identifiers.rb +119 -118
- data/lib/rbbt/entity/refactor.rb +12 -0
- data/lib/rbbt/entity.rb +319 -315
- data/lib/rbbt/hpc/batch.rb +72 -53
- data/lib/rbbt/hpc/lsf.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
- data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
- data/lib/rbbt/hpc/orchestrate.rb +19 -13
- data/lib/rbbt/hpc/slurm.rb +18 -18
- data/lib/rbbt/knowledge_base/entity.rb +13 -5
- data/lib/rbbt/knowledge_base/query.rb +2 -2
- data/lib/rbbt/knowledge_base/registry.rb +32 -31
- data/lib/rbbt/knowledge_base/traverse.rb +1 -1
- data/lib/rbbt/knowledge_base.rb +1 -1
- data/lib/rbbt/monitor.rb +36 -25
- data/lib/rbbt/persist/refactor.rb +166 -0
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
- data/lib/rbbt/persist/tsv.rb +187 -185
- data/lib/rbbt/persist.rb +556 -551
- data/lib/rbbt/refactor.rb +20 -0
- data/lib/rbbt/resource/path/refactor.rb +178 -0
- data/lib/rbbt/resource/path.rb +317 -497
- data/lib/rbbt/resource/util.rb +0 -48
- data/lib/rbbt/resource.rb +3 -390
- data/lib/rbbt/tsv/accessor.rb +2 -838
- data/lib/rbbt/tsv/attach.rb +303 -299
- data/lib/rbbt/tsv/change_id.rb +244 -245
- data/lib/rbbt/tsv/csv.rb +87 -85
- data/lib/rbbt/tsv/dumper.rb +2 -100
- data/lib/rbbt/tsv/excel.rb +26 -24
- data/lib/rbbt/tsv/field_index.rb +4 -1
- data/lib/rbbt/tsv/filter.rb +3 -2
- data/lib/rbbt/tsv/index.rb +2 -284
- data/lib/rbbt/tsv/manipulate.rb +750 -747
- data/lib/rbbt/tsv/marshal.rb +3 -3
- data/lib/rbbt/tsv/matrix.rb +2 -2
- data/lib/rbbt/tsv/parallel/through.rb +2 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
- data/lib/rbbt/tsv/parser.rb +678 -678
- data/lib/rbbt/tsv/refactor.rb +195 -0
- data/lib/rbbt/tsv/stream.rb +253 -251
- data/lib/rbbt/tsv/util.rb +420 -420
- data/lib/rbbt/tsv.rb +210 -208
- data/lib/rbbt/util/R/eval.rb +4 -4
- data/lib/rbbt/util/R/plot.rb +62 -166
- data/lib/rbbt/util/R.rb +21 -18
- data/lib/rbbt/util/cmd.rb +2 -318
- data/lib/rbbt/util/color.rb +269 -269
- data/lib/rbbt/util/colorize.rb +89 -89
- data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
- data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +389 -386
- data/lib/rbbt/util/config.rb +169 -167
- data/lib/rbbt/util/iruby.rb +20 -0
- data/lib/rbbt/util/log/progress/report.rb +241 -241
- data/lib/rbbt/util/log/progress/util.rb +99 -99
- data/lib/rbbt/util/log/progress.rb +102 -102
- data/lib/rbbt/util/log/refactor.rb +49 -0
- data/lib/rbbt/util/log.rb +486 -532
- data/lib/rbbt/util/migrate.rb +1 -1
- data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
- data/lib/rbbt/util/misc/development.rb +12 -11
- data/lib/rbbt/util/misc/exceptions.rb +117 -112
- data/lib/rbbt/util/misc/format.rb +2 -230
- data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
- data/lib/rbbt/util/misc/inspect.rb +2 -476
- data/lib/rbbt/util/misc/lock.rb +109 -106
- data/lib/rbbt/util/misc/omics.rb +9 -1
- data/lib/rbbt/util/misc/pipes.rb +765 -793
- data/lib/rbbt/util/misc/refactor.rb +20 -0
- data/lib/rbbt/util/misc/ssw.rb +27 -17
- data/lib/rbbt/util/misc/system.rb +0 -15
- data/lib/rbbt/util/misc.rb +39 -20
- data/lib/rbbt/util/named_array/refactor.rb +4 -0
- data/lib/rbbt/util/named_array.rb +3 -220
- data/lib/rbbt/util/open/refactor.rb +7 -0
- data/lib/rbbt/util/open.rb +3 -857
- data/lib/rbbt/util/procpath.rb +6 -6
- data/lib/rbbt/util/python/paths.rb +27 -0
- data/lib/rbbt/util/python/run.rb +115 -0
- data/lib/rbbt/util/python/script.rb +110 -0
- data/lib/rbbt/util/python/util.rb +3 -3
- data/lib/rbbt/util/python.rb +22 -81
- data/lib/rbbt/util/semaphore.rb +152 -148
- data/lib/rbbt/util/simpleopt.rb +9 -8
- data/lib/rbbt/util/ssh/refactor.rb +19 -0
- data/lib/rbbt/util/ssh.rb +122 -118
- data/lib/rbbt/util/tar.rb +117 -115
- data/lib/rbbt/util/tmpfile.rb +69 -67
- data/lib/rbbt/util/version.rb +2 -0
- data/lib/rbbt/workflow/refactor/entity.rb +11 -0
- data/lib/rbbt/workflow/refactor/export.rb +66 -0
- data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
- data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
- data/lib/rbbt/workflow/refactor/task_info.rb +65 -0
- data/lib/rbbt/workflow/refactor.rb +153 -0
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
- data/lib/rbbt/workflow/remote_workflow.rb +6 -1
- data/lib/rbbt/workflow/step/run.rb +766 -766
- data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
- data/lib/rbbt/workflow/step.rb +2 -362
- data/lib/rbbt/workflow/task.rb +118 -118
- data/lib/rbbt/workflow/usage.rb +289 -287
- data/lib/rbbt/workflow/util/archive.rb +6 -5
- data/lib/rbbt/workflow/util/data.rb +1 -1
- data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
- data/lib/rbbt/workflow/util/trace.rb +79 -44
- data/lib/rbbt/workflow.rb +4 -882
- data/lib/rbbt-util.rb +21 -13
- data/lib/rbbt.rb +16 -3
- data/python/rbbt/__init__.py +19 -1
- data/share/Rlib/plot.R +37 -37
- data/share/Rlib/svg.R +22 -5
- data/share/install/software/lib/install_helpers +1 -1
- data/share/rbbt_commands/hpc/list +2 -3
- data/share/rbbt_commands/hpc/orchestrate +4 -4
- data/share/rbbt_commands/hpc/tail +2 -0
- data/share/rbbt_commands/hpc/task +10 -7
- data/share/rbbt_commands/lsf/list +2 -3
- data/share/rbbt_commands/lsf/orchestrate +4 -4
- data/share/rbbt_commands/lsf/tail +2 -0
- data/share/rbbt_commands/lsf/task +10 -7
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/pbs/list +2 -3
- data/share/rbbt_commands/pbs/orchestrate +4 -4
- data/share/rbbt_commands/pbs/tail +2 -0
- data/share/rbbt_commands/pbs/task +10 -7
- data/share/rbbt_commands/resource/produce +8 -1
- data/share/rbbt_commands/slurm/list +2 -3
- data/share/rbbt_commands/slurm/orchestrate +4 -4
- data/share/rbbt_commands/slurm/tail +2 -0
- data/share/rbbt_commands/slurm/task +10 -7
- data/share/rbbt_commands/system/clean +5 -5
- data/share/rbbt_commands/system/status +5 -5
- data/share/rbbt_commands/tsv/get +2 -3
- data/share/rbbt_commands/tsv/info +10 -13
- data/share/rbbt_commands/tsv/keys +18 -14
- data/share/rbbt_commands/tsv/slice +2 -2
- data/share/rbbt_commands/tsv/transpose +6 -2
- data/share/rbbt_commands/workflow/info +20 -24
- data/share/rbbt_commands/workflow/list +1 -1
- data/share/rbbt_commands/workflow/prov +20 -13
- data/share/rbbt_commands/workflow/server +11 -1
- data/share/rbbt_commands/workflow/task +76 -71
- data/share/rbbt_commands/workflow/write_info +26 -9
- data/share/software/opt/ssw/ssw.c +861 -0
- data/share/software/opt/ssw/ssw.h +130 -0
- data/share/workflow_config.ru +3 -3
- metadata +40 -2
@@ -1,766 +1,766 @@
|
|
1
|
-
require 'rbbt/workflow/step/dependencies'
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
|
5
|
-
module StreamArray; end
|
6
|
-
|
7
|
-
class Step
|
8
|
-
|
9
|
-
attr_reader :stream, :dupped, :saved_stream
|
10
|
-
|
11
|
-
def get_stream
|
12
|
-
@mutex.synchronize do
|
13
|
-
Log.low "Getting stream from #{path} #{!@saved_stream} [#{object_id}-#{Misc.fingerprint(@result)}]"
|
14
|
-
begin
|
15
|
-
if IO === @result
|
16
|
-
return nil if @saved_stream
|
17
|
-
@saved_stream = @result
|
18
|
-
elsif StreamArray === @result and @result.any?
|
19
|
-
@saved_stream = @result.pop
|
20
|
-
else
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def resolve_input_steps
|
28
|
-
step = false
|
29
|
-
pos = 0
|
30
|
-
|
31
|
-
input_options = Workflow === workflow ? workflow.task_info(task_name)[:input_options] : {}
|
32
|
-
new_inputs = inputs.collect do |i|
|
33
|
-
begin
|
34
|
-
if Step === i
|
35
|
-
if i.error?
|
36
|
-
e = i.get_exception
|
37
|
-
if e
|
38
|
-
raise e
|
39
|
-
else
|
40
|
-
raise DependencyError, "Error in dep. #{Log.blue e.path}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
step = true
|
44
|
-
i.produce unless i.done? || i.error? || i.started?
|
45
|
-
if i.done?
|
46
|
-
if (task.input_options[task.inputs[pos]] || {})[:stream]
|
47
|
-
TSV.get_stream i
|
48
|
-
else
|
49
|
-
if (task.input_options[task.inputs[pos]] || {})[:nofile]
|
50
|
-
i.path
|
51
|
-
else
|
52
|
-
i.load
|
53
|
-
end
|
54
|
-
end
|
55
|
-
elsif i.streaming? and (task.input_options[task.inputs[pos]] || {})[:stream]
|
56
|
-
TSV.get_stream i
|
57
|
-
else
|
58
|
-
i.join
|
59
|
-
if (task.input_options[task.inputs[pos]] || {})[:stream]
|
60
|
-
TSV.get_stream i
|
61
|
-
else
|
62
|
-
if (task.input_options[task.inputs[pos]] || {})[:nofile]
|
63
|
-
i.path
|
64
|
-
else
|
65
|
-
i.load
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
else
|
70
|
-
i
|
71
|
-
end
|
72
|
-
ensure
|
73
|
-
pos += 1
|
74
|
-
end
|
75
|
-
end
|
76
|
-
@inputs.replace new_inputs if step
|
77
|
-
end
|
78
|
-
|
79
|
-
def rewind_inputs
|
80
|
-
return if @inputs.nil?
|
81
|
-
Log.debug "Rewinding inputs for #{path}"
|
82
|
-
@inputs.each do |input|
|
83
|
-
next unless input.respond_to? :rewind
|
84
|
-
begin
|
85
|
-
input.rewind
|
86
|
-
input.first_line = nil if TSV::Parser === input
|
87
|
-
Log.debug "Rewinded #{Misc.fingerprint input}"
|
88
|
-
rescue
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def _exec
|
94
|
-
resolve_input_steps
|
95
|
-
rewind_inputs
|
96
|
-
@exec = true if @exec.nil?
|
97
|
-
begin
|
98
|
-
old = Signal.trap("INT"){ Thread.current.raise Aborted }
|
99
|
-
if @task.respond_to?(:exec_in)
|
100
|
-
@task.exec_in((bindings || self), *@inputs)
|
101
|
-
elsif @task
|
102
|
-
(bindings || self).instance_exec *@inputs, &@task
|
103
|
-
else
|
104
|
-
raise DependencyError, "Dependency #{self.path} cannot be produced"
|
105
|
-
end
|
106
|
-
ensure
|
107
|
-
Signal.trap("INT", old)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def exec(no_load=false)
|
112
|
-
dependencies.each{|dependency| dependency.exec(no_load) }
|
113
|
-
@mutex.synchronize do
|
114
|
-
@result = self._exec
|
115
|
-
@result = @result.stream if TSV::Dumper === @result
|
116
|
-
end
|
117
|
-
(no_load || ENV["RBBT_NO_STREAM"]) ? @result : prepare_result(@result, @task.result_description)
|
118
|
-
end
|
119
|
-
|
120
|
-
def updatable?
|
121
|
-
return true if ENV["RBBT_UPDATE_ALL_JOBS"] == 'true'
|
122
|
-
return false unless ENV["RBBT_UPDATE"] == "true"
|
123
|
-
return false unless Open.exists?(info_file)
|
124
|
-
return true if status != :noinfo && ! (relocated? && done?)
|
125
|
-
false
|
126
|
-
end
|
127
|
-
|
128
|
-
def dependency_checks
|
129
|
-
return [] if ENV["RBBT_UPDATE"] != "true"
|
130
|
-
|
131
|
-
rec_dependencies(true).
|
132
|
-
reject{|dependency| (defined?(WorkflowRemoteClient) && WorkflowRemoteClient::RemoteStep === dependency) || Open.remote?(dependency.path) }.
|
133
|
-
reject{|dependency| dependency.error? }.
|
134
|
-
#select{|dependency| Open.exists?(dependency.path) || ((Open.exists?(dependency.info_file) && (dependency.status == :cleaned) || dependency.status == :waiting)) }.
|
135
|
-
#select{|dependency| dependency.updatable? }.
|
136
|
-
collect{|dependency| Workflow.relocate_dependency(self, dependency)}
|
137
|
-
end
|
138
|
-
|
139
|
-
def input_checks
|
140
|
-
(inputs.select{|i| Step === i } + inputs.select{|i| Path === i && Step === i.resource}.collect{|i| i.resource})
|
141
|
-
#select{|dependency| dependency.updatable? }
|
142
|
-
end
|
143
|
-
|
144
|
-
def checks
|
145
|
-
(dependency_checks + input_checks).uniq
|
146
|
-
end
|
147
|
-
|
148
|
-
def persist_checks
|
149
|
-
canfail_paths = self.canfail_paths
|
150
|
-
checks.collect do |dep|
|
151
|
-
path = dep.path
|
152
|
-
next if ! dep.done? && canfail_paths.include?(path)
|
153
|
-
path
|
154
|
-
end.compact
|
155
|
-
end
|
156
|
-
|
157
|
-
def out_of_date
|
158
|
-
|
159
|
-
checks = self.checks
|
160
|
-
return [] if checks.empty?
|
161
|
-
outdated_time = []
|
162
|
-
outdated_dep = []
|
163
|
-
canfail_paths = self.canfail_paths
|
164
|
-
this_mtime = Open.mtime(self.path) if Open.exists?(self.path)
|
165
|
-
|
166
|
-
#outdated_time = checks.select{|dep| dep.updatable? && dep.done? && Persist.newer?(path, dep.path) }
|
167
|
-
outdated_time = checks.select{|dep| dep.done? && Persist.newer?(path, dep.path) }
|
168
|
-
outdated_dep = checks.reject{|dep| dep.done? || (dep.error? && ! dep.recoverable_error? && canfail_paths.include?(dep.path)) }
|
169
|
-
|
170
|
-
#checks.each do |dep|
|
171
|
-
# next unless dep.updatable?
|
172
|
-
# dep_done = dep.done?
|
173
|
-
|
174
|
-
# begin
|
175
|
-
# if this_mtime && dep_done && Open.exists?(dep.path) && (Open.mtime(dep.path) > this_mtime + 1)
|
176
|
-
# outdated_time << dep
|
177
|
-
# end
|
178
|
-
# rescue
|
179
|
-
# end
|
180
|
-
|
181
|
-
# # Is this pointless? this would mean some dep got updated after a later
|
182
|
-
# # dep but but before this one.
|
183
|
-
# #if (! dep.done? && ! canfail_paths.include?(dep.path)) || ! dep.updated?
|
184
|
-
|
185
|
-
# if (! dep_done && ! canfail_paths.include?(dep.path))
|
186
|
-
# outdated_dep << dep
|
187
|
-
# end
|
188
|
-
#end
|
189
|
-
|
190
|
-
Log.medium "Some newer files found: #{Misc.fingerprint outdated_time}" if outdated_time.any?
|
191
|
-
Log.medium "Some outdated files found: #{Misc.fingerprint outdated_dep}" if outdated_dep.any?
|
192
|
-
|
193
|
-
outdated_time + outdated_dep
|
194
|
-
end
|
195
|
-
|
196
|
-
def updated?
|
197
|
-
return true if ENV["RBBT_UPDATE"] != "true"
|
198
|
-
return true unless (done? || error? || ! writable?)
|
199
|
-
|
200
|
-
@updated ||= out_of_date.empty?
|
201
|
-
end
|
202
|
-
|
203
|
-
def kill_children
|
204
|
-
begin
|
205
|
-
children_pids = info[:children_pids]
|
206
|
-
if children_pids and children_pids.any?
|
207
|
-
Log.medium("Killing children: #{ children_pids * ", " }")
|
208
|
-
children_pids.each do |pid|
|
209
|
-
Log.medium("Killing child #{ pid }")
|
210
|
-
begin
|
211
|
-
Process.kill "TERM", pid.to_i
|
212
|
-
rescue Exception
|
213
|
-
Log.medium("Exception killing child #{ pid }: #{$!.message}")
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
rescue
|
218
|
-
Log.medium("Exception finding children")
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def run(no_load = false)
|
223
|
-
result = nil
|
224
|
-
|
225
|
-
if Workflow === workflow && workflow.relay_tasks && workflow.relay_tasks.include?(task_name)
|
226
|
-
server, options = workflow.relay_tasks[task_name]
|
227
|
-
options[:migrate] = true
|
228
|
-
return RemoteWorkflow::SSH.relay_job(self, server, options)
|
229
|
-
end
|
230
|
-
|
231
|
-
begin
|
232
|
-
no_load = :stream if no_load
|
233
|
-
result_type = self.result_type || info[:result_type]
|
234
|
-
|
235
|
-
res = @mutex.synchronize do
|
236
|
-
time_elapsed = total_time_elapsed = nil
|
237
|
-
Open.write(pid_file, Process.pid.to_s) unless Open.exists?(path) or Open.exists?(pid_file)
|
238
|
-
|
239
|
-
result = Persist.persist "Job", result_type, :file => path, :check => persist_checks, :no_load => no_load do
|
240
|
-
|
241
|
-
if Step === Step.log_relay_step and not self == Step.log_relay_step
|
242
|
-
relay_log(Step.log_relay_step) unless self.respond_to? :relay_step and self.relay_step
|
243
|
-
end
|
244
|
-
|
245
|
-
Open.write(pid_file, Process.pid.to_s) unless Open.exists? pid_file
|
246
|
-
|
247
|
-
@exec = false
|
248
|
-
init_info(true)
|
249
|
-
|
250
|
-
#workflow = @workflow || @task.respond_to?(:workflow) ? @task.workflow : nil
|
251
|
-
result_type = @task.respond_to?(:result_type) ? @task.result_type : nil
|
252
|
-
result_description = @task.respond_to?(:result_description) ? @task.result_description : nil
|
253
|
-
|
254
|
-
log :setup, "#{Log.color :green, "Setup"} step #{Log.color :yellow, task_name}"
|
255
|
-
|
256
|
-
merge_info({
|
257
|
-
:issued => (issue_time = Time.now),
|
258
|
-
:name => name,
|
259
|
-
:pid => Process.pid.to_s,
|
260
|
-
:pid_hostname => Socket.gethostname,
|
261
|
-
:clean_name => clean_name,
|
262
|
-
:workflow => workflow.to_s,
|
263
|
-
:task_name => task_name,
|
264
|
-
:result_type => result_type,
|
265
|
-
:result_description => result_description,
|
266
|
-
:dependencies => dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]},
|
267
|
-
:versions => Rbbt.versions
|
268
|
-
})
|
269
|
-
|
270
|
-
new_inputs = []
|
271
|
-
@inputs.each_with_index do |input,i|
|
272
|
-
name = @task.respond_to?(:inputs) ? @task.inputs[i] : nil
|
273
|
-
type = @task.respond_to?(:input_types) ? @task.input_types[i] : nil
|
274
|
-
|
275
|
-
if type == :directory
|
276
|
-
directory_inputs = file('directory_inputs')
|
277
|
-
input_source = directory_inputs['.source'][name].find
|
278
|
-
input_dir = directory_inputs[name].find
|
279
|
-
|
280
|
-
case input
|
281
|
-
when Path
|
282
|
-
if input.directory?
|
283
|
-
new_inputs << input
|
284
|
-
else
|
285
|
-
input.open do |io|
|
286
|
-
begin
|
287
|
-
Misc.untar(io, input_source)
|
288
|
-
rescue
|
289
|
-
raise ParameterException, "Error unpackaging tar directory input '#{name}':\n\n#{$!.message}"
|
290
|
-
end
|
291
|
-
end
|
292
|
-
tar_1 = input_source.glob("*")
|
293
|
-
raise ParameterException, "When using tar.gz files for directories, the directory must be the single first level entry" if tar_1.length != 1
|
294
|
-
FileUtils.ln_s Misc.path_relative_to(directory_inputs, tar_1.first), input_dir
|
295
|
-
new_inputs << input_dir
|
296
|
-
end
|
297
|
-
when File, IO, Tempfile
|
298
|
-
begin
|
299
|
-
Misc.untar(Open.gunzip(input), input_source)
|
300
|
-
rescue
|
301
|
-
raise ParameterException, "Error unpackaging tar directory input '#{name}':\n\n#{$!.message}"
|
302
|
-
end
|
303
|
-
tar_1 = input_source.glob("*")
|
304
|
-
raise ParameterException, "When using tar.gz files for directories, the directory must be the single first level entry" if tar_1.length != 1
|
305
|
-
FileUtils.ln_s Misc.path_relative_to(directory_inputs, tar_1.first), input_dir
|
306
|
-
new_inputs << input_dir
|
307
|
-
else
|
308
|
-
raise ParameterException, "Format of directory input '#{name}' not understood: #{Misc.fingerprint input}"
|
309
|
-
end
|
310
|
-
else
|
311
|
-
new_inputs << input
|
312
|
-
end
|
313
|
-
end if @inputs
|
314
|
-
|
315
|
-
@inputs = new_inputs if @inputs
|
316
|
-
|
317
|
-
if @inputs && task.respond_to?(:inputs) && ! task.inputs.nil?
|
318
|
-
info_inputs = @inputs.collect do |i|
|
319
|
-
if Path === i
|
320
|
-
i.to_s
|
321
|
-
else
|
322
|
-
i
|
323
|
-
end
|
324
|
-
end
|
325
|
-
set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, info_inputs))
|
326
|
-
end
|
327
|
-
|
328
|
-
begin
|
329
|
-
run_dependencies
|
330
|
-
rescue Exception
|
331
|
-
Open.rm pid_file if Open.exists?(pid_file)
|
332
|
-
stop_dependencies
|
333
|
-
raise $!
|
334
|
-
end
|
335
|
-
|
336
|
-
set_info :started, (start_time = Time.now)
|
337
|
-
log :started, "Starting step #{Log.color :yellow, task_name}"
|
338
|
-
|
339
|
-
config_keys_pre = Rbbt::Config::GOT_KEYS.dup
|
340
|
-
begin
|
341
|
-
|
342
|
-
result = _exec
|
343
|
-
rescue Aborted, Interrupt
|
344
|
-
log(:aborted, "Aborted")
|
345
|
-
raise $!
|
346
|
-
rescue Exception
|
347
|
-
backtrace = $!.backtrace
|
348
|
-
|
349
|
-
# HACK: This fixes an strange behaviour in 1.9.3 where some
|
350
|
-
# backtrace strings are coded in ASCII-8BIT
|
351
|
-
backtrace = backtrace.collect{|l| l.dup.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
|
352
|
-
set_info :backtrace, backtrace
|
353
|
-
log(:error, "#{$!.class}: #{$!.message}")
|
354
|
-
stop_dependencies
|
355
|
-
raise $!
|
356
|
-
end
|
357
|
-
|
358
|
-
if not no_load or ENV["RBBT_NO_STREAM"] == "true"
|
359
|
-
result = prepare_result result, @task.description, info if IO === result
|
360
|
-
result = prepare_result result.stream, @task.description, info if TSV::Dumper === result
|
361
|
-
end
|
362
|
-
|
363
|
-
stream = case result
|
364
|
-
when IO
|
365
|
-
result
|
366
|
-
when TSV::Dumper
|
367
|
-
result.stream
|
368
|
-
end
|
369
|
-
|
370
|
-
if stream
|
371
|
-
log :streaming, "Streaming step #{Log.color :yellow, task_name.to_s || ""}"
|
372
|
-
|
373
|
-
callback = Proc.new do
|
374
|
-
if AbortedStream === stream
|
375
|
-
if stream.exception
|
376
|
-
raise stream.exception
|
377
|
-
else
|
378
|
-
raise Aborted
|
379
|
-
end
|
380
|
-
end
|
381
|
-
begin
|
382
|
-
status = self.status
|
383
|
-
if status != :done and status != :error and status != :aborted
|
384
|
-
Misc.insist do
|
385
|
-
merge_info({
|
386
|
-
:done => (done_time = Time.now),
|
387
|
-
:total_time_elapsed => (total_time_elapsed = done_time - issue_time),
|
388
|
-
:time_elapsed => (time_elapsed = done_time - start_time),
|
389
|
-
:versions => Rbbt.versions
|
390
|
-
})
|
391
|
-
log :done, "Completed step #{Log.color :yellow, task_name.to_s || ""} in #{time_elapsed.to_i}+#{(total_time_elapsed - time_elapsed).to_i} sec."
|
392
|
-
end
|
393
|
-
end
|
394
|
-
rescue
|
395
|
-
Log.exception $!
|
396
|
-
ensure
|
397
|
-
Step.purge_stream_cache
|
398
|
-
Open.rm pid_file if Open.exist?(pid_file)
|
399
|
-
end
|
400
|
-
end
|
401
|
-
|
402
|
-
abort_callback = Proc.new do |exception|
|
403
|
-
begin
|
404
|
-
if exception
|
405
|
-
self.exception exception
|
406
|
-
else
|
407
|
-
log :aborted, "#{Log.color :red, "Aborted"} step #{Log.color :yellow, task_name.to_s || ""}" if status == :streaming
|
408
|
-
end
|
409
|
-
_clean_finished
|
410
|
-
rescue
|
411
|
-
stop_dependencies
|
412
|
-
Open.rm pid_file if Open.exist?(pid_file)
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
ConcurrentStream.setup stream, :callback => callback, :abort_callback => abort_callback
|
417
|
-
|
418
|
-
if AbortedStream === stream
|
419
|
-
exception = stream.exception || Aborted.new("Aborted stream: #{Misc.fingerprint stream}")
|
420
|
-
self.exception exception
|
421
|
-
_clean_finished
|
422
|
-
raise exception
|
423
|
-
end
|
424
|
-
else
|
425
|
-
merge_info({
|
426
|
-
:done => (done_time = Time.now),
|
427
|
-
:total_time_elapsed => (total_time_elapsed = done_time - issue_time),
|
428
|
-
:time_elapsed => (time_elapsed = done_time - start_time),
|
429
|
-
:versions => Rbbt.versions
|
430
|
-
})
|
431
|
-
log :ending
|
432
|
-
Step.purge_stream_cache
|
433
|
-
end
|
434
|
-
|
435
|
-
set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]}
|
436
|
-
|
437
|
-
config_keys = Rbbt::Config::GOT_KEYS[config_keys_pre.length..-1]
|
438
|
-
set_info :config_keys, config_keys.uniq
|
439
|
-
|
440
|
-
if result.nil? && File.exist?(self.tmp_path) && ! File.exist?(self.path)
|
441
|
-
Open.mv self.tmp_path, self.path
|
442
|
-
end
|
443
|
-
Open.rm pid_file if Open.exist?(pid_file) unless stream
|
444
|
-
result
|
445
|
-
end # END PERSIST
|
446
|
-
log :done, "Completed step #{Log.color :yellow, task_name.to_s || ""} in #{time_elapsed.to_i}+#{(total_time_elapsed - time_elapsed).to_i} sec." unless stream or time_elapsed.nil?
|
447
|
-
|
448
|
-
if no_load
|
449
|
-
@result ||= result
|
450
|
-
self
|
451
|
-
else
|
452
|
-
Step.purge_stream_cache
|
453
|
-
@result = prepare_result result, result_description
|
454
|
-
end
|
455
|
-
end # END SYNC
|
456
|
-
res
|
457
|
-
rescue DependencyError, DependencyRbbtException
|
458
|
-
exception $!
|
459
|
-
rescue LockInterrupted
|
460
|
-
raise $!
|
461
|
-
rescue Aborted, Interrupt
|
462
|
-
abort
|
463
|
-
stop_dependencies
|
464
|
-
raise $!
|
465
|
-
rescue Exception
|
466
|
-
exception $!
|
467
|
-
stop_dependencies
|
468
|
-
raise $!
|
469
|
-
ensure
|
470
|
-
no_load = false unless IO === result
|
471
|
-
Open.rm pid_file if Open.exist?(pid_file) unless no_load
|
472
|
-
#set_info :pid, nil unless no_load
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
def produce(force=false, dofork=false)
|
477
|
-
return self if done? and not dirty?
|
478
|
-
|
479
|
-
self.status_lock.synchronize do
|
480
|
-
if error? || aborted? || stalled?
|
481
|
-
if stalled?
|
482
|
-
Log.warn "Aborting stalled job #{self.path}"
|
483
|
-
abort
|
484
|
-
end
|
485
|
-
if force or aborted? or recoverable_error?
|
486
|
-
clean
|
487
|
-
else
|
488
|
-
e = get_exception
|
489
|
-
if e
|
490
|
-
Log.error "Raising exception in produced job #{self.path}: #{e.message}"
|
491
|
-
raise e
|
492
|
-
else
|
493
|
-
raise "Error in job: #{self.path}"
|
494
|
-
end
|
495
|
-
end
|
496
|
-
end
|
497
|
-
end
|
498
|
-
|
499
|
-
update if done?
|
500
|
-
|
501
|
-
if dofork
|
502
|
-
fork(true) unless started?
|
503
|
-
|
504
|
-
join unless done? or dofork == :nowait
|
505
|
-
else
|
506
|
-
run(true) unless started?
|
507
|
-
|
508
|
-
join unless done?
|
509
|
-
end
|
510
|
-
|
511
|
-
self
|
512
|
-
end
|
513
|
-
|
514
|
-
def fork(no_load = false, semaphore = nil)
|
515
|
-
raise "Can not fork: Step is waiting for proces #{@pid} to finish" if not @pid.nil? and not Process.pid == @pid and Misc.pid_exists?(@pid) and not done? and info[:forked]
|
516
|
-
Log.debug "Fork to run #{self.path}"
|
517
|
-
sout, sin = Misc.pipe if no_load == :stream
|
518
|
-
@pid = Process.fork do
|
519
|
-
Signal.trap(:TERM) do
|
520
|
-
raise Aborted, "Recieved TERM Signal on forked process #{Process.pid}"
|
521
|
-
end
|
522
|
-
sout.close if sout
|
523
|
-
Misc.pre_fork
|
524
|
-
Open.mkdir File.dirname(path) unless Open.exist?(File.dirname(path))
|
525
|
-
Open.write(pid_file, Process.pid.to_s) unless Open.exists?(path) or Open.exists?(pid_file)
|
526
|
-
|
527
|
-
if semaphore
|
528
|
-
init_info
|
529
|
-
log :queue, "Queued over semaphore: #{semaphore}"
|
530
|
-
ret = RbbtSemaphore.wait_semaphore(semaphore)
|
531
|
-
raise SemaphoreInterrupted if ret == -1
|
532
|
-
end
|
533
|
-
|
534
|
-
begin
|
535
|
-
begin
|
536
|
-
@forked = true
|
537
|
-
res = run no_load
|
538
|
-
set_info :forked, true
|
539
|
-
if sin
|
540
|
-
io = TSV.get_stream res
|
541
|
-
if io.respond_to? :setup
|
542
|
-
io.setup(sin)
|
543
|
-
sin.pair = io
|
544
|
-
io.pair = sin
|
545
|
-
end
|
546
|
-
begin
|
547
|
-
Misc.consume_stream(io, false, sin)
|
548
|
-
rescue
|
549
|
-
Log.warn "Could not consume stream (#{io.closed? ? 'closed' : 'open'}) into pipe for forked job: #{self.path}"
|
550
|
-
Misc.consume_stream(io) unless io.closed?
|
551
|
-
end
|
552
|
-
end
|
553
|
-
rescue Aborted, Interrupt
|
554
|
-
Log.debug{"Forked process aborted: #{path}"}
|
555
|
-
log :aborted, "Job aborted (#{Process.pid})"
|
556
|
-
raise $!
|
557
|
-
rescue Exception
|
558
|
-
Log.debug("Exception '#{$!.message}' caught on forked process: #{path}")
|
559
|
-
raise $!
|
560
|
-
ensure
|
561
|
-
join_stream
|
562
|
-
end
|
563
|
-
|
564
|
-
begin
|
565
|
-
children_pids = info[:children_pids]
|
566
|
-
if children_pids
|
567
|
-
children_pids.each do |pid|
|
568
|
-
if Misc.pid_exists? pid
|
569
|
-
begin
|
570
|
-
Process.waitpid pid
|
571
|
-
rescue Errno::ECHILD
|
572
|
-
Log.low "Waiting on #{ pid } failed: #{$!.message}"
|
573
|
-
end
|
574
|
-
end
|
575
|
-
end
|
576
|
-
set_info :children_done, Time.now
|
577
|
-
end
|
578
|
-
rescue Exception
|
579
|
-
Log.debug("Exception waiting for children: #{$!.message}")
|
580
|
-
RbbtSemaphore.post_semaphore(semaphore) if semaphore
|
581
|
-
Kernel.exit! -1
|
582
|
-
end
|
583
|
-
#set_info :pid, nil
|
584
|
-
ensure
|
585
|
-
RbbtSemaphore.post_semaphore(semaphore) if semaphore
|
586
|
-
end
|
587
|
-
end
|
588
|
-
sin.close if sin
|
589
|
-
@result = sout if sout
|
590
|
-
Process.detach(@pid)
|
591
|
-
self
|
592
|
-
end
|
593
|
-
|
594
|
-
def abort_pid
|
595
|
-
@pid ||= info[:pid] || Open.read(pid_file)
|
596
|
-
|
597
|
-
case @pid
|
598
|
-
when nil
|
599
|
-
Log.medium "Could not abort #{path}: no pid"
|
600
|
-
false
|
601
|
-
when Process.pid
|
602
|
-
Log.medium "Could not abort #{path}: same process"
|
603
|
-
false
|
604
|
-
else
|
605
|
-
Log.medium "Aborting pid #{path}: #{ @pid } #{Process.pid}"
|
606
|
-
begin
|
607
|
-
Process.kill("TERM", @pid.to_i)
|
608
|
-
s = Process.waitpid2 @pid.to_i
|
609
|
-
Log.medium "Aborted pid #{path} #{s}"
|
610
|
-
rescue Exception
|
611
|
-
Log.debug("Aborted job #{@pid} was not killed: #{$!.message}")
|
612
|
-
end
|
613
|
-
true
|
614
|
-
end
|
615
|
-
end
|
616
|
-
|
617
|
-
def abort_stream
|
618
|
-
stream = @result if IO === @result
|
619
|
-
@saved_stream = nil
|
620
|
-
if stream and stream.respond_to? :abort and not stream.aborted?
|
621
|
-
doretry = true
|
622
|
-
begin
|
623
|
-
Log.medium "Aborting job stream #{stream.inspect} -- #{Log.color :blue, path}"
|
624
|
-
stream.abort
|
625
|
-
rescue Aborted, Interrupt
|
626
|
-
Log.medium "Aborting job stream #{stream.inspect} ABORTED RETRY -- #{Log.color :blue, path}"
|
627
|
-
if doretry
|
628
|
-
doretry = false
|
629
|
-
retry
|
630
|
-
end
|
631
|
-
end
|
632
|
-
end
|
633
|
-
end
|
634
|
-
|
635
|
-
def _clean_finished
|
636
|
-
if Open.exists?(path) && status != :done
|
637
|
-
Log.warn "Aborted job had finished. Removing result -- #{ path }"
|
638
|
-
begin
|
639
|
-
Open.rm path
|
640
|
-
rescue Exception
|
641
|
-
Log.warn "Exception removing result of aborted job: #{$!.message}"
|
642
|
-
end
|
643
|
-
end
|
644
|
-
|
645
|
-
if Open.exists?(tmp_path) && status != :done
|
646
|
-
Log.warn "Aborted job had finished. Removing tmp result -- #{ tmp_path }"
|
647
|
-
begin
|
648
|
-
Open.rm tmp_path
|
649
|
-
rescue Exception
|
650
|
-
Log.warn "Exception removing tmp result of aborted job: #{$!.message}"
|
651
|
-
end
|
652
|
-
end
|
653
|
-
end
|
654
|
-
|
655
|
-
def _abort
|
656
|
-
return if @aborted
|
657
|
-
@aborted = true
|
658
|
-
Log.medium{"#{Log.color :red, "Aborting"} #{Log.color :blue, path}"}
|
659
|
-
doretry = true
|
660
|
-
begin
|
661
|
-
return if done?
|
662
|
-
abort_pid if running?
|
663
|
-
kill_children
|
664
|
-
abort_stream
|
665
|
-
stop_dependencies
|
666
|
-
rescue Aborted, Interrupt
|
667
|
-
Log.medium{"#{Log.color :red, "Aborting ABORTED RETRY"} #{Log.color :blue, path}"}
|
668
|
-
if doretry
|
669
|
-
doretry = false
|
670
|
-
retry
|
671
|
-
end
|
672
|
-
raise $!
|
673
|
-
rescue Exception
|
674
|
-
if doretry
|
675
|
-
doretry = false
|
676
|
-
retry
|
677
|
-
end
|
678
|
-
ensure
|
679
|
-
_clean_finished
|
680
|
-
end
|
681
|
-
end
|
682
|
-
|
683
|
-
def abort
|
684
|
-
return if done? and (status == :done or status == :noinfo)
|
685
|
-
_abort
|
686
|
-
log(:aborted, "Job aborted") unless aborted? or error?
|
687
|
-
self
|
688
|
-
end
|
689
|
-
|
690
|
-
def join_stream
|
691
|
-
stream = get_stream if @result
|
692
|
-
@result = nil
|
693
|
-
if stream
|
694
|
-
begin
|
695
|
-
Misc.consume_stream stream
|
696
|
-
stream.join if stream.respond_to? :join
|
697
|
-
rescue Exception
|
698
|
-
stream.abort $!
|
699
|
-
self._abort
|
700
|
-
end
|
701
|
-
end
|
702
|
-
end
|
703
|
-
|
704
|
-
def soft_grace
|
705
|
-
until done? or (Open.exist?(info_file) && info[:status] != :noinfo)
|
706
|
-
sleep 1
|
707
|
-
end
|
708
|
-
self
|
709
|
-
end
|
710
|
-
|
711
|
-
def grace
|
712
|
-
until done? || result || error? || aborted? || streaming? || waiting? || running?
|
713
|
-
sleep 1
|
714
|
-
end
|
715
|
-
self
|
716
|
-
end
|
717
|
-
|
718
|
-
def join
|
719
|
-
|
720
|
-
grace if Open.exists?(info_file)
|
721
|
-
|
722
|
-
if streaming?
|
723
|
-
join_stream
|
724
|
-
end
|
725
|
-
|
726
|
-
return self if not Open.exists? info_file
|
727
|
-
|
728
|
-
return self if info[:joined]
|
729
|
-
|
730
|
-
pid = @pid
|
731
|
-
|
732
|
-
Misc.insist [0.1, 0.2, 0.5, 1] do
|
733
|
-
pid ||= info[:pid]
|
734
|
-
end
|
735
|
-
|
736
|
-
begin
|
737
|
-
|
738
|
-
if pid.nil? or Process.pid == pid
|
739
|
-
dependencies.each{|dep| dep.join }
|
740
|
-
else
|
741
|
-
begin
|
742
|
-
pid = pid.to_i if String === pid
|
743
|
-
Log.debug{"Waiting for pid: #{pid}"}
|
744
|
-
Process.waitpid pid
|
745
|
-
rescue Errno::ECHILD
|
746
|
-
Log.debug{"Process #{ pid } already finished: #{ path }"}
|
747
|
-
end if Misc.pid_exists? pid
|
748
|
-
pid = nil
|
749
|
-
dependencies.each{|dep| dep.join }
|
750
|
-
end
|
751
|
-
|
752
|
-
until (Open.exists?(path) && (status == :done || status == :noinfo)) or error? or aborted? or waiting?
|
753
|
-
sleep 1
|
754
|
-
join_stream if streaming?
|
755
|
-
end
|
756
|
-
|
757
|
-
self
|
758
|
-
ensure
|
759
|
-
begin
|
760
|
-
set_info :joined, true
|
761
|
-
rescue
|
762
|
-
end if Open.exists?(info_file) && writable?
|
763
|
-
@result = nil
|
764
|
-
end
|
765
|
-
end
|
766
|
-
end
|
1
|
+
#require 'rbbt/workflow/step/dependencies'
|
2
|
+
#require 'socket'
|
3
|
+
#
|
4
|
+
#
|
5
|
+
#module StreamArray; end
|
6
|
+
#
|
7
|
+
#class Step
|
8
|
+
#
|
9
|
+
# attr_reader :stream, :dupped, :saved_stream
|
10
|
+
#
|
11
|
+
# def get_stream
|
12
|
+
# @mutex.synchronize do
|
13
|
+
# Log.low "Getting stream from #{path} #{!@saved_stream} [#{object_id}-#{Misc.fingerprint(@result)}]"
|
14
|
+
# begin
|
15
|
+
# if IO === @result
|
16
|
+
# return nil if @saved_stream
|
17
|
+
# @saved_stream = @result
|
18
|
+
# elsif StreamArray === @result and @result.any?
|
19
|
+
# @saved_stream = @result.pop
|
20
|
+
# else
|
21
|
+
# nil
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# def resolve_input_steps
|
28
|
+
# step = false
|
29
|
+
# pos = 0
|
30
|
+
#
|
31
|
+
# input_options = Workflow === workflow ? workflow.task_info(task_name)[:input_options] : {}
|
32
|
+
# new_inputs = inputs.collect do |i|
|
33
|
+
# begin
|
34
|
+
# if Step === i
|
35
|
+
# if i.error?
|
36
|
+
# e = i.get_exception
|
37
|
+
# if e
|
38
|
+
# raise e
|
39
|
+
# else
|
40
|
+
# raise DependencyError, "Error in dep. #{Log.blue e.path}"
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# step = true
|
44
|
+
# i.produce unless i.done? || i.error? || i.started?
|
45
|
+
# if i.done?
|
46
|
+
# if (task.input_options[task.inputs[pos]] || {})[:stream]
|
47
|
+
# TSV.get_stream i
|
48
|
+
# else
|
49
|
+
# if (task.input_options[task.inputs[pos]] || {})[:nofile]
|
50
|
+
# i.path
|
51
|
+
# else
|
52
|
+
# i.load
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
# elsif i.streaming? and (task.input_options[task.inputs[pos]] || {})[:stream]
|
56
|
+
# TSV.get_stream i
|
57
|
+
# else
|
58
|
+
# i.join
|
59
|
+
# if (task.input_options[task.inputs[pos]] || {})[:stream]
|
60
|
+
# TSV.get_stream i
|
61
|
+
# else
|
62
|
+
# if (task.input_options[task.inputs[pos]] || {})[:nofile]
|
63
|
+
# i.path
|
64
|
+
# else
|
65
|
+
# i.load
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
# else
|
70
|
+
# i
|
71
|
+
# end
|
72
|
+
# ensure
|
73
|
+
# pos += 1
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
# @inputs.replace new_inputs if step
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# def rewind_inputs
|
80
|
+
# return if @inputs.nil?
|
81
|
+
# Log.debug "Rewinding inputs for #{path}"
|
82
|
+
# @inputs.each do |input|
|
83
|
+
# next unless input.respond_to? :rewind
|
84
|
+
# begin
|
85
|
+
# input.rewind
|
86
|
+
# input.first_line = nil if TSV::Parser === input
|
87
|
+
# Log.debug "Rewinded #{Misc.fingerprint input}"
|
88
|
+
# rescue
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# def _exec
|
94
|
+
# resolve_input_steps
|
95
|
+
# rewind_inputs
|
96
|
+
# @exec = true if @exec.nil?
|
97
|
+
# begin
|
98
|
+
# old = Signal.trap("INT"){ Thread.current.raise Aborted }
|
99
|
+
# if @task.respond_to?(:exec_in)
|
100
|
+
# @task.exec_in((bindings || self), *@inputs)
|
101
|
+
# elsif @task
|
102
|
+
# (bindings || self).instance_exec *@inputs, &@task
|
103
|
+
# else
|
104
|
+
# raise DependencyError, "Dependency #{self.path} cannot be produced"
|
105
|
+
# end
|
106
|
+
# ensure
|
107
|
+
# Signal.trap("INT", old)
|
108
|
+
# end
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# def exec(no_load=false)
|
112
|
+
# dependencies.each{|dependency| dependency.exec(no_load) }
|
113
|
+
# @mutex.synchronize do
|
114
|
+
# @result = self._exec
|
115
|
+
# @result = @result.stream if TSV::Dumper === @result
|
116
|
+
# end
|
117
|
+
# (no_load || ENV["RBBT_NO_STREAM"]) ? @result : prepare_result(@result, @task.result_description)
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# def updatable?
|
121
|
+
# return true if ENV["RBBT_UPDATE_ALL_JOBS"] == 'true'
|
122
|
+
# return false unless ENV["RBBT_UPDATE"] == "true"
|
123
|
+
# return false unless Open.exists?(info_file)
|
124
|
+
# return true if status != :noinfo && ! (relocated? && done?)
|
125
|
+
# false
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
# def dependency_checks
|
129
|
+
# return [] if ENV["RBBT_UPDATE"] != "true"
|
130
|
+
#
|
131
|
+
# rec_dependencies(true).
|
132
|
+
# reject{|dependency| (defined?(WorkflowRemoteClient) && WorkflowRemoteClient::RemoteStep === dependency) || Open.remote?(dependency.path) }.
|
133
|
+
# reject{|dependency| dependency.error? }.
|
134
|
+
# #select{|dependency| Open.exists?(dependency.path) || ((Open.exists?(dependency.info_file) && (dependency.status == :cleaned) || dependency.status == :waiting)) }.
|
135
|
+
# #select{|dependency| dependency.updatable? }.
|
136
|
+
# collect{|dependency| Workflow.relocate_dependency(self, dependency)}
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# def input_checks
|
140
|
+
# (inputs.select{|i| Step === i } + inputs.select{|i| Path === i && Step === i.resource}.collect{|i| i.resource})
|
141
|
+
# #select{|dependency| dependency.updatable? }
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# def checks
|
145
|
+
# (dependency_checks + input_checks).uniq
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# def persist_checks
|
149
|
+
# canfail_paths = self.canfail_paths
|
150
|
+
# checks.collect do |dep|
|
151
|
+
# path = dep.path
|
152
|
+
# next if ! dep.done? && canfail_paths.include?(path)
|
153
|
+
# path
|
154
|
+
# end.compact
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
# def out_of_date
|
158
|
+
#
|
159
|
+
# checks = self.checks
|
160
|
+
# return [] if checks.empty?
|
161
|
+
# outdated_time = []
|
162
|
+
# outdated_dep = []
|
163
|
+
# canfail_paths = self.canfail_paths
|
164
|
+
# this_mtime = Open.mtime(self.path) if Open.exists?(self.path)
|
165
|
+
#
|
166
|
+
# #outdated_time = checks.select{|dep| dep.updatable? && dep.done? && Persist.newer?(path, dep.path) }
|
167
|
+
# outdated_time = checks.select{|dep| dep.done? && Persist.newer?(path, dep.path) }
|
168
|
+
# outdated_dep = checks.reject{|dep| dep.done? || (dep.error? && ! dep.recoverable_error? && canfail_paths.include?(dep.path)) }
|
169
|
+
#
|
170
|
+
# #checks.each do |dep|
|
171
|
+
# # next unless dep.updatable?
|
172
|
+
# # dep_done = dep.done?
|
173
|
+
#
|
174
|
+
# # begin
|
175
|
+
# # if this_mtime && dep_done && Open.exists?(dep.path) && (Open.mtime(dep.path) > this_mtime + 1)
|
176
|
+
# # outdated_time << dep
|
177
|
+
# # end
|
178
|
+
# # rescue
|
179
|
+
# # end
|
180
|
+
#
|
181
|
+
# # # Is this pointless? this would mean some dep got updated after a later
|
182
|
+
# # # dep but but before this one.
|
183
|
+
# # #if (! dep.done? && ! canfail_paths.include?(dep.path)) || ! dep.updated?
|
184
|
+
#
|
185
|
+
# # if (! dep_done && ! canfail_paths.include?(dep.path))
|
186
|
+
# # outdated_dep << dep
|
187
|
+
# # end
|
188
|
+
# #end
|
189
|
+
#
|
190
|
+
# Log.medium "Some newer files found: #{Misc.fingerprint outdated_time}" if outdated_time.any?
|
191
|
+
# Log.medium "Some outdated files found: #{Misc.fingerprint outdated_dep}" if outdated_dep.any?
|
192
|
+
#
|
193
|
+
# outdated_time + outdated_dep
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# def updated?
|
197
|
+
# return true if ENV["RBBT_UPDATE"] != "true"
|
198
|
+
# return true unless (done? || error? || ! writable?)
|
199
|
+
#
|
200
|
+
# @updated ||= out_of_date.empty?
|
201
|
+
# end
|
202
|
+
#
|
203
|
+
# def kill_children
|
204
|
+
# begin
|
205
|
+
# children_pids = info[:children_pids]
|
206
|
+
# if children_pids and children_pids.any?
|
207
|
+
# Log.medium("Killing children: #{ children_pids * ", " }")
|
208
|
+
# children_pids.each do |pid|
|
209
|
+
# Log.medium("Killing child #{ pid }")
|
210
|
+
# begin
|
211
|
+
# Process.kill "TERM", pid.to_i
|
212
|
+
# rescue Exception
|
213
|
+
# Log.medium("Exception killing child #{ pid }: #{$!.message}")
|
214
|
+
# end
|
215
|
+
# end
|
216
|
+
# end
|
217
|
+
# rescue
|
218
|
+
# Log.medium("Exception finding children")
|
219
|
+
# end
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# def run(no_load = false)
|
223
|
+
# result = nil
|
224
|
+
#
|
225
|
+
# if Workflow === workflow && workflow.relay_tasks && workflow.relay_tasks.include?(task_name)
|
226
|
+
# server, options = workflow.relay_tasks[task_name]
|
227
|
+
# options[:migrate] = true
|
228
|
+
# return RemoteWorkflow::SSH.relay_job(self, server, options)
|
229
|
+
# end
|
230
|
+
#
|
231
|
+
# begin
|
232
|
+
# no_load = :stream if no_load
|
233
|
+
# result_type = self.result_type || info[:result_type]
|
234
|
+
#
|
235
|
+
# res = @mutex.synchronize do
|
236
|
+
# time_elapsed = total_time_elapsed = nil
|
237
|
+
# Open.write(pid_file, Process.pid.to_s) unless Open.exists?(path) or Open.exists?(pid_file)
|
238
|
+
#
|
239
|
+
# result = Persist.persist "Job", result_type, :file => path, :check => persist_checks, :no_load => no_load do
|
240
|
+
#
|
241
|
+
# if Step === Step.log_relay_step and not self == Step.log_relay_step
|
242
|
+
# relay_log(Step.log_relay_step) unless self.respond_to? :relay_step and self.relay_step
|
243
|
+
# end
|
244
|
+
#
|
245
|
+
# Open.write(pid_file, Process.pid.to_s) unless Open.exists? pid_file
|
246
|
+
#
|
247
|
+
# @exec = false
|
248
|
+
# init_info(true)
|
249
|
+
#
|
250
|
+
# #workflow = @workflow || @task.respond_to?(:workflow) ? @task.workflow : nil
|
251
|
+
# result_type = @task.respond_to?(:result_type) ? @task.result_type : nil
|
252
|
+
# result_description = @task.respond_to?(:result_description) ? @task.result_description : nil
|
253
|
+
#
|
254
|
+
# log :setup, "#{Log.color :green, "Setup"} step #{Log.color :yellow, task_name}"
|
255
|
+
#
|
256
|
+
# merge_info({
|
257
|
+
# :issued => (issue_time = Time.now),
|
258
|
+
# :name => name,
|
259
|
+
# :pid => Process.pid.to_s,
|
260
|
+
# :pid_hostname => Socket.gethostname,
|
261
|
+
# :clean_name => clean_name,
|
262
|
+
# :workflow => workflow.to_s,
|
263
|
+
# :task_name => task_name,
|
264
|
+
# :result_type => result_type,
|
265
|
+
# :result_description => result_description,
|
266
|
+
# :dependencies => dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]},
|
267
|
+
# :versions => Rbbt.versions
|
268
|
+
# })
|
269
|
+
#
|
270
|
+
# new_inputs = []
|
271
|
+
# @inputs.each_with_index do |input,i|
|
272
|
+
# name = @task.respond_to?(:inputs) ? @task.inputs[i] : nil
|
273
|
+
# type = @task.respond_to?(:input_types) ? @task.input_types[i] : nil
|
274
|
+
#
|
275
|
+
# if type == :directory
|
276
|
+
# directory_inputs = file('directory_inputs')
|
277
|
+
# input_source = directory_inputs['.source'][name].find
|
278
|
+
# input_dir = directory_inputs[name].find
|
279
|
+
#
|
280
|
+
# case input
|
281
|
+
# when Path
|
282
|
+
# if input.directory?
|
283
|
+
# new_inputs << input
|
284
|
+
# else
|
285
|
+
# input.open do |io|
|
286
|
+
# begin
|
287
|
+
# Misc.untar(io, input_source)
|
288
|
+
# rescue
|
289
|
+
# raise ParameterException, "Error unpackaging tar directory input '#{name}':\n\n#{$!.message}"
|
290
|
+
# end
|
291
|
+
# end
|
292
|
+
# tar_1 = input_source.glob("*")
|
293
|
+
# raise ParameterException, "When using tar.gz files for directories, the directory must be the single first level entry" if tar_1.length != 1
|
294
|
+
# FileUtils.ln_s Misc.path_relative_to(directory_inputs, tar_1.first), input_dir
|
295
|
+
# new_inputs << input_dir
|
296
|
+
# end
|
297
|
+
# when File, IO, Tempfile
|
298
|
+
# begin
|
299
|
+
# Misc.untar(Open.gunzip(input), input_source)
|
300
|
+
# rescue
|
301
|
+
# raise ParameterException, "Error unpackaging tar directory input '#{name}':\n\n#{$!.message}"
|
302
|
+
# end
|
303
|
+
# tar_1 = input_source.glob("*")
|
304
|
+
# raise ParameterException, "When using tar.gz files for directories, the directory must be the single first level entry" if tar_1.length != 1
|
305
|
+
# FileUtils.ln_s Misc.path_relative_to(directory_inputs, tar_1.first), input_dir
|
306
|
+
# new_inputs << input_dir
|
307
|
+
# else
|
308
|
+
# raise ParameterException, "Format of directory input '#{name}' not understood: #{Misc.fingerprint input}"
|
309
|
+
# end
|
310
|
+
# else
|
311
|
+
# new_inputs << input
|
312
|
+
# end
|
313
|
+
# end if @inputs
|
314
|
+
#
|
315
|
+
# @inputs = new_inputs if @inputs
|
316
|
+
#
|
317
|
+
# if @inputs && task.respond_to?(:inputs) && ! task.inputs.nil?
|
318
|
+
# info_inputs = @inputs.collect do |i|
|
319
|
+
# if Path === i
|
320
|
+
# i.to_s
|
321
|
+
# else
|
322
|
+
# i
|
323
|
+
# end
|
324
|
+
# end
|
325
|
+
# set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, info_inputs))
|
326
|
+
# end
|
327
|
+
#
|
328
|
+
# begin
|
329
|
+
# run_dependencies
|
330
|
+
# rescue Exception
|
331
|
+
# Open.rm pid_file if Open.exists?(pid_file)
|
332
|
+
# stop_dependencies
|
333
|
+
# raise $!
|
334
|
+
# end
|
335
|
+
#
|
336
|
+
# set_info :started, (start_time = Time.now)
|
337
|
+
# log :started, "Starting step #{Log.color :yellow, task_name}"
|
338
|
+
#
|
339
|
+
# config_keys_pre = Rbbt::Config::GOT_KEYS.dup
|
340
|
+
# begin
|
341
|
+
#
|
342
|
+
# result = _exec
|
343
|
+
# rescue Aborted, Interrupt
|
344
|
+
# log(:aborted, "Aborted")
|
345
|
+
# raise $!
|
346
|
+
# rescue Exception
|
347
|
+
# backtrace = $!.backtrace
|
348
|
+
#
|
349
|
+
# # HACK: This fixes an strange behaviour in 1.9.3 where some
|
350
|
+
# # backtrace strings are coded in ASCII-8BIT
|
351
|
+
# backtrace = backtrace.collect{|l| l.dup.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
|
352
|
+
# set_info :backtrace, backtrace
|
353
|
+
# log(:error, "#{$!.class}: #{$!.message}")
|
354
|
+
# stop_dependencies
|
355
|
+
# raise $!
|
356
|
+
# end
|
357
|
+
#
|
358
|
+
# if not no_load or ENV["RBBT_NO_STREAM"] == "true"
|
359
|
+
# result = prepare_result result, @task.description, info if IO === result
|
360
|
+
# result = prepare_result result.stream, @task.description, info if TSV::Dumper === result
|
361
|
+
# end
|
362
|
+
#
|
363
|
+
# stream = case result
|
364
|
+
# when IO
|
365
|
+
# result
|
366
|
+
# when TSV::Dumper
|
367
|
+
# result.stream
|
368
|
+
# end
|
369
|
+
#
|
370
|
+
# if stream
|
371
|
+
# log :streaming, "Streaming step #{Log.color :yellow, task_name.to_s || ""}"
|
372
|
+
#
|
373
|
+
# callback = Proc.new do
|
374
|
+
# if AbortedStream === stream
|
375
|
+
# if stream.exception
|
376
|
+
# raise stream.exception
|
377
|
+
# else
|
378
|
+
# raise Aborted
|
379
|
+
# end
|
380
|
+
# end
|
381
|
+
# begin
|
382
|
+
# status = self.status
|
383
|
+
# if status != :done and status != :error and status != :aborted
|
384
|
+
# Misc.insist do
|
385
|
+
# merge_info({
|
386
|
+
# :done => (done_time = Time.now),
|
387
|
+
# :total_time_elapsed => (total_time_elapsed = done_time - issue_time),
|
388
|
+
# :time_elapsed => (time_elapsed = done_time - start_time),
|
389
|
+
# :versions => Rbbt.versions
|
390
|
+
# })
|
391
|
+
# log :done, "Completed step #{Log.color :yellow, task_name.to_s || ""} in #{time_elapsed.to_i}+#{(total_time_elapsed - time_elapsed).to_i} sec."
|
392
|
+
# end
|
393
|
+
# end
|
394
|
+
# rescue
|
395
|
+
# Log.exception $!
|
396
|
+
# ensure
|
397
|
+
# Step.purge_stream_cache
|
398
|
+
# Open.rm pid_file if Open.exist?(pid_file)
|
399
|
+
# end
|
400
|
+
# end
|
401
|
+
#
|
402
|
+
# abort_callback = Proc.new do |exception|
|
403
|
+
# begin
|
404
|
+
# if exception
|
405
|
+
# self.exception exception
|
406
|
+
# else
|
407
|
+
# log :aborted, "#{Log.color :red, "Aborted"} step #{Log.color :yellow, task_name.to_s || ""}" if status == :streaming
|
408
|
+
# end
|
409
|
+
# _clean_finished
|
410
|
+
# rescue
|
411
|
+
# stop_dependencies
|
412
|
+
# Open.rm pid_file if Open.exist?(pid_file)
|
413
|
+
# end
|
414
|
+
# end
|
415
|
+
#
|
416
|
+
# ConcurrentStream.setup stream, :callback => callback, :abort_callback => abort_callback
|
417
|
+
#
|
418
|
+
# if AbortedStream === stream
|
419
|
+
# exception = stream.exception || Aborted.new("Aborted stream: #{Misc.fingerprint stream}")
|
420
|
+
# self.exception exception
|
421
|
+
# _clean_finished
|
422
|
+
# raise exception
|
423
|
+
# end
|
424
|
+
# else
|
425
|
+
# merge_info({
|
426
|
+
# :done => (done_time = Time.now),
|
427
|
+
# :total_time_elapsed => (total_time_elapsed = done_time - issue_time),
|
428
|
+
# :time_elapsed => (time_elapsed = done_time - start_time),
|
429
|
+
# :versions => Rbbt.versions
|
430
|
+
# })
|
431
|
+
# log :ending
|
432
|
+
# Step.purge_stream_cache
|
433
|
+
# end
|
434
|
+
#
|
435
|
+
# set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]}
|
436
|
+
#
|
437
|
+
# config_keys = Rbbt::Config::GOT_KEYS[config_keys_pre.length..-1]
|
438
|
+
# set_info :config_keys, config_keys.uniq
|
439
|
+
#
|
440
|
+
# if result.nil? && File.exist?(self.tmp_path) && ! File.exist?(self.path)
|
441
|
+
# Open.mv self.tmp_path, self.path
|
442
|
+
# end
|
443
|
+
# Open.rm pid_file if Open.exist?(pid_file) unless stream
|
444
|
+
# result
|
445
|
+
# end # END PERSIST
|
446
|
+
# log :done, "Completed step #{Log.color :yellow, task_name.to_s || ""} in #{time_elapsed.to_i}+#{(total_time_elapsed - time_elapsed).to_i} sec." unless stream or time_elapsed.nil?
|
447
|
+
#
|
448
|
+
# if no_load
|
449
|
+
# @result ||= result
|
450
|
+
# self
|
451
|
+
# else
|
452
|
+
# Step.purge_stream_cache
|
453
|
+
# @result = prepare_result result, result_description
|
454
|
+
# end
|
455
|
+
# end # END SYNC
|
456
|
+
# res
|
457
|
+
# rescue DependencyError, DependencyRbbtException
|
458
|
+
# exception $!
|
459
|
+
# rescue LockInterrupted
|
460
|
+
# raise $!
|
461
|
+
# rescue Aborted, Interrupt
|
462
|
+
# abort
|
463
|
+
# stop_dependencies
|
464
|
+
# raise $!
|
465
|
+
# rescue Exception
|
466
|
+
# exception $!
|
467
|
+
# stop_dependencies
|
468
|
+
# raise $!
|
469
|
+
# ensure
|
470
|
+
# no_load = false unless IO === result
|
471
|
+
# Open.rm pid_file if Open.exist?(pid_file) unless no_load
|
472
|
+
# #set_info :pid, nil unless no_load
|
473
|
+
# end
|
474
|
+
# end
|
475
|
+
#
|
476
|
+
# def produce(force=false, dofork=false)
|
477
|
+
# return self if done? and not dirty?
|
478
|
+
#
|
479
|
+
# self.status_lock.synchronize do
|
480
|
+
# if error? || aborted? || stalled?
|
481
|
+
# if stalled?
|
482
|
+
# Log.warn "Aborting stalled job #{self.path}"
|
483
|
+
# abort
|
484
|
+
# end
|
485
|
+
# if force or aborted? or recoverable_error?
|
486
|
+
# clean
|
487
|
+
# else
|
488
|
+
# e = get_exception
|
489
|
+
# if e
|
490
|
+
# Log.error "Raising exception in produced job #{self.path}: #{e.message}"
|
491
|
+
# raise e
|
492
|
+
# else
|
493
|
+
# raise "Error in job: #{self.path}"
|
494
|
+
# end
|
495
|
+
# end
|
496
|
+
# end
|
497
|
+
# end
|
498
|
+
#
|
499
|
+
# update if done?
|
500
|
+
#
|
501
|
+
# if dofork
|
502
|
+
# fork(true) unless started?
|
503
|
+
#
|
504
|
+
# join unless done? or dofork == :nowait
|
505
|
+
# else
|
506
|
+
# run(true) unless started?
|
507
|
+
#
|
508
|
+
# join unless done?
|
509
|
+
# end
|
510
|
+
#
|
511
|
+
# self
|
512
|
+
# end
|
513
|
+
#
|
514
|
+
# def fork(no_load = false, semaphore = nil)
|
515
|
+
# raise "Can not fork: Step is waiting for proces #{@pid} to finish" if not @pid.nil? and not Process.pid == @pid and Misc.pid_exists?(@pid) and not done? and info[:forked]
|
516
|
+
# Log.debug "Fork to run #{self.path}"
|
517
|
+
# sout, sin = Misc.pipe if no_load == :stream
|
518
|
+
# @pid = Process.fork do
|
519
|
+
# Signal.trap(:TERM) do
|
520
|
+
# raise Aborted, "Recieved TERM Signal on forked process #{Process.pid}"
|
521
|
+
# end
|
522
|
+
# sout.close if sout
|
523
|
+
# Misc.pre_fork
|
524
|
+
# Open.mkdir File.dirname(path) unless Open.exist?(File.dirname(path))
|
525
|
+
# Open.write(pid_file, Process.pid.to_s) unless Open.exists?(path) or Open.exists?(pid_file)
|
526
|
+
#
|
527
|
+
# if semaphore
|
528
|
+
# init_info
|
529
|
+
# log :queue, "Queued over semaphore: #{semaphore}"
|
530
|
+
# ret = RbbtSemaphore.wait_semaphore(semaphore)
|
531
|
+
# raise SemaphoreInterrupted if ret == -1
|
532
|
+
# end
|
533
|
+
#
|
534
|
+
# begin
|
535
|
+
# begin
|
536
|
+
# @forked = true
|
537
|
+
# res = run no_load
|
538
|
+
# set_info :forked, true
|
539
|
+
# if sin
|
540
|
+
# io = TSV.get_stream res
|
541
|
+
# if io.respond_to? :setup
|
542
|
+
# io.setup(sin)
|
543
|
+
# sin.pair = io
|
544
|
+
# io.pair = sin
|
545
|
+
# end
|
546
|
+
# begin
|
547
|
+
# Misc.consume_stream(io, false, sin)
|
548
|
+
# rescue
|
549
|
+
# Log.warn "Could not consume stream (#{io.closed? ? 'closed' : 'open'}) into pipe for forked job: #{self.path}"
|
550
|
+
# Misc.consume_stream(io) unless io.closed?
|
551
|
+
# end
|
552
|
+
# end
|
553
|
+
# rescue Aborted, Interrupt
|
554
|
+
# Log.debug{"Forked process aborted: #{path}"}
|
555
|
+
# log :aborted, "Job aborted (#{Process.pid})"
|
556
|
+
# raise $!
|
557
|
+
# rescue Exception
|
558
|
+
# Log.debug("Exception '#{$!.message}' caught on forked process: #{path}")
|
559
|
+
# raise $!
|
560
|
+
# ensure
|
561
|
+
# join_stream
|
562
|
+
# end
|
563
|
+
#
|
564
|
+
# begin
|
565
|
+
# children_pids = info[:children_pids]
|
566
|
+
# if children_pids
|
567
|
+
# children_pids.each do |pid|
|
568
|
+
# if Misc.pid_exists? pid
|
569
|
+
# begin
|
570
|
+
# Process.waitpid pid
|
571
|
+
# rescue Errno::ECHILD
|
572
|
+
# Log.low "Waiting on #{ pid } failed: #{$!.message}"
|
573
|
+
# end
|
574
|
+
# end
|
575
|
+
# end
|
576
|
+
# set_info :children_done, Time.now
|
577
|
+
# end
|
578
|
+
# rescue Exception
|
579
|
+
# Log.debug("Exception waiting for children: #{$!.message}")
|
580
|
+
# RbbtSemaphore.post_semaphore(semaphore) if semaphore
|
581
|
+
# Kernel.exit! -1
|
582
|
+
# end
|
583
|
+
# #set_info :pid, nil
|
584
|
+
# ensure
|
585
|
+
# RbbtSemaphore.post_semaphore(semaphore) if semaphore
|
586
|
+
# end
|
587
|
+
# end
|
588
|
+
# sin.close if sin
|
589
|
+
# @result = sout if sout
|
590
|
+
# Process.detach(@pid)
|
591
|
+
# self
|
592
|
+
# end
|
593
|
+
#
|
594
|
+
# def abort_pid
|
595
|
+
# @pid ||= info[:pid] || Open.read(pid_file)
|
596
|
+
#
|
597
|
+
# case @pid
|
598
|
+
# when nil
|
599
|
+
# Log.medium "Could not abort #{path}: no pid"
|
600
|
+
# false
|
601
|
+
# when Process.pid
|
602
|
+
# Log.medium "Could not abort #{path}: same process"
|
603
|
+
# false
|
604
|
+
# else
|
605
|
+
# Log.medium "Aborting pid #{path}: #{ @pid } #{Process.pid}"
|
606
|
+
# begin
|
607
|
+
# Process.kill("TERM", @pid.to_i)
|
608
|
+
# s = Process.waitpid2 @pid.to_i
|
609
|
+
# Log.medium "Aborted pid #{path} #{s}"
|
610
|
+
# rescue Exception
|
611
|
+
# Log.debug("Aborted job #{@pid} was not killed: #{$!.message}")
|
612
|
+
# end
|
613
|
+
# true
|
614
|
+
# end
|
615
|
+
# end
|
616
|
+
#
|
617
|
+
# def abort_stream
|
618
|
+
# stream = @result if IO === @result
|
619
|
+
# @saved_stream = nil
|
620
|
+
# if stream and stream.respond_to? :abort and not stream.aborted?
|
621
|
+
# doretry = true
|
622
|
+
# begin
|
623
|
+
# Log.medium "Aborting job stream #{stream.inspect} -- #{Log.color :blue, path}"
|
624
|
+
# stream.abort
|
625
|
+
# rescue Aborted, Interrupt
|
626
|
+
# Log.medium "Aborting job stream #{stream.inspect} ABORTED RETRY -- #{Log.color :blue, path}"
|
627
|
+
# if doretry
|
628
|
+
# doretry = false
|
629
|
+
# retry
|
630
|
+
# end
|
631
|
+
# end
|
632
|
+
# end
|
633
|
+
# end
|
634
|
+
#
|
635
|
+
# def _clean_finished
|
636
|
+
# if Open.exists?(path) && status != :done
|
637
|
+
# Log.warn "Aborted job had finished. Removing result -- #{ path }"
|
638
|
+
# begin
|
639
|
+
# Open.rm path
|
640
|
+
# rescue Exception
|
641
|
+
# Log.warn "Exception removing result of aborted job: #{$!.message}"
|
642
|
+
# end
|
643
|
+
# end
|
644
|
+
#
|
645
|
+
# if Open.exists?(tmp_path) && status != :done
|
646
|
+
# Log.warn "Aborted job had finished. Removing tmp result -- #{ tmp_path }"
|
647
|
+
# begin
|
648
|
+
# Open.rm tmp_path
|
649
|
+
# rescue Exception
|
650
|
+
# Log.warn "Exception removing tmp result of aborted job: #{$!.message}"
|
651
|
+
# end
|
652
|
+
# end
|
653
|
+
# end
|
654
|
+
#
|
655
|
+
# def _abort
|
656
|
+
# return if @aborted
|
657
|
+
# @aborted = true
|
658
|
+
# Log.medium{"#{Log.color :red, "Aborting"} #{Log.color :blue, path}"}
|
659
|
+
# doretry = true
|
660
|
+
# begin
|
661
|
+
# return if done?
|
662
|
+
# abort_pid if running?
|
663
|
+
# kill_children
|
664
|
+
# abort_stream
|
665
|
+
# stop_dependencies
|
666
|
+
# rescue Aborted, Interrupt
|
667
|
+
# Log.medium{"#{Log.color :red, "Aborting ABORTED RETRY"} #{Log.color :blue, path}"}
|
668
|
+
# if doretry
|
669
|
+
# doretry = false
|
670
|
+
# retry
|
671
|
+
# end
|
672
|
+
# raise $!
|
673
|
+
# rescue Exception
|
674
|
+
# if doretry
|
675
|
+
# doretry = false
|
676
|
+
# retry
|
677
|
+
# end
|
678
|
+
# ensure
|
679
|
+
# _clean_finished
|
680
|
+
# end
|
681
|
+
# end
|
682
|
+
#
|
683
|
+
# def abort
|
684
|
+
# return if done? and (status == :done or status == :noinfo)
|
685
|
+
# _abort
|
686
|
+
# log(:aborted, "Job aborted") unless aborted? or error?
|
687
|
+
# self
|
688
|
+
# end
|
689
|
+
#
|
690
|
+
# def join_stream
|
691
|
+
# stream = get_stream if @result
|
692
|
+
# @result = nil
|
693
|
+
# if stream
|
694
|
+
# begin
|
695
|
+
# Misc.consume_stream stream
|
696
|
+
# stream.join if stream.respond_to? :join
|
697
|
+
# rescue Exception
|
698
|
+
# stream.abort $!
|
699
|
+
# self._abort
|
700
|
+
# end
|
701
|
+
# end
|
702
|
+
# end
|
703
|
+
#
|
704
|
+
# def soft_grace
|
705
|
+
# until done? or (Open.exist?(info_file) && info[:status] != :noinfo)
|
706
|
+
# sleep 1
|
707
|
+
# end
|
708
|
+
# self
|
709
|
+
# end
|
710
|
+
#
|
711
|
+
# def grace
|
712
|
+
# until done? || result || error? || aborted? || streaming? || waiting? || running?
|
713
|
+
# sleep 1
|
714
|
+
# end
|
715
|
+
# self
|
716
|
+
# end
|
717
|
+
#
|
718
|
+
# def join
|
719
|
+
#
|
720
|
+
# grace if Open.exists?(info_file)
|
721
|
+
#
|
722
|
+
# if streaming?
|
723
|
+
# join_stream
|
724
|
+
# end
|
725
|
+
#
|
726
|
+
# return self if not Open.exists? info_file
|
727
|
+
#
|
728
|
+
# return self if info[:joined]
|
729
|
+
#
|
730
|
+
# pid = @pid
|
731
|
+
#
|
732
|
+
# Misc.insist [0.1, 0.2, 0.5, 1] do
|
733
|
+
# pid ||= info[:pid]
|
734
|
+
# end
|
735
|
+
#
|
736
|
+
# begin
|
737
|
+
#
|
738
|
+
# if pid.nil? or Process.pid == pid
|
739
|
+
# dependencies.each{|dep| dep.join }
|
740
|
+
# else
|
741
|
+
# begin
|
742
|
+
# pid = pid.to_i if String === pid
|
743
|
+
# Log.debug{"Waiting for pid: #{pid}"}
|
744
|
+
# Process.waitpid pid
|
745
|
+
# rescue Errno::ECHILD
|
746
|
+
# Log.debug{"Process #{ pid } already finished: #{ path }"}
|
747
|
+
# end if Misc.pid_exists? pid
|
748
|
+
# pid = nil
|
749
|
+
# dependencies.each{|dep| dep.join }
|
750
|
+
# end
|
751
|
+
#
|
752
|
+
# until (Open.exists?(path) && (status == :done || status == :noinfo)) or error? or aborted? or waiting?
|
753
|
+
# sleep 1
|
754
|
+
# join_stream if streaming?
|
755
|
+
# end
|
756
|
+
#
|
757
|
+
# self
|
758
|
+
# ensure
|
759
|
+
# begin
|
760
|
+
# set_info :joined, true
|
761
|
+
# rescue
|
762
|
+
# end if Open.exists?(info_file) && writable?
|
763
|
+
# @result = nil
|
764
|
+
# end
|
765
|
+
# end
|
766
|
+
#end
|