rbbt-util 5.11.1 → 5.11.2
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 +97 -27
- data/lib/rbbt/tsv/parallel/traverse.rb +24 -16
- data/lib/rbbt/util/concurrency/processes.rb +3 -3
- data/lib/rbbt/util/concurrency/processes/socket.rb +1 -1
- data/lib/rbbt/util/log.rb +105 -47
- data/lib/rbbt/util/misc.rb +64 -21
- data/lib/rbbt/workflow.rb +30 -11
- data/lib/rbbt/workflow/accessor.rb +29 -12
- data/lib/rbbt/workflow/step.rb +113 -100
- data/share/rbbt_commands/workflow/task +2 -2
- data/test/rbbt/util/test_log.rb +8 -0
- 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: 06c3a98f22b69a5738d6c9b478a2cee9a4e52e66
|
4
|
+
data.tar.gz: d60e07e6371c2c6c88359d6b028e7c7fdcbd0c64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dab5cbee06c6169ab384555b53e6ea3407cb2c3f18b0b8d99f9aac6d6209d4c8656a6baeba4d46ede3c87c8eb141a870723d7a8336f7f58c85535d6d2f3f54a6
|
7
|
+
data.tar.gz: e3268aebe76ca88cfbc948b34367992188e38289fe966fc90ffc07609e2f6b355d751327008b691fbe4e94a1d7b9085e32fd0f73734ee538b041b9bd982486b0
|
data/lib/rbbt/persist.rb
CHANGED
@@ -172,59 +172,118 @@ module Persist
|
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
|
-
def self.tee_stream_fork(stream, path, type, callback = nil)
|
175
|
+
#def self.tee_stream_fork(stream, path, type, callback = nil)
|
176
|
+
# file, out = Misc.tee_stream(stream)
|
177
|
+
|
178
|
+
# saver_pid = Process.fork do
|
179
|
+
# out.close
|
180
|
+
# stream.close
|
181
|
+
# Misc.purge_pipes
|
182
|
+
# begin
|
183
|
+
# Misc.lock(path) do
|
184
|
+
# save_file(path, type, file)
|
185
|
+
# end
|
186
|
+
# rescue Aborted
|
187
|
+
# stream.abort if stream.respond_to? :abort
|
188
|
+
# raise $!
|
189
|
+
# rescue Exception
|
190
|
+
# Log.exception $!
|
191
|
+
# Kernel.exit! -1
|
192
|
+
# end
|
193
|
+
# Kernel.exit! 0
|
194
|
+
# end
|
195
|
+
# file.close
|
196
|
+
# ConcurrentStream.setup(out, :pids => [saver_pid], :filename => path)
|
197
|
+
#end
|
198
|
+
|
199
|
+
def self.tee_stream_thread(stream, path, type, callback = nil)
|
176
200
|
file, out = Misc.tee_stream(stream)
|
177
201
|
|
178
|
-
|
179
|
-
out.close
|
180
|
-
stream.close
|
181
|
-
Misc.purge_pipes
|
202
|
+
saver_thread = Thread.new(Thread.current, path, file) do |parent,path,file|
|
182
203
|
begin
|
204
|
+
Thread.current["name"] = "file saver: " + path
|
183
205
|
Misc.lock(path) do
|
184
206
|
save_file(path, type, file)
|
185
207
|
end
|
186
208
|
rescue Aborted
|
209
|
+
Log.error "Persist stream thread aborted: #{ Log.color :blue, path }"
|
187
210
|
stream.abort if stream.respond_to? :abort
|
188
|
-
raise $!
|
189
211
|
rescue Exception
|
212
|
+
Log.error "Persist stream thread exception: #{ Log.color :blue, path }"
|
190
213
|
Log.exception $!
|
191
|
-
|
214
|
+
stream.abort if stream.respond_to? :abort
|
215
|
+
parent.raise $!
|
192
216
|
end
|
193
|
-
Kernel.exit! 0
|
194
217
|
end
|
195
|
-
|
196
|
-
ConcurrentStream.setup(out, :pids => [saver_pid], :filename => path)
|
218
|
+
ConcurrentStream.setup(out, :threads => saver_thread, :filename => path)
|
197
219
|
end
|
198
220
|
|
199
|
-
def self.
|
200
|
-
|
201
|
-
|
202
|
-
saver_thread = Thread.new(Thread.current, path, file) do |parent,path,file|
|
221
|
+
def self.tee_stream_pipe(stream, path, type, callback = nil)
|
222
|
+
parent_pid = Process.pid
|
223
|
+
out = Misc.open_pipe true, false do |sin|
|
203
224
|
begin
|
204
|
-
|
205
|
-
|
206
|
-
|
225
|
+
file, out = Misc.tee_stream(stream)
|
226
|
+
|
227
|
+
saver_th = Thread.new(Thread.current, path, file) do |parent,path,file|
|
228
|
+
begin
|
229
|
+
Misc.lock(path) do
|
230
|
+
save_file(path, type, file)
|
231
|
+
end
|
232
|
+
Log.high "Stream pipe saved: #{path}"
|
233
|
+
rescue Aborted
|
234
|
+
Log.error "Persist stream pipe exception: #{ Log.color :blue, path }"
|
235
|
+
stream.abort if stream.respond_to? :abort
|
236
|
+
rescue Exception
|
237
|
+
Log.error "Persist stream pipe exception: #{ Log.color :blue, path }"
|
238
|
+
Log.exception $!
|
239
|
+
stream.abort if stream.respond_to? :abort
|
240
|
+
parent.raise $!
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
tee_th = Thread.new(Thread.current) do |parent|
|
245
|
+
begin
|
246
|
+
while block = out.read(2028)
|
247
|
+
sin.write block
|
248
|
+
end
|
249
|
+
rescue Aborted
|
250
|
+
Log.error "Tee stream thread aborted"
|
251
|
+
stream.abort if stream.respond_to? :abort
|
252
|
+
rescue Exception
|
253
|
+
stream.abort if stream.respond_to? :abort
|
254
|
+
Log.exception $!
|
255
|
+
parent.raise $!
|
256
|
+
ensure
|
257
|
+
sin.close unless sin.closed?
|
258
|
+
end
|
207
259
|
end
|
260
|
+
saver_th.join
|
261
|
+
tee_th.join
|
208
262
|
rescue Aborted
|
209
|
-
|
210
|
-
|
263
|
+
tee_th.raise Aborted.new if tee_th and tee_th.alive?
|
264
|
+
saver_th.raise Aborted.new if saver_th and saver_th.alive?
|
265
|
+
Kernel.exit! -1
|
211
266
|
rescue Exception
|
212
|
-
|
267
|
+
tee_th.raise Aborted.new if tee_th and tee_th.alive?
|
268
|
+
saver_th.raise Aborted.new if saver_th and saver_th.alive?
|
213
269
|
Log.exception $!
|
214
|
-
|
270
|
+
Process.kill :INT, parent_pid
|
271
|
+
Kernel.exit! -1
|
215
272
|
end
|
216
273
|
end
|
217
|
-
|
274
|
+
stream.close
|
275
|
+
out
|
218
276
|
end
|
219
277
|
|
220
278
|
class << self
|
221
279
|
alias tee_stream tee_stream_thread
|
222
280
|
end
|
223
281
|
|
282
|
+
|
224
283
|
def self.persist(name, type = nil, persist_options = {})
|
225
284
|
type ||= :marshal
|
226
285
|
|
227
|
-
return (persist_options[:repo] || Persist::MEMORY)[persist_options[:file]] ||= yield if type ==:memory and persist_options[:file]
|
286
|
+
return (persist_options[:repo] || Persist::MEMORY)[persist_options[:file]] ||= yield if type ==:memory and persist_options[:file] and persist_options[:persist] and persist_options[:persist] != :update
|
228
287
|
|
229
288
|
if FalseClass != persist_options[:persist]
|
230
289
|
other_options = Misc.process_options persist_options, :other
|
@@ -327,6 +386,7 @@ module Persist
|
|
327
386
|
|
328
387
|
lock_filename = Persist.persistence_path(path + '.persist', {:dir => Persist.lock_dir})
|
329
388
|
Misc.lock lock_filename do |lockfile|
|
389
|
+
|
330
390
|
if is_persisted?(path, persist_options)
|
331
391
|
Log.low "Persist up-to-date (suddenly): #{ path } - #{Misc.fingerprint persist_options}"
|
332
392
|
return path if persist_options[:no_load]
|
@@ -342,13 +402,21 @@ module Persist
|
|
342
402
|
when IO
|
343
403
|
res = tee_stream(res, path, type, res.respond_to?(:callback)? res.callback : nil)
|
344
404
|
ConcurrentStream.setup res do
|
345
|
-
|
405
|
+
begin
|
406
|
+
lockfile.unlock
|
407
|
+
rescue
|
408
|
+
Log.warn "Lockfile exception: " << $!.message
|
409
|
+
end
|
346
410
|
end
|
347
411
|
raise KeepLocked.new res
|
348
412
|
when TSV::Dumper
|
349
413
|
res = tee_stream(res.stream, path, type, res.respond_to?(:callback)? res.callback : nil)
|
350
414
|
ConcurrentStream.setup res do
|
351
|
-
|
415
|
+
begin
|
416
|
+
lockfile.unlock
|
417
|
+
rescue
|
418
|
+
Log.warn "Lockfile exception: " << $!.message
|
419
|
+
end
|
352
420
|
end
|
353
421
|
raise KeepLocked.new res
|
354
422
|
end
|
@@ -367,6 +435,7 @@ module Persist
|
|
367
435
|
end
|
368
436
|
rescue
|
369
437
|
res.abort if res.respond_to? :abort
|
438
|
+
raise $!
|
370
439
|
ensure
|
371
440
|
res.join if res.respond_to? :join
|
372
441
|
end
|
@@ -376,6 +445,7 @@ module Persist
|
|
376
445
|
res = TSV.open(io)
|
377
446
|
rescue
|
378
447
|
io.abort if io.respond_to? :abort
|
448
|
+
raise $!
|
379
449
|
ensure
|
380
450
|
io.join if io.respond_to? :join
|
381
451
|
end
|
@@ -389,7 +459,7 @@ module Persist
|
|
389
459
|
end
|
390
460
|
|
391
461
|
rescue
|
392
|
-
Log.
|
462
|
+
Log.error "Error in persist: #{path}#{Open.exists?(path) ? Log.color(:red, " Erasing") : ""}"
|
393
463
|
FileUtils.rm path if Open.exists? path
|
394
464
|
raise $!
|
395
465
|
end
|
@@ -410,7 +480,7 @@ module Persist
|
|
410
480
|
file = name
|
411
481
|
repo = options.delete :repo if options and options.any?
|
412
482
|
file << "_" << (options[:key] ? options[:key] : Misc.hash2md5(options)) if options and options.any?
|
413
|
-
persist name, :memory,
|
483
|
+
persist name, :memory, {:repo => repo, :persist => true, :file => file}.merge(options), &block
|
414
484
|
end
|
415
485
|
end
|
416
486
|
end
|
@@ -115,7 +115,7 @@ module TSV
|
|
115
115
|
else
|
116
116
|
obj.traverse(options, &block)
|
117
117
|
end
|
118
|
-
when IO, File
|
118
|
+
when IO, File
|
119
119
|
begin
|
120
120
|
if options[:type] == :array
|
121
121
|
traverse_io_array(obj, options, &block)
|
@@ -123,7 +123,8 @@ module TSV
|
|
123
123
|
traverse_io(obj, options, &block)
|
124
124
|
end
|
125
125
|
rescue Exception
|
126
|
-
|
126
|
+
obj.abort if obj.respond_to? :abort
|
127
|
+
raise $!
|
127
128
|
ensure
|
128
129
|
begin
|
129
130
|
obj.close if obj.respond_to? :close and not obj.closed?
|
@@ -150,7 +151,7 @@ module TSV
|
|
150
151
|
when Array
|
151
152
|
traverse_array(obj, options, &block)
|
152
153
|
when nil
|
153
|
-
raise "Can not traverse nil object"
|
154
|
+
raise "Can not traverse nil object into #{stream_name(options)}"
|
154
155
|
else
|
155
156
|
raise "Unknown object for traversal: #{Misc.fingerprint obj }"
|
156
157
|
end
|
@@ -191,18 +192,24 @@ module TSV
|
|
191
192
|
q.callback &callback
|
192
193
|
q.init &block
|
193
194
|
|
194
|
-
|
195
|
-
q.
|
195
|
+
pid = Process.fork do
|
196
|
+
Misc.purge_pipes(q.queue.swrite)
|
197
|
+
traverse_obj(obj, options) do |*p|
|
198
|
+
q.process *p
|
199
|
+
end
|
196
200
|
end
|
197
201
|
|
198
|
-
|
202
|
+
#stream = obj_stream(obj)
|
203
|
+
#stream.close if stream
|
204
|
+
|
205
|
+
Process.waitpid pid
|
199
206
|
rescue Exception
|
207
|
+
Log.exception $!
|
200
208
|
q.abort
|
201
209
|
raise $!
|
202
210
|
ensure
|
203
211
|
q.join
|
204
212
|
end
|
205
|
-
|
206
213
|
end
|
207
214
|
|
208
215
|
def self.store_into(store, value)
|
@@ -243,11 +250,13 @@ module TSV
|
|
243
250
|
when TSV::Dumper
|
244
251
|
close_streams << obj.result.in_stream
|
245
252
|
when (defined? Step and Step)
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
253
|
+
obj.mutex.synchronize do
|
254
|
+
case obj.result
|
255
|
+
when IO
|
256
|
+
close_streams << obj.result
|
257
|
+
when TSV::Dumper
|
258
|
+
close_streams << obj.result.in_stream
|
259
|
+
end
|
251
260
|
end
|
252
261
|
obj.inputs.each do |input|
|
253
262
|
close_streams = get_streams_to_close(input) + close_streams
|
@@ -294,7 +303,6 @@ module TSV
|
|
294
303
|
parent.raise $!
|
295
304
|
end
|
296
305
|
end
|
297
|
-
thread.wakeup
|
298
306
|
ConcurrentStream.setup(obj_stream(into), :threads => thread)
|
299
307
|
end
|
300
308
|
|
@@ -311,7 +319,8 @@ module TSV
|
|
311
319
|
begin
|
312
320
|
traverse(obj, options.merge(:into => sin), &block)
|
313
321
|
rescue Exception
|
314
|
-
|
322
|
+
sout.abort if sout.respond_to? :abort
|
323
|
+
sout.join if sout.respond_to? :join
|
315
324
|
end
|
316
325
|
end
|
317
326
|
return sout
|
@@ -328,11 +337,10 @@ module TSV
|
|
328
337
|
end
|
329
338
|
|
330
339
|
case into
|
331
|
-
when TSV::Dumper, IO
|
340
|
+
when TSV::Dumper, IO
|
332
341
|
traverse_stream(obj, threads, cpus, options, &block)
|
333
342
|
else
|
334
343
|
traverse_run(obj, threads, cpus, options, &block)
|
335
|
-
into.join if into.respond_to? :join
|
336
344
|
into.close if into.respond_to? :close
|
337
345
|
end
|
338
346
|
|
@@ -31,7 +31,7 @@ class RbbtProcessQueue
|
|
31
31
|
Log.error "Callback thread aborted"
|
32
32
|
rescue ClosedStream
|
33
33
|
rescue Exception
|
34
|
-
Log.exception
|
34
|
+
Log.error "Callback thread exception"
|
35
35
|
parent.raise $!
|
36
36
|
ensure
|
37
37
|
@callback_queue.sread.close unless @callback_queue.sread.closed?
|
@@ -68,7 +68,6 @@ class RbbtProcessQueue
|
|
68
68
|
|
69
69
|
def close_callback
|
70
70
|
@callback_queue.push ClosedStream.new if @callback_thread.alive?
|
71
|
-
@callback_queue.swrite.close
|
72
71
|
@callback_thread.join
|
73
72
|
end
|
74
73
|
|
@@ -81,6 +80,7 @@ class RbbtProcessQueue
|
|
81
80
|
close_callback if @callback
|
82
81
|
rescue Exception
|
83
82
|
Log.exception $!
|
83
|
+
raise $!
|
84
84
|
ensure
|
85
85
|
@queue.swrite.close
|
86
86
|
end
|
@@ -100,7 +100,7 @@ class RbbtProcessQueue
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def abort
|
103
|
-
@process_monitor.raise Aborted.new if @process_monitor.alive?
|
103
|
+
@process_monitor.raise Aborted.new if @process_monitor and @process_monitor.alive?
|
104
104
|
@callback_thread.raise Aborted.new if @callback_thread and @callback_thread.alive?
|
105
105
|
end
|
106
106
|
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -4,13 +4,29 @@ require 'rbbt/util/color'
|
|
4
4
|
module Log
|
5
5
|
extend Term::ANSIColor
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
|
8
|
+
SEVERITY_NAMES ||= begin
|
9
|
+
names = %w(DEBUG LOW MEDIUM HIGH INFO WARN ERROR )
|
10
|
+
names.each_with_index do |name,i|
|
11
|
+
eval "#{ name } = #{ i }"
|
12
|
+
end
|
13
|
+
names
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get_level(level)
|
17
|
+
case level
|
18
|
+
when Fixnum
|
19
|
+
level
|
20
|
+
when String
|
21
|
+
begin
|
22
|
+
Log.const_get(level.upcase)
|
23
|
+
rescue
|
24
|
+
Log.exception $!
|
25
|
+
end
|
26
|
+
when Symbol
|
27
|
+
get_level(level.to_s)
|
28
|
+
end || 0
|
29
|
+
end
|
14
30
|
|
15
31
|
class << self
|
16
32
|
attr_accessor :logfile, :severity, :nocolor, :tty_size
|
@@ -42,11 +58,15 @@ module Log
|
|
42
58
|
Term::ANSIColor.uncolor(str)
|
43
59
|
end
|
44
60
|
|
45
|
-
def self.
|
61
|
+
def self.reset_color
|
62
|
+
reset
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.color(severity, str = nil, reset = false)
|
46
66
|
return str || "" if nocolor
|
47
|
-
color =
|
48
|
-
color
|
49
|
-
color
|
67
|
+
color = reset ? Term::ANSIColor.reset : ""
|
68
|
+
color << SEVERITY_COLOR[severity] if Fixnum === severity
|
69
|
+
color << Term::ANSIColor.send(severity) if Symbol === severity and Term::ANSIColor.respond_to? severity
|
50
70
|
if str.nil?
|
51
71
|
color
|
52
72
|
else
|
@@ -92,6 +112,40 @@ module Log
|
|
92
112
|
end
|
93
113
|
end
|
94
114
|
|
115
|
+
def self.log_obj_inspect(obj, level, file = $stdout)
|
116
|
+
stack = caller
|
117
|
+
|
118
|
+
line = nil
|
119
|
+
while line.nil? or line =~ /util\/log\.rb/ and stack.any?
|
120
|
+
line = stack.shift
|
121
|
+
end
|
122
|
+
line ||= caller.first
|
123
|
+
|
124
|
+
level = Log.get_level level
|
125
|
+
name = Log::SEVERITY_NAMES[level] + ": "
|
126
|
+
Log.log Log.color(level, name, true) << line, level
|
127
|
+
Log.log "", level
|
128
|
+
Log.log Log.color(level, "=> ", true) << obj.inspect, level
|
129
|
+
Log.log "", level
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.log_obj_fingerprint(obj, level, file = $stdout)
|
133
|
+
stack = caller
|
134
|
+
|
135
|
+
line = nil
|
136
|
+
while line.nil? or line =~ /util\/log\.rb/ and stack.any?
|
137
|
+
line = stack.shift
|
138
|
+
end
|
139
|
+
line ||= caller.first
|
140
|
+
|
141
|
+
level = Log.get_level level
|
142
|
+
name = Log::SEVERITY_NAMES[level] + ": "
|
143
|
+
Log.log Log.color(level, name, true) << line, level
|
144
|
+
Log.log "", level
|
145
|
+
Log.log Log.color(level, "=> ", true) << Misc.fingerprint(obj), level
|
146
|
+
Log.log "", level
|
147
|
+
end
|
148
|
+
|
95
149
|
def self.debug(message = nil, &block)
|
96
150
|
log(message, DEBUG, &block)
|
97
151
|
end
|
@@ -157,52 +211,52 @@ def fff(object)
|
|
157
211
|
Log.debug{""}
|
158
212
|
end
|
159
213
|
|
160
|
-
def ddd(
|
161
|
-
|
162
|
-
Log.debug{"#{Log.color :cyan, "DEBUG:"} " << stack.first}
|
163
|
-
Log.debug{""}
|
164
|
-
Log.debug{"=> " << message.inspect}
|
165
|
-
Log.debug{""}
|
214
|
+
def ddd(obj, file = $stdout)
|
215
|
+
Log.log_obj_inspect(obj, :debug, file)
|
166
216
|
end
|
167
217
|
|
168
|
-
def lll(
|
169
|
-
|
170
|
-
Log.low{"#{Log.color :cyan, "LOW:"} " << stack.first}
|
171
|
-
Log.low{""}
|
172
|
-
Log.low{"=> " << message.inspect}
|
173
|
-
Log.low{""}
|
218
|
+
def lll(obj, file = $stdout)
|
219
|
+
Log.log_obj_inspect(obj, :low, file)
|
174
220
|
end
|
175
221
|
|
176
|
-
def mmm(
|
177
|
-
|
178
|
-
Log.low{"#{Log.color :cyan, "MEDIUM:"} " << stack.first}
|
179
|
-
Log.low{""}
|
180
|
-
Log.low{"=> " << message.inspect}
|
181
|
-
Log.low{""}
|
222
|
+
def mmm(obj, file = $stdout)
|
223
|
+
Log.log_obj_inspect(obj, :medium, file)
|
182
224
|
end
|
183
225
|
|
184
|
-
def
|
185
|
-
|
186
|
-
Log.high{"#{Log.color :cyan, "HIGH:"} " << stack.first}
|
187
|
-
Log.high{""}
|
188
|
-
Log.high{"=> " << message.inspect}
|
189
|
-
Log.high{""}
|
226
|
+
def iii(obj, file = $stdout)
|
227
|
+
Log.log_obj_inspect(obj, :info, file)
|
190
228
|
end
|
191
229
|
|
192
|
-
def
|
193
|
-
|
194
|
-
Log.info{"#{Log.color :cyan, "INFO:"} " << stack.first}
|
195
|
-
Log.info{""}
|
196
|
-
Log.info{"=> " << message.inspect}
|
197
|
-
Log.info{""}
|
230
|
+
def wwww(obj, file = $stdout)
|
231
|
+
Log.log_obj_inspect(obj, :warn, file)
|
198
232
|
end
|
199
233
|
|
200
|
-
def eee(
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Log.
|
234
|
+
def eee(obj, file = $stdout)
|
235
|
+
Log.log_obj_inspect(obj, :error, file)
|
236
|
+
end
|
237
|
+
|
238
|
+
def ddf(obj, file = $stdout)
|
239
|
+
Log.log_obj_fingerprint(obj, :debug, file)
|
240
|
+
end
|
241
|
+
|
242
|
+
def llf(obj, file = $stdout)
|
243
|
+
Log.log_obj_fingerprint(obj, :low, file)
|
244
|
+
end
|
245
|
+
|
246
|
+
def mmf(obj, file = $stdout)
|
247
|
+
Log.log_obj_fingerprint(obj, :medium, file)
|
248
|
+
end
|
249
|
+
|
250
|
+
def iif(obj, file = $stdout)
|
251
|
+
Log.log_obj_fingerprint(obj, :info, file)
|
252
|
+
end
|
253
|
+
|
254
|
+
def wwwf(obj, file = $stdout)
|
255
|
+
Log.log_obj_fingerprint(obj, :warn, file)
|
256
|
+
end
|
257
|
+
|
258
|
+
def eef(obj, file = $stdout)
|
259
|
+
Log.log_obj_fingerprint(obj, :error, file)
|
206
260
|
end
|
207
261
|
|
208
262
|
if __FILE__ == $0
|
@@ -211,4 +265,8 @@ if __FILE__ == $0
|
|
211
265
|
(0..6).each do |level|
|
212
266
|
Log.log("Level #{level}", level)
|
213
267
|
end
|
268
|
+
|
269
|
+
require 'rbbt/util/misc'
|
270
|
+
eee [1,2,3]
|
271
|
+
eef [1,2,3]
|
214
272
|
end
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -35,7 +35,11 @@ module LaterString
|
|
35
35
|
end
|
36
36
|
|
37
37
|
module ConcurrentStream
|
38
|
-
attr_accessor :threads, :pids, :callback, :filename
|
38
|
+
attr_accessor :threads, :pids, :callback, :filename, :joined
|
39
|
+
|
40
|
+
def joined?
|
41
|
+
@joined
|
42
|
+
end
|
39
43
|
|
40
44
|
def join
|
41
45
|
|
@@ -57,10 +61,12 @@ module ConcurrentStream
|
|
57
61
|
@pids = []
|
58
62
|
end
|
59
63
|
|
60
|
-
if @callback
|
64
|
+
if @callback and not joined?
|
61
65
|
@callback.call
|
62
66
|
@callback = nil
|
63
67
|
end
|
68
|
+
|
69
|
+
@joined = true
|
64
70
|
end
|
65
71
|
|
66
72
|
def abort
|
@@ -147,11 +153,11 @@ module Misc
|
|
147
153
|
Process.kill :INT, parent_pid
|
148
154
|
Kernel.exit! -1
|
149
155
|
ensure
|
150
|
-
sin.close
|
156
|
+
sin.close if close and not sin.closed?
|
151
157
|
end
|
152
158
|
Kernel.exit! 0
|
153
159
|
}
|
154
|
-
sin.close if close
|
160
|
+
sin.close #if close
|
155
161
|
ConcurrentStream.setup sout, :pids => [pid]
|
156
162
|
else
|
157
163
|
thread = Thread.new(Thread.current) do |parent|
|
@@ -160,7 +166,7 @@ module Misc
|
|
160
166
|
rescue
|
161
167
|
parent.raise $!
|
162
168
|
ensure
|
163
|
-
sin.close if close
|
169
|
+
sin.close if close and not sin.closed?
|
164
170
|
end
|
165
171
|
end
|
166
172
|
ConcurrentStream.setup sout, :threads => [thread]
|
@@ -246,6 +252,10 @@ module Misc
|
|
246
252
|
alias tee_stream tee_stream_thread
|
247
253
|
end
|
248
254
|
|
255
|
+
def self.consume_stream(io)
|
256
|
+
Thread.pass while block = io.read(2048)
|
257
|
+
end
|
258
|
+
|
249
259
|
def self.format_paragraph(text, size = 80, indent = 0, offset = 0)
|
250
260
|
i = 0
|
251
261
|
re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
|
@@ -320,6 +330,14 @@ module Misc
|
|
320
330
|
str
|
321
331
|
end
|
322
332
|
|
333
|
+
def self.read_stream(stream, size)
|
334
|
+
str = ""
|
335
|
+
while (len=str.length) < size
|
336
|
+
str << stream.read(size-len)
|
337
|
+
end
|
338
|
+
str
|
339
|
+
end
|
340
|
+
|
323
341
|
def self.parse_cmd_params(str)
|
324
342
|
return str if Array === str
|
325
343
|
str.scan(/
|
@@ -531,9 +549,9 @@ module Misc
|
|
531
549
|
else
|
532
550
|
"'" << obj << "'"
|
533
551
|
end
|
534
|
-
when AnnotatedArray
|
552
|
+
when (defined? AnnotatedArray and AnnotatedArray)
|
535
553
|
"<A: #{fingerprint Annotated.purge(obj)} #{fingerprint obj.info}>"
|
536
|
-
when TSV::Parser
|
554
|
+
when (defined? TSV and TSV::Parser)
|
537
555
|
"<TSVStream:" + obj.filename + "--" << Misc.fingerprint(obj.options) << ">"
|
538
556
|
when IO
|
539
557
|
"<IO:" + (obj.respond_to?(:filename) ? obj.filename : obj.inspect) + ">"
|
@@ -545,7 +563,7 @@ module Misc
|
|
545
563
|
else
|
546
564
|
"[" << (obj.collect{|e| fingerprint(e) } * ",") << "]"
|
547
565
|
end
|
548
|
-
when TSV
|
566
|
+
when (defined? TSV and TSV)
|
549
567
|
obj.with_unnamed do
|
550
568
|
"TSV:{"<< fingerprint(obj.all_fields|| []).inspect << ";" << fingerprint(obj.keys).inspect << "}"
|
551
569
|
end
|
@@ -1301,6 +1319,7 @@ end
|
|
1301
1319
|
@hostanem ||= `hostname`.strip
|
1302
1320
|
end
|
1303
1321
|
|
1322
|
+
LOCK_MUTEX = Mutex.new
|
1304
1323
|
def self.lock(file, unlock = true)
|
1305
1324
|
return yield if file.nil?
|
1306
1325
|
FileUtils.mkdir_p File.dirname(File.expand_path(file)) unless File.exists? File.dirname(File.expand_path(file))
|
@@ -1310,24 +1329,49 @@ end
|
|
1310
1329
|
lock_path = File.expand_path(file + '.lock')
|
1311
1330
|
lockfile = Lockfile.new(lock_path)
|
1312
1331
|
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1332
|
+
hostname = Misc.hostname
|
1333
|
+
LOCK_MUTEX.synchronize do
|
1334
|
+
Misc.insist 3, 0.1 do
|
1335
|
+
begin
|
1336
|
+
if File.exists? lock_path
|
1337
|
+
info = Open.open(lock_path){|f| YAML.load(f) }
|
1338
|
+
raise "No info" unless info
|
1318
1339
|
|
1319
|
-
|
1320
|
-
|
1340
|
+
if hostname == info["host"] and not Misc.pid_exists?(info["pid"])
|
1341
|
+
Log.info("Removing lockfile: #{lock_path}. This pid #{Process.pid}. Content: #{info.inspect}")
|
1342
|
+
FileUtils.rm lock_path
|
1343
|
+
end
|
1344
|
+
end
|
1345
|
+
rescue Exception
|
1346
|
+
FileUtils.rm lock_path if File.exists? lock_path
|
1347
|
+
raise $!
|
1348
|
+
ensure
|
1349
|
+
lockfile = Lockfile.new(lock_path) unless File.exists? lock_path
|
1321
1350
|
end
|
1322
1351
|
end
|
1323
|
-
rescue
|
1324
|
-
Log.warn("Error checking lockfile #{lock_path}: #{$!.message}. Removing. Content: #{begin Open.read(lock_path) rescue "Could not open file" end}")
|
1325
|
-
FileUtils.rm lock_path if File.exists?(lock_path)
|
1326
|
-
lockfile = Lockfile.new(lock_path)
|
1327
|
-
retry
|
1328
1352
|
end
|
1329
1353
|
|
1354
|
+
#begin
|
1355
|
+
# Misc.insist 3 do
|
1356
|
+
# LOCK_MUTEX.synchronize do
|
1357
|
+
# if File.exists? lock_path and
|
1358
|
+
# Misc.hostname == (info = Open.open(lock_path){|f| YAML.load(f) })["host"] and
|
1359
|
+
# info["pid"] and not Misc.pid_exists?(info["pid"])
|
1360
|
+
|
1361
|
+
# Log.info("Removing lockfile: #{lock_path}. This pid #{Process.pid}. Content: #{info.inspect}")
|
1362
|
+
# FileUtils.rm lock_path
|
1363
|
+
# end
|
1364
|
+
# end
|
1365
|
+
# end
|
1366
|
+
#rescue
|
1367
|
+
# Log.warn("Error checking lockfile #{lock_path}: #{$!.message}. Removing. Content: #{begin Open.read(lock_path) rescue "Could not open file" end}")
|
1368
|
+
# FileUtils.rm lock_path if File.exists?(lock_path)
|
1369
|
+
# lockfile = Lockfile.new(lock_path)
|
1370
|
+
# retry
|
1371
|
+
#end
|
1372
|
+
|
1330
1373
|
begin
|
1374
|
+
|
1331
1375
|
lockfile.lock
|
1332
1376
|
res = yield lockfile
|
1333
1377
|
rescue Lockfile::StolenLockError
|
@@ -1338,7 +1382,6 @@ end
|
|
1338
1382
|
ensure
|
1339
1383
|
if unlock and lockfile.locked?
|
1340
1384
|
lockfile.unlock
|
1341
|
-
FileUtils.rm lock_path if File.exists? lock_path
|
1342
1385
|
end
|
1343
1386
|
end
|
1344
1387
|
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -159,6 +159,7 @@ module Workflow
|
|
159
159
|
attr_accessor :helpers, :tasks
|
160
160
|
attr_accessor :task_dependencies, :task_description, :last_task
|
161
161
|
attr_accessor :asynchronous_exports, :synchronous_exports, :exec_exports
|
162
|
+
attr_accessor :step_cache
|
162
163
|
|
163
164
|
#{{{ ATTR DEFAULTS
|
164
165
|
|
@@ -180,6 +181,10 @@ module Workflow
|
|
180
181
|
@libdir = Path.caller_lib_dir if @libdir.nil?
|
181
182
|
@libdir
|
182
183
|
end
|
184
|
+
|
185
|
+
def step_cache
|
186
|
+
@step_cache ||= {}
|
187
|
+
end
|
183
188
|
|
184
189
|
|
185
190
|
def helpers
|
@@ -226,6 +231,28 @@ module Workflow
|
|
226
231
|
end
|
227
232
|
end
|
228
233
|
|
234
|
+
def get_job_step(step_path, task = nil, input_values = nil, dependencies = nil)
|
235
|
+
step_path = step_path.call if Proc === step_path
|
236
|
+
persist = input_values.nil? ? false : true
|
237
|
+
step = Persist.memory("Step", :key => step_path, :repo => step_cache, :persist => persist ) do
|
238
|
+
step = Step.new step_path, task, input_values, dependencies
|
239
|
+
|
240
|
+
helpers.each do |name, block|
|
241
|
+
(class << step; self; end).instance_eval do
|
242
|
+
define_method name, &block
|
243
|
+
end
|
244
|
+
end
|
245
|
+
step
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
step.task ||= task
|
250
|
+
step.inputs ||= input_values
|
251
|
+
step.dependencies = dependencies if dependencies and (step.dependencies.nil? or step.dependencies.length < dependencies.length)
|
252
|
+
|
253
|
+
step
|
254
|
+
end
|
255
|
+
|
229
256
|
def job(taskname, jobname = nil, inputs = {})
|
230
257
|
taskname = taskname.to_sym
|
231
258
|
jobname = DEFAULT_NAME if jobname.nil? or jobname.empty?
|
@@ -247,20 +274,12 @@ module Workflow
|
|
247
274
|
step_path = step_path taskname, jobname, input_values, dependencies, task.extension
|
248
275
|
end
|
249
276
|
|
250
|
-
|
251
|
-
|
252
|
-
helpers.each do |name, block|
|
253
|
-
(class << step; self; end).instance_eval do
|
254
|
-
define_method name, &block
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
step
|
277
|
+
get_job_step step_path, task, input_values, dependencies
|
259
278
|
end
|
260
279
|
|
261
280
|
def load_step(path)
|
262
281
|
task = task_for path
|
263
|
-
|
282
|
+
get_job_step path, tasks[task.to_sym]
|
264
283
|
end
|
265
284
|
|
266
285
|
def load_id(id)
|
@@ -279,7 +298,7 @@ module Workflow
|
|
279
298
|
def load_name(task, name)
|
280
299
|
task = tasks[task.to_sym] if String === task or Symbol === task
|
281
300
|
path = step_path task.name, name, [], [], task.extension
|
282
|
-
|
301
|
+
get_job_step path, task
|
283
302
|
end
|
284
303
|
|
285
304
|
def jobs(taskname, query = nil)
|
@@ -42,24 +42,29 @@ class Step
|
|
42
42
|
def info
|
43
43
|
return {} if info_file.nil? or not Open.exists? info_file
|
44
44
|
begin
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
Misc.insist(2,
|
52
|
-
|
53
|
-
|
45
|
+
@info_mutex.synchronize do
|
46
|
+
begin
|
47
|
+
return @info_cache if @info_cache and File.mtime(info_file) < @info_cache_time
|
48
|
+
rescue Exception
|
49
|
+
end
|
50
|
+
begin
|
51
|
+
@info_cache = Misc.insist(2, 1, info_file) do
|
52
|
+
Misc.insist(2, 0.5, info_file) do
|
53
|
+
Misc.insist(3, 0.1, info_file) do
|
54
|
+
Open.open(info_file) do |file|
|
55
|
+
INFO_SERIALIAZER.load(file) || {}
|
56
|
+
end
|
57
|
+
end
|
54
58
|
end
|
55
59
|
end
|
60
|
+
@info_cache_time = Time.now
|
61
|
+
@info_cache
|
56
62
|
end
|
57
63
|
end
|
58
|
-
@info_cache_time = Time.now
|
59
|
-
@info_cache
|
60
64
|
rescue Exception
|
61
65
|
Log.debug{"Error loading info file: " + info_file}
|
62
66
|
Open.write(info_file, INFO_SERIALIAZER.dump({:status => :error, :messages => ["Info file lost"]}))
|
67
|
+
self.abort
|
63
68
|
raise $!
|
64
69
|
end
|
65
70
|
end
|
@@ -69,7 +74,7 @@ class Step
|
|
69
74
|
value = Annotated.purge value if defined? Annotated
|
70
75
|
Open.lock(info_file) do
|
71
76
|
i = info
|
72
|
-
i[key] = value
|
77
|
+
i[key] = value
|
73
78
|
@info_cache = i
|
74
79
|
Open.write(info_file, INFO_SERIALIAZER.dump(i))
|
75
80
|
@info_cache_time = Time.now
|
@@ -143,6 +148,10 @@ class Step
|
|
143
148
|
path and path.exists?
|
144
149
|
end
|
145
150
|
|
151
|
+
def streaming?
|
152
|
+
IO === @result or status == :streaming
|
153
|
+
end
|
154
|
+
|
146
155
|
def running?
|
147
156
|
return nil if not Open.exists? info_file
|
148
157
|
return nil if info[:pid].nil?
|
@@ -239,6 +248,14 @@ class Step
|
|
239
248
|
end
|
240
249
|
{:inputs => info[:inputs], :provenance => provenance}
|
241
250
|
end
|
251
|
+
|
252
|
+
def provenance_paths
|
253
|
+
provenance = {}
|
254
|
+
dependencies.each do |dep|
|
255
|
+
provenance[dep.path] = dep.provenance_paths if File.exists? dep.path
|
256
|
+
end
|
257
|
+
provenance
|
258
|
+
end
|
242
259
|
end
|
243
260
|
|
244
261
|
module Workflow
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -9,10 +9,11 @@ class Step
|
|
9
9
|
attr_accessor :path, :task, :inputs, :dependencies, :bindings
|
10
10
|
attr_accessor :pid
|
11
11
|
attr_accessor :exec
|
12
|
-
attr_accessor :result
|
12
|
+
attr_accessor :result, :mutex
|
13
13
|
|
14
14
|
def initialize(path, task = nil, inputs = nil, dependencies = nil, bindings = nil)
|
15
15
|
path = Path.setup(Misc.sanitize_filename(path)) if String === path
|
16
|
+
pat = path.call if Proc === path
|
16
17
|
@path = path
|
17
18
|
@task = task
|
18
19
|
@bindings = bindings
|
@@ -25,6 +26,7 @@ class Step
|
|
25
26
|
[dependencies]
|
26
27
|
end
|
27
28
|
@mutex = Mutex.new
|
29
|
+
@info_mutex = Mutex.new
|
28
30
|
@inputs = inputs || []
|
29
31
|
end
|
30
32
|
|
@@ -59,6 +61,7 @@ class Step
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def prepare_result(value, description = nil, info = {})
|
64
|
+
#info = self.info
|
62
65
|
case
|
63
66
|
when IO === value
|
64
67
|
begin
|
@@ -98,8 +101,7 @@ class Step
|
|
98
101
|
def get_stream
|
99
102
|
@mutex.synchronize do
|
100
103
|
begin
|
101
|
-
|
102
|
-
IO === res ? res : nil
|
104
|
+
IO === @result ? @result : nil
|
103
105
|
ensure
|
104
106
|
@result = nil
|
105
107
|
end
|
@@ -112,6 +114,7 @@ class Step
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def exec(no_load=false)
|
117
|
+
dependencies.each{|dependency| dependency.exec(no_load) }
|
115
118
|
@result = _exec
|
116
119
|
@result = @result.stream if TSV::Dumper === @result
|
117
120
|
no_load ? @result : prepare_result(@result, @task.result_description)
|
@@ -120,17 +123,17 @@ class Step
|
|
120
123
|
def join
|
121
124
|
stream = get_stream
|
122
125
|
begin
|
123
|
-
|
126
|
+
Misc.consume_stream stream if stream
|
124
127
|
rescue
|
125
128
|
stream.abort if stream.respond_to? :abort
|
126
129
|
raise $!
|
127
130
|
ensure
|
128
|
-
stream.join if stream.respond_to? :join
|
131
|
+
stream.join if stream.respond_to? :join and not stream.joined?
|
129
132
|
end
|
130
133
|
|
131
|
-
dependencies.each{|dep| dep.join }
|
132
134
|
|
133
135
|
if @pid.nil?
|
136
|
+
dependencies.each{|dep| dep.join }
|
134
137
|
self
|
135
138
|
else
|
136
139
|
begin
|
@@ -140,8 +143,9 @@ class Step
|
|
140
143
|
Log.debug{"Process #{ @pid } already finished: #{ path }"}
|
141
144
|
end if Misc.pid_exists? @pid
|
142
145
|
@pid = nil
|
146
|
+
dependencies.each{|dep| dep.join }
|
147
|
+
self
|
143
148
|
end
|
144
|
-
self
|
145
149
|
end
|
146
150
|
|
147
151
|
def checks
|
@@ -150,110 +154,113 @@ class Step
|
|
150
154
|
|
151
155
|
def run(no_load = false)
|
152
156
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
157
|
+
@mutex.synchronize do
|
158
|
+
result = Persist.persist "Job", @task.result_type, :file => path, :check => checks, :no_load => no_load ? :stream : false do
|
159
|
+
if Step === Step.log_relay_step and not self == Step.log_relay_step
|
160
|
+
relay_log(Step.log_relay_step) unless self.respond_to? :relay_step and self.relay_step
|
161
|
+
end
|
162
|
+
@exec = false
|
163
|
+
|
164
|
+
Open.rm info_file if Open.exists? info_file
|
165
|
+
|
166
|
+
set_info :pid, Process.pid
|
167
|
+
set_info :issued, Time.now
|
168
|
+
|
169
|
+
log(:preparing, "Preparing job: #{Misc.fingerprint dependencies}")
|
170
|
+
set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name]}
|
171
|
+
seen_deps = []
|
172
|
+
dependencies.uniq.each{|dependency|
|
173
|
+
Log.info "#{Log.color :magenta, "Checking dependency"} #{Log.color :yellow, task.name.to_s || ""} => #{Log.color :yellow, dependency.task_name.to_s || ""}"
|
174
|
+
begin
|
175
|
+
next if seen_deps.include? dependency.path
|
176
|
+
dependency.relay_log self
|
177
|
+
dependency.clean if not dependency.done? and dependency.error?
|
178
|
+
dependency.clean if dependency.streaming? and not dependency.running?
|
179
|
+
dependency.run true unless dependency.result
|
180
|
+
seen_deps.concat dependency.rec_dependencies.collect{|d| d.path}
|
181
|
+
rescue Exception
|
182
|
+
backtrace = $!.backtrace
|
183
|
+
set_info :backtrace, backtrace
|
184
|
+
log(:error, "Exception processing dependency #{Log.color :yellow, dependency.task.name.to_s} -- #{$!.class}: #{$!.message}")
|
185
|
+
raise $!
|
186
|
+
end
|
187
|
+
}
|
158
188
|
|
159
|
-
|
189
|
+
set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, @inputs)) unless task.inputs.nil?
|
160
190
|
|
161
|
-
|
162
|
-
|
191
|
+
set_info :started, (start_time = Time.now)
|
192
|
+
log :started, "#{Log.color :green, "Starting task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
163
193
|
|
164
|
-
set_info :dependencies, dependencies.collect{|dep| [dep.task.name, dep.name]}
|
165
|
-
log(:preparing, "Preparing job")
|
166
|
-
seen_deps = []
|
167
|
-
dependencies.each{|dependency|
|
168
|
-
Log.info "#{Log.color :magenta, "Checking dependency"} #{Log.color :yellow, task.name.to_s || ""} => #{Log.color :yellow, dependency.task.name.to_s || ""}"
|
169
194
|
begin
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
195
|
+
result = _exec
|
196
|
+
rescue Aborted
|
197
|
+
log(:error, "Aborted")
|
198
|
+
|
199
|
+
children_pids = info[:children_pids]
|
200
|
+
if children_pids and children_pids.any?
|
201
|
+
Log.medium("Killing children: #{ children_pids * ", " }")
|
202
|
+
children_pids.each do |pid|
|
203
|
+
Log.medium("Killing child #{ pid }")
|
204
|
+
begin
|
205
|
+
Process.kill "INT", pid
|
206
|
+
rescue Exception
|
207
|
+
Log.medium("Exception killing child #{ pid }: #{$!.message}")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
raise $!
|
175
213
|
rescue Exception
|
176
214
|
backtrace = $!.backtrace
|
215
|
+
|
216
|
+
# HACK: This fixes an strange behaviour in 1.9.3 where some
|
217
|
+
# backtrace strings are coded in ASCII-8BIT
|
218
|
+
backtrace.each{|l| l.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
|
219
|
+
|
177
220
|
set_info :backtrace, backtrace
|
178
|
-
log(:error, "
|
221
|
+
log(:error, "#{$!.class}: #{$!.message}")
|
179
222
|
raise $!
|
180
223
|
end
|
181
|
-
}
|
182
|
-
|
183
|
-
set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, @inputs)) unless task.inputs.nil?
|
184
224
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
225
|
+
case result
|
226
|
+
when IO
|
227
|
+
log :streaming, "#{Log.color :magenta, "Streaming task result IO"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
228
|
+
ConcurrentStream.setup result do
|
229
|
+
begin
|
230
|
+
set_info :done, (done_time = Time.now)
|
231
|
+
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
232
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i} -- #{path}"
|
233
|
+
rescue
|
234
|
+
Log.exception $!
|
235
|
+
end
|
236
|
+
end
|
237
|
+
when TSV::Dumper
|
238
|
+
log :streaming, "#{Log.color :magenta, "Streaming task result TSV::Dumper"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
239
|
+
ConcurrentStream.setup result.stream do
|
198
240
|
begin
|
199
|
-
|
200
|
-
|
201
|
-
|
241
|
+
set_info :done, (done_time = Time.now)
|
242
|
+
set_info :done, (done_time = Time.now)
|
243
|
+
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
244
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i} -- #{path}"
|
245
|
+
rescue
|
246
|
+
Log.exception $!
|
202
247
|
end
|
203
248
|
end
|
249
|
+
else
|
250
|
+
set_info :done, (done_time = Time.now)
|
251
|
+
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
252
|
+
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
204
253
|
end
|
205
254
|
|
206
|
-
|
207
|
-
rescue Exception
|
208
|
-
backtrace = $!.backtrace
|
209
|
-
|
210
|
-
# HACK: This fixes an strange behaviour in 1.9.3 where some
|
211
|
-
# backtrace strings are coded in ASCII-8BIT
|
212
|
-
backtrace.each{|l| l.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
|
213
|
-
|
214
|
-
set_info :backtrace, backtrace
|
215
|
-
log(:error, "#{$!.class}: #{$!.message}")
|
216
|
-
raise $!
|
255
|
+
result
|
217
256
|
end
|
218
257
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
ConcurrentStream.setup result do
|
223
|
-
begin
|
224
|
-
set_info :done, (done_time = Time.now)
|
225
|
-
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
226
|
-
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
227
|
-
rescue
|
228
|
-
Log.exception $!
|
229
|
-
end
|
230
|
-
end
|
231
|
-
when TSV::Dumper
|
232
|
-
log :streaming, "#{Log.color :magenta, "Streaming task result TSV::Dumper"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}]"
|
233
|
-
ConcurrentStream.setup result.stream do
|
234
|
-
begin
|
235
|
-
set_info :done, (done_time = Time.now)
|
236
|
-
set_info :done, (done_time = Time.now)
|
237
|
-
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
238
|
-
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
239
|
-
rescue
|
240
|
-
Log.exception $!
|
241
|
-
end
|
242
|
-
end
|
258
|
+
if no_load
|
259
|
+
@result ||= result
|
260
|
+
self
|
243
261
|
else
|
244
|
-
|
245
|
-
set_info :time_elapsed, (time_elapsed = done_time - start_time)
|
246
|
-
log :done, "#{Log.color :red, "Completed task"} #{Log.color :yellow, task.name.to_s || ""} [#{Process.pid}] +#{time_elapsed.to_i}"
|
262
|
+
@result = prepare_result result, @task.result_description
|
247
263
|
end
|
248
|
-
|
249
|
-
result
|
250
|
-
end
|
251
|
-
|
252
|
-
if no_load
|
253
|
-
@result = result
|
254
|
-
self
|
255
|
-
else
|
256
|
-
@result = prepare_result result, @task.result_description, info
|
257
264
|
end
|
258
265
|
end
|
259
266
|
|
@@ -266,11 +273,10 @@ class Step
|
|
266
273
|
begin
|
267
274
|
res = run(true)
|
268
275
|
io = get_stream
|
269
|
-
#io = res.result if IO === res.result
|
270
|
-
#io = res.result.stream if TSV::Dumper === res.result
|
271
276
|
if IO === io
|
272
|
-
io
|
273
|
-
io.
|
277
|
+
Misc.consume_stream(io)
|
278
|
+
io.close unless io.closed?
|
279
|
+
io.join if io.respond_to? :join and not io.joined?
|
274
280
|
end
|
275
281
|
rescue Aborted
|
276
282
|
Log.debug{"Forked process aborted: #{path}"}
|
@@ -363,6 +369,9 @@ class Step
|
|
363
369
|
rescue Exception
|
364
370
|
end
|
365
371
|
|
372
|
+
@result = nil
|
373
|
+
@pid = nil
|
374
|
+
|
366
375
|
begin
|
367
376
|
Open.rm info_file if Open.exists? info_file
|
368
377
|
Open.rm info_file + '.lock' if Open.exists? info_file + '.lock'
|
@@ -378,14 +387,17 @@ class Step
|
|
378
387
|
|
379
388
|
# A step result with no info_file means that it was manually
|
380
389
|
# placed. In that case, do not consider its dependencies
|
381
|
-
return [] if self.
|
390
|
+
return [] if Open.exists?(self.path.to_s) and not Open.exists? self.info_file
|
382
391
|
|
383
392
|
return [] if dependencies.nil? or dependencies.empty?
|
384
393
|
new_dependencies = dependencies.collect{|step|
|
385
394
|
step.rec_dependencies
|
386
|
-
}.flatten
|
395
|
+
}.flatten.uniq.compact
|
387
396
|
|
388
|
-
dependencies + new_dependencies
|
397
|
+
dependencies = self.dependencies ? self.dependencies + new_dependencies : new_dependencies
|
398
|
+
dependencies.flatten!
|
399
|
+
dependencies.uniq!
|
400
|
+
dependencies
|
389
401
|
end
|
390
402
|
|
391
403
|
def recursive_clean
|
@@ -398,7 +410,8 @@ class Step
|
|
398
410
|
end
|
399
411
|
|
400
412
|
def step(name)
|
401
|
-
|
413
|
+
@steps ||= {}
|
414
|
+
@steps[name] ||= rec_dependencies.select do |step|
|
402
415
|
step.task_name.to_sym == name.to_sym
|
403
416
|
end.first
|
404
417
|
end
|
@@ -81,7 +81,7 @@ def fix_options(workflow, task, job_options)
|
|
81
81
|
job_options.each do |name, value|
|
82
82
|
value = case input_types[name].to_sym
|
83
83
|
when :boolean
|
84
|
-
TrueClass
|
84
|
+
TrueClass === value or %w(true TRUE T yes).include? value
|
85
85
|
when :float
|
86
86
|
value.to_f
|
87
87
|
when :integer
|
@@ -322,7 +322,7 @@ begin
|
|
322
322
|
|
323
323
|
if options.delete(:provenance)
|
324
324
|
job.join
|
325
|
-
pp job.
|
325
|
+
pp job.provenance_paths
|
326
326
|
exit 0
|
327
327
|
end
|
328
328
|
|
data/test/rbbt/util/test_log.rb
CHANGED
@@ -2,6 +2,14 @@ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'test_helpe
|
|
2
2
|
require 'rbbt/util/log'
|
3
3
|
|
4
4
|
class TestLog < Test::Unit::TestCase
|
5
|
+
def test_get_level
|
6
|
+
assert_equal 0, Log.get_level(:debug)
|
7
|
+
assert_equal 1, Log.get_level(:low)
|
8
|
+
assert_equal 1, Log.get_level("LOW")
|
9
|
+
assert_equal 1, Log.get_level(1)
|
10
|
+
assert_equal 0, Log.get_level(nil)
|
11
|
+
end
|
12
|
+
|
5
13
|
def test_color
|
6
14
|
assert Log.color(:green, "green")
|
7
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.11.
|
4
|
+
version: 5.11.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|