scout-gear 8.0.0 → 9.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +48 -9
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/bin/scout +16 -4
- data/doc/lib/scout/path.md +35 -0
- data/doc/lib/scout/workflow/task.md +13 -0
- data/lib/rbbt-scout.rb +2 -1
- data/lib/scout/cmd.rb +32 -29
- data/lib/scout/concurrent_stream.rb +36 -19
- data/lib/scout/exceptions.rb +10 -0
- data/lib/scout/indiferent_hash.rb +17 -0
- data/lib/scout/log/color.rb +11 -11
- data/lib/scout/log/progress/report.rb +8 -5
- data/lib/scout/log/progress/util.rb +3 -0
- data/lib/scout/log/trap.rb +3 -3
- data/lib/scout/log.rb +67 -36
- data/lib/scout/meta_extension.rb +34 -0
- data/lib/scout/misc/digest.rb +11 -2
- data/lib/scout/misc/filesystem.rb +2 -3
- data/lib/scout/misc/format.rb +12 -7
- data/lib/scout/misc/monitor.rb +11 -0
- data/lib/scout/misc/system.rb +48 -0
- data/lib/scout/named_array.rb +8 -0
- data/lib/scout/offsite/ssh.rb +174 -0
- data/lib/scout/offsite/step.rb +100 -0
- data/lib/scout/offsite/sync.rb +55 -0
- data/lib/scout/offsite.rb +3 -0
- data/lib/scout/open/lock.rb +5 -24
- data/lib/scout/open/remote.rb +12 -1
- data/lib/scout/open/stream.rb +109 -122
- data/lib/scout/open/util.rb +9 -0
- data/lib/scout/open.rb +12 -11
- data/lib/scout/path/find.rb +15 -10
- data/lib/scout/path/util.rb +5 -0
- data/lib/scout/path.rb +1 -1
- data/lib/scout/persist/serialize.rb +4 -4
- data/lib/scout/persist.rb +1 -1
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +16 -9
- data/lib/scout/resource/software.rb +4 -2
- data/lib/scout/resource/util.rb +10 -4
- data/lib/scout/resource.rb +2 -0
- data/lib/scout/tsv/dumper.rb +5 -1
- data/lib/scout/tsv/index.rb +28 -86
- data/lib/scout/tsv/open.rb +35 -14
- data/lib/scout/tsv/parser.rb +22 -5
- data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
- data/lib/scout/tsv/stream.rb +204 -0
- data/lib/scout/tsv/transformer.rb +11 -0
- data/lib/scout/tsv.rb +9 -2
- data/lib/scout/work_queue/worker.rb +2 -2
- data/lib/scout/work_queue.rb +37 -12
- data/lib/scout/workflow/definition.rb +2 -1
- data/lib/scout/workflow/deployment/orchestrator.rb +254 -0
- data/lib/scout/workflow/deployment.rb +1 -0
- data/lib/scout/workflow/step/dependencies.rb +46 -14
- data/lib/scout/workflow/step/file.rb +5 -0
- data/lib/scout/workflow/step/info.rb +13 -3
- data/lib/scout/workflow/step/inputs.rb +5 -0
- data/lib/scout/workflow/step/load.rb +1 -1
- data/lib/scout/workflow/step/provenance.rb +1 -0
- data/lib/scout/workflow/step/status.rb +27 -9
- data/lib/scout/workflow/step.rb +82 -30
- data/lib/scout/workflow/task/dependencies.rb +116 -0
- data/lib/scout/workflow/task/inputs.rb +36 -17
- data/lib/scout/workflow/task.rb +12 -109
- data/lib/scout/workflow/usage.rb +57 -41
- data/lib/scout/workflow.rb +19 -13
- data/lib/scout-gear.rb +2 -0
- data/lib/scout.rb +6 -0
- data/scout-gear.gemspec +38 -7
- data/scout_commands/doc +37 -0
- data/scout_commands/find +1 -0
- data/scout_commands/offsite +30 -0
- data/scout_commands/resource/produce +66 -0
- data/scout_commands/template +52 -0
- data/scout_commands/update +29 -0
- data/scout_commands/workflow/info +15 -3
- data/scout_commands/workflow/install +105 -0
- data/scout_commands/workflow/task +46 -6
- data/share/software/install_helpers +2 -2
- data/share/templates/command +25 -0
- data/share/templates/workflow.rb +14 -0
- data/test/scout/offsite/test_ssh.rb +15 -0
- data/test/scout/offsite/test_step.rb +32 -0
- data/test/scout/offsite/test_sync.rb +36 -0
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/resource/test_path.rb +6 -0
- data/test/scout/test_named_array.rb +6 -0
- data/test/scout/test_persist.rb +3 -2
- data/test/scout/test_tsv.rb +17 -0
- data/test/scout/test_work_queue.rb +64 -42
- data/test/scout/tsv/persist/test_adapter.rb +1 -1
- data/test/scout/tsv/test_index.rb +14 -0
- data/test/scout/tsv/test_parser.rb +35 -0
- data/test/scout/tsv/test_stream.rb +200 -0
- data/test/scout/tsv/test_transformer.rb +12 -0
- data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
- data/test/scout/workflow/step/test_dependencies.rb +68 -0
- data/test/scout/workflow/step/test_info.rb +17 -0
- data/test/scout/workflow/step/test_status.rb +0 -1
- data/test/scout/workflow/task/test_dependencies.rb +357 -0
- data/test/scout/workflow/task/test_inputs.rb +52 -0
- data/test/scout/workflow/test_definition.rb +18 -0
- data/test/scout/workflow/test_documentation.rb +24 -0
- data/test/scout/workflow/test_step.rb +109 -0
- data/test/scout/workflow/test_task.rb +0 -287
- data/test/test_scout.rb +9 -0
- metadata +89 -5
- data/scout_commands/workflow/task_old +0 -706
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98b3f84350f2f451b717f004bfc97cd7767f7e0fed58e1a2d0cd023bc700185f
|
4
|
+
data.tar.gz: '00847ad4d92b1cab22305ea867dc12c870b22e192e79536917f82aa90cc82989'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4af5e13873fa13dea33161e9200aa725bb4329899e9242ae6504ffae2ab82e7eb01b82a53edc2a4331ede06d0f12bb07f86f579cb29ecbf0d36e791bf6d53f3e
|
7
|
+
data.tar.gz: fc773eb933e5c851aa1d642e872df02d282fbcb29ee1b8e1bf150ffebf9bd4ce8c3670d43a284ff2c8197477a8cf6f71dfcd49b265ad938c723292ec57579998
|
data/.vimproject
CHANGED
@@ -8,11 +8,18 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
8
8
|
alias
|
9
9
|
find
|
10
10
|
glob
|
11
|
+
doc
|
12
|
+
update
|
13
|
+
template
|
14
|
+
offsite
|
11
15
|
workflow=workflow{
|
12
16
|
task
|
13
17
|
list
|
14
18
|
info
|
15
|
-
|
19
|
+
install
|
20
|
+
}
|
21
|
+
resource=resource{
|
22
|
+
produce
|
16
23
|
}
|
17
24
|
}
|
18
25
|
lib=lib {
|
@@ -99,24 +106,30 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
99
106
|
workflow.rb
|
100
107
|
workflow=workflow{
|
101
108
|
definition.rb
|
109
|
+
documentation.rb
|
110
|
+
usage.rb
|
111
|
+
util.rb
|
102
112
|
step.rb
|
103
113
|
step=step{
|
104
|
-
info.rb
|
105
|
-
status.rb
|
106
|
-
load.rb
|
107
|
-
file.rb
|
108
114
|
config.rb
|
109
115
|
dependencies.rb
|
110
|
-
|
116
|
+
file.rb
|
117
|
+
info.rb
|
118
|
+
load.rb
|
111
119
|
progress.rb
|
120
|
+
provenance.rb
|
121
|
+
status.rb
|
122
|
+
inputs.rb
|
112
123
|
}
|
113
124
|
task.rb
|
114
125
|
task=task{
|
126
|
+
dependencies.rb
|
115
127
|
inputs.rb
|
116
128
|
}
|
117
|
-
|
118
|
-
|
119
|
-
|
129
|
+
deployment.rb
|
130
|
+
deployment=deployment{
|
131
|
+
orchestrator.rb
|
132
|
+
}
|
120
133
|
}
|
121
134
|
semaphore.rb
|
122
135
|
work_queue.rb
|
@@ -141,6 +154,8 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
141
154
|
persist=persist{
|
142
155
|
adapter.rb
|
143
156
|
serialize.rb
|
157
|
+
sdbm.rb
|
158
|
+
tkrzw.rb
|
144
159
|
tokyocabinet.rb
|
145
160
|
fix_width_table.rb
|
146
161
|
}
|
@@ -149,8 +164,18 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
149
164
|
attach.rb
|
150
165
|
change_id.rb
|
151
166
|
path.rb
|
167
|
+
stream.rb
|
152
168
|
open.rb
|
153
169
|
}
|
170
|
+
offsite.rb
|
171
|
+
offsite=offsite{
|
172
|
+
ssh.rb
|
173
|
+
sync.rb
|
174
|
+
step.rb
|
175
|
+
}
|
176
|
+
hpc=hpc{
|
177
|
+
slurm.rb
|
178
|
+
}
|
154
179
|
}
|
155
180
|
}
|
156
181
|
test=test {
|
@@ -181,7 +206,18 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
181
206
|
test_task.rb
|
182
207
|
test_usage.rb
|
183
208
|
test_util.rb
|
209
|
+
step=step{
|
210
|
+
test_dependencies.rb
|
211
|
+
test_info.rb
|
212
|
+
test_load.rb
|
213
|
+
test_provenance.rb
|
214
|
+
test_status.rb
|
215
|
+
}
|
216
|
+
task=task{
|
217
|
+
test_dependencies.rb
|
218
|
+
test_inputs.rb
|
184
219
|
}
|
220
|
+
}
|
185
221
|
indiferent_hash=indiferent_hash{
|
186
222
|
test_case_insensitive.rb
|
187
223
|
test_options.rb
|
@@ -192,6 +228,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
192
228
|
software=software{
|
193
229
|
install_helpers
|
194
230
|
}
|
231
|
+
templates=templates{
|
232
|
+
workflow.rb
|
233
|
+
}
|
195
234
|
}
|
196
235
|
|
197
236
|
|
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
|
-
|
1
|
+
9.0.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|
|
@@ -48,6 +54,7 @@ if dev_dir
|
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
57
|
+
require 'scout'
|
51
58
|
|
52
59
|
require 'scout/simple_opt'
|
53
60
|
|
@@ -62,6 +69,7 @@ $ #{$0} <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-valu
|
|
62
69
|
--nocolor #{Log.color :yellow, "Disable colored output"}
|
63
70
|
--nobar #{Log.color :yellow, "Disable progress report"}
|
64
71
|
--locate_file #{Log.color :yellow, "Report the location of the script instead of executing it"}
|
72
|
+
-ck--config_keys* #{Log.color :yellow, "Override some config keys"}
|
65
73
|
EOF
|
66
74
|
|
67
75
|
Log.nocolor = true if options[:nocolor]
|
@@ -84,6 +92,14 @@ else
|
|
84
92
|
end
|
85
93
|
end
|
86
94
|
|
95
|
+
if config_keys = options.delete(:config_keys)
|
96
|
+
config_keys.split(",").each do |config|
|
97
|
+
config = config.strip
|
98
|
+
Scout::Config.process_config config
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
87
103
|
$scout_command_dir = Scout.bin.scout
|
88
104
|
$scout_command_dir.path_maps[:scout_commands] = File.join(File.dirname(__dir__), "{PATH/bin\\/scout/scout_commands}")
|
89
105
|
|
@@ -217,7 +233,6 @@ begin
|
|
217
233
|
|
218
234
|
scout_usage($previous_commands)
|
219
235
|
exit_status = 0
|
220
|
-
exit exit_status
|
221
236
|
|
222
237
|
rescue ParameterException
|
223
238
|
puts
|
@@ -225,14 +240,11 @@ rescue ParameterException
|
|
225
240
|
print_error($!.message, $!.backtrace)
|
226
241
|
puts
|
227
242
|
exit_status = -1
|
228
|
-
exit exit_status
|
229
243
|
rescue SystemExit,CmdStop
|
230
244
|
exit_status = $!.status
|
231
|
-
exit exit_status
|
232
245
|
rescue Exception
|
233
246
|
Log.exception $!
|
234
247
|
exit_status = -1
|
235
|
-
exit exit_status
|
236
248
|
ensure
|
237
249
|
if options[:profile]
|
238
250
|
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/rbbt-scout.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
$LOAD_PATH.unshift File.join(__dir__, '../modules/rbbt-util/lib')
|
2
2
|
module Rbbt
|
3
3
|
extend Resource
|
4
|
-
self.pkgdir = 'rbbt'
|
5
4
|
self.path_maps = Path.path_maps.merge(:rbbt_lib => File.expand_path(File.join(__dir__, '../modules/rbbt-util/', '{TOPLEVEL}','{SUBPATH}')))
|
6
5
|
end
|
6
|
+
|
7
|
+
Resource.set_software_env Rbbt.software
|
data/lib/scout/cmd.rb
CHANGED
@@ -14,23 +14,28 @@ 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
|
|
23
|
+
|
23
24
|
def self.get_tool(tool)
|
24
25
|
return tool.to_s unless TOOLS[tool]
|
25
26
|
|
26
27
|
@@init_cmd_tool ||= IndiferentHash.setup({})
|
28
|
+
|
29
|
+
claim, test, block, cmd = TOOLS[tool]
|
30
|
+
cmd = tool.to_s if cmd.nil?
|
31
|
+
|
27
32
|
if !@@init_cmd_tool[tool]
|
28
|
-
|
33
|
+
|
29
34
|
begin
|
30
35
|
if test
|
31
36
|
CMD.cmd(test + " ")
|
32
37
|
else
|
33
|
-
CMD.cmd("#{
|
38
|
+
CMD.cmd("#{cmd} --help")
|
34
39
|
end
|
35
40
|
rescue
|
36
41
|
if claim
|
@@ -43,7 +48,7 @@ module CMD
|
|
43
48
|
version = nil
|
44
49
|
["--version", "-version", "--help", ""].each do |f|
|
45
50
|
begin
|
46
|
-
version_txt += CMD.cmd("#{
|
51
|
+
version_txt += CMD.cmd("#{cmd} #{f} 2>&1", :nofail => true).read
|
47
52
|
version = CMD.scan_version_text(version_txt, tool)
|
48
53
|
break if version
|
49
54
|
rescue
|
@@ -56,11 +61,11 @@ module CMD
|
|
56
61
|
return cmd if cmd
|
57
62
|
end
|
58
63
|
|
59
|
-
|
64
|
+
cmd
|
60
65
|
end
|
61
|
-
|
62
66
|
def self.scan_version_text(text, cmd = nil)
|
63
67
|
cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
|
68
|
+
text = Misc.fixutf8 text
|
64
69
|
text.split("\n").each do |line|
|
65
70
|
next unless line =~ /\W#{cmd}\W/i
|
66
71
|
m = line.match(/(v(?:\d+\.)*\d+(?:-[a-z_]+)?)/i)
|
@@ -98,8 +103,8 @@ module CMD
|
|
98
103
|
|
99
104
|
option = "--" << option.to_s if add_dashes and option.to_s[0] != '-'
|
100
105
|
|
101
|
-
case
|
102
|
-
when value.nil? || FalseClass === value
|
106
|
+
case
|
107
|
+
when value.nil? || FalseClass === value
|
103
108
|
next
|
104
109
|
when TrueClass === value
|
105
110
|
string << "#{option} "
|
@@ -136,8 +141,8 @@ module CMD
|
|
136
141
|
dont_close_in = options.delete(:dont_close_in)
|
137
142
|
|
138
143
|
log = true if log.nil?
|
139
|
-
|
140
|
-
if cmd.nil? && ! Symbol === tool
|
144
|
+
|
145
|
+
if cmd.nil? && ! Symbol === tool
|
141
146
|
cmd = tool
|
142
147
|
else
|
143
148
|
tool = get_tool(tool)
|
@@ -163,7 +168,7 @@ module CMD
|
|
163
168
|
|
164
169
|
cmd_options = process_cmd_options options
|
165
170
|
if cmd =~ /'\{opt\}'/
|
166
|
-
cmd.sub!('\'{opt}\'', cmd_options)
|
171
|
+
cmd.sub!('\'{opt}\'', cmd_options)
|
167
172
|
else
|
168
173
|
cmd << " " << cmd_options
|
169
174
|
end
|
@@ -179,29 +184,28 @@ module CMD
|
|
179
184
|
end
|
180
185
|
pid = wait_thr.pid
|
181
186
|
|
182
|
-
Log.debug{"CMD: [#{pid}] #{cmd}" if log}
|
187
|
+
Log.debug{"CMD: [#{pid}] #{cmd}".strip if log}
|
183
188
|
|
184
189
|
if in_content.respond_to?(:read)
|
185
190
|
in_thread = Thread.new(Thread.current) do |parent|
|
186
|
-
Thread.current.report_on_exception = false if no_fail
|
187
191
|
begin
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
rescue EOFError
|
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
|
193
196
|
end
|
194
197
|
sin.close unless sin.closed?
|
195
198
|
|
196
199
|
unless dont_close_in
|
197
|
-
in_content.close unless in_content.closed?
|
198
|
-
in_content.join if in_content.respond_to? :join
|
200
|
+
in_content.close unless in_content.closed?
|
201
|
+
in_content.join if in_content.respond_to? :join
|
199
202
|
end
|
200
203
|
rescue
|
201
204
|
Log.error "Error in CMD [#{pid}] #{cmd}: #{$!.message}" unless no_fail
|
202
205
|
raise $!
|
203
206
|
end
|
204
207
|
end
|
208
|
+
Thread.pass until in_thread["name"]
|
205
209
|
else
|
206
210
|
in_thread = nil
|
207
211
|
sin.close
|
@@ -211,7 +215,7 @@ module CMD
|
|
211
215
|
|
212
216
|
if pipe
|
213
217
|
|
214
|
-
ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
|
218
|
+
ConcurrentStream.setup sout, :pids => pids, :autojoin => autojoin, :no_fail => no_fail
|
215
219
|
|
216
220
|
sout.callback = post if post
|
217
221
|
|
@@ -224,7 +228,7 @@ module CMD
|
|
224
228
|
sout.log = line
|
225
229
|
sout.std_err << line if save_stderr
|
226
230
|
Log.log "STDERR [#{pid}]: " + line, stderr if log
|
227
|
-
end
|
231
|
+
end
|
228
232
|
serr.close
|
229
233
|
rescue
|
230
234
|
Log.exception $!
|
@@ -244,8 +248,8 @@ module CMD
|
|
244
248
|
err = ""
|
245
249
|
err_thread = Thread.new do
|
246
250
|
while not serr.eof?
|
247
|
-
line = serr.gets
|
248
|
-
bar.process(line)
|
251
|
+
line = serr.gets
|
252
|
+
bar.process(line)
|
249
253
|
err << line if Integer === stderr and log
|
250
254
|
end
|
251
255
|
serr.close
|
@@ -254,18 +258,17 @@ module CMD
|
|
254
258
|
err = ""
|
255
259
|
err_thread = Thread.new do
|
256
260
|
while not serr.eof?
|
257
|
-
err << serr.gets
|
261
|
+
err << serr.gets
|
258
262
|
end
|
259
263
|
serr.close
|
260
264
|
end
|
261
265
|
else
|
262
266
|
Open.consume_stream(serr, true)
|
263
|
-
#serr.close
|
264
267
|
err_thread = nil
|
265
268
|
err = ""
|
266
269
|
end
|
267
270
|
|
268
|
-
ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
|
271
|
+
ConcurrentStream.setup sout, :pids => pids, :threads => [in_thread, err_thread].compact, :autojoin => autojoin, :no_fail => no_fail
|
269
272
|
|
270
273
|
begin
|
271
274
|
out = StringIO.new sout.read
|
@@ -324,7 +327,7 @@ module CMD
|
|
324
327
|
starting = true
|
325
328
|
line = "" if bar
|
326
329
|
end
|
327
|
-
end
|
330
|
+
end
|
328
331
|
begin
|
329
332
|
io.join
|
330
333
|
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
|
data/lib/scout/exceptions.rb
CHANGED
@@ -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
|
@@ -75,5 +75,22 @@ module IndiferentHash
|
|
75
75
|
end
|
76
76
|
clean
|
77
77
|
end
|
78
|
+
|
79
|
+
def slice(*list)
|
80
|
+
ext_list = []
|
81
|
+
list.each do |e|
|
82
|
+
case e
|
83
|
+
when Symbol
|
84
|
+
ext_list << e
|
85
|
+
ext_list << e.to_s
|
86
|
+
when String
|
87
|
+
ext_list << e
|
88
|
+
ext_list << e.to_sym
|
89
|
+
else
|
90
|
+
ext_list << e
|
91
|
+
end
|
92
|
+
end
|
93
|
+
IndiferentHash.setup(super(*ext_list))
|
94
|
+
end
|
78
95
|
end
|
79
96
|
|