rbbt-util 5.10.2 → 5.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/persist.rb +60 -20
- data/lib/rbbt/tsv/dumper.rb +1 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +83 -65
- data/lib/rbbt/tsv/parser.rb +23 -8
- data/lib/rbbt/util/concurrency/processes.rb +23 -10
- data/lib/rbbt/util/concurrency/processes/worker.rb +3 -1
- data/lib/rbbt/util/log.rb +5 -10
- data/lib/rbbt/util/misc.rb +85 -52
- data/lib/rbbt/workflow.rb +2 -1
- data/lib/rbbt/workflow/step.rb +79 -29
- data/share/rbbt_commands/benchmark/throughput +5 -4
- data/share/rbbt_commands/tsv/slice +13 -4
- data/share/rbbt_commands/workflow/task +13 -7
- data/test/rbbt/test_persist.rb +21 -4
- data/test/rbbt/tsv/parallel/test_traverse.rb +9 -0
- data/test/rbbt/util/concurrency/processes/test_socket.rb +3 -1
- data/test/rbbt/util/concurrency/test_processes.rb +29 -0
- data/test/rbbt/util/test_misc.rb +6 -6
- data/test/rbbt/workflow/test_step.rb +1 -1
- metadata +2 -2
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)
|