rbbt-util 5.44.1 → 6.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rbbt +67 -90
  3. data/etc/app.d/base.rb +2 -2
  4. data/etc/app.d/semaphores.rb +3 -3
  5. data/lib/rbbt/annotations/annotated_array.rb +207 -207
  6. data/lib/rbbt/annotations/refactor.rb +27 -0
  7. data/lib/rbbt/annotations/util.rb +282 -282
  8. data/lib/rbbt/annotations.rb +343 -320
  9. data/lib/rbbt/association/database.rb +200 -225
  10. data/lib/rbbt/association/index.rb +294 -291
  11. data/lib/rbbt/association/item.rb +227 -227
  12. data/lib/rbbt/association/open.rb +35 -34
  13. data/lib/rbbt/association/util.rb +0 -169
  14. data/lib/rbbt/association.rb +2 -4
  15. data/lib/rbbt/entity/identifiers.rb +119 -118
  16. data/lib/rbbt/entity/refactor.rb +12 -0
  17. data/lib/rbbt/entity.rb +319 -315
  18. data/lib/rbbt/hpc/batch.rb +72 -53
  19. data/lib/rbbt/hpc/lsf.rb +2 -2
  20. data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
  21. data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
  22. data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
  23. data/lib/rbbt/hpc/orchestrate.rb +19 -13
  24. data/lib/rbbt/hpc/slurm.rb +18 -18
  25. data/lib/rbbt/knowledge_base/entity.rb +13 -5
  26. data/lib/rbbt/knowledge_base/query.rb +2 -2
  27. data/lib/rbbt/knowledge_base/registry.rb +32 -31
  28. data/lib/rbbt/knowledge_base/traverse.rb +1 -1
  29. data/lib/rbbt/knowledge_base.rb +1 -1
  30. data/lib/rbbt/monitor.rb +36 -25
  31. data/lib/rbbt/persist/refactor.rb +166 -0
  32. data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
  33. data/lib/rbbt/persist/tsv.rb +187 -185
  34. data/lib/rbbt/persist.rb +556 -551
  35. data/lib/rbbt/refactor.rb +20 -0
  36. data/lib/rbbt/resource/path/refactor.rb +178 -0
  37. data/lib/rbbt/resource/path.rb +317 -497
  38. data/lib/rbbt/resource/util.rb +0 -48
  39. data/lib/rbbt/resource.rb +3 -390
  40. data/lib/rbbt/tsv/accessor.rb +2 -838
  41. data/lib/rbbt/tsv/attach.rb +303 -299
  42. data/lib/rbbt/tsv/change_id.rb +244 -245
  43. data/lib/rbbt/tsv/csv.rb +87 -85
  44. data/lib/rbbt/tsv/dumper.rb +2 -100
  45. data/lib/rbbt/tsv/excel.rb +26 -24
  46. data/lib/rbbt/tsv/field_index.rb +4 -1
  47. data/lib/rbbt/tsv/filter.rb +3 -2
  48. data/lib/rbbt/tsv/index.rb +2 -284
  49. data/lib/rbbt/tsv/manipulate.rb +750 -747
  50. data/lib/rbbt/tsv/marshal.rb +3 -3
  51. data/lib/rbbt/tsv/matrix.rb +2 -2
  52. data/lib/rbbt/tsv/parallel/through.rb +2 -1
  53. data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
  54. data/lib/rbbt/tsv/parser.rb +678 -678
  55. data/lib/rbbt/tsv/refactor.rb +195 -0
  56. data/lib/rbbt/tsv/stream.rb +253 -251
  57. data/lib/rbbt/tsv/util.rb +420 -420
  58. data/lib/rbbt/tsv.rb +210 -208
  59. data/lib/rbbt/util/R/eval.rb +4 -4
  60. data/lib/rbbt/util/R/plot.rb +62 -166
  61. data/lib/rbbt/util/R.rb +21 -18
  62. data/lib/rbbt/util/cmd.rb +2 -318
  63. data/lib/rbbt/util/color.rb +269 -269
  64. data/lib/rbbt/util/colorize.rb +89 -89
  65. data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
  66. data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
  67. data/lib/rbbt/util/concurrency/processes.rb +389 -386
  68. data/lib/rbbt/util/config.rb +169 -167
  69. data/lib/rbbt/util/iruby.rb +20 -0
  70. data/lib/rbbt/util/log/progress/report.rb +241 -241
  71. data/lib/rbbt/util/log/progress/util.rb +99 -99
  72. data/lib/rbbt/util/log/progress.rb +102 -102
  73. data/lib/rbbt/util/log/refactor.rb +49 -0
  74. data/lib/rbbt/util/log.rb +486 -532
  75. data/lib/rbbt/util/migrate.rb +1 -1
  76. data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
  77. data/lib/rbbt/util/misc/development.rb +12 -11
  78. data/lib/rbbt/util/misc/exceptions.rb +117 -112
  79. data/lib/rbbt/util/misc/format.rb +2 -230
  80. data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
  81. data/lib/rbbt/util/misc/inspect.rb +2 -476
  82. data/lib/rbbt/util/misc/lock.rb +109 -106
  83. data/lib/rbbt/util/misc/omics.rb +9 -1
  84. data/lib/rbbt/util/misc/pipes.rb +765 -793
  85. data/lib/rbbt/util/misc/refactor.rb +20 -0
  86. data/lib/rbbt/util/misc/ssw.rb +27 -17
  87. data/lib/rbbt/util/misc/system.rb +0 -15
  88. data/lib/rbbt/util/misc.rb +39 -20
  89. data/lib/rbbt/util/named_array/refactor.rb +4 -0
  90. data/lib/rbbt/util/named_array.rb +3 -220
  91. data/lib/rbbt/util/open/refactor.rb +7 -0
  92. data/lib/rbbt/util/open.rb +3 -857
  93. data/lib/rbbt/util/procpath.rb +6 -6
  94. data/lib/rbbt/util/python/paths.rb +27 -0
  95. data/lib/rbbt/util/python/run.rb +115 -0
  96. data/lib/rbbt/util/python/script.rb +110 -0
  97. data/lib/rbbt/util/python/util.rb +3 -3
  98. data/lib/rbbt/util/python.rb +22 -81
  99. data/lib/rbbt/util/semaphore.rb +152 -148
  100. data/lib/rbbt/util/simpleopt.rb +9 -8
  101. data/lib/rbbt/util/ssh/refactor.rb +19 -0
  102. data/lib/rbbt/util/ssh.rb +122 -118
  103. data/lib/rbbt/util/tar.rb +117 -115
  104. data/lib/rbbt/util/tmpfile.rb +69 -67
  105. data/lib/rbbt/util/version.rb +2 -0
  106. data/lib/rbbt/workflow/refactor/entity.rb +11 -0
  107. data/lib/rbbt/workflow/refactor/export.rb +66 -0
  108. data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
  109. data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
  110. data/lib/rbbt/workflow/refactor/task_info.rb +65 -0
  111. data/lib/rbbt/workflow/refactor.rb +153 -0
  112. data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
  113. data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
  114. data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
  115. data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
  116. data/lib/rbbt/workflow/remote_workflow.rb +6 -1
  117. data/lib/rbbt/workflow/step/run.rb +766 -766
  118. data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
  119. data/lib/rbbt/workflow/step.rb +2 -362
  120. data/lib/rbbt/workflow/task.rb +118 -118
  121. data/lib/rbbt/workflow/usage.rb +289 -287
  122. data/lib/rbbt/workflow/util/archive.rb +6 -5
  123. data/lib/rbbt/workflow/util/data.rb +1 -1
  124. data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
  125. data/lib/rbbt/workflow/util/trace.rb +79 -44
  126. data/lib/rbbt/workflow.rb +4 -882
  127. data/lib/rbbt-util.rb +21 -13
  128. data/lib/rbbt.rb +16 -3
  129. data/python/rbbt/__init__.py +19 -1
  130. data/share/Rlib/plot.R +37 -37
  131. data/share/Rlib/svg.R +22 -5
  132. data/share/install/software/lib/install_helpers +1 -1
  133. data/share/rbbt_commands/hpc/list +2 -3
  134. data/share/rbbt_commands/hpc/orchestrate +4 -4
  135. data/share/rbbt_commands/hpc/tail +2 -0
  136. data/share/rbbt_commands/hpc/task +10 -7
  137. data/share/rbbt_commands/lsf/list +2 -3
  138. data/share/rbbt_commands/lsf/orchestrate +4 -4
  139. data/share/rbbt_commands/lsf/tail +2 -0
  140. data/share/rbbt_commands/lsf/task +10 -7
  141. data/share/rbbt_commands/migrate +1 -1
  142. data/share/rbbt_commands/pbs/list +2 -3
  143. data/share/rbbt_commands/pbs/orchestrate +4 -4
  144. data/share/rbbt_commands/pbs/tail +2 -0
  145. data/share/rbbt_commands/pbs/task +10 -7
  146. data/share/rbbt_commands/resource/produce +8 -1
  147. data/share/rbbt_commands/slurm/list +2 -3
  148. data/share/rbbt_commands/slurm/orchestrate +4 -4
  149. data/share/rbbt_commands/slurm/tail +2 -0
  150. data/share/rbbt_commands/slurm/task +10 -7
  151. data/share/rbbt_commands/system/clean +5 -5
  152. data/share/rbbt_commands/system/status +5 -5
  153. data/share/rbbt_commands/tsv/get +2 -3
  154. data/share/rbbt_commands/tsv/info +10 -13
  155. data/share/rbbt_commands/tsv/keys +18 -14
  156. data/share/rbbt_commands/tsv/slice +2 -2
  157. data/share/rbbt_commands/tsv/transpose +6 -2
  158. data/share/rbbt_commands/workflow/info +20 -24
  159. data/share/rbbt_commands/workflow/list +1 -1
  160. data/share/rbbt_commands/workflow/prov +20 -13
  161. data/share/rbbt_commands/workflow/server +11 -1
  162. data/share/rbbt_commands/workflow/task +76 -71
  163. data/share/rbbt_commands/workflow/write_info +26 -9
  164. data/share/software/opt/ssw/ssw.c +861 -0
  165. data/share/software/opt/ssw/ssw.h +130 -0
  166. data/share/workflow_config.ru +3 -3
  167. metadata +40 -2
@@ -1,386 +1,389 @@
1
- require 'rbbt/util/concurrency/processes/worker'
2
- require 'rbbt/util/concurrency/processes/socket'
3
-
4
- class RbbtProcessQueue
5
-
6
- attr_accessor :num_processes, :queue, :process_monitor, :cleanup, :join, :reswpan, :offset
7
- def initialize(num_processes, cleanup = nil, join = nil, reswpan = nil, offset = false)
8
- @num_processes = num_processes
9
- @cleanup = cleanup
10
- @join = join
11
- @respawn = reswpan
12
- @offset = offset
13
- @queue = RbbtProcessSocket.new
14
-
15
- key = "/" << rand(1000000000).to_s << '.' << Process.pid.to_s;
16
- @sem = key + '.process'
17
- Log.debug "Creating process semaphore: #{@sem}"
18
- RbbtSemaphore.create_semaphore(@sem,1)
19
- end
20
-
21
-
22
- ABORT_SIGNAL = :INT
23
- CLOSE_SIGNAL = :PIPE
24
-
25
- attr_accessor :callback, :callback_queue, :callback_thread
26
- def callback(&block)
27
- if block_given?
28
-
29
- @callback = block
30
-
31
- @callback_queue = RbbtProcessSocket.new
32
-
33
- else
34
- @callback, @callback_queue, @callback_thread = nil, nil, nil
35
- end
36
- end
37
-
38
- def init_master
39
- RbbtSemaphore.wait_semaphore(@sem)
40
- @master_pid = Process.fork do
41
- @close_up = false
42
- processes_initiated = false
43
- processes = []
44
- process_mutex = Mutex.new
45
-
46
- Signal.trap(CLOSE_SIGNAL) do
47
- if ! @closing_thread
48
- @close_up = true
49
- Misc.insist([0,0.01,0.1,0.2,0.5]) do
50
- if ! @manager_thread
51
- Thread.pass
52
- raise "Manager thread for #{Process.pid} not found yet"
53
- end
54
-
55
- if @manager_thread.alive?
56
- raise "Manager thread for #{Process.pid} not working yet" unless @manager_thread["working"]
57
- @manager_thread.raise TryAgain
58
- end
59
- end
60
- end
61
- end
62
-
63
- Signal.trap(:USR1) do
64
- @count += 1
65
- @manager_thread.raise TryAgain
66
- end
67
-
68
- Signal.trap(:USR2) do
69
- @count -= 1
70
- @manager_thread.raise TryAgain
71
- end
72
-
73
- Signal.trap(ABORT_SIGNAL) do
74
- @abort_monitor = true
75
- @monitor_thread.raise Aborted if @monitor_thread && @monitor_thread.alive?
76
- end
77
-
78
- if @callback_queue
79
- Misc.purge_pipes(@queue.swrite, @queue.sread, @callback_queue.swrite)
80
- else
81
- Misc.purge_pipes(@queue.swrite, @queue.sread)
82
- end
83
-
84
- @total = 0
85
- @count = 0
86
-
87
- @manager_thread = Thread.new do
88
- while true
89
- break if processes_initiated && processes.empty? && (@monitor_thread && ! @monitor_thread.alive?)
90
- begin
91
- Thread.current["working"] = true
92
- if @close_up
93
- Thread.handle_interrupt(TryAgain => :never) do
94
- Log.debug "Closing up process queue #{Process.pid}"
95
- @count = 0
96
- @closing_thread = Thread.new do
97
- Thread.handle_interrupt(TryAgain => :never) do
98
- Log.debug "Pushing closed stream #{Process.pid}"
99
- while true
100
- @queue.push ClosedStream.new unless @queue.cleaned
101
- break if processes_initiated && processes.empty?
102
- end unless processes_initiated && processes.empty?
103
- end
104
- end
105
- @close_up = false
106
- end
107
- end
108
-
109
- begin
110
- sleep 3
111
- rescue TryAgain
112
- end
113
-
114
- raise TryAgain if @close_up
115
-
116
- process_mutex.synchronize do
117
- Thread.handle_interrupt(TryAgain => :never) do
118
- while @count > 0
119
- @count -= 1
120
- @total += 1
121
- processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, (@offset ? @total : false), &@init_block)
122
- Log.warn "Added process #{processes.last.pid} to #{Process.pid} (#{processes.length})"
123
- end
124
-
125
- while @count < 0
126
- @count += 1
127
- @total -= 1
128
- next unless processes.length > 1
129
- last = processes.reject{|p| p.stopping }.last
130
- last.stop
131
- Log.warn "Removed process #{last.pid} from #{Process.pid} (#{processes.length})"
132
- end
133
- end
134
- end
135
- rescue TryAgain
136
- retry
137
- rescue Aborted
138
- Log.low "Aborting manager thread #{Process.pid}"
139
- raise $!
140
- rescue Exception
141
- raise Exception
142
- end
143
- end
144
- Log.low "Manager thread stopped #{Process.pid}"
145
- end
146
-
147
- @callback_queue.close_read if @callback_queue
148
-
149
- num_processes.to_i.times do |i|
150
- @total += 1
151
- process_mutex.synchronize do
152
- processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, (@offset ? @total : false), &@init_block)
153
- end
154
- end
155
-
156
- processes_initiated = true
157
-
158
- @monitor_thread = Thread.new do
159
- begin
160
- while processes.any?
161
- raise Aborted if @abort_monitor
162
- #processes[0].join
163
- #Log.debug "Joined process #{processes[0].pid} of queue #{Process.pid}"
164
- #processes.shift
165
- pid, status = Process.wait2
166
- Log.debug "Joined process #{pid} of queue #{Process.pid} (status: #{status})"
167
- processes.reject!{|p| p.pid == pid}
168
- raise ProcessFailed.new pid if not status.success?
169
- end
170
- Log.low "All processes completed #{Process.pid}"
171
- rescue Aborted
172
- Log.exception $!
173
- Log.low "Aborting process monitor #{Process.pid}"
174
- processes.each{|p| p.abort_and_join}
175
- Log.low "Processes aborted #{Process.pid}"
176
- processes.clear
177
-
178
- @manager_thread.raise Aborted if @manager_thread.alive?
179
- raise Aborted, "Aborted monitor thread"
180
- rescue Exception
181
- Log.low "Process monitor exception [#{Process.pid}]: #{$!.message}"
182
- processes.each{|p| p.abort_and_join}
183
- Log.low "Processes aborted for monitor #{Process.pid}"
184
- processes.clear
185
-
186
- @manager_thread.report_on_exception = false
187
- @manager_thread.raise $! if @manager_thread.alive?
188
- raise Aborted, "Aborted monitor thread with exception"
189
- end
190
- end
191
- @monitor_thread.report_on_exception = false
192
-
193
- RbbtSemaphore.post_semaphore(@sem)
194
-
195
- Log.low "Process monitor #{Process.pid} joining threads"
196
- begin
197
- @monitor_thread.join
198
- @manager_thread.raise TryAgain if @manager_thread.alive?
199
- @manager_thread.join
200
- @callback_queue.push ClosedStream.new if @callback_queue
201
- rescue Exception
202
- Kernel.exit -1
203
- end
204
- Log.low "Process monitor #{Process.pid} threads joined successfully, now exit"
205
-
206
- Kernel.exit 0
207
- end
208
-
209
- @queue.close_read
210
- Log.info "Cpu process #{@master_pid} with #{num_processes} workers."
211
- Log.low "Signal #{@master_pid} USR1/USR2 (#10/#12) to increase/decrease workers."
212
- end
213
-
214
- def init(&block)
215
- @init_block = block
216
-
217
- init_master
218
-
219
- RbbtSemaphore.synchronize(@sem) do
220
- @callback_thread = Thread.new do
221
- begin
222
- loop do
223
- p = @callback_queue.pop unless @callback_queue.cleaned
224
-
225
- if Exception === p or (Array === p and Exception === p.first)
226
- e = Array === p ? p.first : p
227
- Log.low "Callback recieved exception from worker: #{e.message}" unless Aborted === e or ClosedStream === e
228
- raise e
229
- end
230
-
231
- if @callback.arity == 0
232
- @callback.call
233
- else
234
- @callback.call p
235
- end
236
- end
237
- rescue ClosedStream
238
- Log.low "Callback thread closing"
239
- rescue Aborted
240
- Log.low "Callback thread aborted"
241
- raise $!
242
- rescue Exception
243
- Log.low "Exception captured in callback: #{$!.message}"
244
- raise $!
245
- end
246
- end if @callback_queue
247
-
248
- @callback_thread.report_on_exception = false if @callback_thread
249
-
250
- end
251
-
252
- end
253
-
254
- def add_process
255
- Process.kill :USR1, @master_pid
256
- end
257
-
258
- def remove_process
259
- Process.kill :USR2, @master_pid
260
- end
261
-
262
- def _join
263
- error = :redo
264
- begin
265
- pid, @status = Process.waitpid2 @master_pid unless @status
266
- error = true unless @status.success?
267
- begin
268
- @callback_thread.join if @callback_thread
269
- raise ProcessFailed.new @master_pid unless @status.success?
270
- rescue
271
- exception = $!
272
- raise $!
273
- end
274
- error = false
275
- rescue Aborted, Interrupt
276
- exception = $!
277
- Log.exception $!
278
- error = true
279
- if @aborted
280
- raise $!
281
- else
282
- self.abort
283
- Log.high "Process queue #{@master_pid} aborted"
284
- retry
285
- end
286
- rescue Errno::ESRCH, Errno::ECHILD
287
- retry if Misc.pid_exists? @master_pid
288
- error = ! @status.success?
289
- ensure
290
- begin
291
- begin
292
- self.abort
293
- ensure
294
- _join
295
- end if error == :redo
296
-
297
- begin
298
- @callback_thread.join
299
- rescue Exception
300
- end
301
-
302
- Log.medium "Joining process queue #{"(error) " if error}#{@master_pid} #{@join}"
303
- begin
304
- if @join
305
- if @join.arity == 1
306
- @join.call(error)
307
- else
308
- @join.call
309
- end
310
- end
311
- end
312
- ensure
313
- self.clean
314
- end
315
-
316
- if exception
317
- raise exception
318
- else
319
- raise "Process queue #{@master_pid} failed"
320
- end if error
321
- end
322
- end
323
-
324
- def close_up_queue
325
- begin
326
- RbbtSemaphore.synchronize(@sem) do
327
- Process.kill CLOSE_SIGNAL, @master_pid
328
- end
329
- rescue Errno::ECHILD, Errno::ESRCH
330
- Log.debug "Cannot kill (CLOSE) #{@master_pid}: #{$!.message}"
331
- end if Misc.pid_exists? @master_pid
332
- end
333
-
334
- def join
335
- close_up_queue
336
-
337
- _join
338
- end
339
-
340
- def _abort
341
- begin
342
- Log.warn "Aborting process queue #{@master_pid}"
343
- Process.kill ABORT_SIGNAL, @master_pid
344
- rescue Errno::ECHILD, Errno::ESRCH
345
- Log.debug "Cannot abort #{@master_pid}: #{$!.message}"
346
- end
347
- end
348
-
349
- def abort
350
- _abort
351
- @callback_thread.raise(Aborted.new) if @callback_thread and @callback_thread.alive?
352
- @aborted = true
353
- begin
354
- _join
355
- rescue
356
- end
357
- end
358
-
359
- def clean
360
- RbbtSemaphore.delete_semaphore(@sem)
361
- begin
362
- self.abort if Misc.pid_exists?(@master_pid)
363
-
364
- ensure
365
- @queue.clean if @queue
366
- #@callback_thread.push ClosedStream if @callback_thread && @callback_thread.alive?
367
- @callback_queue.clean if @callback_queue
368
- end
369
- end
370
-
371
-
372
- def process(*e)
373
- begin
374
- @queue.push e
375
- rescue Errno::EPIPE
376
- raise Aborted
377
- end
378
- end
379
-
380
- def self.each(list, num = 3, &block)
381
- q = RbbtProcessQueue.new num
382
- q.init(&block)
383
- list.each do |elem| q.process elem end
384
- q.join
385
- end
386
- end
1
+ require 'rbbt/refactor'
2
+ Rbbt.require_instead 'scout/work_queue'
3
+ require_relative 'processes/refactor'
4
+ #require 'rbbt/util/concurrency/processes/worker'
5
+ #require 'rbbt/util/concurrency/processes/socket'
6
+ #
7
+ #class RbbtProcessQueue
8
+ #
9
+ # attr_accessor :num_processes, :queue, :process_monitor, :cleanup, :join, :reswpan, :offset
10
+ # def initialize(num_processes, cleanup = nil, join = nil, reswpan = nil, offset = false)
11
+ # @num_processes = num_processes
12
+ # @cleanup = cleanup
13
+ # @join = join
14
+ # @respawn = reswpan
15
+ # @offset = offset
16
+ # @queue = RbbtProcessSocket.new
17
+ #
18
+ # key = "/" << rand(1000000000).to_s << '.' << Process.pid.to_s;
19
+ # @sem = key + '.process'
20
+ # Log.debug "Creating process semaphore: #{@sem}"
21
+ # RbbtSemaphore.create_semaphore(@sem,1)
22
+ # end
23
+ #
24
+ #
25
+ # ABORT_SIGNAL = :INT
26
+ # CLOSE_SIGNAL = :PIPE
27
+ #
28
+ # attr_accessor :callback, :callback_queue, :callback_thread
29
+ # def callback(&block)
30
+ # if block_given?
31
+ #
32
+ # @callback = block
33
+ #
34
+ # @callback_queue = RbbtProcessSocket.new
35
+ #
36
+ # else
37
+ # @callback, @callback_queue, @callback_thread = nil, nil, nil
38
+ # end
39
+ # end
40
+ #
41
+ # def init_master
42
+ # RbbtSemaphore.wait_semaphore(@sem)
43
+ # @master_pid = Process.fork do
44
+ # @close_up = false
45
+ # processes_initiated = false
46
+ # processes = []
47
+ # process_mutex = Mutex.new
48
+ #
49
+ # Signal.trap(CLOSE_SIGNAL) do
50
+ # if ! @closing_thread
51
+ # @close_up = true
52
+ # Misc.insist([0,0.01,0.1,0.2,0.5]) do
53
+ # if ! @manager_thread
54
+ # Thread.pass
55
+ # raise "Manager thread for #{Process.pid} not found yet"
56
+ # end
57
+ #
58
+ # if @manager_thread.alive?
59
+ # raise "Manager thread for #{Process.pid} not working yet" unless @manager_thread["working"]
60
+ # @manager_thread.raise TryAgain
61
+ # end
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ # Signal.trap(:USR1) do
67
+ # @count += 1
68
+ # @manager_thread.raise TryAgain
69
+ # end
70
+ #
71
+ # Signal.trap(:USR2) do
72
+ # @count -= 1
73
+ # @manager_thread.raise TryAgain
74
+ # end
75
+ #
76
+ # Signal.trap(ABORT_SIGNAL) do
77
+ # @abort_monitor = true
78
+ # @monitor_thread.raise Aborted if @monitor_thread && @monitor_thread.alive?
79
+ # end
80
+ #
81
+ # if @callback_queue
82
+ # Open.purge_pipes(@queue.swrite, @queue.sread, @callback_queue.swrite)
83
+ # else
84
+ # Open.purge_pipes(@queue.swrite, @queue.sread)
85
+ # end
86
+ #
87
+ # @total = 0
88
+ # @count = 0
89
+ #
90
+ # @manager_thread = Thread.new do
91
+ # while true
92
+ # break if processes_initiated && processes.empty? && (@monitor_thread && ! @monitor_thread.alive?)
93
+ # begin
94
+ # Thread.current["working"] = true
95
+ # if @close_up
96
+ # Thread.handle_interrupt(TryAgain => :never) do
97
+ # Log.debug "Closing up process queue #{Process.pid}"
98
+ # @count = 0
99
+ # @closing_thread = Thread.new do
100
+ # Thread.handle_interrupt(TryAgain => :never) do
101
+ # Log.debug "Pushing closed stream #{Process.pid}"
102
+ # while true
103
+ # @queue.push ClosedStream.new unless @queue.cleaned
104
+ # break if processes_initiated && processes.empty?
105
+ # end unless processes_initiated && processes.empty?
106
+ # end
107
+ # end
108
+ # @close_up = false
109
+ # end
110
+ # end
111
+ #
112
+ # begin
113
+ # sleep 3
114
+ # rescue TryAgain
115
+ # end
116
+ #
117
+ # raise TryAgain if @close_up
118
+ #
119
+ # process_mutex.synchronize do
120
+ # Thread.handle_interrupt(TryAgain => :never) do
121
+ # while @count > 0
122
+ # @count -= 1
123
+ # @total += 1
124
+ # processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, (@offset ? @total : false), &@init_block)
125
+ # Log.warn "Added process #{processes.last.pid} to #{Process.pid} (#{processes.length})"
126
+ # end
127
+ #
128
+ # while @count < 0
129
+ # @count += 1
130
+ # @total -= 1
131
+ # next unless processes.length > 1
132
+ # last = processes.reject{|p| p.stopping }.last
133
+ # last.stop
134
+ # Log.warn "Removed process #{last.pid} from #{Process.pid} (#{processes.length})"
135
+ # end
136
+ # end
137
+ # end
138
+ # rescue TryAgain
139
+ # retry
140
+ # rescue Aborted
141
+ # Log.low "Aborting manager thread #{Process.pid}"
142
+ # raise $!
143
+ # rescue Exception
144
+ # raise Exception
145
+ # end
146
+ # end
147
+ # Log.low "Manager thread stopped #{Process.pid}"
148
+ # end
149
+ #
150
+ # @callback_queue.close_read if @callback_queue
151
+ #
152
+ # num_processes.to_i.times do |i|
153
+ # @total += 1
154
+ # process_mutex.synchronize do
155
+ # processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, (@offset ? @total : false), &@init_block)
156
+ # end
157
+ # end
158
+ #
159
+ # processes_initiated = true
160
+ #
161
+ # @monitor_thread = Thread.new do
162
+ # begin
163
+ # while processes.any?
164
+ # raise Aborted if @abort_monitor
165
+ # #processes[0].join
166
+ # #Log.debug "Joined process #{processes[0].pid} of queue #{Process.pid}"
167
+ # #processes.shift
168
+ # pid, status = Process.wait2
169
+ # Log.debug "Joined process #{pid} of queue #{Process.pid} (status: #{status})"
170
+ # processes.reject!{|p| p.pid == pid}
171
+ # raise ProcessFailed.new pid if not status.success?
172
+ # end
173
+ # Log.low "All processes completed #{Process.pid}"
174
+ # rescue Aborted
175
+ # Log.exception $!
176
+ # Log.low "Aborting process monitor #{Process.pid}"
177
+ # processes.each{|p| p.abort_and_join}
178
+ # Log.low "Processes aborted #{Process.pid}"
179
+ # processes.clear
180
+ #
181
+ # @manager_thread.raise Aborted if @manager_thread.alive?
182
+ # raise Aborted, "Aborted monitor thread"
183
+ # rescue Exception
184
+ # Log.low "Process monitor exception [#{Process.pid}]: #{$!.message}"
185
+ # processes.each{|p| p.abort_and_join}
186
+ # Log.low "Processes aborted for monitor #{Process.pid}"
187
+ # processes.clear
188
+ #
189
+ # @manager_thread.report_on_exception = false
190
+ # @manager_thread.raise $! if @manager_thread.alive?
191
+ # raise Aborted, "Aborted monitor thread with exception"
192
+ # end
193
+ # end
194
+ # @monitor_thread.report_on_exception = false
195
+ #
196
+ # RbbtSemaphore.post_semaphore(@sem)
197
+ #
198
+ # Log.low "Process monitor #{Process.pid} joining threads"
199
+ # begin
200
+ # @monitor_thread.join
201
+ # @manager_thread.raise TryAgain if @manager_thread.alive?
202
+ # @manager_thread.join
203
+ # @callback_queue.push ClosedStream.new if @callback_queue
204
+ # rescue Exception
205
+ # Kernel.exit -1
206
+ # end
207
+ # Log.low "Process monitor #{Process.pid} threads joined successfully, now exit"
208
+ #
209
+ # Kernel.exit 0
210
+ # end
211
+ #
212
+ # @queue.close_read
213
+ # Log.info "Cpu process #{@master_pid} with #{num_processes} workers."
214
+ # Log.low "Signal #{@master_pid} USR1/USR2 (#10/#12) to increase/decrease workers."
215
+ # end
216
+ #
217
+ # def init(&block)
218
+ # @init_block = block
219
+ #
220
+ # init_master
221
+ #
222
+ # RbbtSemaphore.synchronize(@sem) do
223
+ # @callback_thread = Thread.new do
224
+ # begin
225
+ # loop do
226
+ # p = @callback_queue.pop unless @callback_queue.cleaned
227
+ #
228
+ # if Exception === p or (Array === p and Exception === p.first)
229
+ # e = Array === p ? p.first : p
230
+ # Log.low "Callback recieved exception from worker: #{e.message}" unless Aborted === e or ClosedStream === e
231
+ # raise e
232
+ # end
233
+ #
234
+ # if @callback.arity == 0
235
+ # @callback.call
236
+ # else
237
+ # @callback.call p
238
+ # end
239
+ # end
240
+ # rescue ClosedStream
241
+ # Log.low "Callback thread closing"
242
+ # rescue Aborted
243
+ # Log.low "Callback thread aborted"
244
+ # raise $!
245
+ # rescue Exception
246
+ # Log.low "Exception captured in callback: #{$!.message}"
247
+ # raise $!
248
+ # end
249
+ # end if @callback_queue
250
+ #
251
+ # @callback_thread.report_on_exception = false if @callback_thread
252
+ #
253
+ # end
254
+ #
255
+ # end
256
+ #
257
+ # def add_process
258
+ # Process.kill :USR1, @master_pid
259
+ # end
260
+ #
261
+ # def remove_process
262
+ # Process.kill :USR2, @master_pid
263
+ # end
264
+ #
265
+ # def _join
266
+ # error = :redo
267
+ # begin
268
+ # pid, @status = Process.waitpid2 @master_pid unless @status
269
+ # error = true unless @status.success?
270
+ # begin
271
+ # @callback_thread.join if @callback_thread
272
+ # raise ProcessFailed.new @master_pid unless @status.success?
273
+ # rescue
274
+ # exception = $!
275
+ # raise $!
276
+ # end
277
+ # error = false
278
+ # rescue Aborted, Interrupt
279
+ # exception = $!
280
+ # Log.exception $!
281
+ # error = true
282
+ # if @aborted
283
+ # raise $!
284
+ # else
285
+ # self.abort
286
+ # Log.high "Process queue #{@master_pid} aborted"
287
+ # retry
288
+ # end
289
+ # rescue Errno::ESRCH, Errno::ECHILD
290
+ # retry if Misc.pid_exists? @master_pid
291
+ # error = ! @status.success?
292
+ # ensure
293
+ # begin
294
+ # begin
295
+ # self.abort
296
+ # ensure
297
+ # _join
298
+ # end if error == :redo
299
+ #
300
+ # begin
301
+ # @callback_thread.join
302
+ # rescue Exception
303
+ # end
304
+ #
305
+ # Log.medium "Joining process queue #{"(error) " if error}#{@master_pid} #{@join}"
306
+ # begin
307
+ # if @join
308
+ # if @join.arity == 1
309
+ # @join.call(error)
310
+ # else
311
+ # @join.call
312
+ # end
313
+ # end
314
+ # end
315
+ # ensure
316
+ # self.clean
317
+ # end
318
+ #
319
+ # if exception
320
+ # raise exception
321
+ # else
322
+ # raise "Process queue #{@master_pid} failed"
323
+ # end if error
324
+ # end
325
+ # end
326
+ #
327
+ # def close_up_queue
328
+ # begin
329
+ # RbbtSemaphore.synchronize(@sem) do
330
+ # Process.kill CLOSE_SIGNAL, @master_pid
331
+ # end
332
+ # rescue Errno::ECHILD, Errno::ESRCH
333
+ # Log.debug "Cannot kill (CLOSE) #{@master_pid}: #{$!.message}"
334
+ # end if Misc.pid_exists? @master_pid
335
+ # end
336
+ #
337
+ # def join
338
+ # close_up_queue
339
+ #
340
+ # _join
341
+ # end
342
+ #
343
+ # def _abort
344
+ # begin
345
+ # Log.warn "Aborting process queue #{@master_pid}"
346
+ # Process.kill ABORT_SIGNAL, @master_pid
347
+ # rescue Errno::ECHILD, Errno::ESRCH
348
+ # Log.debug "Cannot abort #{@master_pid}: #{$!.message}"
349
+ # end
350
+ # end
351
+ #
352
+ # def abort
353
+ # _abort
354
+ # @callback_thread.raise(Aborted.new) if @callback_thread and @callback_thread.alive?
355
+ # @aborted = true
356
+ # begin
357
+ # _join
358
+ # rescue
359
+ # end
360
+ # end
361
+ #
362
+ # def clean
363
+ # RbbtSemaphore.delete_semaphore(@sem)
364
+ # begin
365
+ # self.abort if Misc.pid_exists?(@master_pid)
366
+ #
367
+ # ensure
368
+ # @queue.clean if @queue
369
+ # #@callback_thread.push ClosedStream if @callback_thread && @callback_thread.alive?
370
+ # @callback_queue.clean if @callback_queue
371
+ # end
372
+ # end
373
+ #
374
+ #
375
+ # def process(*e)
376
+ # begin
377
+ # @queue.push e
378
+ # rescue Errno::EPIPE
379
+ # raise Aborted
380
+ # end
381
+ # end
382
+ #
383
+ # def self.each(list, num = 3, &block)
384
+ # q = RbbtProcessQueue.new num
385
+ # q.init(&block)
386
+ # list.each do |elem| q.process elem end
387
+ # q.join
388
+ # end
389
+ #end