rbbt-util 5.13.1 → 5.13.2
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 +10 -35
- data/lib/rbbt/tsv/parallel/traverse.rb +118 -78
- data/lib/rbbt/tsv/parser.rb +6 -4
- data/lib/rbbt/tsv/stream.rb +107 -2
- data/lib/rbbt/tsv/util.rb +7 -15
- data/lib/rbbt/util/concurrency/processes.rb +16 -17
- data/lib/rbbt/util/concurrency/processes/worker.rb +5 -3
- data/lib/rbbt/util/log.rb +2 -1
- data/lib/rbbt/util/log/progress.rb +46 -20
- data/lib/rbbt/util/misc/exceptions.rb +11 -1
- data/lib/rbbt/util/misc/inspect.rb +1 -1
- data/lib/rbbt/util/misc/lock.rb +1 -1
- data/lib/rbbt/util/misc/pipes.rb +66 -25
- data/lib/rbbt/util/semaphore.rb +3 -3
- data/lib/rbbt/workflow/accessor.rb +34 -12
- data/lib/rbbt/workflow/definition.rb +7 -3
- data/lib/rbbt/workflow/step.rb +4 -3
- data/lib/rbbt/workflow/step/run.rb +104 -30
- data/lib/rbbt/workflow/usage.rb +1 -1
- data/share/rbbt_commands/workflow/task +11 -1
- data/test/rbbt/tsv/parallel/test_traverse.rb +31 -34
- data/test/rbbt/tsv/test_filter.rb +6 -6
- data/test/rbbt/util/concurrency/test_processes.rb +0 -1
- metadata +2 -2
data/lib/rbbt/tsv/util.rb
CHANGED
@@ -80,20 +80,6 @@ module TSV
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
def self.get_stream(file, open_options = {})
|
84
|
-
case
|
85
|
-
when Path === file
|
86
|
-
file.open(open_options)
|
87
|
-
when file.respond_to?(:gets)
|
88
|
-
file.rewind if file.respond_to?(:rewind) and file.eof?
|
89
|
-
file
|
90
|
-
when String === file
|
91
|
-
Open.open(file, open_options)
|
92
|
-
else
|
93
|
-
raise "Cannot get stream from: #{file.inspect}"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
83
|
def self.get_stream(file, open_options = {})
|
98
84
|
case file
|
99
85
|
when Path
|
@@ -108,8 +94,14 @@ module TSV
|
|
108
94
|
raise "Could not open file given by String: #{Misc.fingerprint file}" unless Open.remote?(file) or File.exists? file
|
109
95
|
Open.open(file, open_options)
|
110
96
|
when (defined? Step and Step)
|
97
|
+
file.grace
|
111
98
|
stream = file.get_stream
|
112
|
-
stream
|
99
|
+
if stream
|
100
|
+
stream
|
101
|
+
else
|
102
|
+
file.join
|
103
|
+
get_stream(file.path)
|
104
|
+
end
|
113
105
|
when TSV::Dumper
|
114
106
|
file.stream
|
115
107
|
when Array
|
@@ -29,10 +29,10 @@ class RbbtProcessQueue
|
|
29
29
|
@callback.call p
|
30
30
|
end
|
31
31
|
rescue Aborted
|
32
|
-
|
32
|
+
parent.raise $!
|
33
33
|
rescue ClosedStream
|
34
34
|
rescue Exception
|
35
|
-
Log.
|
35
|
+
Log.warn "Callback thread exception"
|
36
36
|
parent.raise $!
|
37
37
|
ensure
|
38
38
|
@callback_queue.sread.close unless @callback_queue.sread.closed?
|
@@ -58,9 +58,9 @@ class RbbtProcessQueue
|
|
58
58
|
rescue Aborted
|
59
59
|
@processes.each{|p| p.abort }
|
60
60
|
@processes.each{|p| p.join }
|
61
|
-
Log.
|
61
|
+
Log.warn "Process monitor aborted"
|
62
62
|
rescue Exception
|
63
|
-
Log.
|
63
|
+
Log.warn "Process monitor exception: #{$!.message}"
|
64
64
|
@processes.each{|p| p.abort }
|
65
65
|
@callback_thread.raise $! if @callback_thread
|
66
66
|
parent.raise $!
|
@@ -72,7 +72,7 @@ class RbbtProcessQueue
|
|
72
72
|
begin
|
73
73
|
@callback_queue.push ClosedStream.new if @callback_thread.alive?
|
74
74
|
rescue
|
75
|
-
Log.
|
75
|
+
Log.warn "Error closing callback: #{$!.message}"
|
76
76
|
end
|
77
77
|
@callback_thread.join if @callback_thread.alive?
|
78
78
|
end
|
@@ -89,28 +89,27 @@ class RbbtProcessQueue
|
|
89
89
|
Log.exception $!
|
90
90
|
raise $!
|
91
91
|
ensure
|
92
|
-
@queue.swrite.close
|
92
|
+
@queue.swrite.close unless @queue.swrite.closed?
|
93
93
|
end
|
94
94
|
|
95
95
|
@join.call if @join
|
96
96
|
end
|
97
97
|
|
98
98
|
def clean
|
99
|
-
if @process_monitor.alive?
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
if @callback_thread and @callback_thread.alive?
|
105
|
-
@callback_thread.raise Aborted.new
|
106
|
-
aborted = true
|
99
|
+
if @process_monitor.alive? or @callback_thread.alive?
|
100
|
+
self.abort
|
101
|
+
else
|
102
|
+
self.join
|
107
103
|
end
|
108
|
-
raise Aborted.new if aborted
|
109
104
|
end
|
110
105
|
|
111
106
|
def abort
|
112
|
-
|
113
|
-
|
107
|
+
begin
|
108
|
+
@process_monitor.raise(Aborted.new); @process_monitor.join if @process_monitor and @process_monitor.alive?
|
109
|
+
@callback_thread.raise(Aborted.new); @callback_thread.join if @callback_thread and @callback_thread.alive?
|
110
|
+
ensure
|
111
|
+
join
|
112
|
+
end
|
114
113
|
end
|
115
114
|
|
116
115
|
def process(*e)
|
@@ -17,7 +17,9 @@ class RbbtProcessQueue
|
|
17
17
|
Misc.purge_pipes
|
18
18
|
end
|
19
19
|
|
20
|
-
Signal.trap(:INT){
|
20
|
+
Signal.trap(:INT){
|
21
|
+
Kernel.exit! -1
|
22
|
+
}
|
21
23
|
|
22
24
|
loop do
|
23
25
|
p = @queue.pop
|
@@ -29,8 +31,8 @@ class RbbtProcessQueue
|
|
29
31
|
end
|
30
32
|
Kernel.exit! 0
|
31
33
|
rescue ClosedStream
|
32
|
-
rescue Aborted
|
33
|
-
Log.
|
34
|
+
rescue Aborted, Interrupt
|
35
|
+
Log.warn "Worker #{Process.pid} aborted"
|
34
36
|
Kernel.exit! -1
|
35
37
|
rescue Exception
|
36
38
|
Log.exception $!
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rbbt/util/log'
|
|
2
2
|
module Log
|
3
3
|
class ProgressBar
|
4
4
|
|
5
|
-
attr_accessor :depth, :num_reports, :desc, :io, :severity, :history
|
5
|
+
attr_accessor :depth, :num_reports, :desc, :io, :severity, :history, :max
|
6
6
|
|
7
7
|
# Creates a new instance. Max is the total number of iterations of the
|
8
8
|
# loop. The depth represents how many other loops are above this one,
|
@@ -46,7 +46,6 @@ module Log
|
|
46
46
|
nil
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
def progress
|
51
50
|
@current.to_f/ @max
|
52
51
|
end
|
@@ -104,13 +103,17 @@ module Log
|
|
104
103
|
end
|
105
104
|
|
106
105
|
def thr
|
107
|
-
@history ||= []
|
108
106
|
@last_report = Time.now if @last_report == -1
|
109
107
|
time = Time.now - @last_report
|
108
|
+
time = 0.000001 if time == 0
|
110
109
|
thr = (@current / time).to_i
|
111
110
|
|
112
|
-
@history
|
113
|
-
|
111
|
+
if @history.nil?
|
112
|
+
@history ||= []
|
113
|
+
else
|
114
|
+
@history << thr
|
115
|
+
@history.shift if @history.length > 10
|
116
|
+
end
|
114
117
|
|
115
118
|
thr
|
116
119
|
end
|
@@ -118,7 +121,7 @@ module Log
|
|
118
121
|
def mean
|
119
122
|
@mean_max ||= 0
|
120
123
|
if @history.length > 3
|
121
|
-
mean = Misc.mean(@history
|
124
|
+
mean = Misc.mean(@history)
|
122
125
|
@mean_max = mean if mean > @mean_max
|
123
126
|
end
|
124
127
|
mean
|
@@ -132,7 +135,7 @@ module Log
|
|
132
135
|
indicator = Log.color(:magenta, @desc)
|
133
136
|
indicator << " #{ Log.color :blue, thr } per second"
|
134
137
|
|
135
|
-
indicator << "
|
138
|
+
indicator << " #{ Log.color :yellow, mean.to_i } avg. #{ Log.color :yellow, @mean_max.to_i} max." if mean
|
136
139
|
|
137
140
|
indicator
|
138
141
|
end
|
@@ -150,7 +153,9 @@ module Log
|
|
150
153
|
# original line. Everything is printed to stderr.
|
151
154
|
def report(io = STDERR)
|
152
155
|
if Log::LAST != "progress"
|
153
|
-
|
156
|
+
Log::ProgressBar.cleanup_bars
|
157
|
+
print(io, Log.color(:yellow, "== Progress"))
|
158
|
+
(BARS.length-1).times{print(io, "\n")}
|
154
159
|
end
|
155
160
|
print(io, up_lines(@depth) << report_msg << down_lines(@depth)) if severity >= Log.severity
|
156
161
|
@last_report = Time.now if @last_report == -1
|
@@ -158,15 +163,24 @@ module Log
|
|
158
163
|
|
159
164
|
def throughput(io = STDERR)
|
160
165
|
if Log::LAST != "progress"
|
161
|
-
|
166
|
+
Log::ProgressBar.cleanup_bars
|
167
|
+
print(io, Log.color(:yellow, "== Progress"))
|
168
|
+
(BARS.length-1).times{print(io, "\n")}
|
162
169
|
end
|
163
170
|
print(io, up_lines(@depth) << throughput_msg << down_lines(@depth)) if severity >= Log.severity
|
164
171
|
@last_report = Time.now
|
165
172
|
@current = 0
|
166
173
|
end
|
174
|
+
|
175
|
+
def done
|
176
|
+
print(io, up_lines(@depth) << Log.color(:magenta, @desc) << Log.color(:green, " DONE") << down_lines(@depth)) if severity >= Log.severity
|
177
|
+
end
|
178
|
+
|
167
179
|
BAR_MUTEX = Mutex.new
|
168
180
|
BARS = []
|
181
|
+
REMOVE = []
|
169
182
|
def self.new_bar(max, options = {})
|
183
|
+
cleanup_bars
|
170
184
|
BAR_MUTEX.synchronize do
|
171
185
|
options = Misc.add_defaults options, :depth => BARS.length
|
172
186
|
BARS << (bar = ProgressBar.new(max, options))
|
@@ -174,18 +188,27 @@ module Log
|
|
174
188
|
end
|
175
189
|
end
|
176
190
|
|
177
|
-
def self.
|
191
|
+
def self.cleanup_bars
|
178
192
|
BAR_MUTEX.synchronize do
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
193
|
+
REMOVE.each do |bar|
|
194
|
+
index = BARS.index bar
|
195
|
+
if index
|
196
|
+
(index..BARS.length-1).each do |pos|
|
197
|
+
bar = BARS[pos]
|
198
|
+
bar.depth = pos - 1
|
199
|
+
BARS[pos-1] = bar
|
200
|
+
end
|
201
|
+
BARS.pop
|
202
|
+
end
|
187
203
|
end
|
188
|
-
|
204
|
+
REMOVE.clear
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.remove_bar(bar)
|
209
|
+
BAR_MUTEX.synchronize do
|
210
|
+
bar.done unless bar.max
|
211
|
+
REMOVE << bar
|
189
212
|
end
|
190
213
|
end
|
191
214
|
|
@@ -193,8 +216,11 @@ module Log
|
|
193
216
|
bar = new_bar(max, options)
|
194
217
|
begin
|
195
218
|
yield bar
|
219
|
+
keep = false
|
220
|
+
rescue KeepBar
|
221
|
+
keep = true
|
196
222
|
ensure
|
197
|
-
remove_bar(bar)
|
223
|
+
remove_bar(bar) unless bar
|
198
224
|
end
|
199
225
|
end
|
200
226
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
class ParameterException < Exception; end
|
2
2
|
class FieldNotFoundError < Exception;end
|
3
|
-
class Aborted < Exception
|
3
|
+
class Aborted < Exception
|
4
|
+
def initialize(*args)
|
5
|
+
super(*args)
|
6
|
+
end
|
7
|
+
end
|
4
8
|
class TryAgain < Exception; end
|
5
9
|
class ClosedStream < Exception; end
|
6
10
|
class ProcessFailed < Exception; end
|
@@ -10,3 +14,9 @@ class KeepLocked < Exception
|
|
10
14
|
@payload = payload
|
11
15
|
end
|
12
16
|
end
|
17
|
+
class KeepBar < Exception
|
18
|
+
attr_accessor :payload
|
19
|
+
def initialize(payload)
|
20
|
+
@payload = payload
|
21
|
+
end
|
22
|
+
end
|
@@ -42,7 +42,7 @@ module Misc
|
|
42
42
|
when (defined? TSV and TSV::Parser)
|
43
43
|
"<TSVStream:" + (obj.filename || "NOFILENAME") + "--" << Misc.fingerprint(obj.options) << ">"
|
44
44
|
when IO
|
45
|
-
|
45
|
+
(obj.respond_to?(:filename) and obj.filename ) ? "<IO:" + (obj.filename || obj.inspect) + ">" : obj.inspect
|
46
46
|
when File
|
47
47
|
"<File:" + obj.path + ">"
|
48
48
|
when Array
|
data/lib/rbbt/util/misc/lock.rb
CHANGED
@@ -22,7 +22,7 @@ module Misc
|
|
22
22
|
raise "No info" unless info
|
23
23
|
|
24
24
|
if hostname == info["host"] and not Misc.pid_exists?(info["pid"])
|
25
|
-
Log.
|
25
|
+
Log.high("Removing lockfile: #{lock_path}. This pid #{Process.pid}. Content: #{info.inspect}")
|
26
26
|
FileUtils.rm lock_path
|
27
27
|
end
|
28
28
|
end
|
data/lib/rbbt/util/misc/pipes.rb
CHANGED
@@ -124,22 +124,22 @@ module Misc
|
|
124
124
|
begin
|
125
125
|
stream_in1.write block;
|
126
126
|
rescue IOError
|
127
|
-
Log.
|
127
|
+
Log.warn("Tee stream 1 #{Misc.fingerprint stream} IOError: #{$!.message}");
|
128
128
|
skip1 = true
|
129
129
|
end unless skip1
|
130
130
|
|
131
131
|
begin
|
132
132
|
stream_in2.write block
|
133
133
|
rescue IOError
|
134
|
-
Log.
|
134
|
+
Log.warn("Tee stream 2 #{Misc.fingerprint stream} IOError: #{$!.message}");
|
135
135
|
skip2 = true
|
136
136
|
end unless skip2
|
137
137
|
end
|
138
138
|
stream_in1.close unless stream_in1.closed?
|
139
139
|
stream_in2.close unless stream_in2.closed?
|
140
140
|
stream.join if stream.respond_to? :join
|
141
|
-
rescue Aborted
|
142
|
-
Log.
|
141
|
+
rescue Aborted, Interrupt
|
142
|
+
Log.warn("Tee stream #{Misc.fingerprint stream} Aborted");
|
143
143
|
stream.abort if stream.respond_to? :abort
|
144
144
|
rescue Exception
|
145
145
|
Log.exception $!
|
@@ -177,6 +177,8 @@ module Misc
|
|
177
177
|
io.join if io.respond_to? :join
|
178
178
|
return
|
179
179
|
end
|
180
|
+
|
181
|
+
Log.medium "Consuming stream #{Misc.fingerprint io}"
|
180
182
|
if in_thread
|
181
183
|
Thread.new do
|
182
184
|
consume_stream(io, false)
|
@@ -188,9 +190,9 @@ module Misc
|
|
188
190
|
Thread.pass
|
189
191
|
end
|
190
192
|
io.join if io.respond_to? :join
|
193
|
+
rescue IOError
|
191
194
|
rescue
|
192
|
-
Log.
|
193
|
-
Log.exception $!
|
195
|
+
Log.warn "Exception consuming stream: #{io.inspect}"
|
194
196
|
io.abort if io.respond_to? :abort
|
195
197
|
end
|
196
198
|
end
|
@@ -240,9 +242,13 @@ module Misc
|
|
240
242
|
|
241
243
|
Open.mv tmp_path, path
|
242
244
|
rescue Aborted
|
243
|
-
Log.
|
245
|
+
Log.warn "Aborted sensiblewrite -- #{ Log.reset << Log.color(:blue, path) }"
|
246
|
+
content.abort if content.respond_to? :abort
|
247
|
+
content.join if content.respond_to? :join
|
244
248
|
rescue Exception
|
245
|
-
Log.
|
249
|
+
Log.warn "Exception in sensiblewrite: #{$!.message} -- #{ Log.color :blue, path }"
|
250
|
+
content.abort if content.respond_to? :abort
|
251
|
+
content.join if content.respond_to? :join
|
246
252
|
Open.rm_f path if File.exists? path
|
247
253
|
raise $!
|
248
254
|
ensure
|
@@ -264,29 +270,40 @@ module Misc
|
|
264
270
|
|
265
271
|
def self.sort_stream(stream, header_hash = "#")
|
266
272
|
Misc.open_pipe do |sin|
|
267
|
-
|
268
|
-
|
269
|
-
|
273
|
+
begin
|
274
|
+
if defined? Step and Step === stream
|
275
|
+
step = stream
|
276
|
+
stream = stream.get_stream || stream.path.open
|
277
|
+
end
|
278
|
+
|
270
279
|
line = stream.gets
|
271
|
-
|
280
|
+
while line =~ /^#{header_hash}/ do
|
281
|
+
sin.puts line
|
282
|
+
line = stream.gets
|
283
|
+
end
|
272
284
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
285
|
+
line_stream = Misc.open_pipe do |line_stream_in|
|
286
|
+
begin
|
287
|
+
while line
|
288
|
+
line_stream_in.puts line
|
289
|
+
line = stream.gets
|
290
|
+
end
|
291
|
+
stream.join if stream.respond_to? :join
|
292
|
+
rescue
|
293
|
+
stream.abort if stream.respond_to? :abort
|
294
|
+
raise $!
|
278
295
|
end
|
279
|
-
stream.join if stream.respond_to? :join
|
280
|
-
rescue
|
281
|
-
stream.abort if stream.respond_to? :abort
|
282
|
-
raise $!
|
283
296
|
end
|
284
|
-
end
|
285
297
|
|
286
|
-
|
298
|
+
sorted = CMD.cmd("sort", :in => line_stream, :pipe => true)
|
287
299
|
|
288
|
-
|
289
|
-
|
300
|
+
while block = sorted.read(2048)
|
301
|
+
sin.write block
|
302
|
+
end
|
303
|
+
rescue
|
304
|
+
if defined? step and step
|
305
|
+
step.abort
|
306
|
+
end
|
290
307
|
end
|
291
308
|
end
|
292
309
|
end
|
@@ -330,6 +347,14 @@ module Misc
|
|
330
347
|
num_streams = streams.length
|
331
348
|
Misc.open_pipe do |sin|
|
332
349
|
sin.puts header if header
|
350
|
+
streams = streams.collect do |stream|
|
351
|
+
if defined? Step and Step === stream
|
352
|
+
stream.get_stream || stream.join.path.open
|
353
|
+
else
|
354
|
+
stream
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
333
358
|
begin
|
334
359
|
done_streams = []
|
335
360
|
lines ||= streams.collect{|s| s.gets }
|
@@ -369,6 +394,7 @@ module Misc
|
|
369
394
|
stream.join if stream.respond_to? :join
|
370
395
|
end
|
371
396
|
rescue
|
397
|
+
Log.exception $!
|
372
398
|
streams.each do |stream|
|
373
399
|
stream.abort if stream.respond_to? :abort
|
374
400
|
end
|
@@ -388,4 +414,19 @@ module Misc
|
|
388
414
|
tee2
|
389
415
|
end
|
390
416
|
|
417
|
+
def self.save_stream(file, stream)
|
418
|
+
out, save = Misc.tee_stream stream
|
419
|
+
|
420
|
+
Thread.new(Thread.current) do |parent|
|
421
|
+
begin
|
422
|
+
Misc.sensiblewrite(file, save)
|
423
|
+
rescue
|
424
|
+
save.abort if save.respond_to? :abort
|
425
|
+
parent.raise $!
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
out
|
430
|
+
end
|
431
|
+
|
391
432
|
end
|