rbbt-util 5.10.2 → 5.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/persist.rb +60 -20
- data/lib/rbbt/tsv/dumper.rb +1 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +83 -65
- data/lib/rbbt/tsv/parser.rb +23 -8
- data/lib/rbbt/util/concurrency/processes.rb +23 -10
- data/lib/rbbt/util/concurrency/processes/worker.rb +3 -1
- data/lib/rbbt/util/log.rb +5 -10
- data/lib/rbbt/util/misc.rb +85 -52
- data/lib/rbbt/workflow.rb +2 -1
- data/lib/rbbt/workflow/step.rb +79 -29
- data/share/rbbt_commands/benchmark/throughput +5 -4
- data/share/rbbt_commands/tsv/slice +13 -4
- data/share/rbbt_commands/workflow/task +13 -7
- data/test/rbbt/test_persist.rb +21 -4
- data/test/rbbt/tsv/parallel/test_traverse.rb +9 -0
- data/test/rbbt/util/concurrency/processes/test_socket.rb +3 -1
- data/test/rbbt/util/concurrency/test_processes.rb +29 -0
- data/test/rbbt/util/test_misc.rb +6 -6
- data/test/rbbt/workflow/test_step.rb +1 -1
- metadata +2 -2
@@ -28,9 +28,11 @@ class RbbtProcessQueue
|
|
28
28
|
|
29
29
|
rescue ClosedStream
|
30
30
|
rescue Aborted
|
31
|
-
Log.
|
31
|
+
Log.error "Worker #{Process.pid} aborted"
|
32
|
+
Kernel.exit! -1
|
32
33
|
rescue Exception
|
33
34
|
@callback_queue.push($!) if @callback_queue
|
35
|
+
Kernel.exit! -1
|
34
36
|
ensure
|
35
37
|
@callback_queue.close_write if @callback_queue
|
36
38
|
end
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -72,6 +72,7 @@ module Log
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
LOG_MUTEX = Mutex.new
|
75
76
|
def self.log(message = nil, severity = MEDIUM, &block)
|
76
77
|
return if severity < self.severity
|
77
78
|
message ||= block.call if block_given?
|
@@ -85,8 +86,10 @@ module Log
|
|
85
86
|
message = "" << highlight << message << color(0) if severity >= INFO
|
86
87
|
str = prefix << " " << message
|
87
88
|
|
88
|
-
|
89
|
-
|
89
|
+
LOG_MUTEX.synchronize do
|
90
|
+
STDERR.puts str
|
91
|
+
logfile.puts str unless logfile.nil?
|
92
|
+
end
|
90
93
|
end
|
91
94
|
|
92
95
|
def self.debug(message = nil, &block)
|
@@ -194,14 +197,6 @@ def iii(message, file = $stdout)
|
|
194
197
|
Log.info{""}
|
195
198
|
end
|
196
199
|
|
197
|
-
def www(message, file = $stdout)
|
198
|
-
stack = caller
|
199
|
-
Log.warn{"#{Log.color :cyan, "INFO:"} " << stack.first}
|
200
|
-
Log.warn{""}
|
201
|
-
Log.warn{"=> " << message.inspect}
|
202
|
-
Log.warn{""}
|
203
|
-
end
|
204
|
-
|
205
200
|
def eee(message, file = $stdout)
|
206
201
|
stack = caller
|
207
202
|
Log.error{"#{Log.color :cyan, "INFO:"} " << stack.first}
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -21,6 +21,12 @@ class FieldNotFoundError < Exception;end
|
|
21
21
|
class Aborted < Exception; end
|
22
22
|
class TryAgain < Exception; end
|
23
23
|
class ClosedStream < Exception; end
|
24
|
+
class KeepLocked < Exception
|
25
|
+
attr_accessor :payload
|
26
|
+
def initialize(payload)
|
27
|
+
@payload = payload
|
28
|
+
end
|
29
|
+
end
|
24
30
|
|
25
31
|
module LaterString
|
26
32
|
def to_s
|
@@ -31,27 +37,35 @@ end
|
|
31
37
|
module ConcurrentStream
|
32
38
|
attr_accessor :threads, :pids, :callback, :filename
|
33
39
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
40
|
+
def join
|
41
|
+
|
42
|
+
if @threads and @threads.any?
|
43
|
+
@threads.each do |t|
|
44
|
+
t.join
|
45
|
+
end
|
46
|
+
@threads = []
|
47
|
+
end
|
48
|
+
|
49
|
+
if @pids and @pids.any?
|
50
|
+
@pids.each do |pid|
|
51
|
+
begin
|
52
|
+
Process.waitpid(pid, Process::WUNTRACED)
|
53
|
+
raise "Error joining process #{pid} in #{self.inspect}" unless $?.success?
|
54
|
+
rescue Errno::ECHILD
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@pids = []
|
38
58
|
end
|
39
|
-
end
|
40
59
|
|
41
|
-
def join
|
42
|
-
filename = self.respond_to?(:filename)? self.filename : :none
|
43
60
|
if @callback
|
44
61
|
@callback.call
|
62
|
+
@callback = nil
|
45
63
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
raise "Error joining process #{pid} in #{self.inspect}" unless $?.success?
|
52
|
-
rescue Errno::ECHILD
|
53
|
-
end
|
54
|
-
end if @pids
|
64
|
+
end
|
65
|
+
|
66
|
+
def abort
|
67
|
+
@threads.each{|t| t.raise Aborted.new } if @threads
|
68
|
+
@pids.each{|pid| Process.kill :INT, pid } if @pids
|
55
69
|
end
|
56
70
|
|
57
71
|
def self.setup(stream, options = {}, &block)
|
@@ -116,9 +130,11 @@ module Misc
|
|
116
130
|
end
|
117
131
|
end
|
118
132
|
|
119
|
-
def self.open_pipe(do_fork = false,
|
133
|
+
def self.open_pipe(do_fork = false, close = true)
|
120
134
|
raise "No block given" unless block_given?
|
135
|
+
|
121
136
|
sout, sin = Misc.pipe
|
137
|
+
|
122
138
|
if do_fork
|
123
139
|
parent_pid = Process.pid
|
124
140
|
pid = Process.fork {
|
@@ -131,22 +147,23 @@ module Misc
|
|
131
147
|
Process.kill :INT, parent_pid
|
132
148
|
Kernel.exit! -1
|
133
149
|
ensure
|
134
|
-
|
150
|
+
sin.close unless sin.closed?
|
135
151
|
end
|
136
152
|
Kernel.exit! 0
|
137
153
|
}
|
138
|
-
|
154
|
+
sin.close if close
|
155
|
+
ConcurrentStream.setup sout, :pids => [pid]
|
139
156
|
else
|
140
157
|
thread = Thread.new(Thread.current) do |parent|
|
141
158
|
begin
|
142
159
|
yield sin
|
143
160
|
rescue
|
144
|
-
Log.exception $!
|
145
161
|
parent.raise $!
|
146
162
|
ensure
|
147
|
-
|
163
|
+
sin.close if close
|
148
164
|
end
|
149
165
|
end
|
166
|
+
ConcurrentStream.setup sout, :threads => [thread]
|
150
167
|
end
|
151
168
|
sout
|
152
169
|
end
|
@@ -161,20 +178,24 @@ module Misc
|
|
161
178
|
stream_out2.close
|
162
179
|
begin
|
163
180
|
filename = stream.respond_to?(:filename)? stream.filename : nil
|
181
|
+
skip1 = skip2 = false
|
164
182
|
while block = stream.read(2048)
|
165
|
-
begin stream_in1.write block; rescue Exception; Log.exception
|
166
|
-
begin stream_in2.write block; rescue Exception; Log.exception
|
183
|
+
begin stream_in1.write block; rescue Exception; Log.exception $!; skip1 = true end unless skip1
|
184
|
+
begin stream_in2.write block; rescue Exception; Log.exception $!; skip2 = true end unless skip2
|
167
185
|
end
|
186
|
+
raise "Error writing in stream_in2" if skip2
|
187
|
+
raise "Error writing in stream_in2" if skip2
|
188
|
+
rescue Aborted
|
189
|
+
stream.abort if stream.respond_to? :abort
|
190
|
+
raise $!
|
168
191
|
rescue IOError
|
169
192
|
Log.exception $!
|
170
193
|
rescue Exception
|
171
194
|
Log.exception $!
|
172
195
|
ensure
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
Misc.release_pipes(stream_in1)
|
177
|
-
Misc.release_pipes(stream_in2)
|
196
|
+
stream_in1.close
|
197
|
+
stream_in2.close
|
198
|
+
stream.join if stream.respond_to? :join
|
178
199
|
end
|
179
200
|
end
|
180
201
|
stream.close
|
@@ -195,21 +216,23 @@ module Misc
|
|
195
216
|
splitter_thread = Thread.new(Thread.current, stream_in1, stream_in2) do |parent,stream_in1,stream_in2|
|
196
217
|
begin
|
197
218
|
filename = stream.respond_to?(:filename)? stream.filename : nil
|
219
|
+
skip1 = skip2 = false
|
198
220
|
while block = stream.read(2048)
|
199
|
-
begin stream_in1.write block; rescue Exception;
|
200
|
-
begin stream_in2.write block; rescue Exception;
|
221
|
+
begin stream_in1.write block; rescue Exception; Aborted === $! ? raise($!): Log.exception($!); skip1 = true end unless skip1
|
222
|
+
begin stream_in2.write block; rescue Exception; Aborted === $! ? raise($!): Log.exception($!); skip2 = true end unless skip2
|
201
223
|
end
|
224
|
+
rescue Aborted
|
225
|
+
stream.abort if stream.respond_to? :abort
|
226
|
+
raise $!
|
202
227
|
rescue IOError
|
203
228
|
Log.exception $!
|
204
229
|
rescue Exception
|
205
230
|
Log.exception $!
|
206
231
|
parent.raise $!
|
207
232
|
ensure
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
Misc.release_pipes(stream_in1)
|
212
|
-
Misc.release_pipes(stream_in2)
|
233
|
+
stream_in1.close
|
234
|
+
stream_in2.close
|
235
|
+
stream.join if stream.respond_to? :join
|
213
236
|
end
|
214
237
|
end
|
215
238
|
|
@@ -220,7 +243,7 @@ module Misc
|
|
220
243
|
end
|
221
244
|
|
222
245
|
class << self
|
223
|
-
alias tee_stream
|
246
|
+
alias tee_stream tee_stream_thread
|
224
247
|
end
|
225
248
|
|
226
249
|
def self.format_paragraph(text, size = 80, indent = 0, offset = 0)
|
@@ -494,6 +517,8 @@ module Misc
|
|
494
517
|
case obj
|
495
518
|
when nil
|
496
519
|
"nil"
|
520
|
+
when (defined? Step and Step)
|
521
|
+
obj.path || Misc.fingerprint([obj.task.name, obj.inputs])
|
497
522
|
when TrueClass
|
498
523
|
"true"
|
499
524
|
when FalseClass
|
@@ -1276,8 +1301,8 @@ end
|
|
1276
1301
|
@hostanem ||= `hostname`.strip
|
1277
1302
|
end
|
1278
1303
|
|
1279
|
-
def self.lock(file,
|
1280
|
-
return yield
|
1304
|
+
def self.lock(file, unlock = true)
|
1305
|
+
return yield if file.nil?
|
1281
1306
|
FileUtils.mkdir_p File.dirname(File.expand_path(file)) unless File.exists? File.dirname(File.expand_path(file))
|
1282
1307
|
|
1283
1308
|
res = nil
|
@@ -1287,27 +1312,34 @@ end
|
|
1287
1312
|
|
1288
1313
|
begin
|
1289
1314
|
Misc.insist 3 do
|
1290
|
-
if File.exists?
|
1291
|
-
Misc.hostname == (info = Open.open(
|
1315
|
+
if File.exists? lock_path and
|
1316
|
+
Misc.hostname == (info = Open.open(lock_path){|f| YAML.load(f) })["host"] and
|
1292
1317
|
info["pid"] and not Misc.pid_exists?(info["pid"])
|
1293
1318
|
|
1294
|
-
Log.info("Removing lockfile: #{
|
1295
|
-
FileUtils.rm
|
1319
|
+
Log.info("Removing lockfile: #{lock_path}. This pid #{Process.pid}. Content: #{info.inspect}")
|
1320
|
+
FileUtils.rm lock_path
|
1296
1321
|
end
|
1297
1322
|
end
|
1298
1323
|
rescue
|
1299
|
-
Log.warn("Error checking lockfile #{
|
1300
|
-
FileUtils.rm
|
1324
|
+
Log.warn("Error checking lockfile #{lock_path}: #{$!.message}. Removing. Content: #{begin Open.read(lock_path) rescue "Could not open file" end}")
|
1325
|
+
FileUtils.rm lock_path if File.exists?(lock_path)
|
1301
1326
|
lockfile = Lockfile.new(lock_path)
|
1302
1327
|
retry
|
1303
1328
|
end
|
1304
1329
|
|
1305
1330
|
begin
|
1306
|
-
lockfile.lock
|
1307
|
-
|
1331
|
+
lockfile.lock
|
1332
|
+
res = yield lockfile
|
1333
|
+
rescue Lockfile::StolenLockError
|
1334
|
+
unlock = false
|
1335
|
+
rescue KeepLocked
|
1336
|
+
unlock = false
|
1337
|
+
res = $!.payload
|
1338
|
+
ensure
|
1339
|
+
if unlock and lockfile.locked?
|
1340
|
+
lockfile.unlock
|
1341
|
+
FileUtils.rm lock_path if File.exists? lock_path
|
1308
1342
|
end
|
1309
|
-
rescue Interrupt
|
1310
|
-
raise $!
|
1311
1343
|
end
|
1312
1344
|
|
1313
1345
|
res
|
@@ -1315,7 +1347,6 @@ end
|
|
1315
1347
|
|
1316
1348
|
|
1317
1349
|
LOCK_REPO_SERIALIZER=Marshal
|
1318
|
-
|
1319
1350
|
def self.lock_in_repo(repo, key, *args)
|
1320
1351
|
return yield file, *args if repo.nil? or key.nil?
|
1321
1352
|
|
@@ -1402,17 +1433,17 @@ end
|
|
1402
1433
|
|
1403
1434
|
def self.sensiblewrite(path, content = nil, &block)
|
1404
1435
|
return if File.exists? path
|
1405
|
-
|
1436
|
+
tmp_path = path + '.sensible_write'
|
1437
|
+
Misc.lock tmp_path do
|
1406
1438
|
if not File.exists? path
|
1439
|
+
FileUtils.rm_f tmp_path if File.exists? tmp_path
|
1407
1440
|
begin
|
1408
|
-
tmp_path = path + '.sensible_write'
|
1409
1441
|
case
|
1410
1442
|
when block_given?
|
1411
1443
|
File.open(tmp_path, 'w', &block)
|
1412
1444
|
when String === content
|
1413
1445
|
File.open(tmp_path, 'w') do |f| f.write content end
|
1414
1446
|
when (IO === content or StringIO === content or File === content)
|
1415
|
-
#Thread.pass while IO.select([content], nil, nil, 1) if IO === content
|
1416
1447
|
File.open(tmp_path, 'w') do |f|
|
1417
1448
|
while block = content.read(2048);
|
1418
1449
|
f.write block
|
@@ -1488,6 +1519,8 @@ end
|
|
1488
1519
|
str << remove_long_items(v)
|
1489
1520
|
when Array === v
|
1490
1521
|
str << k.to_s << "=>[" << v * "," << "]"
|
1522
|
+
when File === v
|
1523
|
+
str << k.to_s << "=>[File:" << v.path << "]"
|
1491
1524
|
else
|
1492
1525
|
v_ins = v.inspect
|
1493
1526
|
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -138,7 +138,8 @@ module Workflow
|
|
138
138
|
if wf_name =~ /::\w+$/
|
139
139
|
clean_name = wf_name.sub(/::.*/,'')
|
140
140
|
Log.info{"Looking for '#{wf_name}' in '#{clean_name}'"}
|
141
|
-
|
141
|
+
require_workflow clean_name
|
142
|
+
return Misc.string2const Misc.camel_case(wf_name)
|
142
143
|
end
|
143
144
|
|
144
145
|
Log.info{"Loading workflow #{wf_name}"}
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -24,9 +24,14 @@ class Step
|
|
24
24
|
else
|
25
25
|
[dependencies]
|
26
26
|
end
|
27
|
+
@mutex = Mutex.new
|
27
28
|
@inputs = inputs || []
|
28
29
|
end
|
29
30
|
|
31
|
+
def task_name
|
32
|
+
@task.name
|
33
|
+
end
|
34
|
+
|
30
35
|
def path
|
31
36
|
@path = Misc.sanitize_filename(Path.setup(@path.call)) if Proc === @path
|
32
37
|
@path
|
@@ -43,10 +48,9 @@ class Step
|
|
43
48
|
attr_accessor :relay_step
|
44
49
|
alias original_log log
|
45
50
|
def log(status, message = nil)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
relay_step.log([task.name.to_s, status.to_s] * ">", message.nil? ? nil : [task.name.to_s, message] * ">")
|
51
|
+
self.status = status
|
52
|
+
message message
|
53
|
+
relay_step.log([task.name.to_s, status.to_s] * ">", message.nil? ? nil : message )
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
@@ -70,7 +74,10 @@ class Step
|
|
70
74
|
else
|
71
75
|
value.read
|
72
76
|
end
|
77
|
+
rescue Exception
|
78
|
+
value.abort if value.respond_to? :abort
|
73
79
|
ensure
|
80
|
+
value.close unless value.closed?
|
74
81
|
value.join if value.respond_to? :join
|
75
82
|
end
|
76
83
|
when (not defined? Entity or description.nil? or not Entity.formats.include? description)
|
@@ -88,6 +95,17 @@ class Step
|
|
88
95
|
end
|
89
96
|
end
|
90
97
|
|
98
|
+
def get_stream
|
99
|
+
@mutex.synchronize do
|
100
|
+
begin
|
101
|
+
res = @result
|
102
|
+
IO === res ? res : nil
|
103
|
+
ensure
|
104
|
+
@result = nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
91
109
|
def _exec
|
92
110
|
@exec = true if @exec.nil?
|
93
111
|
@task.exec_in((bindings ? bindings : self), *@inputs)
|
@@ -100,13 +118,18 @@ class Step
|
|
100
118
|
end
|
101
119
|
|
102
120
|
def join
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
121
|
+
stream = get_stream
|
122
|
+
begin
|
123
|
+
stream.read if stream
|
124
|
+
rescue
|
125
|
+
stream.abort if stream.respond_to? :abort
|
126
|
+
raise $!
|
127
|
+
ensure
|
128
|
+
stream.join if stream.respond_to? :join
|
108
129
|
end
|
109
130
|
|
131
|
+
dependencies.each{|dep| dep.join }
|
132
|
+
|
110
133
|
if @pid.nil?
|
111
134
|
self
|
112
135
|
else
|
@@ -140,12 +163,15 @@ class Step
|
|
140
163
|
|
141
164
|
set_info :dependencies, dependencies.collect{|dep| [dep.task.name, dep.name]}
|
142
165
|
log(:preparing, "Preparing job")
|
166
|
+
seen_deps = []
|
143
167
|
dependencies.each{|dependency|
|
144
168
|
Log.info "#{Log.color :magenta, "Checking dependency"} #{Log.color :yellow, task.name.to_s || ""} => #{Log.color :yellow, dependency.task.name.to_s || ""}"
|
145
169
|
begin
|
170
|
+
next if seen_deps.include? dependency.path
|
146
171
|
dependency.relay_log self
|
147
172
|
dependency.clean if not dependency.done? and dependency.error?
|
148
|
-
dependency.run true
|
173
|
+
dependency.run true unless dependency.done?
|
174
|
+
seen_deps.concat dependency.rec_dependencies.collect{|d| d.path}
|
149
175
|
rescue Exception
|
150
176
|
backtrace = $!.backtrace
|
151
177
|
set_info :backtrace, backtrace
|
@@ -157,7 +183,7 @@ class Step
|
|
157
183
|
set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, @inputs)) unless task.inputs.nil?
|
158
184
|
|
159
185
|
set_info :started, (start_time = Time.now)
|
160
|
-
log :started, "#{Log.color :
|
186
|
+
log :started, "#{Log.color :green, "Starting task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
161
187
|
|
162
188
|
begin
|
163
189
|
result = _exec
|
@@ -191,26 +217,33 @@ class Step
|
|
191
217
|
end
|
192
218
|
|
193
219
|
case result
|
194
|
-
when IO
|
220
|
+
when IO
|
195
221
|
log :streaming, "#{Log.color :magenta, "Streaming task result IO"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
196
222
|
ConcurrentStream.setup result do
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
223
|
+
begin
|
224
|
+
set_info :done, (done_time = Time.now)
|
225
|
+
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
226
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
227
|
+
rescue
|
228
|
+
Log.exception $!
|
229
|
+
end
|
201
230
|
end
|
202
231
|
when TSV::Dumper
|
203
232
|
log :streaming, "#{Log.color :magenta, "Streaming task result TSV::Dumper"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
204
233
|
ConcurrentStream.setup result.stream do
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
234
|
+
begin
|
235
|
+
set_info :done, (done_time = Time.now)
|
236
|
+
set_info :done, (done_time = Time.now)
|
237
|
+
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
238
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
239
|
+
rescue
|
240
|
+
Log.exception $!
|
241
|
+
end
|
209
242
|
end
|
210
243
|
else
|
211
244
|
set_info :done, (done_time = Time.now)
|
212
245
|
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
213
|
-
log :done, "#{Log.color :
|
246
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
214
247
|
end
|
215
248
|
|
216
249
|
result
|
@@ -232,9 +265,13 @@ class Step
|
|
232
265
|
FileUtils.mkdir_p File.dirname(path) unless Open.exists? File.dirname(path)
|
233
266
|
begin
|
234
267
|
res = run(true)
|
235
|
-
io =
|
236
|
-
io = res.result
|
237
|
-
|
268
|
+
io = get_stream
|
269
|
+
#io = res.result if IO === res.result
|
270
|
+
#io = res.result.stream if TSV::Dumper === res.result
|
271
|
+
if IO === io
|
272
|
+
io.read
|
273
|
+
io.join if io.respond_to? :join
|
274
|
+
end
|
238
275
|
rescue Aborted
|
239
276
|
Log.debug{"Forked process aborted: #{path}"}
|
240
277
|
log :aborted, "Aborted"
|
@@ -275,13 +312,20 @@ class Step
|
|
275
312
|
|
276
313
|
def abort
|
277
314
|
@pid ||= info[:pid]
|
278
|
-
|
315
|
+
|
316
|
+
return true unless info[:forked]
|
317
|
+
|
318
|
+
case @pid
|
319
|
+
when nil
|
279
320
|
Log.medium "Could not abort #{path}: no pid"
|
280
321
|
false
|
322
|
+
when Process.pid
|
323
|
+
Log.medium "Could not abort #{path}: same process"
|
324
|
+
false
|
281
325
|
else
|
282
326
|
Log.medium "Aborting #{path}: #{ @pid }"
|
283
327
|
begin
|
284
|
-
Process.kill("KILL", @pid)
|
328
|
+
Process.kill("KILL", @pid)
|
285
329
|
Process.waitpid @pid
|
286
330
|
rescue Exception
|
287
331
|
Log.debug("Aborted job #{@pid} was not killed: #{$!.message}")
|
@@ -289,6 +333,7 @@ class Step
|
|
289
333
|
log(:aborted, "Job aborted by user")
|
290
334
|
true
|
291
335
|
end
|
336
|
+
log(:aborted, "Job aborted by user")
|
292
337
|
end
|
293
338
|
|
294
339
|
def child(&block)
|
@@ -335,9 +380,12 @@ class Step
|
|
335
380
|
# placed. In that case, do not consider its dependencies
|
336
381
|
return [] if self.done? and not Open.exists? self.info_file
|
337
382
|
|
338
|
-
dependencies.
|
383
|
+
return [] if dependencies.nil? or dependencies.empty?
|
384
|
+
new_dependencies = dependencies.collect{|step|
|
339
385
|
step.rec_dependencies
|
340
|
-
}.flatten
|
386
|
+
}.flatten
|
387
|
+
|
388
|
+
dependencies + new_dependencies
|
341
389
|
end
|
342
390
|
|
343
391
|
def recursive_clean
|
@@ -350,6 +398,8 @@ class Step
|
|
350
398
|
end
|
351
399
|
|
352
400
|
def step(name)
|
353
|
-
rec_dependencies.select
|
401
|
+
rec_dependencies.select do |step|
|
402
|
+
step.task_name.to_sym == name.to_sym
|
403
|
+
end.first
|
354
404
|
end
|
355
405
|
end
|