rbbt-util 5.22.1 → 5.22.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b9813fbac7c55028b0e3ad16c838bc28c11ba00
4
- data.tar.gz: 2f2aca52f1ee3cf761e02abdda0d0b8909030749
3
+ metadata.gz: a706bb947413cbe8267aac3c21f7d23668313123
4
+ data.tar.gz: 835cc701d39015fbdb0379ff483c38513e77a134
5
5
  SHA512:
6
- metadata.gz: bfab013cd31214571c69b04043e6847f2fb654a2b3b018f4bb316c8a01161b94ae4bb512a226b500db6486f1f1f6d81a0f1aa67ba78531c6d76f8dfc255354ef
7
- data.tar.gz: 49b27fb08c8a80bbddb2939cff3321f8908ecc6e64d909be74756f95cd25413f8cea2d86a5f3202022a5d51db265ca610570cc4d298e6ecd3d6e04277a28021d
6
+ metadata.gz: c7db876d745f2dfc5dbefb8798145a29f3ef32962a31f1940bc611589fd61a9feb918616cfa1f45c769b2d67767f9eb5a9b487b2f1d35fa845c0bb645d3915f6
7
+ data.tar.gz: 68fe15aa3feaab425c9d90424f4bdba20206f5f10a541ace9c7a8aef6d956b4c980566feb1253501999d53a58d58bd1d3d91c0b5ec624bae5e333889cdfe24e4
data/lib/rbbt/monitor.rb CHANGED
@@ -146,7 +146,8 @@ module Rbbt
146
146
  task = File.basename(taskdir)
147
147
  next if tasks and not tasks.include? task
148
148
 
149
- cmd = "find -L '#{ taskdir }/' -not \\( -path \"#{taskdir}/*.files\" -prune \\) -not -path '*/*.pid' -not -type d 2>/dev/null"
149
+ cmd = "find -L '#{ taskdir }/' -not \\( -path \"#{taskdir}/*.files\" -prune \\) -not -name '*.pid' -not -name '*.notify' -not -name '\\.*' -not -type d 2>/dev/null"
150
+
150
151
  files = CMD.cmd(cmd, :pipe => true)
151
152
  TSV.traverse files, :type => :array, :into => jobs, :_bar => "Finding jobs in #{ taskdir }" do |file|
152
153
  _files << file
@@ -393,7 +393,9 @@ module TSV
393
393
  raise $!
394
394
  ensure
395
395
  q.clean
396
- Log::ProgressBar.remove_bar(bar, error) if bar
396
+ if bar
397
+ Log::ProgressBar.remove_bar(bar, error)
398
+ end
397
399
  end
398
400
  end
399
401
 
@@ -595,8 +597,9 @@ module TSV
595
597
  if into
596
598
  bar = Misc.process_options options, :bar
597
599
 
598
- options[:join] = Proc.new do
599
- Log::ProgressBar.remove_bar(bar)
600
+ options[:join] = Proc.new do |error|
601
+ error = false if error.nil?
602
+ Log::ProgressBar.remove_bar(bar, error)
600
603
  end if bar
601
604
 
602
605
  options[:callback] = Proc.new do |e|
@@ -12,6 +12,7 @@ class RbbtProcessQueue
12
12
  @respawn = reswpan
13
13
  @offset = offset
14
14
  @queue = RbbtProcessSocket.new
15
+ @process_mutex = Mutex.new
15
16
  end
16
17
 
17
18
  attr_accessor :callback, :callback_queue, :callback_thread
@@ -25,7 +26,7 @@ class RbbtProcessQueue
25
26
  @callback_thread = Thread.new(Thread.current) do |parent|
26
27
  begin
27
28
  loop do
28
- p = @callback_queue.pop
29
+ p = @callback_queue.pop unless @callback_queue.cleaned
29
30
 
30
31
  if Exception === p or (Array === p and Exception === p.first)
31
32
  e = Array === p ? p.first : p
@@ -39,14 +40,14 @@ class RbbtProcessQueue
39
40
  @callback.call p
40
41
  end
41
42
  end
43
+ rescue ClosedStream
42
44
  rescue Aborted
43
45
  Log.warn "Callback thread aborted"
44
- @process_monitor.raise $!
46
+ self._abort
45
47
  raise $!
46
- rescue ClosedStream
47
48
  rescue Exception
48
49
  Log.warn "Exception captured in callback: #{$!.message}"
49
- @process_monitor.raise $!
50
+ self._abort
50
51
  raise $!
51
52
  ensure
52
53
 
@@ -59,61 +60,160 @@ class RbbtProcessQueue
59
60
  end
60
61
 
61
62
  def init(&block)
62
- num_processes.times do |i|
63
- @processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, @offset, &block)
64
- end
65
- @queue.close_read
63
+ @init_block = block
66
64
 
67
- @process_monitor = Thread.new(Thread.current) do |parent|
68
- begin
69
- while @processes.any?
70
- @processes[0].join
71
- @processes.shift
72
- end
73
- rescue Aborted
74
- Log.warn "Aborting process monitor"
75
- @processes.each{|p| p.abort }
76
- @processes.each{|p|
65
+ @master_pid = Process.fork do
66
+ if @callback_queue
67
+ Misc.purge_pipes(@queue.swrite,@queue.sread,@callback_queue.swrite, @callback_queue.sread)
68
+ else
69
+ Misc.purge_pipes(@queue.swrite,@queue.sread)
70
+ end
71
+
72
+ @total = num_processes
73
+ @count = 0
74
+ @processes = []
75
+ @close_up = false
76
+
77
+
78
+ Signal.trap(:INT) do
79
+ @close_up = true
80
+ @manager_thread.raise TryAgain
81
+ end
82
+
83
+ @manager_thread = Thread.new do
84
+ while true
77
85
  begin
78
- p.join
79
- rescue ProcessFailed
86
+ begin
87
+ sleep 10
88
+ rescue TryAgain
89
+ end
90
+
91
+ @process_mutex.synchronize do
92
+ if @close_up
93
+ @total.times do
94
+ @queue.push ClosedStream.new unless @queue.cleaned
95
+ end unless @processes.empty?
96
+ @count = 0
97
+ end
98
+ while @count > 0
99
+ @count -= 1
100
+ @total += 1
101
+ @processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, @offset, &@init_block)
102
+ Log.low "Added process #{@processes.last.pid} to #{Process.pid} (#{@processes.length})"
103
+ end
104
+
105
+ while @count < 0
106
+ @count += 1
107
+ next unless @processes.length > 1
108
+ first = @processes.shift
109
+ first.stop
110
+ Log.low "Removed process #{first.pid} from #{Process.pid} (#{@processes.length})"
111
+ end
112
+ end
113
+ rescue TryAgain
114
+ retry
115
+ rescue Aborted
116
+ Log.low "Closing manager thread"
117
+ raise Aborted
118
+ rescue Exception
119
+ Log.exception $!
120
+ raise Exception
80
121
  end
81
- }
82
- rescue Exception
83
- Log.warn "Process monitor exception: #{$!.message}"
84
- @processes.each{|p| p.abort }
85
- @processes.each{|p|
86
- begin
87
- p.join
88
- rescue ProcessFailed
122
+ end
123
+ end
124
+
125
+ Signal.trap(:USR1) do
126
+ @count += 1
127
+ @manager_thread.raise TryAgain
128
+ end
129
+
130
+ Signal.trap(:USR2) do
131
+ @count -= 1
132
+ @manager_thread.raise TryAgain
133
+ end
134
+
135
+
136
+ @callback_queue.close_read if @callback_queue
137
+
138
+ num_processes.times do |i|
139
+ @process_mutex.synchronize do
140
+ @processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, @offset, &@init_block)
141
+ end
142
+ end
143
+
144
+ @monitor_thread = Thread.new do
145
+ begin
146
+ while @processes.any?
147
+ @processes[0].join
148
+ @processes.shift
89
149
  end
90
- }
91
- @callback_thread.raise $! if @callback_thread and @callback_thread.alive?
92
- raise $!
150
+ rescue Aborted
151
+ Log.warn "Aborting process monitor"
152
+ @processes.each{|p| p.abort_and_join}
153
+ @processes.clear
154
+
155
+ @callback_thread.kill if @callback_thread && @callback_thread.alive?
156
+ @manager_thread.kill if @manager_thread.alive?
157
+ rescue Exception
158
+ Log.warn "Process monitor exception: #{$!.message}"
159
+ @processes.each{|p| p.abort_and_join}
160
+ @processes.clear
161
+
162
+ @callback_thread.kill if @callback_thread && @callback_thread.alive?
163
+ @manager_thread.kill if @manager_thread.alive?
164
+ end
165
+ end
166
+
167
+ Signal.trap(20) do
168
+ begin
169
+ @monitor_thread.raise Aborted.new
170
+ rescue Exception
171
+ Log.exception $!
172
+ end
173
+ end
174
+
175
+ begin
176
+ @monitor_thread.join
177
+ rescue Exception
178
+ Log.exception $!
93
179
  end
180
+
181
+ Kernel.exit! 0
94
182
  end
183
+
184
+ Log.info "Cpu process (#{num_processes}) started with master: #{@master_pid}"
185
+
186
+ @queue.close_read
187
+ end
188
+
189
+ def add_process
190
+ Process.kill :USR1, @master_pid
191
+ end
192
+
193
+ def remove_process
194
+ Process.kill :USR2, @master_pid
95
195
  end
96
196
 
97
197
  def close_callback
198
+ return unless @callback_thread.alive?
98
199
  begin
99
- @callback_queue.push ClosedStream.new if @callback_thread.alive?
200
+ t = Thread.new do
201
+ @callback_queue.push ClosedStream.new
202
+ end
100
203
  rescue Exception
101
204
  Log.warn "Error closing callback: #{$!.message}"
102
205
  end
103
206
  @callback_thread.join #if @callback_thread.alive?
207
+ t.join
104
208
  end
105
209
 
106
- def join
107
- begin
108
- @processes.length.times do
109
- @queue.push ClosedStream.new
110
- end if @process_monitor.alive?
111
- rescue Exception
112
- end
113
-
210
+ def _join
211
+ error = true
114
212
  begin
115
- @process_monitor.join
116
- close_callback if @callback
213
+ pid, status = Process.waitpid2 @master_pid
214
+ error = false if status.success?
215
+ raise ProcessFailed if error
216
+ rescue Errno::ECHILD
117
217
  rescue Aborted
118
218
  Log.error "Aborted joining queue"
119
219
  raise $!
@@ -121,34 +221,64 @@ class RbbtProcessQueue
121
221
  Log.error "Exception joining queue: #{$!.message}"
122
222
  raise $!
123
223
  ensure
124
- @queue.swrite.close unless @queue.swrite.closed?
224
+ if @join
225
+ if @join.arity == 1
226
+ @join.call(error)
227
+ else
228
+ @join.call
229
+ end
230
+ end
125
231
  end
126
232
 
127
- @join.call if @join
128
233
  end
129
234
 
130
- def clean
131
- if (@process_monitor and @process_monitor.alive?) or (@callback_thread and @callback_thread.alive?)
132
- self.abort
133
- self.join
235
+ def join
236
+ begin
237
+ Process.kill :INT, @master_pid
238
+ rescue Errno::ECHILD, Errno::ESRCH
239
+ Log.debug "Cannot kill #{@master_pid}: #{$!.message}"
240
+ end
241
+
242
+ begin
243
+ _join
244
+ ensure
245
+ close_callback if @callback
246
+ @queue.swrite.close unless @queue.swrite.closed?
134
247
  end
248
+ @callback_thread.join if @callback_thread
249
+ self.clean
250
+ end
135
251
 
136
- @queue.clean if @queue
137
- @callback_queue.clean if @callback_queue
252
+ def _abort
253
+ begin
254
+ Process.kill 20, @master_pid
255
+ rescue Errno::ECHILD, Errno::ESRCH
256
+ Log.debug "Cannot kill #{@master_pid}: #{$!.message}"
257
+ end
258
+
259
+ begin
260
+ _join
261
+ rescue ProcessFailed
262
+ end
138
263
  end
139
264
 
140
265
  def abort
266
+ _abort
267
+ (@callback_thread.raise(Aborted.new); @callback_thread.join) if @callback_thread and @callback_thread.alive?
268
+ raise Aborted.new
269
+ end
270
+
271
+ def clean
141
272
  begin
142
- (@process_monitor.raise(Aborted.new); @process_monitor.join) if @process_monitor and @process_monitor.alive?
143
- (@callback_thread.raise(Aborted.new); @callback_thread.join) if @callback_thread and @callback_thread.alive?
273
+ self.abort if Misc.pid_exists?(@master_pid)
274
+
144
275
  ensure
145
- begin
146
- join
147
- rescue ProcessFailed
148
- end
276
+ @queue.clean if @queue
277
+ @callback_queue.clean if @callback_queue
149
278
  end
150
279
  end
151
280
 
281
+
152
282
  def process(*e)
153
283
  begin
154
284
  @queue.push e
@@ -3,12 +3,11 @@ require 'rbbt/util/semaphore'
3
3
  class RbbtProcessQueue
4
4
  class RbbtProcessSocket
5
5
 
6
- attr_accessor :sread, :swrite, :write_sem, :read_sem
6
+ attr_accessor :sread, :swrite, :write_sem, :read_sem, :cleaned
7
7
  def initialize(serializer = nil)
8
8
  @sread, @swrite = Misc.pipe
9
9
 
10
10
  @serializer = serializer || Marshal
11
-
12
11
 
13
12
  @key = "/" << rand(1000000000).to_s << '.' << Process.pid.to_s;
14
13
  @write_sem = @key + '.in'
@@ -19,6 +18,7 @@ class RbbtProcessQueue
19
18
  end
20
19
 
21
20
  def clean
21
+ @cleaned = true
22
22
  @sread.close unless @sread.closed?
23
23
  @swrite.close unless @swrite.closed?
24
24
  Log.debug "Destroying socket semaphores: #{[@key] * ", "}"
@@ -12,48 +12,63 @@ class RbbtProcessQueue
12
12
 
13
13
  def run
14
14
  begin
15
- Signal.trap(:INT){
16
- Kernel.exit! -1
17
- }
15
+ begin
16
+ Signal.trap(:INT){
17
+ Kernel.exit! -1
18
+ }
18
19
 
19
- @stop = false
20
- Signal.trap(:USR1){
21
- @stop = true
22
- }
20
+ @respawn = false
21
+ Signal.trap(:USR1){
22
+ @respawn = true
23
+ }
23
24
 
24
- @abort = false
25
- Signal.trap(:USR2){
26
- @abort = true
27
- }
25
+ @stop = false
26
+ Signal.trap(:USR2){
27
+ @stop = true
28
+ }
28
29
 
30
+ @abort = false
31
+ Signal.trap(20){
32
+ @abort = true
33
+ raise Aborted
34
+ }
29
35
 
30
- loop do
31
- p = @queue.pop
32
- next if p.nil?
33
- raise p if Exception === p
34
- raise p.first if Array === p and Exception === p.first
35
- begin
36
- res = @block.call *p
37
- @callback_queue.push res if @callback_queue
38
- rescue Respawn
39
- @callback_queue.push $!.payload
40
- raise $!
36
+ loop do
37
+ p = @queue.pop
38
+ next if p.nil?
39
+ raise p if Exception === p
40
+ raise p.first if Array === p and Exception === p.first
41
+ begin
42
+ res = @block.call *p
43
+ @callback_queue.push res if @callback_queue
44
+ rescue Respawn
45
+ @callback_queue.push $!.payload
46
+ raise $!
47
+ end
48
+ raise Respawn if @respawn
49
+ if @stop
50
+ Log.high "Worker #{Process.pid} leaving"
51
+ break
52
+ end
41
53
  end
42
- raise Respawn if @stop
43
- raise Aborted if @abort
54
+ Kernel.exit! 0
55
+ rescue Respawn
56
+ Kernel.exit! 28
57
+ rescue ClosedStream
58
+ rescue Interrupt,Aborted
59
+ Log.high "Worker #{Process.pid} aborted"
60
+ rescue SemaphoreInterrupted
61
+ retry unless @stop
62
+ Log.high "Worker #{Process.pid} leaving"
63
+ rescue Exception
64
+ Log.exception $!
65
+ @callback_queue.push($!) if @callback_queue
66
+ Kernel.exit! -1
67
+ ensure
68
+ @callback_queue.close_write if @callback_queue
44
69
  end
45
- Kernel.exit! 0
46
- rescue Respawn
47
- Kernel.exit! 28
48
- rescue ClosedStream
49
- rescue Aborted, Interrupt
50
- Log.info "Worker #{Process.pid} aborted"
51
- rescue Exception
52
- Log.exception $!
53
- @callback_queue.push($!) if @callback_queue
54
- Kernel.exit! -1
55
- ensure
56
- @callback_queue.close_write if @callback_queue
70
+ rescue Aborted
71
+ Log.high "Worker #{Process.pid} aborted"
57
72
  end
58
73
  Kernel.exit! 0
59
74
  end
@@ -81,15 +96,16 @@ class RbbtProcessQueue
81
96
  begin
82
97
  while true
83
98
  @monitored = true
84
- current = @current ? 0 : Misc.memory_use(@current)
85
- if current > memory_cap and not @asked
86
- Log.medium "Worker #{@current} for #{Process.pid} asked to respawn -- initial: #{initial} - multiplier: #{multiplier} - cap: #{memory_cap} - current: #{current}"
99
+
100
+ current_mem = @current ? Misc.memory_use(@current) : 0
101
+ if current_mem > memory_cap and not @asked
102
+ Log.medium "Worker #{@current} for #{Process.pid} asked to respawn -- initial: #{initial} - multiplier: #{multiplier} - cap: #{memory_cap} - current: #{current_mem}"
87
103
  RbbtSemaphore.synchronize(@callback_queue.write_sem) do
88
104
  Process.kill "USR1", @current if @current
89
105
  end
90
106
  @asked = true
91
107
  end
92
- sleep 3 + rand(5)
108
+ sleep 2
93
109
  end
94
110
  rescue
95
111
  Log.exception $!
@@ -99,6 +115,7 @@ class RbbtProcessQueue
99
115
  while ! @monitored
100
116
  sleep 0.1
101
117
  end
118
+
102
119
  @current = Process.fork do
103
120
  run
104
121
  end
@@ -161,14 +178,65 @@ class RbbtProcessQueue
161
178
  end
162
179
 
163
180
  def join
164
- Process.waitpid @pid
165
- raise ProcessFailed if not $?.success?
181
+ return unless Misc.pid_exists? @pid
182
+ begin
183
+ pid, status = Process.waitpid2 @pid
184
+ raise ProcessFailed if not status.success?
185
+ rescue Aborted
186
+ self.abort
187
+ raise $!
188
+ rescue Errno::ESRCH, Errno::ECHILD
189
+ Log.exception $!
190
+ rescue ProcessFailed
191
+ raise $!
192
+ rescue Exception
193
+ Log.exception $!
194
+ raise $!
195
+ end
166
196
  end
167
197
 
198
+
168
199
  def abort
200
+ begin
201
+ Process.kill 20, @pid
202
+ rescue Errno::ESRCH, Errno::ECHILD
203
+ rescue Exception
204
+ Log.exception $!
205
+ end
206
+ end
207
+
208
+ def abort_and_join
209
+ begin
210
+ Process.kill 20, @pid
211
+ rescue Errno::ESRCH, Errno::ECHILD
212
+ Log.low "Already joined worker #{@pid}"
213
+ return
214
+ end
215
+
216
+ Misc.insist([0,0.05,0.5,1,2]) do
217
+ begin
218
+ pid, status = Process.waitpid2 @pid, Process::WNOHANG
219
+ raise if status.nil?
220
+ Log.low "Abort and join of #{@pid}"
221
+ return
222
+ rescue Errno::ESRCH, Errno::ECHILD
223
+ Log.low "Already joined worker #{@pid}"
224
+ return
225
+ end
226
+ end
227
+
228
+
229
+ begin
230
+ Log.low "Forcing abort of #{@pid}"
231
+ Process.kill 9, @pid
232
+ pid, status = Process.waitpid2 @pid
233
+ rescue Errno::ESRCH, Errno::ECHILD
234
+ end
235
+ end
236
+
237
+ def stop
169
238
  begin
170
239
  Process.kill :USR2, @pid
171
- Process.kill :INT, @pid
172
240
  rescue Errno::ESRCH
173
241
  rescue Exception
174
242
  Log.exception $!
@@ -58,6 +58,9 @@ module Log
58
58
  end
59
59
 
60
60
  def self.remove_bar(bar, error = false)
61
+ BAR_MUTEX.synchronize do
62
+ return if REMOVE.include? bar
63
+ end
61
64
  if error
62
65
  bar.error if bar.respond_to? :error
63
66
  else
@@ -84,7 +84,7 @@ module ConcurrentStream
84
84
  if no_fail
85
85
  Log.low "Not failing on exception joining thread in ConcurrenStream: #{filename}"
86
86
  else
87
- Log.warn "Exception joining thread in ConcurrenStream: #{filename}"
87
+ Log.low "Exception joining thread in ConcurrenStream: #{filename}"
88
88
  raise $!
89
89
  end
90
90
  end
@@ -1,13 +1,15 @@
1
1
  class RbbtException < StandardError; end
2
2
  class ParameterException < RbbtException; end
3
3
  class FieldNotFoundError < RbbtException;end
4
- class TryAgain < RbbtException; end
5
4
  class ClosedStream < RbbtException; end
6
5
 
7
6
  class ProcessFailed < RbbtException; end
8
7
 
9
8
  class Aborted < StandardError; end
10
9
 
10
+ class TryAgain < StandardError; end
11
+ class SemaphoreInterrupted < TryAgain; end
12
+
11
13
  class RemoteServerError < RbbtException; end
12
14
 
13
15
  class DependencyError < Aborted
@@ -95,6 +95,14 @@ module Misc
95
95
  end
96
96
  new
97
97
  end
98
+ when Float
99
+ if obj.abs > 10
100
+ "%.1f" % obj
101
+ elsif obj.abs > 1
102
+ "%.3f" % obj
103
+ else
104
+ "%.6f" % obj
105
+ end
98
106
  else
99
107
  obj.to_s
100
108
  end
@@ -472,8 +472,11 @@ module Open
472
472
  case
473
473
  when block_given?
474
474
  begin
475
- File.open(file, mode) do |f|
475
+ f = File.open(file, mode)
476
+ begin
476
477
  yield f
478
+ ensure
479
+ f.close unless f.closed?
477
480
  end
478
481
  rescue Exception
479
482
  FileUtils.rm file if File.exist? file
@@ -33,11 +33,13 @@ if continue
33
33
  EOF
34
34
 
35
35
  builder.c_singleton <<-EOF
36
- void wait_semaphore(char* name){
36
+ int wait_semaphore(char* name){
37
+ int ret;
37
38
  sem_t* sem;
38
39
  sem = sem_open(name, 0);
39
- sem_wait(sem);
40
+ ret = sem_wait(sem);
40
41
  sem_close(sem);
42
+ return(ret);
41
43
  }
42
44
  EOF
43
45
 
@@ -53,7 +55,8 @@ if continue
53
55
 
54
56
  SEM_MUTEX = Mutex.new
55
57
  def self.synchronize(sem)
56
- RbbtSemaphore.wait_semaphore(sem)
58
+ ret = RbbtSemaphore.wait_semaphore(sem)
59
+ raise SemaphoreInterrupted if ret == -1
57
60
  begin
58
61
  yield
59
62
  ensure
@@ -50,6 +50,14 @@ class Step
50
50
  path.nil? ? nil : path + '.info'
51
51
  end
52
52
 
53
+ def self.tmp_path(path)
54
+ path = path.find if Path === path
55
+ path = File.expand_path(path)
56
+ dir = File.dirname(path)
57
+ filename = File.basename(path)
58
+ File.join(dir, '.' << filename)
59
+ end
60
+
53
61
  def self.pid_file(path)
54
62
  path.nil? ? nil : path + '.pid'
55
63
  end
@@ -447,6 +455,10 @@ class Step
447
455
  @files_dir ||= Step.files_dir path
448
456
  end
449
457
 
458
+ def tmp_path
459
+ @tmp_path ||= Step.tmp_path path
460
+ end
461
+
450
462
  def files
451
463
  files = Dir.glob(File.join(files_dir, '**', '*')).reject{|path| File.directory? path}.collect do |path|
452
464
  Misc.path_relative_to(files_dir, path)
@@ -898,7 +910,7 @@ module Workflow
898
910
  if inputs.length > 0 or dependencies.any?
899
911
  tagged_jobname = case TAG
900
912
  when :hash
901
- hash_str = Misc.obj2digest({:inputs => inputs, :dependencies => dependencies})
913
+ hash_str = Misc.obj2digest({:inputs => Annotated.purge(inputs), :dependencies => dependencies})
902
914
  jobname + '_' << hash_str
903
915
  when :inputs
904
916
  all_inputs = {}
@@ -266,9 +266,7 @@ class Step
266
266
 
267
267
  Misc.insist do
268
268
  Open.rm info_file if Open.exists? info_file
269
- #Open.rm info_file + '.lock' if Open.exists? info_file + '.lock'
270
269
  Open.rm path if Open.exists? path
271
- #Open.rm path + '.lock' if Open.exists? path + '.lock'
272
270
  Open.rm_rf files_dir if Open.exists? files_dir
273
271
  Open.rm pid_file if Open.exists? pid_file
274
272
  end
@@ -364,6 +364,9 @@ class Step
364
364
 
365
365
  set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]}
366
366
 
367
+ if result.nil? && File.exists?(self.tmp_path) && ! File.exists?(self.path)
368
+ FileUtils.mv self.tmp_path, self.path
369
+ end
367
370
  result
368
371
  end
369
372
 
@@ -526,7 +529,6 @@ class Step
526
529
  stream.abort
527
530
  rescue Aborted, Interrupt
528
531
  Log.medium "Aborting job stream #{stream.inspect} ABORTED RETRY -- #{Log.color :blue, path}"
529
- Log.exception $!
530
532
  if doretry
531
533
  doretry = false
532
534
  retry
@@ -563,7 +565,6 @@ class Step
563
565
  retry
564
566
  end
565
567
  rescue Exception
566
- Log.exception $!
567
568
  if doretry
568
569
  doretry = false
569
570
  retry
@@ -124,7 +124,7 @@ jobs = Rbbt.job_info workflow, task
124
124
  workflows = {}
125
125
 
126
126
  TSV.traverse jobs, :_bar => "Checking job status" do |file,info|
127
- next unless all or not info[:done] or not File.exist? file
127
+ next unless all || ! info[:done] || ! File.exist?(file)
128
128
  workflow = info[:workflow]
129
129
  task = info[:task]
130
130
  workflows[workflow] ||= {}
@@ -182,7 +182,7 @@ workflows.sort.each do |workflow,tasks|
182
182
  value = info[field]
183
183
  next if value.nil?
184
184
  value_str = Misc.fingerprint(value)
185
- str << " #{field}=#{value_str}"
185
+ str << "\t#{Log.color :magenta, field}=#{value_str}"
186
186
  end
187
187
  end
188
188
  end
@@ -80,7 +80,7 @@ def report_msg(status, name, path, info = nil)
80
80
  value = job_inputs[input]
81
81
  next if value.nil?
82
82
  value_str = Misc.fingerprint(value)
83
- str << " #{Log.color :magenta, input}=#{value_str}"
83
+ str << "\t#{Log.color :magenta, input}=#{value_str}"
84
84
  end
85
85
  end
86
86
 
@@ -88,9 +88,9 @@ def report_msg(status, name, path, info = nil)
88
88
  $info_fields.each do |field|
89
89
  IndiferentHash.setup(info)
90
90
  value = info[field]
91
- next if value.nil?
91
+ next if value.nil?
92
92
  value_str = Misc.fingerprint(value)
93
- str << " #{Log.color :magenta, field}=#{value_str}"
93
+ str << "\t#{Log.color :magenta, field}=#{value_str}"
94
94
  end
95
95
  end
96
96
 
@@ -6,6 +6,68 @@ require 'rbbt/util/concurrency/processes'
6
6
 
7
7
  class TestConcurrencyProcess < Test::Unit::TestCase
8
8
 
9
+ def setup
10
+ Log.severity = 0
11
+ end
12
+
13
+ def test_process_throttle
14
+ q = RbbtProcessQueue.new 10
15
+
16
+ times = 500
17
+
18
+ res = []
19
+ q.callback do |v|
20
+ res << v
21
+ end
22
+
23
+ q.init do |i|
24
+ sleep 0.001
25
+ Process.pid
26
+ end
27
+
28
+ times.times do |i|
29
+ q.process i
30
+ end
31
+
32
+ sleep 1 while res.length < times
33
+ assert_equal 10, res.uniq.length
34
+
35
+ q.add_process
36
+ sleep 0.1
37
+ q.add_process
38
+ sleep 0.1
39
+ q.add_process
40
+ sleep 0.1
41
+
42
+ times.times do |i|
43
+ q.process i
44
+ end
45
+
46
+ sleep 1 while res.length < times * 2
47
+ assert_equal 13, res[(times + 20)..-1].uniq.length
48
+
49
+ q.remove_process
50
+ sleep 0.1
51
+ q.remove_process
52
+ sleep 0.1
53
+ q.remove_process
54
+ sleep 0.1
55
+ q.remove_process
56
+ sleep 0.1
57
+ q.remove_process
58
+ sleep 0.1
59
+
60
+ times.times do |i|
61
+ q.process i
62
+ end
63
+
64
+ sleep 1 while res.length < times * 3
65
+ assert_equal 8, res[(2*times + 30)..-1].uniq.length
66
+
67
+ q.join
68
+ assert_equal times * 3, res.length
69
+ end
70
+
9
71
  def test_process
10
72
  q = RbbtProcessQueue.new 10
11
73
 
@@ -20,7 +82,6 @@ class TestConcurrencyProcess < Test::Unit::TestCase
20
82
  end
21
83
 
22
84
  times = 500
23
- t = TSV.setup({"a" => 1}, :type => :single)
24
85
 
25
86
  times.times do |i|
26
87
  q.process i
@@ -45,6 +106,34 @@ class TestConcurrencyProcess < Test::Unit::TestCase
45
106
  end
46
107
  end
47
108
 
109
+ def test_error
110
+ assert_raise RbbtException do
111
+ q = RbbtProcessQueue.new 3
112
+
113
+ res = []
114
+
115
+ q.callback do |v|
116
+ res << v
117
+ end
118
+
119
+ q.init do |i|
120
+ raise RbbtException.new "MY ERROR" if i == 300
121
+ i * 2
122
+ end
123
+
124
+ times = 500
125
+
126
+ times.times do |i|
127
+ q.process i
128
+ end
129
+
130
+ q.join
131
+
132
+ assert_equal times, res.length
133
+ assert_equal [0, 2, 4], res.sort[0..2]
134
+ end
135
+ end
136
+
48
137
  def test_process_abort
49
138
  assert_raise Aborted do
50
139
  q = RbbtProcessQueue.new 10
@@ -60,15 +149,14 @@ class TestConcurrencyProcess < Test::Unit::TestCase
60
149
  end
61
150
 
62
151
  times = 500
63
- t = TSV.setup({"a" => 1}, :type => :single)
64
152
 
65
153
  times.times do |i|
66
154
  q.process i
67
155
  end
68
156
 
69
- sleep 2
157
+ sleep 1
70
158
  q.clean
71
-
159
+ sleep 1
72
160
 
73
161
  q.join
74
162
  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.22.1
4
+ version: 5.22.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-26 00:00:00.000000000 Z
11
+ date: 2018-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -271,7 +271,6 @@ files:
271
271
  - lib/rbbt/util/concurrency.rb
272
272
  - lib/rbbt/util/concurrency/processes.rb
273
273
  - lib/rbbt/util/concurrency/processes/socket.rb
274
- - lib/rbbt/util/concurrency/processes/socket_old.rb
275
274
  - lib/rbbt/util/concurrency/processes/worker.rb
276
275
  - lib/rbbt/util/concurrency/threads.rb
277
276
  - lib/rbbt/util/config.rb
@@ -1,144 +0,0 @@
1
- class RbbtProcessQueue
2
- class RbbtProcessSocket
3
-
4
- class ClosedSocket < Exception; end
5
-
6
- attr_accessor :sin, :sout, :in_lockfile, :out_lockfile
7
- def initialize(lockfile = nil)
8
- @sout, @sin = File.pipe
9
-
10
- lockfile ||= TmpFile.tmp_file
11
-
12
- @lockfile = lockfile
13
- @in_lockfile = lockfile + '.in'
14
- @out_lockfile = lockfile + '.out'
15
- raise "in_lockfile exists?" if File.exists? @in_lockfile
16
- raise "out_lockfile exists?" if File.exists? @in_lockfile
17
- FileUtils.touch @in_lockfile
18
- FileUtils.touch @out_lockfile
19
- end
20
-
21
- def self.serialize(obj)
22
- dump = nil
23
- begin
24
- case obj
25
- when TSV
26
- type = "T"
27
- info = obj.info
28
- info.delete_if{|k,v| v.nil?}
29
- dump = Marshal.dump([info, {}.merge(obj)])
30
- else
31
- type = "M"
32
- dump = Marshal.dump(obj)
33
- end
34
- payload = [type, dump].pack('A1a*')
35
- length = payload.bytesize
36
- #Log.info "Writing #{ length }"
37
- [length].pack('L') << payload
38
- rescue Exception
39
- Log.error "Serialize error for: #{Misc.fingerprint obj} - #{Misc.fingerprint dump}"
40
- raise $!
41
- end
42
- end
43
-
44
- def self.unserialize(str)
45
- begin
46
- c, dump = str.unpack("A1a*")
47
- case c
48
- when "M"
49
- return Marshal.load(dump)
50
- when "T"
51
- info, hash = Marshal.load(dump)
52
- return TSV.setup(hash, info)
53
- end
54
- rescue Exception
55
- Log.error "Unserialize error for: #{Misc.fingerprint str}"
56
- raise $!
57
- end
58
- end
59
-
60
- def read_sout(length)
61
- str = ""
62
- str << sout.readpartial(length-str.length) while str.length < length
63
- str
64
- end
65
-
66
- def write_sin(str)
67
- str_length = str.length
68
- wrote = 0
69
- wrote += sin.write_nonblock(str[wrote..-1]) while wrote < str_length
70
- end
71
-
72
- def push(obj)
73
- Filelock in_lockfile do
74
- payload = RbbtProcessSocket.serialize(obj)
75
- sin << payload
76
- end
77
- end
78
-
79
-
80
- def pop
81
- r = []
82
-
83
- payload = begin
84
- Filelock out_lockfile do
85
- raise ClosedQueue if sout.eof?
86
- r,w,e = IO.select([sout], [], [], 1)
87
- raise TryAgain if r.empty?
88
-
89
- first_char = read_sout(4)
90
- length = first_char.unpack('L').first
91
- #Log.info "Reading #{ length }"
92
- read_sout(length)
93
- end
94
- rescue TryAgain
95
- sleep 1
96
- end
97
-
98
- RbbtProcessSocket.unserialize(payload)
99
- end
100
-
101
- def pop
102
- loop do
103
- r,w,e = IO.select([sout], [], [], 1)
104
- next if r.empty?
105
- break
106
- end
107
-
108
- first_char = read_sout(4)
109
- length = first_char.unpack('L').first
110
- #Log.info "Reading #{ length }"
111
- read_sout(length)
112
- end
113
- rescue TryAgain
114
- sleep 1
115
- end
116
-
117
- RbbtProcessSocket.unserialize(payload)
118
- end
119
-
120
- def rest
121
- sin.close
122
- str = sout.read
123
- res = []
124
-
125
- while not str.empty?
126
- first_char = str[0]
127
- next if first_char.nil?
128
- length = first_char.unpack("C").first
129
- dump = str[1..length]
130
- res << Marshal.load(dump)
131
- str = str[length+1..-1]
132
- end
133
-
134
- res
135
- end
136
-
137
- def clean
138
- FileUtils.rm @in_lockfile if File.exists? @in_lockfile
139
- FileUtils.rm @out_lockfile if File.exists? @out_lockfile
140
- sin.close unless sin.closed?
141
- sout.close unless sout.closed?
142
- end
143
- end
144
- end