rbbt-util 5.10.2 → 5.11.1
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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee7693bddd82af53509c8ed2e5414f1a86ac51ce
|
4
|
+
data.tar.gz: 5122a7d8c8404d7a045e571310cfb34c3e808bbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e75a716cf8fd069b161d3f167217b0a329eac88d1458e6133fdbc0b3e51cfcd647e6c53cf2e4cbe9a28ab5499e2822138797688eb75239fffe458975195b6ad3
|
7
|
+
data.tar.gz: ae968a716ff89c35ba2a07300ac56cba42452692a75e2b811051d360fd64ce51c4f95aba36a9d974234450cdfdab846ddd31a367383a41ac80b1b49f177ac303
|
data/lib/rbbt/persist.rb
CHANGED
@@ -155,11 +155,7 @@ module Persist
|
|
155
155
|
Misc.sensiblewrite(path, content * "\n" + "\n")
|
156
156
|
end
|
157
157
|
when IO
|
158
|
-
Misc.sensiblewrite(path)
|
159
|
-
while block = content.read(2048)
|
160
|
-
file.write block
|
161
|
-
end
|
162
|
-
end
|
158
|
+
Misc.sensiblewrite(path, content)
|
163
159
|
else
|
164
160
|
Misc.sensiblewrite(path, content.to_s)
|
165
161
|
end
|
@@ -181,14 +177,20 @@ module Persist
|
|
181
177
|
|
182
178
|
saver_pid = Process.fork do
|
183
179
|
out.close
|
184
|
-
|
180
|
+
stream.close
|
181
|
+
Misc.purge_pipes
|
185
182
|
begin
|
186
183
|
Misc.lock(path) do
|
187
184
|
save_file(path, type, file)
|
188
185
|
end
|
186
|
+
rescue Aborted
|
187
|
+
stream.abort if stream.respond_to? :abort
|
188
|
+
raise $!
|
189
189
|
rescue Exception
|
190
190
|
Log.exception $!
|
191
|
+
Kernel.exit! -1
|
191
192
|
end
|
193
|
+
Kernel.exit! 0
|
192
194
|
end
|
193
195
|
file.close
|
194
196
|
ConcurrentStream.setup(out, :pids => [saver_pid], :filename => path)
|
@@ -203,7 +205,11 @@ module Persist
|
|
203
205
|
Misc.lock(path) do
|
204
206
|
save_file(path, type, file)
|
205
207
|
end
|
208
|
+
rescue Aborted
|
209
|
+
Log.error "Tee stream thread aborted"
|
210
|
+
stream.abort if stream.respond_to? :abort
|
206
211
|
rescue Exception
|
212
|
+
stream.abort if stream.respond_to? :abort
|
207
213
|
Log.exception $!
|
208
214
|
parent.raise $!
|
209
215
|
end
|
@@ -318,36 +324,70 @@ module Persist
|
|
318
324
|
end
|
319
325
|
|
320
326
|
begin
|
327
|
+
|
321
328
|
lock_filename = Persist.persistence_path(path + '.persist', {:dir => Persist.lock_dir})
|
322
|
-
Misc.lock lock_filename do
|
329
|
+
Misc.lock lock_filename do |lockfile|
|
323
330
|
if is_persisted?(path, persist_options)
|
324
331
|
Log.low "Persist up-to-date (suddenly): #{ path } - #{Misc.fingerprint persist_options}"
|
325
332
|
return path if persist_options[:no_load]
|
326
333
|
return load_file(path, type)
|
327
334
|
end
|
328
335
|
|
329
|
-
Log.medium "Persist create: #{ path } - #{persist_options
|
336
|
+
Log.medium "Persist create: #{ path } - #{Misc.fingerprint persist_options}"
|
337
|
+
|
330
338
|
res = yield
|
331
339
|
|
340
|
+
if persist_options[:no_load] == :stream
|
341
|
+
case res
|
342
|
+
when IO
|
343
|
+
res = tee_stream(res, path, type, res.respond_to?(:callback)? res.callback : nil)
|
344
|
+
ConcurrentStream.setup res do
|
345
|
+
lockfile.unlock
|
346
|
+
end
|
347
|
+
raise KeepLocked.new res
|
348
|
+
when TSV::Dumper
|
349
|
+
res = tee_stream(res.stream, path, type, res.respond_to?(:callback)? res.callback : nil)
|
350
|
+
ConcurrentStream.setup res do
|
351
|
+
lockfile.unlock
|
352
|
+
end
|
353
|
+
raise KeepLocked.new res
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
332
357
|
case res
|
333
|
-
when
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
358
|
+
when IO
|
359
|
+
begin
|
360
|
+
res = case
|
361
|
+
when :array
|
362
|
+
res.read.split "\n"
|
363
|
+
when :tsv
|
364
|
+
TSV.open(res)
|
365
|
+
else
|
366
|
+
res.read
|
367
|
+
end
|
368
|
+
rescue
|
369
|
+
res.abort if res.respond_to? :abort
|
370
|
+
ensure
|
371
|
+
res.join if res.respond_to? :join
|
372
|
+
end
|
338
373
|
when TSV::Dumper
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
374
|
+
begin
|
375
|
+
io = res.stream
|
376
|
+
res = TSV.open(io)
|
377
|
+
rescue
|
378
|
+
io.abort if io.respond_to? :abort
|
379
|
+
ensure
|
380
|
+
io.join if io.respond_to? :join
|
344
381
|
end
|
345
382
|
end
|
346
383
|
|
347
|
-
|
384
|
+
Misc.lock(path) do
|
385
|
+
save_file(path, type, res)
|
386
|
+
end
|
348
387
|
|
349
|
-
res
|
388
|
+
persist_options[:no_load] ? path : res
|
350
389
|
end
|
390
|
+
|
351
391
|
rescue
|
352
392
|
Log.high "Error in persist: #{path}#{Open.exists?(path) ? Log.color(:red, " Erasing") : ""}"
|
353
393
|
FileUtils.rm path if Open.exists? path
|
data/lib/rbbt/tsv/dumper.rb
CHANGED
@@ -10,6 +10,19 @@ module TSV
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.stream_name(obj)
|
14
|
+
filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
15
|
+
filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
16
|
+
stream_obj = obj_stream(obj)
|
17
|
+
filename_obj.nil? ? stream_obj.inspect : filename_obj + "(#{stream_obj.inspect})"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.report(msg, obj, into)
|
21
|
+
into = into[:into] if Hash === into and into.include? :into
|
22
|
+
|
23
|
+
Log.error "#{ msg } #{stream_name(obj)} -> #{stream_name(into)}"
|
24
|
+
end
|
25
|
+
|
13
26
|
def self.traverse_tsv(tsv, options = {}, &block)
|
14
27
|
callback = Misc.process_options options, :callback
|
15
28
|
|
@@ -103,15 +116,21 @@ module TSV
|
|
103
116
|
obj.traverse(options, &block)
|
104
117
|
end
|
105
118
|
when IO, File, StringIO
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
119
|
+
begin
|
120
|
+
if options[:type] == :array
|
121
|
+
traverse_io_array(obj, options, &block)
|
122
|
+
else
|
123
|
+
traverse_io(obj, options, &block)
|
124
|
+
end
|
125
|
+
rescue Exception
|
126
|
+
raise Aborted
|
127
|
+
ensure
|
128
|
+
begin
|
129
|
+
obj.close if obj.respond_to? :close and not obj.closed?
|
130
|
+
ensure
|
131
|
+
obj.join if obj.respond_to? :join
|
132
|
+
end
|
110
133
|
end
|
111
|
-
|
112
|
-
io = obj
|
113
|
-
obj.join if io.respond_to? :join
|
114
|
-
io.close if io.respond_to? :close and not io.closed?
|
115
134
|
when Path
|
116
135
|
obj.open do |stream|
|
117
136
|
traverse_obj(stream, options, &block)
|
@@ -120,12 +139,13 @@ module TSV
|
|
120
139
|
traverse_obj(obj.stream, options, &block)
|
121
140
|
when (defined? Step and Step)
|
122
141
|
|
123
|
-
|
124
|
-
|
125
|
-
|
142
|
+
stream = obj.get_stream
|
143
|
+
|
144
|
+
if stream
|
145
|
+
traverse_obj(stream, options, &block)
|
126
146
|
else
|
127
147
|
obj.join
|
128
|
-
traverse_obj(obj.path
|
148
|
+
traverse_obj(obj.path, options, &block)
|
129
149
|
end
|
130
150
|
when Array
|
131
151
|
traverse_array(obj, options, &block)
|
@@ -163,45 +183,55 @@ module TSV
|
|
163
183
|
end
|
164
184
|
|
165
185
|
def self.traverse_cpus(num, obj, options, &block)
|
166
|
-
|
167
|
-
|
168
|
-
|
186
|
+
begin
|
187
|
+
filename = obj.respond_to?(:filename)? obj.filename : "none"
|
188
|
+
callback, cleanup = Misc.process_options options, :callback, :cleanup
|
189
|
+
q = RbbtProcessQueue.new num, cleanup
|
169
190
|
|
170
|
-
|
171
|
-
|
191
|
+
q.callback &callback
|
192
|
+
q.init &block
|
172
193
|
|
173
|
-
|
174
|
-
|
175
|
-
|
194
|
+
traverse_obj(obj, options) do |*p|
|
195
|
+
q.process *p
|
196
|
+
end
|
176
197
|
|
177
|
-
|
198
|
+
into = options[:into]
|
199
|
+
rescue Exception
|
200
|
+
q.abort
|
201
|
+
raise $!
|
202
|
+
ensure
|
203
|
+
q.join
|
204
|
+
end
|
178
205
|
|
179
|
-
q.join
|
180
206
|
end
|
181
207
|
|
182
208
|
def self.store_into(store, value)
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
if
|
188
|
-
store.
|
209
|
+
begin
|
210
|
+
case store
|
211
|
+
when Hash
|
212
|
+
return if value.nil?
|
213
|
+
if Hash === value
|
214
|
+
if TSV === store and store.type == :double
|
215
|
+
store.merge_zip value
|
216
|
+
else
|
217
|
+
store.merge! value
|
218
|
+
end
|
189
219
|
else
|
190
|
-
|
220
|
+
k,v = value
|
221
|
+
store[k] = v
|
191
222
|
end
|
223
|
+
when TSV::Dumper
|
224
|
+
return if value.nil?
|
225
|
+
store.add *value
|
226
|
+
when IO
|
227
|
+
return if value.nil?
|
228
|
+
store.puts value.strip
|
192
229
|
else
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
store.add *value
|
199
|
-
when IO
|
200
|
-
return if value.nil?
|
201
|
-
store.puts value.strip
|
202
|
-
else
|
203
|
-
store << value
|
204
|
-
end
|
230
|
+
store << value
|
231
|
+
end
|
232
|
+
rescue
|
233
|
+
raise "Error storing into #{store.inspect}: #{$!.message}"
|
234
|
+
end
|
205
235
|
end
|
206
236
|
|
207
237
|
def self.get_streams_to_close(obj)
|
@@ -268,30 +298,6 @@ module TSV
|
|
268
298
|
ConcurrentStream.setup(obj_stream(into), :threads => thread)
|
269
299
|
end
|
270
300
|
|
271
|
-
def self.stream_name(obj)
|
272
|
-
filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
273
|
-
filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
274
|
-
stream_obj = obj_stream(obj)
|
275
|
-
filename_obj.nil? ? stream_obj.inspect : filename_obj + "(#{stream_obj.inspect})"
|
276
|
-
end
|
277
|
-
|
278
|
-
def self.report(msg, obj, into)
|
279
|
-
into = into[:into] if Hash === into and into.include? :into
|
280
|
-
|
281
|
-
#filename_into = into.respond_to?(:filename) ? into.filename : nil
|
282
|
-
#filename_into ||= into.respond_to?(:path) ? into.path : nil
|
283
|
-
#stream_into = obj_stream(into)
|
284
|
-
#str_into = filename_into.nil? ? stream_into.inspect : filename_into + "(#{stream_into.inspect})"
|
285
|
-
|
286
|
-
#filename_obj = obj.respond_to?(:filename) ? obj.filename : nil
|
287
|
-
#filename_obj ||= obj.respond_to?(:path) ? obj.path : nil
|
288
|
-
#stream_obj = obj_stream(obj)
|
289
|
-
#str_obj = filename_obj.nil? ? stream_obj.inspect : filename_obj + "(#{stream_obj.inspect})"
|
290
|
-
|
291
|
-
#Log.error "#{ msg } #{filename_obj} - #{filename_into}"
|
292
|
-
Log.error "#{ msg } #{stream_name(obj)} -> #{stream_name(into)}"
|
293
|
-
end
|
294
|
-
|
295
301
|
def self.traverse(obj, options = {}, &block)
|
296
302
|
threads = Misc.process_options options, :threads
|
297
303
|
cpus = Misc.process_options options, :cpus
|
@@ -300,12 +306,24 @@ module TSV
|
|
300
306
|
threads = nil if threads and threads.to_i <= 1
|
301
307
|
cpus = nil if cpus and cpus.to_i <= 1
|
302
308
|
|
309
|
+
if into == :stream
|
310
|
+
sout = Misc.open_pipe false, false do |sin|
|
311
|
+
begin
|
312
|
+
traverse(obj, options.merge(:into => sin), &block)
|
313
|
+
rescue Exception
|
314
|
+
sin.abort if sin.respond_to? :abort
|
315
|
+
end
|
316
|
+
end
|
317
|
+
return sout
|
318
|
+
end
|
319
|
+
|
303
320
|
if into
|
304
321
|
options[:callback] = Proc.new do |e|
|
305
322
|
begin
|
306
323
|
store_into into, e
|
307
324
|
rescue Exception
|
308
325
|
Log.exception $!
|
326
|
+
raise $!
|
309
327
|
end
|
310
328
|
end
|
311
329
|
|
data/lib/rbbt/tsv/parser.rb
CHANGED
@@ -16,9 +16,9 @@ module TSV
|
|
16
16
|
|
17
17
|
# Get line
|
18
18
|
|
19
|
-
Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
19
|
+
#Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
20
20
|
line = stream.gets
|
21
|
-
raise "Empty content" if line.nil?
|
21
|
+
raise "Empty content: #{ stream.inspect }" if line.nil?
|
22
22
|
line = Misc.fixutf8 line
|
23
23
|
line.chomp!
|
24
24
|
|
@@ -41,7 +41,7 @@ module TSV
|
|
41
41
|
@key_field = @fields.shift
|
42
42
|
@key_field = @key_field[(0 + header_hash.length)..-1] # Remove initial hash character
|
43
43
|
|
44
|
-
Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
44
|
+
#Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
45
45
|
line = @header_hash != "" ? Misc.fixutf8(stream.gets) : nil
|
46
46
|
end
|
47
47
|
|
@@ -123,14 +123,20 @@ module TSV
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def get_values_flat(parts)
|
126
|
+
begin
|
127
|
+
orig = parts
|
126
128
|
if key_position and key_position != 0 and field_positions.nil?
|
127
129
|
value = parts.shift
|
128
130
|
keys = parts.dup
|
129
131
|
return [keys, [value]]
|
130
132
|
end
|
131
133
|
|
132
|
-
|
134
|
+
return parts.shift.split(@sep2, -1).first, parts.collect{|value| value.split(@sep2, -1)}.flatten if
|
133
135
|
field_positions.nil? and (key_position.nil? or key_position == 0)
|
136
|
+
rescue
|
137
|
+
eee [:rescue, orig]
|
138
|
+
raise $!
|
139
|
+
end
|
134
140
|
|
135
141
|
keys = parts[key_position].split(@sep2, -1)
|
136
142
|
|
@@ -486,6 +492,7 @@ module TSV
|
|
486
492
|
# parser
|
487
493
|
line_num = 1
|
488
494
|
begin
|
495
|
+
|
489
496
|
while not line.nil?
|
490
497
|
begin
|
491
498
|
progress_monitor.tick(stream.pos) if progress_monitor
|
@@ -494,13 +501,14 @@ module TSV
|
|
494
501
|
|
495
502
|
line = Misc.fixutf8(line)
|
496
503
|
line = self.process line
|
504
|
+
raise SKIP_LINE if line.empty?
|
497
505
|
parts = self.chop_line line
|
498
506
|
key, values = self.get_values parts
|
499
507
|
values = self.cast_values values if self.cast?
|
500
508
|
|
501
509
|
yield key, values
|
502
510
|
|
503
|
-
Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
511
|
+
#Thread.pass while IO.select([stream], nil, nil, 1).nil? if IO === stream
|
504
512
|
|
505
513
|
line = stream.gets
|
506
514
|
|
@@ -515,11 +523,18 @@ module TSV
|
|
515
523
|
end
|
516
524
|
rescue END_PARSING
|
517
525
|
break
|
518
|
-
rescue IOError
|
519
|
-
|
520
|
-
|
526
|
+
#rescue IOError
|
527
|
+
# Log.exception $!
|
528
|
+
# break
|
529
|
+
rescue Exception
|
530
|
+
stream.abort if stream.respond_to? :abort
|
531
|
+
raise $!
|
521
532
|
end
|
522
533
|
end
|
534
|
+
|
535
|
+
ensure
|
536
|
+
stream.close
|
537
|
+
stream.join if stream.respond_to? :join
|
523
538
|
end
|
524
539
|
|
525
540
|
self
|
@@ -27,10 +27,11 @@ class RbbtProcessQueue
|
|
27
27
|
raise p.first if Array === p and Exception === p.first
|
28
28
|
@callback.call p
|
29
29
|
end
|
30
|
+
rescue Aborted
|
31
|
+
Log.error "Callback thread aborted"
|
30
32
|
rescue ClosedStream
|
31
33
|
rescue Exception
|
32
34
|
Log.exception $!
|
33
|
-
sleep 1
|
34
35
|
parent.raise $!
|
35
36
|
ensure
|
36
37
|
@callback_queue.sread.close unless @callback_queue.sread.closed?
|
@@ -53,14 +54,13 @@ class RbbtProcessQueue
|
|
53
54
|
@processes[0].join
|
54
55
|
@processes.shift
|
55
56
|
end
|
57
|
+
rescue Aborted
|
58
|
+
@processes.each{|p| p.abort }
|
59
|
+
Log.error "Process monitor aborted"
|
56
60
|
rescue Exception
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
rescue
|
61
|
-
end
|
62
|
-
end
|
63
|
-
Log.exception $!
|
61
|
+
Log.error "Process monitor exception: #{$!.message}"
|
62
|
+
@processes.each{|p| p.abort }
|
63
|
+
@callback_thread.raise Aborted.new if @callback_thread
|
64
64
|
parent.raise $!
|
65
65
|
end
|
66
66
|
end
|
@@ -87,8 +87,21 @@ class RbbtProcessQueue
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def clean
|
90
|
-
@
|
91
|
-
|
90
|
+
if @process_monitor.alive?
|
91
|
+
@process_monitor.raise Aborted.new
|
92
|
+
aborted = true
|
93
|
+
end
|
94
|
+
|
95
|
+
if @callback_thread and @callback_thread.alive?
|
96
|
+
@callback_thread.raise Aborted.new
|
97
|
+
aborted = true
|
98
|
+
end
|
99
|
+
raise Aborted.new if aborted
|
100
|
+
end
|
101
|
+
|
102
|
+
def abort
|
103
|
+
@process_monitor.raise Aborted.new if @process_monitor.alive?
|
104
|
+
@callback_thread.raise Aborted.new if @callback_thread and @callback_thread.alive?
|
92
105
|
end
|
93
106
|
|
94
107
|
def process(*e)
|