rbbt-util 5.13.2 → 5.13.3
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 +4 -5
- data/lib/rbbt/tsv/parallel/traverse.rb +61 -27
- data/lib/rbbt/tsv/parser.rb +1 -2
- data/lib/rbbt/tsv/stream.rb +6 -5
- data/lib/rbbt/util/concurrency/processes.rb +23 -13
- data/lib/rbbt/util/concurrency/processes/worker.rb +1 -5
- data/lib/rbbt/util/log/progress.rb +27 -15
- data/lib/rbbt/util/misc/concurrent_stream.rb +15 -6
- data/lib/rbbt/util/misc/lock.rb +3 -2
- data/lib/rbbt/util/misc/pipes.rb +15 -49
- data/lib/rbbt/workflow.rb +5 -3
- data/lib/rbbt/workflow/step.rb +16 -15
- data/lib/rbbt/workflow/step/run.rb +47 -25
- data/share/rbbt_commands/workflow/example +13 -6
- data/share/rbbt_commands/workflow/task +1 -8
- data/test/rbbt/tsv/parallel/test_traverse.rb +6 -4
- data/test/rbbt/util/log/test_progress.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 715d410e93dddd02e14dd6d04f31917470c10b3d
|
4
|
+
data.tar.gz: 473271c8efe67c3465b204078d228618bedbc327
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3412998c1d2dce774a3d3a6a41428ab4506a6de2480b73be70890ae97d62be4285d1854881f6af92a551098c93e7b2dc62aaa8867a199e9ad26b3d991a213667
|
7
|
+
data.tar.gz: fb333f016809936f1ab2a928934683a3759a16d5ff3238e088535a7802f62566a732bfc7e7b0e3a7d638ebaa978b6dad6856ef2f3d5795f068213c5c14751e3a
|
data/lib/rbbt/persist.rb
CHANGED
@@ -202,7 +202,6 @@ module Persist
|
|
202
202
|
rescue Aborted
|
203
203
|
Log.warn "Persist stream thread aborted: #{ Log.color :blue, path }"
|
204
204
|
file.abort if file.respond_to? :abort
|
205
|
-
parent.raise $!
|
206
205
|
rescue Exception
|
207
206
|
Log.warn "Persist stream thread exception: #{ Log.color :blue, path }"
|
208
207
|
file.abort if file.respond_to? :abort
|
@@ -284,7 +283,7 @@ module Persist
|
|
284
283
|
res = tee_stream(res, path, type, res.respond_to?(:callback)? res.callback : nil)
|
285
284
|
ConcurrentStream.setup res do
|
286
285
|
begin
|
287
|
-
lockfile.unlock if lockfile.locked?
|
286
|
+
lockfile.unlock if File.exists? lockfile.path and lockfile.locked?
|
288
287
|
rescue
|
289
288
|
Log.exception $!
|
290
289
|
Log.warn "Lockfile exception: " << $!.message
|
@@ -292,7 +291,7 @@ module Persist
|
|
292
291
|
end
|
293
292
|
res.abort_callback = Proc.new do
|
294
293
|
begin
|
295
|
-
lockfile.unlock if lockfile.locked?
|
294
|
+
lockfile.unlock if File.exists? lockfile.path and lockfile.locked?
|
296
295
|
rescue
|
297
296
|
Log.exception $!
|
298
297
|
Log.warn "Lockfile exception: " << $!.message
|
@@ -303,7 +302,7 @@ module Persist
|
|
303
302
|
res = tee_stream(res.stream, path, type, res.respond_to?(:callback)? res.callback : nil)
|
304
303
|
ConcurrentStream.setup res do
|
305
304
|
begin
|
306
|
-
lockfile.unlock if lockfile.locked?
|
305
|
+
lockfile.unlock if File.exists? lockfile.path and lockfile.locked?
|
307
306
|
rescue
|
308
307
|
Log.exception $!
|
309
308
|
Log.warn "Lockfile exception: " << $!.message
|
@@ -311,7 +310,7 @@ module Persist
|
|
311
310
|
end
|
312
311
|
res.abort_callback = Proc.new do
|
313
312
|
begin
|
314
|
-
lockfile.unlock if lockfile.locked?
|
313
|
+
lockfile.unlock if File.exists? lockfile.path and lockfile.locked?
|
315
314
|
rescue
|
316
315
|
Log.exception $!
|
317
316
|
Log.warn "Lockfile exception: " << $!.message
|
@@ -10,7 +10,29 @@ module TSV
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.guess_max(obj)
|
14
|
+
begin
|
15
|
+
case obj
|
16
|
+
when Step
|
17
|
+
if obj.done?
|
18
|
+
CMD.cmd("wc -l '#{obj.path.find}'").read.to_i
|
19
|
+
else
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
when Array, Hash
|
23
|
+
obj.size
|
24
|
+
when File
|
25
|
+
CMD.cmd("wc -l '#{obj.filename}'").read.to_i
|
26
|
+
when Path
|
27
|
+
CMD.cmd("wc -l '#{obj.find}'").read.to_i
|
28
|
+
end
|
29
|
+
rescue
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
13
34
|
def self.stream_name(obj)
|
35
|
+
return "nil" if obj.nil?
|
14
36
|
filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
15
37
|
filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
16
38
|
stream_obj = obj_stream(obj) || obj
|
@@ -149,7 +171,6 @@ module TSV
|
|
149
171
|
|
150
172
|
Log.medium "Traversing #{stream_name(obj)} #{Log.color :green, "->"} #{stream_name(options[:into])}"
|
151
173
|
begin
|
152
|
-
sleep 1
|
153
174
|
case obj
|
154
175
|
when TSV
|
155
176
|
traverse_tsv(obj, options, &block)
|
@@ -173,7 +194,6 @@ module TSV
|
|
173
194
|
end
|
174
195
|
rescue Aborted
|
175
196
|
obj.abort if obj.respond_to? :abort
|
176
|
-
raise $!
|
177
197
|
rescue Exception
|
178
198
|
obj.abort if obj.respond_to? :abort
|
179
199
|
raise $!
|
@@ -216,20 +236,28 @@ module TSV
|
|
216
236
|
Log.warn "IOError traversing #{stream_name(obj)}: #{$!.message}"
|
217
237
|
stream = obj_stream(obj)
|
218
238
|
stream.abort if stream and stream.respond_to? :abort
|
239
|
+
stream = obj_stream(options[:into])
|
240
|
+
stream.abort if stream.respond_to? :abort
|
219
241
|
raise $!
|
220
242
|
rescue Errno::EPIPE
|
221
243
|
Log.warn "Pipe closed while traversing #{stream_name(obj)}: #{$!.message}"
|
244
|
+
stream = obj_stream(obj)
|
245
|
+
stream.abort if stream and stream.respond_to? :abort
|
246
|
+
stream = obj_stream(options[:into])
|
247
|
+
stream.abort if stream.respond_to? :abort
|
222
248
|
raise $!
|
223
249
|
rescue Aborted
|
224
250
|
Log.warn "Aborted traversing #{stream_name(obj)}"
|
225
251
|
stream = obj_stream(obj)
|
226
252
|
stream.abort if stream and stream.respond_to? :abort
|
227
|
-
|
253
|
+
stream = obj_stream(options[:into])
|
254
|
+
stream.abort if stream.respond_to? :abort
|
228
255
|
rescue Exception
|
229
256
|
Log.warn "Exception traversing #{stream_name(obj)}"
|
230
|
-
Log.exception $!
|
231
257
|
stream = obj_stream(obj)
|
232
258
|
stream.abort if stream and stream.respond_to? :abort
|
259
|
+
stream = obj_stream(options[:into])
|
260
|
+
stream.abort if stream.respond_to? :abort
|
233
261
|
raise $!
|
234
262
|
end
|
235
263
|
end
|
@@ -263,40 +291,38 @@ module TSV
|
|
263
291
|
def self.traverse_cpus(num, obj, options, &block)
|
264
292
|
begin
|
265
293
|
callback, cleanup, join = Misc.process_options options, :callback, :cleanup, :join
|
266
|
-
q = RbbtProcessQueue.new num, cleanup, join
|
267
294
|
|
268
|
-
|
269
|
-
|
295
|
+
begin
|
296
|
+
q = RbbtProcessQueue.new num, cleanup, join
|
297
|
+
q.callback &callback
|
298
|
+
q.init &block
|
270
299
|
|
271
|
-
thread = Thread.new do
|
272
300
|
traverse_obj(obj, options) do |*p|
|
273
301
|
q.process *p
|
274
302
|
end
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
rescue
|
303
|
+
rescue Aborted, Errno::EPIPE
|
304
|
+
Log.warn "Aborted"
|
305
|
+
rescue Exception
|
306
|
+
Log.exception $!
|
280
307
|
raise $!
|
308
|
+
ensure
|
309
|
+
q.join
|
281
310
|
end
|
282
311
|
rescue Interrupt, Aborted
|
283
|
-
Log.warn "Aborted traversal in CPUs for #{stream_name(obj) || Misc.fingerprint(obj)}"
|
312
|
+
Log.warn "Aborted traversal in CPUs for #{stream_name(obj) || Misc.fingerprint(obj)}: #{$!.backtrace*","}"
|
313
|
+
q.abort
|
284
314
|
stream = obj_stream(obj)
|
285
315
|
stream.abort if stream.respond_to? :abort
|
286
316
|
stream = obj_stream(options[:into])
|
287
317
|
stream.abort if stream.respond_to? :abort
|
288
|
-
|
289
|
-
raise $!
|
318
|
+
raise "Traversal aborted"
|
290
319
|
rescue Exception
|
291
|
-
Log.warn "Exception during traversal in CPUs for #{stream_name(obj) || Misc.fingerprint(obj)}"
|
320
|
+
Log.warn "Exception during traversal in CPUs for #{stream_name(obj) || Misc.fingerprint(obj)}: #{$!.message}"
|
292
321
|
stream = obj_stream(obj)
|
293
322
|
stream.abort if stream.respond_to? :abort
|
294
323
|
stream = obj_stream(options[:into])
|
295
324
|
stream.abort if stream.respond_to? :abort
|
296
|
-
q.abort
|
297
325
|
raise $!
|
298
|
-
ensure
|
299
|
-
q.join
|
300
326
|
end
|
301
327
|
end
|
302
328
|
|
@@ -326,8 +352,15 @@ module TSV
|
|
326
352
|
store << value
|
327
353
|
end
|
328
354
|
true
|
329
|
-
rescue
|
330
|
-
|
355
|
+
rescue Aborted, Interrupt
|
356
|
+
Log.warn "Aborted storing into #{Misc.fingerprint store}: #{$!.message}"
|
357
|
+
stream = obj_stream(store)
|
358
|
+
stream.abort if stream.respond_to? :abort
|
359
|
+
rescue Exception
|
360
|
+
stream = obj_stream(store)
|
361
|
+
stream.abort if stream.respond_to? :abort
|
362
|
+
Log.exception $!
|
363
|
+
raise $!
|
331
364
|
end
|
332
365
|
end
|
333
366
|
|
@@ -423,15 +456,16 @@ module TSV
|
|
423
456
|
|
424
457
|
bar = Misc.process_options options, :bar
|
425
458
|
bar ||= Misc.process_options options, :progress
|
459
|
+
max = guess_max(obj)
|
426
460
|
options[:bar] = case bar
|
427
461
|
when String
|
428
|
-
Log::ProgressBar.new_bar(
|
462
|
+
Log::ProgressBar.new_bar(max, {:desc => bar})
|
429
463
|
when TrueClass
|
430
|
-
Log::ProgressBar.new_bar(
|
464
|
+
Log::ProgressBar.new_bar(max, nil)
|
431
465
|
when Fixnum
|
432
466
|
Log::ProgressBar.new_bar(bar)
|
433
467
|
when Hash
|
434
|
-
max = Misc.process_options
|
468
|
+
max = Misc.process_options(bar, :max) || max
|
435
469
|
Log::ProgressBar.new_bar(max, bar)
|
436
470
|
else
|
437
471
|
bar
|
@@ -448,10 +482,10 @@ module TSV
|
|
448
482
|
begin
|
449
483
|
store_into into, e
|
450
484
|
rescue Aborted
|
451
|
-
|
485
|
+
Log.warn "Aborted callback #{stream_name(obj)} #{Log.color :green, "->"} #{stream_name(options[:into])}"
|
452
486
|
rescue Exception
|
487
|
+
Log.warn "Exception callback #{stream_name(obj)} #{Log.color :green, "->"} #{stream_name(options[:into])}"
|
453
488
|
Log.exception $!
|
454
|
-
raise $!
|
455
489
|
ensure
|
456
490
|
bar.tick if bar
|
457
491
|
end
|
data/lib/rbbt/tsv/parser.rb
CHANGED
@@ -537,12 +537,11 @@ module TSV
|
|
537
537
|
break
|
538
538
|
rescue Errno::EPIPE
|
539
539
|
Log.error "Pipe closed while parsing #{Misc.fingerprint stream}: #{$!.message}"
|
540
|
+
stream.abort if stream.respond_to? :abort
|
540
541
|
raise $!
|
541
542
|
rescue Exception
|
542
543
|
Log.error "Exception parsing #{Misc.fingerprint stream}: #{$!.message}"
|
543
|
-
Log.exception $!
|
544
544
|
stream.abort if stream.respond_to? :abort
|
545
|
-
stream.join if stream.respond_to? :join
|
546
545
|
raise $!
|
547
546
|
end
|
548
547
|
end
|
data/lib/rbbt/tsv/stream.rb
CHANGED
@@ -130,7 +130,7 @@ module TSV
|
|
130
130
|
end
|
131
131
|
if line.nil?
|
132
132
|
stream = streams[i]
|
133
|
-
|
133
|
+
stream.join if stream.respond_to? :join
|
134
134
|
keys[i] = nil
|
135
135
|
parts[i] = nil
|
136
136
|
else
|
@@ -146,12 +146,13 @@ module TSV
|
|
146
146
|
sin.puts [min, str*sep] * sep
|
147
147
|
end
|
148
148
|
streams.each do |stream|
|
149
|
-
|
149
|
+
stream.join if stream.respond_to? :join
|
150
150
|
end
|
151
|
-
rescue
|
152
|
-
Log.exception $!
|
151
|
+
rescue Exception
|
153
152
|
streams.each do |stream|
|
154
|
-
|
153
|
+
Thread.new do
|
154
|
+
stream.abort if stream.respond_to? :abort
|
155
|
+
end
|
155
156
|
end
|
156
157
|
raise $!
|
157
158
|
end
|
@@ -29,11 +29,14 @@ class RbbtProcessQueue
|
|
29
29
|
@callback.call p
|
30
30
|
end
|
31
31
|
rescue Aborted
|
32
|
-
|
32
|
+
Log.warn "Callback thread aborted"
|
33
|
+
@process_monitor.raise Aborted.new
|
34
|
+
raise $!
|
33
35
|
rescue ClosedStream
|
34
36
|
rescue Exception
|
35
|
-
Log.warn "Callback thread exception"
|
36
|
-
|
37
|
+
Log.warn "Callback thread exception: #{$!.message}"
|
38
|
+
@process_monitor.raise $!
|
39
|
+
raise $!
|
37
40
|
ensure
|
38
41
|
@callback_queue.sread.close unless @callback_queue.sread.closed?
|
39
42
|
end
|
@@ -56,14 +59,14 @@ class RbbtProcessQueue
|
|
56
59
|
@processes.shift
|
57
60
|
end
|
58
61
|
rescue Aborted
|
62
|
+
Log.warn "Aborting process monitor"
|
59
63
|
@processes.each{|p| p.abort }
|
60
64
|
@processes.each{|p| p.join }
|
61
|
-
Log.warn "Process monitor aborted"
|
62
65
|
rescue Exception
|
63
66
|
Log.warn "Process monitor exception: #{$!.message}"
|
64
67
|
@processes.each{|p| p.abort }
|
65
|
-
@callback_thread.raise $! if @callback_thread
|
66
|
-
|
68
|
+
@callback_thread.raise $! if @callback_thread and @callback_thread.alive?
|
69
|
+
raise $!
|
67
70
|
end
|
68
71
|
end
|
69
72
|
end
|
@@ -71,22 +74,25 @@ class RbbtProcessQueue
|
|
71
74
|
def close_callback
|
72
75
|
begin
|
73
76
|
@callback_queue.push ClosedStream.new if @callback_thread.alive?
|
74
|
-
rescue
|
77
|
+
rescue Exception
|
75
78
|
Log.warn "Error closing callback: #{$!.message}"
|
76
79
|
end
|
77
|
-
@callback_thread.join if @callback_thread.alive?
|
80
|
+
@callback_thread.join #if @callback_thread.alive?
|
78
81
|
end
|
79
82
|
|
80
83
|
def join
|
81
|
-
|
82
|
-
@
|
83
|
-
|
84
|
+
begin
|
85
|
+
@processes.length.times do
|
86
|
+
@queue.push ClosedStream.new
|
87
|
+
end if @process_monitor.alive?
|
88
|
+
rescue Exception
|
89
|
+
end
|
84
90
|
|
85
91
|
begin
|
86
92
|
@process_monitor.join
|
87
93
|
close_callback if @callback
|
88
94
|
rescue Exception
|
89
|
-
Log.
|
95
|
+
Log.error "Exception joining queue: #{$!.message}"
|
90
96
|
raise $!
|
91
97
|
ensure
|
92
98
|
@queue.swrite.close unless @queue.swrite.closed?
|
@@ -113,7 +119,11 @@ class RbbtProcessQueue
|
|
113
119
|
end
|
114
120
|
|
115
121
|
def process(*e)
|
116
|
-
|
122
|
+
begin
|
123
|
+
@queue.push e
|
124
|
+
rescue Errno::EPIPE
|
125
|
+
raise Aborted
|
126
|
+
end
|
117
127
|
end
|
118
128
|
|
119
129
|
def self.each(list, num = 3, &block)
|
@@ -35,7 +35,6 @@ class RbbtProcessQueue
|
|
35
35
|
Log.warn "Worker #{Process.pid} aborted"
|
36
36
|
Kernel.exit! -1
|
37
37
|
rescue Exception
|
38
|
-
Log.exception $!
|
39
38
|
@callback_queue.push($!) if @callback_queue
|
40
39
|
Kernel.exit! -1
|
41
40
|
ensure
|
@@ -45,10 +44,7 @@ class RbbtProcessQueue
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def join
|
48
|
-
|
49
|
-
joined_pid = Process.waitpid @pid
|
50
|
-
rescue
|
51
|
-
end
|
47
|
+
joined_pid = Process.waitpid @pid
|
52
48
|
end
|
53
49
|
|
54
50
|
def abort
|
@@ -103,7 +103,10 @@ module Log
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def thr
|
106
|
-
|
106
|
+
if @last_report == -1
|
107
|
+
@last_report = Time.now
|
108
|
+
return thr
|
109
|
+
end
|
107
110
|
time = Time.now - @last_report
|
108
111
|
time = 0.000001 if time == 0
|
109
112
|
thr = (@current / time).to_i
|
@@ -140,6 +143,10 @@ module Log
|
|
140
143
|
indicator
|
141
144
|
end
|
142
145
|
|
146
|
+
def msg
|
147
|
+
@max ? report_msg : throughput_msg
|
148
|
+
end
|
149
|
+
|
143
150
|
def print(io, str)
|
144
151
|
LOG_MUTEX.synchronize do
|
145
152
|
STDERR.print str
|
@@ -153,9 +160,9 @@ module Log
|
|
153
160
|
# original line. Everything is printed to stderr.
|
154
161
|
def report(io = STDERR)
|
155
162
|
if Log::LAST != "progress"
|
156
|
-
Log::
|
157
|
-
|
158
|
-
|
163
|
+
Log::LAST.replace "progress"
|
164
|
+
length = Log::ProgressBar.cleanup_bars
|
165
|
+
length.times{print(io, "\n")}
|
159
166
|
end
|
160
167
|
print(io, up_lines(@depth) << report_msg << down_lines(@depth)) if severity >= Log.severity
|
161
168
|
@last_report = Time.now if @last_report == -1
|
@@ -163,9 +170,9 @@ module Log
|
|
163
170
|
|
164
171
|
def throughput(io = STDERR)
|
165
172
|
if Log::LAST != "progress"
|
166
|
-
Log::
|
167
|
-
|
168
|
-
|
173
|
+
Log::LAST.replace "progress"
|
174
|
+
length = Log::ProgressBar.cleanup_bars
|
175
|
+
length.times{print(io, "\n")}
|
169
176
|
end
|
170
177
|
print(io, up_lines(@depth) << throughput_msg << down_lines(@depth)) if severity >= Log.severity
|
171
178
|
@last_report = Time.now
|
@@ -173,6 +180,11 @@ module Log
|
|
173
180
|
end
|
174
181
|
|
175
182
|
def done
|
183
|
+
if Log::LAST != "progress"
|
184
|
+
Log::LAST.replace "progress"
|
185
|
+
length = Log::ProgressBar.cleanup_bars
|
186
|
+
length.times{print(io, "\n")}
|
187
|
+
end
|
176
188
|
print(io, up_lines(@depth) << Log.color(:magenta, @desc) << Log.color(:green, " DONE") << down_lines(@depth)) if severity >= Log.severity
|
177
189
|
end
|
178
190
|
|
@@ -193,22 +205,22 @@ module Log
|
|
193
205
|
REMOVE.each do |bar|
|
194
206
|
index = BARS.index bar
|
195
207
|
if index
|
196
|
-
|
197
|
-
|
198
|
-
bar.depth =
|
199
|
-
|
200
|
-
end
|
201
|
-
BARS.pop
|
208
|
+
BARS.delete_at index
|
209
|
+
BARS.each_with_index do |bar,i|
|
210
|
+
bar.depth = i
|
211
|
+
end
|
202
212
|
end
|
203
213
|
end
|
204
214
|
REMOVE.clear
|
215
|
+
BARS.length
|
205
216
|
end
|
206
217
|
end
|
207
218
|
|
208
219
|
def self.remove_bar(bar)
|
220
|
+
bar.done unless bar.max
|
209
221
|
BAR_MUTEX.synchronize do
|
210
|
-
bar.done unless bar.max
|
211
222
|
REMOVE << bar
|
223
|
+
Log::LAST.replace "remove"
|
212
224
|
end
|
213
225
|
end
|
214
226
|
|
@@ -220,7 +232,7 @@ module Log
|
|
220
232
|
rescue KeepBar
|
221
233
|
keep = true
|
222
234
|
ensure
|
223
|
-
remove_bar(bar)
|
235
|
+
remove_bar(bar) if bar
|
224
236
|
end
|
225
237
|
end
|
226
238
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ConcurrentStream
|
2
|
-
attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :autojoin
|
2
|
+
attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :aborted, :autojoin
|
3
3
|
|
4
4
|
def self.setup(stream, options = {}, &block)
|
5
5
|
threads, pids, callback, filename, autojoin = Misc.process_options options, :threads, :pids, :callback, :filename, :autojoin
|
@@ -46,6 +46,10 @@ module ConcurrentStream
|
|
46
46
|
@joined
|
47
47
|
end
|
48
48
|
|
49
|
+
def aborted?
|
50
|
+
@aborted
|
51
|
+
end
|
52
|
+
|
49
53
|
def join_threads
|
50
54
|
if @threads and @threads.any?
|
51
55
|
@threads.each do |t|
|
@@ -97,11 +101,16 @@ module ConcurrentStream
|
|
97
101
|
end
|
98
102
|
|
99
103
|
def abort
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
104
|
+
return if @aborted
|
105
|
+
begin
|
106
|
+
abort_threads
|
107
|
+
abort_pids
|
108
|
+
@abort_callback.call if @abort_callback
|
109
|
+
ensure
|
110
|
+
@abort_callback = nil
|
111
|
+
@callback = nil
|
112
|
+
@aborted = true
|
113
|
+
end
|
105
114
|
end
|
106
115
|
|
107
116
|
def super(*args)
|
data/lib/rbbt/util/misc/lock.rb
CHANGED
data/lib/rbbt/util/misc/pipes.rb
CHANGED
@@ -73,45 +73,6 @@ module Misc
|
|
73
73
|
sout
|
74
74
|
end
|
75
75
|
|
76
|
-
#def self.tee_stream_fork(stream)
|
77
|
-
# stream_out1, stream_in1 = Misc.pipe
|
78
|
-
# stream_out2, stream_in2 = Misc.pipe
|
79
|
-
|
80
|
-
# splitter_pid = Process.fork do
|
81
|
-
# Misc.purge_pipes(stream_in1, stream_in2)
|
82
|
-
# stream_out1.close
|
83
|
-
# stream_out2.close
|
84
|
-
# begin
|
85
|
-
# filename = stream.respond_to?(:filename)? stream.filename : nil
|
86
|
-
# skip1 = skip2 = false
|
87
|
-
# while block = stream.read(2048)
|
88
|
-
# begin stream_in1.write block; rescue Exception; Log.exception $!; skip1 = true end unless skip1
|
89
|
-
# begin stream_in2.write block; rescue Exception; Log.exception $!; skip2 = true end unless skip2
|
90
|
-
# end
|
91
|
-
# raise "Error writing in stream_in1" if skip1
|
92
|
-
# raise "Error writing in stream_in2" if skip2
|
93
|
-
# stream.join if stream.respond_to? :join
|
94
|
-
# stream_in1.close
|
95
|
-
# stream_in2.close
|
96
|
-
# rescue Aborted
|
97
|
-
# stream.abort if stream.respond_to? :abort
|
98
|
-
# raise $!
|
99
|
-
# rescue IOError
|
100
|
-
# Log.exception $!
|
101
|
-
# rescue Exception
|
102
|
-
# Log.exception $!
|
103
|
-
# end
|
104
|
-
# end
|
105
|
-
# stream.close
|
106
|
-
# stream_in1.close
|
107
|
-
# stream_in2.close
|
108
|
-
|
109
|
-
# ConcurrentStream.setup stream_out1, :pids => [splitter_pid]
|
110
|
-
# ConcurrentStream.setup stream_out2, :pids => [splitter_pid]
|
111
|
-
|
112
|
-
# [stream_out1, stream_out2]
|
113
|
-
#end
|
114
|
-
|
115
76
|
def self.tee_stream_thread(stream)
|
116
77
|
stream_out1, stream_in1 = Misc.pipe
|
117
78
|
stream_out2, stream_in2 = Misc.pipe
|
@@ -139,11 +100,14 @@ module Misc
|
|
139
100
|
stream_in2.close unless stream_in2.closed?
|
140
101
|
stream.join if stream.respond_to? :join
|
141
102
|
rescue Aborted, Interrupt
|
142
|
-
|
143
|
-
|
103
|
+
begin
|
104
|
+
stream.abort if stream.respond_to? :abort
|
105
|
+
rescue
|
106
|
+
Log.exception $!
|
107
|
+
end
|
144
108
|
rescue Exception
|
145
109
|
Log.exception $!
|
146
|
-
|
110
|
+
stream.abort if stream.respond_to? :abort
|
147
111
|
end
|
148
112
|
end
|
149
113
|
|
@@ -186,14 +150,17 @@ module Misc
|
|
186
150
|
else
|
187
151
|
begin
|
188
152
|
while block = io.read(2048)
|
189
|
-
return if io.eof?
|
190
|
-
Thread.pass
|
153
|
+
#return if io.eof?
|
154
|
+
#Thread.pass
|
191
155
|
end
|
192
156
|
io.join if io.respond_to? :join
|
193
|
-
rescue
|
194
|
-
|
195
|
-
Log.warn "Exception consuming stream: #{io.inspect}"
|
157
|
+
rescue Aborted
|
158
|
+
Log.warn "Consume stream aborted #{Misc.fingerprint io}"
|
196
159
|
io.abort if io.respond_to? :abort
|
160
|
+
rescue Exception
|
161
|
+
Log.warn "Exception consuming stream: #{Misc.fingerprint io}: #{$!.message}"
|
162
|
+
io.abort if io.respond_to? :abort
|
163
|
+
raise $!
|
197
164
|
end
|
198
165
|
end
|
199
166
|
end
|
@@ -244,11 +211,10 @@ module Misc
|
|
244
211
|
rescue Aborted
|
245
212
|
Log.warn "Aborted sensiblewrite -- #{ Log.reset << Log.color(:blue, path) }"
|
246
213
|
content.abort if content.respond_to? :abort
|
247
|
-
|
214
|
+
Open.rm_f path if File.exists? path
|
248
215
|
rescue Exception
|
249
216
|
Log.warn "Exception in sensiblewrite: #{$!.message} -- #{ Log.color :blue, path }"
|
250
217
|
content.abort if content.respond_to? :abort
|
251
|
-
content.join if content.respond_to? :join
|
252
218
|
Open.rm_f path if File.exists? path
|
253
219
|
raise $!
|
254
220
|
ensure
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -7,6 +7,8 @@ require 'rbbt/workflow/examples'
|
|
7
7
|
|
8
8
|
module Workflow
|
9
9
|
|
10
|
+
STEP_CACHE = {}
|
11
|
+
|
10
12
|
class TaskNotFoundException < Exception
|
11
13
|
def initialize(workflow, task = nil)
|
12
14
|
if task
|
@@ -184,7 +186,7 @@ module Workflow
|
|
184
186
|
end
|
185
187
|
|
186
188
|
def step_cache
|
187
|
-
@step_cache ||=
|
189
|
+
@step_cache ||= Workflow::STEP_CACHE
|
188
190
|
end
|
189
191
|
|
190
192
|
|
@@ -236,7 +238,7 @@ module Workflow
|
|
236
238
|
step_path = step_path.call if Proc === step_path
|
237
239
|
persist = input_values.nil? ? false : true
|
238
240
|
key = Path === step_path ? step_path.find : step_path
|
239
|
-
step = Persist.memory("Step", :key => key, :repo => step_cache, :persist => persist
|
241
|
+
step = Persist.memory("Step", :key => key, :repo => step_cache, :persist => persist) do
|
240
242
|
step = Step.new step_path, task, input_values, dependencies
|
241
243
|
|
242
244
|
helpers.each do |name, block|
|
@@ -244,8 +246,8 @@ module Workflow
|
|
244
246
|
define_method name, &block
|
245
247
|
end
|
246
248
|
end
|
247
|
-
step
|
248
249
|
|
250
|
+
step
|
249
251
|
end
|
250
252
|
|
251
253
|
step.task ||= task
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -71,23 +71,24 @@ class Step
|
|
71
71
|
case
|
72
72
|
when IO === value
|
73
73
|
begin
|
74
|
-
case @task.result_type
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
74
|
+
res = case @task.result_type
|
75
|
+
when :array
|
76
|
+
array = []
|
77
|
+
while line = value.gets
|
78
|
+
array << line.strip
|
79
|
+
end
|
80
|
+
array
|
81
|
+
when :tsv
|
82
|
+
TSV.open(value)
|
83
|
+
else
|
84
|
+
value.read
|
85
|
+
end
|
86
|
+
value.join if value.respond_to? :join
|
87
|
+
res
|
86
88
|
rescue Exception
|
87
89
|
value.abort if value.respond_to? :abort
|
88
|
-
|
89
|
-
|
90
|
-
value.close unless value.closed?
|
90
|
+
self.abort
|
91
|
+
raise $!
|
91
92
|
end
|
92
93
|
when (not defined? Entity or description.nil? or not Entity.formats.include? description)
|
93
94
|
value
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Step
|
2
2
|
|
3
|
-
attr_reader :stream, :dupped
|
3
|
+
attr_reader :stream, :dupped, :saved_stream
|
4
4
|
|
5
5
|
STREAM_CACHE = {}
|
6
6
|
STREAM_CACHE_MUTEX = Mutex.new
|
@@ -67,7 +67,7 @@ class Step
|
|
67
67
|
@mutex.synchronize do
|
68
68
|
begin
|
69
69
|
if IO === @result
|
70
|
-
@result
|
70
|
+
@saved_stream = @result
|
71
71
|
else
|
72
72
|
nil
|
73
73
|
end
|
@@ -146,15 +146,23 @@ class Step
|
|
146
146
|
unless dependency.result or dependency.done?
|
147
147
|
dependency.run(true)
|
148
148
|
end
|
149
|
-
rescue Aborted
|
149
|
+
rescue Aborted
|
150
150
|
backtrace = $!.backtrace
|
151
151
|
set_info :backtrace, backtrace
|
152
152
|
log(:error, "Aborted dependency #{Log.color :yellow, dependency.task.name.to_s}")
|
153
|
+
self.abort
|
154
|
+
raise $!
|
155
|
+
rescue Interrupt
|
156
|
+
backtrace = $!.backtrace
|
157
|
+
set_info :backtrace, backtrace
|
158
|
+
log(:error, "Interrupted dependency #{Log.color :yellow, dependency.task.name.to_s}")
|
159
|
+
self.abort
|
153
160
|
raise $!
|
154
161
|
rescue Exception
|
155
162
|
backtrace = $!.backtrace
|
156
163
|
set_info :backtrace, backtrace
|
157
164
|
log(:error, "Exception processing dependency #{Log.color :yellow, dependency.task.name.to_s} -- #{$!.class}: #{$!.message}")
|
165
|
+
self.abort
|
158
166
|
raise $!
|
159
167
|
end
|
160
168
|
end
|
@@ -163,8 +171,8 @@ class Step
|
|
163
171
|
def run(no_load = false)
|
164
172
|
result = nil
|
165
173
|
|
166
|
-
|
167
|
-
|
174
|
+
@mutex.synchronize do
|
175
|
+
begin
|
168
176
|
no_load = no_load ? :stream : false
|
169
177
|
result = Persist.persist "Job", @task.result_type, :file => path, :check => checks, :no_load => no_load do |lockfile|
|
170
178
|
if Step === Step.log_relay_step and not self == Step.log_relay_step
|
@@ -198,19 +206,18 @@ class Step
|
|
198
206
|
begin
|
199
207
|
result = _exec
|
200
208
|
rescue Aborted
|
209
|
+
stop_dependencies
|
201
210
|
log(:error, "Aborted")
|
202
|
-
|
203
|
-
kill_children
|
204
211
|
raise $!
|
205
212
|
rescue Exception
|
206
213
|
backtrace = $!.backtrace
|
207
214
|
|
208
215
|
# HACK: This fixes an strange behaviour in 1.9.3 where some
|
209
216
|
# backtrace strings are coded in ASCII-8BIT
|
210
|
-
kill_children
|
211
217
|
set_info :backtrace, backtrace
|
212
218
|
log(:error, "#{$!.class}: #{$!.message}")
|
213
219
|
backtrace.each{|l| l.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
|
220
|
+
stop_dependencies
|
214
221
|
raise $!
|
215
222
|
end
|
216
223
|
|
@@ -260,13 +267,9 @@ class Step
|
|
260
267
|
end
|
261
268
|
result.stream.abort_callback = Proc.new do
|
262
269
|
begin
|
263
|
-
log :error, "#{Log.color :red, "ERROR -- streamming aborted"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] -- #{path}" if status == :streaming
|
264
270
|
stop_dependencies
|
265
|
-
|
266
|
-
rescue
|
267
|
-
Log.exception $!
|
268
|
-
ensure
|
269
|
-
join
|
271
|
+
log :error, "#{Log.color :red, "ERROR -- streamming aborted"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] -- #{path}" if status == :streaming
|
272
|
+
rescue Exception
|
270
273
|
end
|
271
274
|
end
|
272
275
|
else
|
@@ -284,9 +287,9 @@ class Step
|
|
284
287
|
else
|
285
288
|
@result = prepare_result result, @task.result_description
|
286
289
|
end
|
290
|
+
rescue Exception
|
291
|
+
self.abort
|
287
292
|
end
|
288
|
-
ensure
|
289
|
-
join unless no_load
|
290
293
|
end
|
291
294
|
end
|
292
295
|
|
@@ -300,7 +303,7 @@ class Step
|
|
300
303
|
res = run true
|
301
304
|
rescue Aborted
|
302
305
|
Log.debug{"Forked process aborted: #{path}"}
|
303
|
-
log :aborted, "
|
306
|
+
log :aborted, "Job aborted (#{Process.pid})"
|
304
307
|
raise $!
|
305
308
|
rescue Exception
|
306
309
|
Log.debug("Exception '#{$!.message}' caught on forked process: #{path}")
|
@@ -340,11 +343,15 @@ class Step
|
|
340
343
|
|
341
344
|
def stop_dependencies
|
342
345
|
dependencies.each do |dep|
|
346
|
+
Log.warn "Stoping #{Misc.fingerprint dep}"
|
343
347
|
begin
|
344
|
-
dep.abort unless dep.done?
|
348
|
+
dep.abort unless dep.done?
|
349
|
+
rescue Exception
|
350
|
+
Log.exception $!
|
345
351
|
rescue Aborted
|
346
352
|
end
|
347
353
|
end
|
354
|
+
kill_children
|
348
355
|
end
|
349
356
|
|
350
357
|
def abort_pid
|
@@ -371,27 +378,42 @@ class Step
|
|
371
378
|
|
372
379
|
def abort_stream
|
373
380
|
stream = get_stream if @result
|
374
|
-
stream ||= @
|
375
|
-
if stream and stream.respond_to? :abort
|
376
|
-
Log.medium "Aborting stream #{stream.inspect} -- #{Log.color :blue, path}"
|
381
|
+
stream ||= @saved_stream
|
382
|
+
if stream and stream.respond_to? :abort and not stream.aborted?
|
377
383
|
begin
|
384
|
+
Log.medium "Aborting job stream #{stream.inspect} -- #{Log.color :blue, path}"
|
378
385
|
stream.abort
|
386
|
+
Log.medium "Aborted job stream #{stream.inspect} -- #{Log.color :blue, path}"
|
387
|
+
#stream.close unless stream.closed?
|
379
388
|
rescue Aborted
|
389
|
+
Log.medium "Aborting job stream #{stream.inspect} ABORTED RETRY -- #{Log.color :blue, path}"
|
390
|
+
retry
|
380
391
|
end
|
381
392
|
end
|
382
393
|
end
|
383
394
|
|
384
395
|
def abort
|
396
|
+
return if @aborted
|
385
397
|
Log.medium{"#{Log.color :red, "Aborting"} #{Log.color :blue, path}"}
|
386
398
|
begin
|
387
|
-
abort_pid
|
388
399
|
stop_dependencies
|
400
|
+
@aborted = true
|
389
401
|
abort_stream
|
390
|
-
|
402
|
+
abort_pid
|
403
|
+
rescue Aborted
|
404
|
+
Log.medium{"#{Log.color :red, "Aborting ABORTED RETRY"} #{Log.color :blue, path}"}
|
405
|
+
retry
|
406
|
+
rescue Exception
|
391
407
|
Log.exception $!
|
392
408
|
ensure
|
393
|
-
|
409
|
+
@aborted = true
|
410
|
+
begin
|
411
|
+
log(:aborted, "Job aborted")
|
412
|
+
rescue Exception
|
413
|
+
Log.exception $!
|
414
|
+
end
|
394
415
|
end
|
416
|
+
Log.medium{"#{Log.color :red, "Aborted"} #{Log.color :blue, path}"}
|
395
417
|
end
|
396
418
|
|
397
419
|
def join_stream
|
@@ -401,9 +423,9 @@ class Step
|
|
401
423
|
Misc.consume_stream stream
|
402
424
|
stream.join if stream.respond_to? :join
|
403
425
|
rescue Exception
|
404
|
-
stream.abort if stream.respond_to? :abort
|
405
426
|
self.abort
|
406
427
|
raise $!
|
428
|
+
#stream.abort if stream.respond_to? :abort
|
407
429
|
end
|
408
430
|
end
|
409
431
|
end
|
@@ -13,27 +13,33 @@ def run_task(workflow, task, name)
|
|
13
13
|
ARGV.replace([workflow.to_s, task, '--load_inputs', example_dir, '--jobname', name,'-pf'] + $saved_args)
|
14
14
|
|
15
15
|
path = nil
|
16
|
+
success = nil
|
16
17
|
TmpFile.with_file do |res|
|
17
18
|
Open.open(res, :mode => 'w') do |file|
|
18
19
|
@pid = Process.fork{
|
19
20
|
STDOUT.reopen res
|
20
21
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
21
22
|
}
|
22
|
-
file.close
|
23
23
|
Signal.trap(:INT) do
|
24
24
|
begin
|
25
25
|
Process.kill "INT", @pid
|
26
26
|
ensure
|
27
|
-
exit -1
|
27
|
+
Kernel.exit! -1
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
file.close
|
31
|
+
begin
|
32
|
+
p,s = Process.waitpid2 @pid
|
33
|
+
success = s.success?
|
34
|
+
rescue Errno::ECHILD
|
35
|
+
success = true
|
36
|
+
end
|
31
37
|
end
|
32
38
|
path = Open.read(res).strip if File.exists? res
|
33
39
|
end
|
34
40
|
path = "NO RESULT" if path.nil? or path.empty?
|
35
41
|
|
36
|
-
if
|
42
|
+
if success
|
37
43
|
Log.info "#{Log.color :green, "SUCCESS"} #{Log.color :magenta, workflow.to_s}##{Log.color :yellow, task} -- #{Log.color :cyan, name}"
|
38
44
|
return [path, true]
|
39
45
|
else
|
@@ -60,14 +66,15 @@ workflow = Workflow.require_workflow workflow
|
|
60
66
|
tasks = task ? [task] : workflow.libdir.examples.glob('*').collect{|file| File.basename file }
|
61
67
|
|
62
68
|
task_result = {}
|
63
|
-
|
69
|
+
TSV.traverse tasks, :threads => 5 do |task|
|
64
70
|
names = name ? [name] : workflow.libdir.examples[task].glob('*').collect{|file| File.basename file }
|
65
|
-
|
71
|
+
TSV.traverse names, :threads => 5 do |name|
|
66
72
|
success = run_task workflow, task, name
|
67
73
|
task_result[[task, name]] = success
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
77
|
+
|
71
78
|
task_result.each do |code,res|
|
72
79
|
task, name = code
|
73
80
|
path, success = res
|
@@ -309,14 +309,6 @@ begin
|
|
309
309
|
exit 0
|
310
310
|
end
|
311
311
|
|
312
|
-
Signal.trap(:INT) do
|
313
|
-
begin
|
314
|
-
job.abort if job.info[:pid] == job.pid
|
315
|
-
rescue
|
316
|
-
end
|
317
|
-
exit 0
|
318
|
-
end
|
319
|
-
|
320
312
|
job.fork
|
321
313
|
else
|
322
314
|
job.run(true)
|
@@ -407,6 +399,7 @@ if options.delete(:list_job_files)
|
|
407
399
|
end
|
408
400
|
|
409
401
|
if job_file = options.delete(:job_file)
|
402
|
+
job.join
|
410
403
|
file = job.file(job_file)
|
411
404
|
out.puts Path === file ? file.read : file
|
412
405
|
exit 0
|
@@ -2,6 +2,8 @@ require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_he
|
|
2
2
|
require 'rbbt/tsv'
|
3
3
|
require 'rbbt/tsv/parallel'
|
4
4
|
|
5
|
+
class StopException < StandardError; end
|
6
|
+
|
5
7
|
class TestTSVParallelThrough < Test::Unit::TestCase
|
6
8
|
|
7
9
|
def _test_traverse_tsv
|
@@ -307,16 +309,16 @@ class TestTSVParallelThrough < Test::Unit::TestCase
|
|
307
309
|
head = 2_000
|
308
310
|
cpus = 2
|
309
311
|
|
310
|
-
|
311
|
-
|
312
|
+
20.times do
|
313
|
+
Log.info Log.color :red, "TRAVERSE EXCEPTION"
|
312
314
|
stream = Organism.identifiers("Hsa/jun2011").open
|
313
315
|
dumper = TSV::Dumper.new Organism.identifiers("Hsa/jun2011").tsv_options
|
314
316
|
dumper.init
|
315
317
|
|
316
|
-
assert_raise do
|
318
|
+
assert_raise StopException do
|
317
319
|
TSV.traverse stream, :head => head, :cpus => cpus, :into => dumper do |k,v|
|
318
320
|
k = k.first
|
319
|
-
raise
|
321
|
+
raise StopException if rand(100) < 1
|
320
322
|
[k,v]
|
321
323
|
end
|
322
324
|
stream = dumper.stream
|
@@ -35,7 +35,7 @@ class TestProgress < Test::Unit::TestCase
|
|
35
35
|
bar.tick
|
36
36
|
sleep 0.3
|
37
37
|
end
|
38
|
-
Log.debug "Done progress"
|
38
|
+
#Log.debug "Done progress"
|
39
39
|
assert bar.history.length > 0
|
40
40
|
end
|
41
41
|
end
|
@@ -46,7 +46,7 @@ class TestProgress < Test::Unit::TestCase
|
|
46
46
|
bar.tick
|
47
47
|
sleep 0.2
|
48
48
|
end
|
49
|
-
Log.debug "Done progress"
|
49
|
+
#Log.debug "Done progress"
|
50
50
|
assert bar.history.length > 0
|
51
51
|
end
|
52
52
|
end
|