scout-gear 9.0.0 → 10.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +3 -3
  3. data/Rakefile +1 -2
  4. data/VERSION +1 -1
  5. data/bin/scout +0 -1
  6. data/lib/rbbt-scout.rb +2 -1
  7. data/lib/scout/offsite/exceptions.rb +9 -0
  8. data/lib/scout/offsite/ssh.rb +1 -0
  9. data/lib/scout/semaphore.rb +2 -0
  10. data/lib/scout/tsv/dumper.rb +1 -0
  11. data/lib/scout/tsv/open.rb +8 -2
  12. data/lib/scout/tsv/parser.rb +1 -1
  13. data/lib/scout/tsv/persist/adapter.rb +2 -2
  14. data/lib/scout/tsv/persist.rb +1 -0
  15. data/lib/scout/tsv/util.rb +1 -1
  16. data/lib/scout/tsv.rb +1 -1
  17. data/lib/scout/work_queue/exceptions.rb +18 -0
  18. data/lib/scout/work_queue.rb +1 -0
  19. data/lib/scout/workflow/definition.rb +1 -1
  20. data/lib/scout/workflow/step/config.rb +1 -1
  21. data/lib/scout/workflow/step/dependencies.rb +3 -2
  22. data/lib/scout/workflow/step/file.rb +5 -1
  23. data/lib/scout/workflow/step/info.rb +8 -2
  24. data/lib/scout/workflow/step/provenance.rb +28 -10
  25. data/lib/scout/workflow/step/status.rb +4 -0
  26. data/lib/scout/workflow/step.rb +18 -6
  27. data/lib/scout/workflow/task/dependencies.rb +1 -0
  28. data/lib/scout/workflow/task/inputs.rb +6 -1
  29. data/lib/scout/workflow/task.rb +22 -3
  30. data/lib/scout/workflow/usage.rb +1 -0
  31. data/lib/scout/workflow.rb +13 -4
  32. data/lib/scout-gear.rb +1 -10
  33. data/scout-gear.gemspec +8 -98
  34. data/scout_commands/workflow/task +2 -3
  35. data/test/scout/workflow/step/test_provenance.rb +24 -1
  36. data/test/scout/workflow/task/test_inputs.rb +0 -4
  37. metadata +7 -110
  38. data/lib/scout/cmd.rb +0 -347
  39. data/lib/scout/concurrent_stream.rb +0 -284
  40. data/lib/scout/config.rb +0 -168
  41. data/lib/scout/exceptions.rb +0 -151
  42. data/lib/scout/indiferent_hash/case_insensitive.rb +0 -30
  43. data/lib/scout/indiferent_hash/options.rb +0 -115
  44. data/lib/scout/indiferent_hash.rb +0 -96
  45. data/lib/scout/log/color.rb +0 -224
  46. data/lib/scout/log/color_class.rb +0 -269
  47. data/lib/scout/log/fingerprint.rb +0 -69
  48. data/lib/scout/log/progress/report.rb +0 -244
  49. data/lib/scout/log/progress/util.rb +0 -173
  50. data/lib/scout/log/progress.rb +0 -106
  51. data/lib/scout/log/trap.rb +0 -107
  52. data/lib/scout/log.rb +0 -441
  53. data/lib/scout/meta_extension.rb +0 -100
  54. data/lib/scout/misc/digest.rb +0 -63
  55. data/lib/scout/misc/filesystem.rb +0 -25
  56. data/lib/scout/misc/format.rb +0 -255
  57. data/lib/scout/misc/helper.rb +0 -31
  58. data/lib/scout/misc/insist.rb +0 -56
  59. data/lib/scout/misc/monitor.rb +0 -66
  60. data/lib/scout/misc/system.rb +0 -73
  61. data/lib/scout/misc.rb +0 -10
  62. data/lib/scout/named_array.rb +0 -138
  63. data/lib/scout/open/lock/lockfile.rb +0 -587
  64. data/lib/scout/open/lock.rb +0 -68
  65. data/lib/scout/open/remote.rb +0 -135
  66. data/lib/scout/open/stream.rb +0 -491
  67. data/lib/scout/open/util.rb +0 -244
  68. data/lib/scout/open.rb +0 -170
  69. data/lib/scout/path/find.rb +0 -204
  70. data/lib/scout/path/tmpfile.rb +0 -8
  71. data/lib/scout/path/util.rb +0 -107
  72. data/lib/scout/path.rb +0 -51
  73. data/lib/scout/persist/open.rb +0 -17
  74. data/lib/scout/persist/path.rb +0 -15
  75. data/lib/scout/persist/serialize.rb +0 -157
  76. data/lib/scout/persist.rb +0 -104
  77. data/lib/scout/resource/open.rb +0 -8
  78. data/lib/scout/resource/path.rb +0 -80
  79. data/lib/scout/resource/produce/rake.rb +0 -69
  80. data/lib/scout/resource/produce.rb +0 -151
  81. data/lib/scout/resource/scout.rb +0 -3
  82. data/lib/scout/resource/software.rb +0 -178
  83. data/lib/scout/resource/util.rb +0 -55
  84. data/lib/scout/resource.rb +0 -41
  85. data/lib/scout/simple_opt/accessor.rb +0 -54
  86. data/lib/scout/simple_opt/doc.rb +0 -126
  87. data/lib/scout/simple_opt/get.rb +0 -57
  88. data/lib/scout/simple_opt/parse.rb +0 -67
  89. data/lib/scout/simple_opt/setup.rb +0 -26
  90. data/lib/scout/simple_opt.rb +0 -5
  91. data/lib/scout/tmpfile.rb +0 -129
  92. data/test/scout/indiferent_hash/test_case_insensitive.rb +0 -16
  93. data/test/scout/indiferent_hash/test_options.rb +0 -46
  94. data/test/scout/log/test_progress.rb +0 -108
  95. data/test/scout/misc/test_digest.rb +0 -30
  96. data/test/scout/misc/test_filesystem.rb +0 -30
  97. data/test/scout/misc/test_insist.rb +0 -13
  98. data/test/scout/misc/test_system.rb +0 -21
  99. data/test/scout/open/test_lock.rb +0 -52
  100. data/test/scout/open/test_remote.rb +0 -25
  101. data/test/scout/open/test_stream.rb +0 -676
  102. data/test/scout/open/test_util.rb +0 -73
  103. data/test/scout/path/test_find.rb +0 -119
  104. data/test/scout/path/test_util.rb +0 -22
  105. data/test/scout/persist/test_open.rb +0 -37
  106. data/test/scout/persist/test_path.rb +0 -37
  107. data/test/scout/persist/test_serialize.rb +0 -114
  108. data/test/scout/resource/test_path.rb +0 -46
  109. data/test/scout/resource/test_produce.rb +0 -77
  110. data/test/scout/resource/test_software.rb +0 -24
  111. data/test/scout/resource/test_util.rb +0 -27
  112. data/test/scout/simple_opt/test_doc.rb +0 -16
  113. data/test/scout/simple_opt/test_get.rb +0 -11
  114. data/test/scout/simple_opt/test_parse.rb +0 -10
  115. data/test/scout/simple_opt/test_setup.rb +0 -77
  116. data/test/scout/test_cmd.rb +0 -85
  117. data/test/scout/test_concurrent_stream.rb +0 -29
  118. data/test/scout/test_config.rb +0 -66
  119. data/test/scout/test_indiferent_hash.rb +0 -26
  120. data/test/scout/test_log.rb +0 -32
  121. data/test/scout/test_meta_extension.rb +0 -80
  122. data/test/scout/test_misc.rb +0 -6
  123. data/test/scout/test_named_array.rb +0 -43
  124. data/test/scout/test_open.rb +0 -146
  125. data/test/scout/test_path.rb +0 -54
  126. data/test/scout/test_persist.rb +0 -186
  127. data/test/scout/test_resource.rb +0 -26
  128. data/test/scout/test_tmpfile.rb +0 -53
  129. /data/test/scout/{log/test_color.rb → test_offsite.rb} +0 -0
data/lib/scout/cmd.rb DELETED
@@ -1,347 +0,0 @@
1
- require_relative 'indiferent_hash'
2
- require_relative 'concurrent_stream'
3
- require_relative 'log'
4
- require_relative 'open/stream'
5
- require 'stringio'
6
- require 'open3'
7
-
8
- module CMD
9
-
10
- TOOLS = IndiferentHash.setup({})
11
- def self.tool(tool, claim = nil, test = nil, cmd = nil, &block)
12
- TOOLS[tool] = [claim, test, block, cmd]
13
- end
14
-
15
- def self.conda(tool, env = nil, channel = 'bioconda')
16
- if env
17
- CMD.cmd("bash -l -c '(conda activate #{env} && conda install #{tool} -c #{channel})'")
18
- else
19
- CMD.cmd("bash -l -c 'conda install #{tool} -c #{channel}'")
20
- end
21
- end
22
-
23
-
24
- def self.get_tool(tool)
25
- return tool.to_s unless TOOLS[tool]
26
-
27
- @@init_cmd_tool ||= IndiferentHash.setup({})
28
-
29
- claim, test, block, cmd = TOOLS[tool]
30
- cmd = tool.to_s if cmd.nil?
31
-
32
- if !@@init_cmd_tool[tool]
33
-
34
- begin
35
- if test
36
- CMD.cmd(test + " ")
37
- else
38
- CMD.cmd("#{cmd} --help")
39
- end
40
- rescue
41
- if claim
42
- claim.produce
43
- else
44
- block.call
45
- end
46
- end
47
- version_txt = ""
48
- version = nil
49
- ["--version", "-version", "--help", ""].each do |f|
50
- begin
51
- version_txt += CMD.cmd("#{cmd} #{f} 2>&1", :nofail => true).read
52
- version = CMD.scan_version_text(version_txt, tool)
53
- break if version
54
- rescue
55
- Log.exception $!
56
- end
57
- end
58
-
59
- @@init_cmd_tool[tool] = version || true
60
-
61
- return cmd if cmd
62
- end
63
-
64
- cmd
65
- end
66
- def self.scan_version_text(text, cmd = nil)
67
- cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
68
- text = Misc.fixutf8 text
69
- text.split("\n").each do |line|
70
- next unless line =~ /\W#{cmd}\W/i
71
- m = line.match(/(v(?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
72
- return m[1] if m
73
- m = line.match(/((?:\d+\.)*\d+(?:-[a-z_]+)?v)/i)
74
- return m[1] if m
75
- next unless line =~ /\Wversion\W/i
76
- m = line.match(/((?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
77
- return m[1] if m
78
- end
79
- m = text.match(/(?:version.*?|#{cmd}.*?|#{cmd.to_s.split(/[-_.]/).first}.*?|v)((?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
80
- return m[1] if m
81
- m = text.match(/(?:#{cmd}.*(v.*|.*v))/i)
82
- return m[1] if m
83
- nil
84
- end
85
- def self.versions
86
- return {} unless defined? @@init_cmd_tool
87
- @@init_cmd_tool.select{|k,v| v =~ /\d+\./ }
88
- end
89
-
90
- def self.bash(cmd)
91
- cmd = %Q(bash <<EOF\n#{cmd}\nEOF\n)
92
- CMD.cmd(cmd, :autojoin => true)
93
- end
94
-
95
- def self.process_cmd_options(options = {})
96
- add_dashes = IndiferentHash.process_options options, :add_option_dashes
97
-
98
- string = ""
99
- options.each do |option, value|
100
- raise "Invalid option key: #{option.inspect}" if option.to_s !~ /^[a-z_0-9\-=.]+$/i
101
- #raise "Invalid option value: #{value.inspect}" if value.to_s.include? "'"
102
- value = value.gsub("'","\\'") if value.to_s.include? "'"
103
-
104
- option = "--" << option.to_s if add_dashes and option.to_s[0] != '-'
105
-
106
- case
107
- when value.nil? || FalseClass === value
108
- next
109
- when TrueClass === value
110
- string << "#{option} "
111
- else
112
- if option.to_s.chars.to_a.last == "="
113
- string << "#{option}'#{value}' "
114
- else
115
- string << "#{option} '#{value}' "
116
- end
117
- end
118
- end
119
-
120
- string.strip
121
- end
122
-
123
- def self.cmd(tool, cmd = nil, options = {}, &block)
124
- options, cmd = cmd, nil if Hash === cmd
125
-
126
- options = IndiferentHash.add_defaults options, :stderr => Log::DEBUG
127
- in_content = options.delete(:in)
128
- stderr = options.delete(:stderr)
129
- post = options.delete(:post)
130
- pipe = options.delete(:pipe)
131
- log = options.delete(:log)
132
- no_fail = options.delete(:no_fail)
133
- no_fail = options.delete(:nofail) if no_fail.nil?
134
- no_wait = options.delete(:no_wait)
135
- xvfb = options.delete(:xvfb)
136
- bar = options.delete(:progress_bar)
137
- save_stderr = options.delete(:save_stderr)
138
- autojoin = options.delete(:autojoin)
139
- autojoin = no_wait if autojoin.nil?
140
-
141
- dont_close_in = options.delete(:dont_close_in)
142
-
143
- log = true if log.nil?
144
-
145
- if cmd.nil? && ! Symbol === tool
146
- cmd = tool
147
- else
148
- tool = get_tool(tool)
149
- if cmd.nil?
150
- cmd = tool
151
- else
152
- cmd = tool + ' ' + cmd
153
- end
154
-
155
- end
156
-
157
- case xvfb
158
- when TrueClass
159
- cmd = "xvfb-run --server-args='-screen 0 1024x768x24' --auto-servernum #{cmd}"
160
- when String
161
- cmd = "xvfb-run --server-args='#{xvfb}' --auto-servernum --server-num=1 #{cmd}"
162
- when String
163
- end
164
-
165
- if stderr == true
166
- stderr = Log::HIGH
167
- end
168
-
169
- cmd_options = process_cmd_options options
170
- if cmd =~ /'\{opt\}'/
171
- cmd.sub!('\'{opt}\'', cmd_options)
172
- else
173
- cmd << " " << cmd_options
174
- end
175
-
176
- in_content = StringIO.new in_content if String === in_content
177
-
178
- sin, sout, serr, wait_thr = begin
179
- Open3.popen3(ENV, cmd)
180
- rescue
181
- Log.warn $!.message
182
- raise ProcessFailed, nil, cmd unless no_fail
183
- return
184
- end
185
- pid = wait_thr.pid
186
-
187
- Log.debug{"CMD: [#{pid}] #{cmd}".strip if log}
188
-
189
- if in_content.respond_to?(:read)
190
- in_thread = Thread.new(Thread.current) do |parent|
191
- begin
192
- Thread.current.report_on_exception = false if no_fail
193
- Thread.current["name"] = "CMD in"
194
- while c = in_content.read(Open::BLOCK_SIZE)
195
- sin << c
196
- end
197
- sin.close unless sin.closed?
198
-
199
- unless dont_close_in
200
- in_content.close unless in_content.closed?
201
- in_content.join if in_content.respond_to? :join
202
- end
203
- rescue
204
- Log.error "Error in CMD [#{pid}] #{cmd}: #{$!.message}" unless no_fail
205
- raise $!
206
- end
207
- end
208
- Thread.pass until in_thread["name"]
209
- else
210
- in_thread = nil
211
- sin.close
212
- end
213
-
214
- pids = [pid]
215
-
216
- if pipe
217
-
218
- ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
219
-
220
- sout.callback = post if post
221
-
222
- if (Integer === stderr and log) || bar
223
- err_thread = Thread.new do
224
- Thread.current["name"] = "Error log: [#{pid}] #{ cmd }"
225
- begin
226
- while line = serr.gets
227
- bar.process(line) if bar
228
- sout.log = line
229
- sout.std_err << line if save_stderr
230
- Log.log "STDERR [#{pid}]: " + line, stderr if log
231
- end
232
- serr.close
233
- rescue
234
- Log.exception $!
235
- raise $!
236
- end
237
- end
238
- else
239
- err_thread = Open.consume_stream(serr, true)
240
- end
241
-
242
- sout.threads = [in_thread, err_thread, wait_thr].compact
243
-
244
- sout
245
- else
246
-
247
- if bar
248
- err = ""
249
- err_thread = Thread.new do
250
- while not serr.eof?
251
- line = serr.gets
252
- bar.process(line)
253
- err << line if Integer === stderr and log
254
- end
255
- serr.close
256
- end
257
- elsif log and Integer === stderr
258
- err = ""
259
- err_thread = Thread.new do
260
- while not serr.eof?
261
- err << serr.gets
262
- end
263
- serr.close
264
- end
265
- else
266
- Open.consume_stream(serr, true)
267
- err_thread = nil
268
- err = ""
269
- end
270
-
271
- ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
272
-
273
- begin
274
- out = StringIO.new sout.read
275
- sout.close unless sout.closed?
276
-
277
- status = wait_thr.value
278
- if status && ! status.success? && ! no_fail
279
- if !err.empty?
280
- raise ProcessFailed.new pid, "#{cmd} failed with error status #{status.exitstatus}.\n#{err}"
281
- else
282
- raise ProcessFailed.new pid, "#{cmd} failed with error status #{status.exitstatus}"
283
- end
284
- else
285
- Log.log err, stderr if Integer === stderr and log
286
- end
287
- out
288
- ensure
289
- post.call if post
290
- end
291
- end
292
- end
293
-
294
- def self.cmd_pid(*args)
295
- all_args = *args
296
-
297
- bar = all_args.last[:progress_bar] if Hash === all_args.last
298
-
299
- all_args << {} unless Hash === all_args.last
300
-
301
- level = all_args.last[:log] || 0
302
- level = 0 if TrueClass === level
303
- level = 10 if FalseClass === level
304
- level = level.to_i
305
-
306
- all_args.last[:log] = true
307
- all_args.last[:pipe] = true
308
-
309
- io = cmd(*all_args)
310
- pid = io.pids.first
311
-
312
- line = "" if bar
313
- starting = true
314
- while c = io.getc
315
- if starting
316
- if pid
317
- Log.logn "STDOUT [#{pid}]: ", level
318
- else
319
- Log.logn "STDOUT: ", level
320
- end
321
- starting = false
322
- end
323
- STDERR << c if Log.severity <= level
324
- line << c if bar
325
- if c == "\n"
326
- bar.process(line) if bar
327
- starting = true
328
- line = "" if bar
329
- end
330
- end
331
- begin
332
- io.join
333
- bar.remove if bar
334
- rescue
335
- bar.remove(true) if bar
336
- raise $!
337
- end
338
-
339
- nil
340
- end
341
-
342
- def self.cmd_log(*args)
343
- cmd_pid(*args)
344
- nil
345
- end
346
-
347
- end
@@ -1,284 +0,0 @@
1
- require_relative 'indiferent_hash'
2
-
3
- module AbortedStream
4
- attr_accessor :exception
5
- def self.setup(obj, exception = nil)
6
- obj.extend AbortedStream
7
- obj.exception = exception
8
- end
9
- end
10
-
11
- module ConcurrentStream
12
- attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :aborted, :autojoin, :lock, :no_fail, :pair, :thread, :stream_exception, :log, :std_err, :next
13
-
14
- def self.setup(stream, options = {}, &block)
15
- threads, pids, callback, abort_callback, filename, autojoin, lock, no_fail, pair, next_stream = IndiferentHash.process_options options, :threads, :pids, :callback, :abort_callback, :filename, :autojoin, :lock, :no_fail, :pair, :next
16
- stream.extend ConcurrentStream unless ConcurrentStream === stream
17
-
18
- stream.threads ||= []
19
- stream.pids ||= []
20
- stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
21
- stream.pids.concat(Array === pids ? pids : [pids]) unless pids.nil? or pids.empty?
22
- stream.autojoin = autojoin unless autojoin.nil?
23
- stream.no_fail = no_fail unless no_fail.nil?
24
- stream.std_err = ""
25
-
26
- stream.next = next_stream unless next_stream.nil?
27
- stream.pair = pair unless pair.nil?
28
-
29
- callback = block if block_given?
30
- if callback
31
- if stream.callback
32
- old_callback = stream.callback
33
- stream.callback = Proc.new do
34
- old_callback.call
35
- callback.call
36
- end
37
- else
38
- stream.callback = callback
39
- end
40
- end
41
-
42
- if abort_callback
43
- if stream.abort_callback
44
- old_abort_callback = stream.abort_callback
45
- stream.abort_callback = Proc.new do
46
- old_abort_callback.call
47
- abort_callback.call
48
- end
49
- else
50
- stream.abort_callback = abort_callback
51
- end
52
- end
53
-
54
- stream.filename = filename.nil? ? stream.inspect.split(":").last[0..-2] : filename
55
-
56
- stream.lock = lock unless lock.nil?
57
-
58
- stream.aborted = false
59
-
60
- stream
61
- end
62
-
63
- def annotate(stream)
64
- ConcurrentStream.setup(stream, :threads => threads, :pids => pids, :callback => callback, :abort_callback => abort_callback, :filename => filename, :autojoin => autojoin, :lock => lock)
65
- stream
66
- end
67
-
68
- def clear
69
- @threads = @pids = @callback = @abort_callback = @joined = nil
70
- end
71
-
72
- def joined?
73
- @joined
74
- end
75
-
76
- def aborted?
77
- @aborted
78
- end
79
-
80
- def join_threads
81
- if @threads
82
- @threads.each do |t|
83
- next if t == Thread.current
84
- begin
85
- t.join
86
- if Process::Status === t.value
87
- if ! (t.value.success? || no_fail)
88
-
89
- if log
90
- msg = "Error joining #{self.filename || self.inspect}. Last log line: #{log}"
91
- else
92
- msg = "Error joining #{self.filename || self.inspect}"
93
- end
94
-
95
- raise ConcurrentStreamProcessFailed.new t.pid, msg, self
96
- end
97
- end
98
- rescue Exception
99
- if no_fail
100
- Log.low "Not failing on exception joining thread in ConcurrenStream - #{filename} - #{$!.message}"
101
- else
102
- Log.low "Exception joining thread in ConcurrenStream #{Log.fingerprint self} - #{Log.fingerprint t} - #{$!.message}"
103
- stream_raise_exception $!
104
- end
105
- end
106
- end
107
- end
108
- @threads = []
109
- end
110
-
111
- def join_pids
112
- if @pids and @pids.any?
113
- @pids.each do |pid|
114
- begin
115
- Process.waitpid(pid, Process::WUNTRACED)
116
- stream_raise_exception ConcurrentStreamProcessFailed.new(pid, "Error in waitpid", self) unless $?.success? or no_fail
117
- rescue Errno::ECHILD
118
- end
119
- end
120
- @pids = []
121
- end
122
- end
123
-
124
- def join_callback
125
- if @callback and not joined?
126
- begin
127
- @callback.call
128
- ensure
129
- @callback = nil
130
- end
131
- end
132
- end
133
-
134
- def join
135
- begin
136
- join_threads
137
- join_pids
138
- raise stream_exception if stream_exception
139
- join_callback
140
- close unless closed?
141
- ensure
142
- @joined = true
143
- begin
144
- lock.unlock if lock && lock.locked?
145
- rescue
146
- Log.exception $!
147
- end
148
- raise stream_exception if stream_exception
149
- end
150
- end
151
-
152
- def abort_threads(exception = nil)
153
- return unless @threads and @threads.any?
154
- name = Log.fingerprint(Thread.current)
155
- name += " - file:#{filename}" if filename
156
- Log.low "Aborting threads (#{name}) - #{@threads.collect{|t| Log.fingerprint(t) } * ", "}"
157
-
158
- threads = @threads.dup
159
- @threads.clear
160
- threads.each do |t|
161
- next if t == Thread.current
162
- next if t["aborted"]
163
- t["aborted"] = true
164
- exception = exception.nil? ? Aborted.new : exception
165
- Log.debug "Aborting thread #{Log.fingerprint(t)} with exception: #{exception}"
166
- t.raise(exception)
167
- t.join
168
- end
169
- end
170
-
171
- def abort_pids
172
- @pids.each do |pid|
173
- begin
174
- Log.low "Killing PID #{pid} in ConcurrentStream #{filename}"
175
- Process.kill :INT, pid
176
- rescue Errno::ESRCH
177
- end
178
- end if @pids
179
- @pids = []
180
- end
181
-
182
- def abort(exception = nil)
183
- self.stream_exception ||= exception
184
- if @aborted
185
- Log.medium "Already aborted stream #{Log.fingerprint self} [#{@aborted}]"
186
- return
187
- else
188
- Log.medium "Aborting stream #{Log.fingerprint self} [#{@aborted}]"
189
- end
190
- AbortedStream.setup(self, exception)
191
- @aborted = true
192
- begin
193
- @abort_callback.call exception if @abort_callback
194
-
195
- abort_threads(exception)
196
- abort_pids
197
-
198
- @callback = nil
199
- @abort_callback = nil
200
-
201
- if @pair && @pair.respond_to?(:abort) && ! @pair.aborted?
202
- Log.medium "Aborting pair stream #{Log.fingerprint self}: #{Log.fingerprint @pair }"
203
- @pair.abort exception
204
- end
205
- ensure
206
- close unless closed?
207
-
208
- if lock and lock.locked?
209
- lock.unlock
210
- end
211
- end
212
- end
213
-
214
- def close(*args)
215
- if autojoin
216
- begin
217
- super(*args)
218
- rescue
219
- self.abort
220
- self.join
221
- stream_raise_exception $!
222
- ensure
223
- self.join if ! @stream_exception && (self.closed? || self.eof?)
224
- end
225
- else
226
- super(*args)
227
- end
228
- end
229
-
230
- def read(*args)
231
- begin
232
- super(*args)
233
- rescue Exception
234
- @stream_exception ||= $!
235
- raise @stream_exception
236
- ensure
237
- if ! @stream_exception && autojoin && ! closed?
238
- begin
239
- done = eof?
240
- rescue Exception
241
- self.abort($!)
242
- raise $!
243
- end
244
- close if done
245
- end
246
- end
247
- end
248
-
249
- def add_callback(&block)
250
- old_callback = callback
251
- @callback = Proc.new do
252
- old_callback.call if old_callback
253
- block.call
254
- end
255
- end
256
-
257
- def stream_raise_exception(exception)
258
- self.stream_exception = exception
259
- threads.each do |thread|
260
- thread.raise exception
261
- end
262
- self.abort
263
- end
264
-
265
- def self.process_stream(stream, close: true, join: true, message: "process_stream", **kwargs, &block)
266
- ConcurrentStream.setup(stream, **kwargs)
267
- begin
268
- begin
269
- yield
270
- ensure
271
- stream.close if close && stream.respond_to?(:close) && ! (stream.respond_to?(:closed?) && stream.closed?)
272
- stream.join if join && stream.respond_to?(:join) && ! stream.joined?
273
- end
274
- rescue Aborted
275
- Log.low "Aborted #{message}: #{$!.message}"
276
- stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
277
- raise $!
278
- rescue Exception
279
- Log.low "Exception #{message}: #{$!.message}"
280
- stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
281
- raise $!
282
- end
283
- end
284
- end