rbbt-util 5.13.2 → 5.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|