scout-gear 8.0.0 → 8.1.0

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +26 -9
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +15 -4
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/scout/cmd.rb +23 -24
  9. data/lib/scout/concurrent_stream.rb +36 -19
  10. data/lib/scout/exceptions.rb +10 -0
  11. data/lib/scout/log/color.rb +11 -11
  12. data/lib/scout/log/progress/report.rb +7 -5
  13. data/lib/scout/log/progress/util.rb +3 -0
  14. data/lib/scout/log/trap.rb +3 -3
  15. data/lib/scout/log.rb +64 -36
  16. data/lib/scout/meta_extension.rb +34 -0
  17. data/lib/scout/misc/digest.rb +11 -2
  18. data/lib/scout/misc/format.rb +12 -7
  19. data/lib/scout/misc/monitor.rb +11 -0
  20. data/lib/scout/misc/system.rb +48 -0
  21. data/lib/scout/named_array.rb +8 -0
  22. data/lib/scout/offsite/ssh.rb +171 -0
  23. data/lib/scout/offsite/step.rb +83 -0
  24. data/lib/scout/offsite/sync.rb +55 -0
  25. data/lib/scout/offsite.rb +3 -0
  26. data/lib/scout/open/lock.rb +5 -24
  27. data/lib/scout/open/remote.rb +12 -1
  28. data/lib/scout/open/stream.rb +110 -122
  29. data/lib/scout/open/util.rb +9 -0
  30. data/lib/scout/open.rb +5 -4
  31. data/lib/scout/path/find.rb +15 -10
  32. data/lib/scout/path/util.rb +5 -0
  33. data/lib/scout/persist/serialize.rb +3 -3
  34. data/lib/scout/persist.rb +1 -1
  35. data/lib/scout/resource/path.rb +4 -0
  36. data/lib/scout/resource/util.rb +10 -4
  37. data/lib/scout/tsv/dumper.rb +2 -0
  38. data/lib/scout/tsv/index.rb +28 -86
  39. data/lib/scout/tsv/open.rb +35 -14
  40. data/lib/scout/tsv/parser.rb +9 -2
  41. data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
  42. data/lib/scout/tsv/stream.rb +204 -0
  43. data/lib/scout/tsv/transformer.rb +11 -0
  44. data/lib/scout/tsv.rb +9 -2
  45. data/lib/scout/work_queue/worker.rb +2 -2
  46. data/lib/scout/work_queue.rb +36 -12
  47. data/lib/scout/workflow/definition.rb +2 -1
  48. data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
  49. data/lib/scout/workflow/deployment.rb +1 -0
  50. data/lib/scout/workflow/step/dependencies.rb +37 -11
  51. data/lib/scout/workflow/step/file.rb +5 -0
  52. data/lib/scout/workflow/step/info.rb +5 -3
  53. data/lib/scout/workflow/step/load.rb +1 -1
  54. data/lib/scout/workflow/step/provenance.rb +1 -0
  55. data/lib/scout/workflow/step/status.rb +6 -8
  56. data/lib/scout/workflow/step.rb +75 -30
  57. data/lib/scout/workflow/task/dependencies.rb +114 -0
  58. data/lib/scout/workflow/task/inputs.rb +27 -13
  59. data/lib/scout/workflow/task.rb +9 -108
  60. data/lib/scout/workflow/usage.rb +40 -12
  61. data/lib/scout/workflow.rb +4 -2
  62. data/lib/scout-gear.rb +2 -0
  63. data/lib/scout.rb +6 -0
  64. data/scout-gear.gemspec +32 -7
  65. data/scout_commands/doc +37 -0
  66. data/scout_commands/find +1 -0
  67. data/scout_commands/offsite +30 -0
  68. data/scout_commands/update +29 -0
  69. data/scout_commands/workflow/info +15 -3
  70. data/scout_commands/workflow/install +102 -0
  71. data/scout_commands/workflow/task +26 -5
  72. data/test/scout/offsite/test_ssh.rb +15 -0
  73. data/test/scout/offsite/test_step.rb +33 -0
  74. data/test/scout/offsite/test_sync.rb +36 -0
  75. data/test/scout/offsite/test_task.rb +0 -0
  76. data/test/scout/resource/test_path.rb +6 -0
  77. data/test/scout/test_named_array.rb +6 -0
  78. data/test/scout/test_persist.rb +3 -2
  79. data/test/scout/test_tsv.rb +17 -0
  80. data/test/scout/test_work_queue.rb +63 -41
  81. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  82. data/test/scout/tsv/test_index.rb +14 -0
  83. data/test/scout/tsv/test_parser.rb +14 -0
  84. data/test/scout/tsv/test_stream.rb +200 -0
  85. data/test/scout/tsv/test_transformer.rb +12 -0
  86. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  87. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  88. data/test/scout/workflow/step/test_info.rb +18 -0
  89. data/test/scout/workflow/step/test_status.rb +0 -1
  90. data/test/scout/workflow/task/test_dependencies.rb +355 -0
  91. data/test/scout/workflow/task/test_inputs.rb +53 -0
  92. data/test/scout/workflow/test_definition.rb +18 -0
  93. data/test/scout/workflow/test_documentation.rb +24 -0
  94. data/test/scout/workflow/test_step.rb +109 -0
  95. data/test/scout/workflow/test_task.rb +0 -287
  96. data/test/test_scout.rb +9 -0
  97. metadata +83 -5
  98. data/scout_commands/workflow/task_old +0 -706
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48f6bb392f3391e2816e701887bfd98617b1a68bc533c8b6de3307f25c84906d
4
- data.tar.gz: 476858f63deaa7fa9fc531c7872bdaefa1d6b3ed32cdacbe41f53d1d170fcc87
3
+ metadata.gz: 9ca509bfb5065aabcdae73545139db0f8b04748084821e002c0475a55be5cb70
4
+ data.tar.gz: 6f0333ca6dd0ceee0ea9290cf3c30f7164c2f0732b76ce739e29da19a0687242
5
5
  SHA512:
6
- metadata.gz: c61501c8cc79b57b64cb8613efc8b00fb84908bf0d55b008c6a6a39b99ea6bffa53630a8e134c07a49cb7bc4145ec181df057b6ba1eebfd2d722b2aa2d2e63d0
7
- data.tar.gz: 100356a04cd34eba627239668747023ee5be4455ebbee715df39dbe04e9c8dfcac7007ce310e4622cf0c7e16ee9159e6fc2d4eefcaa486c24519c7f99185facf
6
+ metadata.gz: 2cbd82d97ec0dad50e624cda26ae6a05aeba8b9e5ff07a5b4746c677b8e2ab1996378237095ba09a70f8ed8cc926d782c1677aa24d6f94784f560090d6845a2c
7
+ data.tar.gz: aa9529b3393016c846b578b736428b964519d2fb5c1507a6335eff651d0588a5d9191cc61cff52279c18902f2efce386415099bcd92f8736f6d67cef1d33b561
data/.vimproject CHANGED
@@ -8,11 +8,14 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
8
8
  alias
9
9
  find
10
10
  glob
11
+ doc
12
+ update
13
+ offsite
11
14
  workflow=workflow{
12
15
  task
13
16
  list
14
17
  info
15
- task_old
18
+ install
16
19
  }
17
20
  }
18
21
  lib=lib {
@@ -99,24 +102,29 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
99
102
  workflow.rb
100
103
  workflow=workflow{
101
104
  definition.rb
105
+ documentation.rb
106
+ usage.rb
107
+ util.rb
102
108
  step.rb
103
109
  step=step{
104
- info.rb
105
- status.rb
106
- load.rb
107
- file.rb
108
110
  config.rb
109
111
  dependencies.rb
110
- provenance.rb
112
+ file.rb
113
+ info.rb
114
+ load.rb
111
115
  progress.rb
116
+ provenance.rb
117
+ status.rb
112
118
  }
113
119
  task.rb
114
120
  task=task{
121
+ dependencies.rb
115
122
  inputs.rb
116
123
  }
117
- documentation.rb
118
- usage.rb
119
- util.rb
124
+ deployment.rb
125
+ deployment=deployment{
126
+ orchestrator.rb
127
+ }
120
128
  }
121
129
  semaphore.rb
122
130
  work_queue.rb
@@ -141,6 +149,8 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
141
149
  persist=persist{
142
150
  adapter.rb
143
151
  serialize.rb
152
+ sdbm.rb
153
+ tkrzw.rb
144
154
  tokyocabinet.rb
145
155
  fix_width_table.rb
146
156
  }
@@ -149,8 +159,15 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
149
159
  attach.rb
150
160
  change_id.rb
151
161
  path.rb
162
+ stream.rb
152
163
  open.rb
153
164
  }
165
+ offsite.rb
166
+ offsite=offsite{
167
+ ssh.rb
168
+ sync.rb
169
+ step.rb
170
+ }
154
171
  }
155
172
  }
156
173
  test=test {
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ Juwelier::Tasks.new do |gem|
12
12
  gem.homepage = "http://github.com/mikisvaz/scout-gear"
13
13
  gem.license = "MIT"
14
14
  gem.summary = %Q{basic gear for scouts}
15
- gem.description = %Q{Temporary files, logs, etc.}
15
+ gem.description = %Q{Temporary files, logs, path, resources, persistence, workflows, TSV, etc.}
16
16
  gem.email = "mikisvaz@gmail.com"
17
17
  gem.authors = ["Miguel Vazquez"]
18
18
 
@@ -21,6 +21,11 @@ Juwelier::Tasks.new do |gem|
21
21
  # gem.add_runtime_dependency 'jabber4r', '> 0.1'
22
22
  # gem.add_development_dependency 'rspec', '> 1.2.3'
23
23
  gem.add_runtime_dependency 'term-ansicolor'
24
+ gem.add_runtime_dependency 'net-ssh'
25
+ gem.add_runtime_dependency 'matrix'
26
+ gem.add_runtime_dependency 'sys-proctable'
27
+ gem.add_runtime_dependency 'RubyInline'
28
+ #gem.add_runtime_dependency 'tokyocabinet'
24
29
 
25
30
  gem.add_development_dependency "rdoc", "~> 3.12"
26
31
  gem.add_development_dependency "bundler", "~> 1.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 8.0.0
1
+ 8.1.0
data/bin/scout CHANGED
@@ -35,6 +35,12 @@ if dev_dir.nil?
35
35
  ARGV.delete _s if _s
36
36
  end
37
37
 
38
+ if dev_dir.nil? && ENV["SCOUT_DEV"]
39
+ dev_dir = ENV["SCOUT_DEV"]
40
+ ARGV.delete "--dev"
41
+ ARGV.delete dev_dir
42
+ end
43
+
38
44
  if dev_dir
39
45
  ['scout-*/lib'].each do |pattern|
40
46
  Dir.glob(File.join(File.expand_path(dev_dir), pattern)).each do |f|
@@ -62,6 +68,7 @@ $ #{$0} <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-valu
62
68
  --nocolor #{Log.color :yellow, "Disable colored output"}
63
69
  --nobar #{Log.color :yellow, "Disable progress report"}
64
70
  --locate_file #{Log.color :yellow, "Report the location of the script instead of executing it"}
71
+ -ck--config_keys* #{Log.color :yellow, "Override some config keys"}
65
72
  EOF
66
73
 
67
74
  Log.nocolor = true if options[:nocolor]
@@ -84,6 +91,14 @@ else
84
91
  end
85
92
  end
86
93
 
94
+ if config_keys = options.delete(:config_keys)
95
+ config_keys.split(",").each do |config|
96
+ config = config.strip
97
+ Scout::Config.process_config config
98
+ end
99
+ end
100
+
101
+
87
102
  $scout_command_dir = Scout.bin.scout
88
103
  $scout_command_dir.path_maps[:scout_commands] = File.join(File.dirname(__dir__), "{PATH/bin\\/scout/scout_commands}")
89
104
 
@@ -217,7 +232,6 @@ begin
217
232
 
218
233
  scout_usage($previous_commands)
219
234
  exit_status = 0
220
- exit exit_status
221
235
 
222
236
  rescue ParameterException
223
237
  puts
@@ -225,14 +239,11 @@ rescue ParameterException
225
239
  print_error($!.message, $!.backtrace)
226
240
  puts
227
241
  exit_status = -1
228
- exit exit_status
229
242
  rescue SystemExit,CmdStop
230
243
  exit_status = $!.status
231
- exit exit_status
232
244
  rescue Exception
233
245
  Log.exception $!
234
246
  exit_status = -1
235
- exit exit_status
236
247
  ensure
237
248
  if options[:profile]
238
249
  result = RubyProf.stop
@@ -0,0 +1,35 @@
1
+ Path
2
+ ===
3
+
4
+ ```ruby
5
+ :current => '{PWD}/{TOPLEVEL}/{SUBPATH}',
6
+ :user => '{HOME}/.{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
7
+ :global => '/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
8
+ :usr => '/usr/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
9
+ :local => '/usr/local/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
10
+ :fast => '/fast/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
11
+ :cache => '/cache/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
12
+ :bulk => '/bulk/{TOPLEVEL}/{PKGDIR}/{SUBPATH}',
13
+ :lib => '{LIBDIR}/{TOPLEVEL}/{SUBPATH}',
14
+ :scout_gear => File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}"),
15
+ :tmp => '/tmp/{PKGDIR}/{TOPLEVEL}/{SUBPATH}',
16
+ :default => :user
17
+
18
+ @@basic_map_order ||= %w(current workflow user local global lib fast cache bulk)
19
+
20
+ ```
21
+
22
+
23
+
24
+ # tags
25
+ {PKGDIR}
26
+ {LIBDIR}
27
+ {RESOURCE}
28
+ {HOME}
29
+ {PWD}
30
+ {TOPLEVEL}
31
+ {SUBPATH}
32
+ {BASENAME}
33
+ {PATH}
34
+ {MAPNAME}
35
+ {REMOVE}
@@ -0,0 +1,13 @@
1
+ Task
2
+ ====
3
+
4
+ ```ruby
5
+ wf = Workflow.annonymous_workflow "TaskInputs" do
6
+ input :input1, :integer
7
+ task :step1 => :integer do |i| i end
8
+
9
+ dep :step1
10
+ input :input2, :integer, "Integer", 3
11
+ task :step2 => :integer do |i| i * step(:step1).load end
12
+ end
13
+ ```
data/lib/scout/cmd.rb CHANGED
@@ -14,9 +14,9 @@ module CMD
14
14
 
15
15
  def self.conda(tool, env = nil, channel = 'bioconda')
16
16
  if env
17
- CMD.cmd("bash -l -c '(conda activate #{env} && conda install #{tool} -c #{channel})'")
17
+ CMD.cmd("bash -l -c '(conda activate #{env} && conda install #{tool} -c #{channel})'")
18
18
  else
19
- CMD.cmd("bash -l -c 'conda install #{tool} -c #{channel}'")
19
+ CMD.cmd("bash -l -c 'conda install #{tool} -c #{channel}'")
20
20
  end
21
21
  end
22
22
 
@@ -61,6 +61,7 @@ module CMD
61
61
 
62
62
  def self.scan_version_text(text, cmd = nil)
63
63
  cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
64
+ text = Misc.fixutf8 text
64
65
  text.split("\n").each do |line|
65
66
  next unless line =~ /\W#{cmd}\W/i
66
67
  m = line.match(/(v(?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
@@ -98,8 +99,8 @@ module CMD
98
99
 
99
100
  option = "--" << option.to_s if add_dashes and option.to_s[0] != '-'
100
101
 
101
- case
102
- when value.nil? || FalseClass === value
102
+ case
103
+ when value.nil? || FalseClass === value
103
104
  next
104
105
  when TrueClass === value
105
106
  string << "#{option} "
@@ -136,8 +137,8 @@ module CMD
136
137
  dont_close_in = options.delete(:dont_close_in)
137
138
 
138
139
  log = true if log.nil?
139
-
140
- if cmd.nil? && ! Symbol === tool
140
+
141
+ if cmd.nil? && ! Symbol === tool
141
142
  cmd = tool
142
143
  else
143
144
  tool = get_tool(tool)
@@ -163,7 +164,7 @@ module CMD
163
164
 
164
165
  cmd_options = process_cmd_options options
165
166
  if cmd =~ /'\{opt\}'/
166
- cmd.sub!('\'{opt}\'', cmd_options)
167
+ cmd.sub!('\'{opt}\'', cmd_options)
167
168
  else
168
169
  cmd << " " << cmd_options
169
170
  end
@@ -179,29 +180,28 @@ module CMD
179
180
  end
180
181
  pid = wait_thr.pid
181
182
 
182
- Log.debug{"CMD: [#{pid}] #{cmd}" if log}
183
+ Log.debug{"CMD: [#{pid}] #{cmd}".strip if log}
183
184
 
184
185
  if in_content.respond_to?(:read)
185
186
  in_thread = Thread.new(Thread.current) do |parent|
186
- Thread.current.report_on_exception = false if no_fail
187
187
  begin
188
- begin
189
- while c = in_content.readpartial(Open::BLOCK_SIZE)
190
- sin << c
191
- end
192
- rescue EOFError
188
+ Thread.current.report_on_exception = false if no_fail
189
+ Thread.current["name"] = "CMD in"
190
+ while c = in_content.read(Open::BLOCK_SIZE)
191
+ sin << c
193
192
  end
194
193
  sin.close unless sin.closed?
195
194
 
196
195
  unless dont_close_in
197
- in_content.close unless in_content.closed?
198
- in_content.join if in_content.respond_to? :join
196
+ in_content.close unless in_content.closed?
197
+ in_content.join if in_content.respond_to? :join
199
198
  end
200
199
  rescue
201
200
  Log.error "Error in CMD [#{pid}] #{cmd}: #{$!.message}" unless no_fail
202
201
  raise $!
203
202
  end
204
203
  end
204
+ Thread.pass until in_thread["name"]
205
205
  else
206
206
  in_thread = nil
207
207
  sin.close
@@ -211,7 +211,7 @@ module CMD
211
211
 
212
212
  if pipe
213
213
 
214
- ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
214
+ ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
215
215
 
216
216
  sout.callback = post if post
217
217
 
@@ -224,7 +224,7 @@ module CMD
224
224
  sout.log = line
225
225
  sout.std_err << line if save_stderr
226
226
  Log.log "STDERR [#{pid}]: " + line, stderr if log
227
- end
227
+ end
228
228
  serr.close
229
229
  rescue
230
230
  Log.exception $!
@@ -244,8 +244,8 @@ module CMD
244
244
  err = ""
245
245
  err_thread = Thread.new do
246
246
  while not serr.eof?
247
- line = serr.gets
248
- bar.process(line)
247
+ line = serr.gets
248
+ bar.process(line)
249
249
  err << line if Integer === stderr and log
250
250
  end
251
251
  serr.close
@@ -254,18 +254,17 @@ module CMD
254
254
  err = ""
255
255
  err_thread = Thread.new do
256
256
  while not serr.eof?
257
- err << serr.gets
257
+ err << serr.gets
258
258
  end
259
259
  serr.close
260
260
  end
261
261
  else
262
262
  Open.consume_stream(serr, true)
263
- #serr.close
264
263
  err_thread = nil
265
264
  err = ""
266
265
  end
267
266
 
268
- ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
267
+ ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
269
268
 
270
269
  begin
271
270
  out = StringIO.new sout.read
@@ -324,7 +323,7 @@ module CMD
324
323
  starting = true
325
324
  line = "" if bar
326
325
  end
327
- end
326
+ end
328
327
  begin
329
328
  io.join
330
329
  bar.remove if bar
@@ -12,13 +12,12 @@ module ConcurrentStream
12
12
  attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :aborted, :autojoin, :lock, :no_fail, :pair, :thread, :stream_exception, :log, :std_err, :next
13
13
 
14
14
  def self.setup(stream, options = {}, &block)
15
-
16
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
17
16
  stream.extend ConcurrentStream unless ConcurrentStream === stream
18
17
 
19
18
  stream.threads ||= []
20
19
  stream.pids ||= []
21
- stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
20
+ stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
22
21
  stream.pids.concat(Array === pids ? pids : [pids]) unless pids.nil? or pids.empty?
23
22
  stream.autojoin = autojoin unless autojoin.nil?
24
23
  stream.no_fail = no_fail unless no_fail.nil?
@@ -36,7 +35,7 @@ module ConcurrentStream
36
35
  callback.call
37
36
  end
38
37
  else
39
- stream.callback = callback
38
+ stream.callback = callback
40
39
  end
41
40
  end
42
41
 
@@ -48,7 +47,7 @@ module ConcurrentStream
48
47
  abort_callback.call
49
48
  end
50
49
  else
51
- stream.abort_callback = abort_callback
50
+ stream.abort_callback = abort_callback
52
51
  end
53
52
  end
54
53
 
@@ -80,7 +79,7 @@ module ConcurrentStream
80
79
 
81
80
  def join_threads
82
81
  if @threads
83
- @threads.each do |t|
82
+ @threads.each do |t|
84
83
  next if t == Thread.current
85
84
  begin
86
85
  t.join
@@ -101,7 +100,7 @@ module ConcurrentStream
101
100
  Log.low "Not failing on exception joining thread in ConcurrenStream - #{filename} - #{$!.message}"
102
101
  else
103
102
  Log.low "Exception joining thread in ConcurrenStream #{Log.fingerprint self} - #{Log.fingerprint t} - #{$!.message}"
104
- stream_raise_exception $!
103
+ stream_raise_exception $!
105
104
  end
106
105
  end
107
106
  end
@@ -111,13 +110,13 @@ module ConcurrentStream
111
110
 
112
111
  def join_pids
113
112
  if @pids and @pids.any?
114
- @pids.each do |pid|
113
+ @pids.each do |pid|
115
114
  begin
116
115
  Process.waitpid(pid, Process::WUNTRACED)
117
116
  stream_raise_exception ConcurrentStreamProcessFailed.new(pid, "Error in waitpid", self) unless $?.success? or no_fail
118
117
  rescue Errno::ECHILD
119
118
  end
120
- end
119
+ end
121
120
  @pids = []
122
121
  end
123
122
  end
@@ -143,7 +142,7 @@ module ConcurrentStream
143
142
  @joined = true
144
143
  begin
145
144
  lock.unlock if lock && lock.locked?
146
- rescue
145
+ rescue
147
146
  Log.exception $!
148
147
  end
149
148
  raise stream_exception if stream_exception
@@ -158,7 +157,7 @@ module ConcurrentStream
158
157
 
159
158
  threads = @threads.dup
160
159
  @threads.clear
161
- threads.each do |t|
160
+ threads.each do |t|
162
161
  next if t == Thread.current
163
162
  next if t["aborted"]
164
163
  t["aborted"] = true
@@ -166,14 +165,14 @@ module ConcurrentStream
166
165
  Log.debug "Aborting thread #{Log.fingerprint(t)} with exception: #{exception}"
167
166
  t.raise(exception)
168
167
  t.join
169
- end
168
+ end
170
169
  end
171
170
 
172
171
  def abort_pids
173
172
  @pids.each do |pid|
174
- begin
173
+ begin
175
174
  Log.low "Killing PID #{pid} in ConcurrentStream #{filename}"
176
- Process.kill :INT, pid
175
+ Process.kill :INT, pid
177
176
  rescue Errno::ESRCH
178
177
  end
179
178
  end if @pids
@@ -189,7 +188,7 @@ module ConcurrentStream
189
188
  Log.medium "Aborting stream #{Log.fingerprint self} [#{@aborted}]"
190
189
  end
191
190
  AbortedStream.setup(self, exception)
192
- @aborted = true
191
+ @aborted = true
193
192
  begin
194
193
  @abort_callback.call exception if @abort_callback
195
194
 
@@ -207,7 +206,7 @@ module ConcurrentStream
207
206
  close unless closed?
208
207
 
209
208
  if lock and lock.locked?
210
- lock.unlock
209
+ lock.unlock
211
210
  end
212
211
  end
213
212
  end
@@ -218,7 +217,7 @@ module ConcurrentStream
218
217
  super(*args)
219
218
  rescue
220
219
  self.abort
221
- self.join
220
+ self.join
222
221
  stream_raise_exception $!
223
222
  ensure
224
223
  self.join if ! @stream_exception && (self.closed? || self.eof?)
@@ -249,19 +248,37 @@ module ConcurrentStream
249
248
 
250
249
  def add_callback(&block)
251
250
  old_callback = callback
252
- @callback = Proc.new do
251
+ @callback = Proc.new do
253
252
  old_callback.call if old_callback
254
253
  block.call
255
254
  end
256
255
  end
257
256
 
258
257
  def stream_raise_exception(exception)
258
+ self.stream_exception = exception
259
259
  threads.each do |thread|
260
260
  thread.raise exception
261
261
  end
262
- self.stream_exception = exception
263
-
264
262
  self.abort
265
263
  end
266
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
267
284
  end
@@ -139,3 +139,13 @@ class SemaphoreInterrupted < TryAgain; end
139
139
  #
140
140
  #
141
141
  class ResourceNotFound < ScoutException; end
142
+
143
+ class SSHProcessFailed < StandardError
144
+ attr_accessor :host, :cmd
145
+ def initialize(host, cmd)
146
+ @host = host
147
+ @cmd = cmd
148
+ message = "SSH server #{host} failed cmd '#{cmd}'"
149
+ super(message)
150
+ end
151
+ end
@@ -10,8 +10,8 @@ module Colorize
10
10
 
11
11
  def self.colors
12
12
  @colors ||= IndiferentHash.setup(Hash[<<-EOF.split("\n").collect{|l| l.split(" ")}])
13
- green #00cd00
14
- red #cd0000
13
+ green #00cd00
14
+ red #cd0000
15
15
  yellow #ffd700
16
16
  blue #0000cd
17
17
  path blue
@@ -49,26 +49,26 @@ EOF
49
49
  when "black"
50
50
  '#fff'
51
51
  when 'green'
52
- colors["green3"]
52
+ colors["green3"]
53
53
  when 'red'
54
- colors["red3"]
54
+ colors["red3"]
55
55
  when 'yellow'
56
- colors["gold1"]
56
+ colors["gold1"]
57
57
  when 'blue'
58
- colors["RoyalBlue"]
58
+ colors["RoyalBlue"]
59
59
  else
60
60
  colors[color.to_s] || color.to_s
61
61
  end
62
62
  end
63
63
 
64
- def self.continuous(array, start = "#40324F", eend = "#EABD5D", percent = false)
64
+ def self.continuous(array, start = "#40324F", eend = "#EABD5D", percent = false)
65
65
  start_color = Color.new from_name(start)
66
66
  end_color = Color.new from_name(eend)
67
67
 
68
68
  if percent
69
69
  array = array.collect{|v| n = v.to_f; n = n > 100 ? 100 : n; n < 0.001 ? 0.001 : n}
70
70
  else
71
- array = array.collect{|v| v.to_f }
71
+ array = array.collect{|v| v.to_f }
72
72
  end
73
73
  max = array.max
74
74
  min = array.min
@@ -157,7 +157,7 @@ module Log
157
157
  :workflow => yellow,
158
158
  })
159
159
  HIGHLIGHT = "\033[1m"
160
-
160
+
161
161
  def self.uncolor(str)
162
162
  "" << Term::ANSIColor.uncolor(str)
163
163
  end
@@ -167,7 +167,7 @@ module Log
167
167
  end
168
168
 
169
169
  def self.color(color, str = nil, reset = false)
170
- return str.dup || "" if nocolor
170
+ return str.dup || "" if nocolor
171
171
 
172
172
  if (color == :integer || color == :float) && Numeric === str
173
173
  color = if str < 0
@@ -179,7 +179,7 @@ module Log
179
179
  end
180
180
  end
181
181
 
182
- if color == :status
182
+ if color == :status
183
183
  color = case str.to_sym
184
184
  when :done
185
185
  :green
@@ -4,8 +4,7 @@ module Log
4
4
  def print(io, str)
5
5
  return if self.severity && self.severity < Log.severity
6
6
  return if Log.no_bar
7
- STDERR.print str
8
- Log.logfile.puts str unless Log.logfile.nil?
7
+ Log.log_write str
9
8
  Log::LAST.replace "progress"
10
9
  end
11
10
 
@@ -57,9 +56,12 @@ module Log
57
56
  thr = short_mean
58
57
  else
59
58
  thr = begin
60
- (@ticks || 1) / (Time.now - @start)
61
- rescue
62
- 1
59
+ d = Time.now - @start
60
+ if d == 0
61
+ 1
62
+ else
63
+ (@ticks || 1) / d
64
+ end
63
65
  end
64
66
  end
65
67
 
@@ -74,6 +74,7 @@ module Log
74
74
  BAR_MUTEX.synchronize do
75
75
  REMOVE << bar
76
76
  end
77
+ cleanup_bars
77
78
  Log::LAST.replace "remove_bar" if Log::LAST == "progress"
78
79
  end
79
80
 
@@ -128,6 +129,8 @@ module Log
128
129
  nil
129
130
  end
130
131
  end
132
+ rescue Interrupt
133
+ raise $!
131
134
  rescue Exception
132
135
  nil
133
136
  end
@@ -1,7 +1,7 @@
1
1
  module Log
2
2
  def self.trap_std(msg = "STDOUT", msge = "STDERR", severity = 0, severity_err = nil)
3
- sout, sin = Misc.pipe
4
- soute, sine = Misc.pipe
3
+ sout, sin = Open.pipe
4
+ soute, sine = Open.pipe
5
5
  backup_stderr = STDERR.dup
6
6
  backup_stdout = STDOUT.dup
7
7
  old_logfile = Log.logfile
@@ -38,7 +38,7 @@ module Log
38
38
  end
39
39
 
40
40
  def self.trap_stderr(msg = "STDERR", severity = 0)
41
- sout, sin = Misc.pipe
41
+ sout, sin = Open.pipe
42
42
  backup_stderr = STDERR.dup
43
43
  old_logfile = Log.logfile
44
44
  Log.logfile(backup_stderr)