scout-gear 7.1.0 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +29 -0
- data/VERSION +1 -1
- data/bin/scout +5 -1
- data/lib/rbbt-scout.rb +5 -0
- data/lib/scout/concurrent_stream.rb +6 -2
- data/lib/scout/config.rb +168 -0
- data/lib/scout/exceptions.rb +4 -3
- data/lib/scout/indiferent_hash/options.rb +1 -0
- data/lib/scout/indiferent_hash.rb +4 -2
- data/lib/scout/log/color.rb +3 -1
- data/lib/scout/log/progress/report.rb +1 -0
- data/lib/scout/log/progress/util.rb +1 -1
- data/lib/scout/log/progress.rb +5 -3
- data/lib/scout/log.rb +3 -2
- data/lib/scout/misc/monitor.rb +3 -0
- data/lib/scout/misc/system.rb +15 -0
- data/lib/scout/misc.rb +1 -0
- data/lib/scout/named_array.rb +68 -0
- data/lib/scout/open/stream.rb +38 -7
- data/lib/scout/path/find.rb +27 -3
- data/lib/scout/path/util.rb +7 -4
- data/lib/scout/persist/serialize.rb +7 -14
- data/lib/scout/persist.rb +21 -1
- data/lib/scout/resource/produce.rb +7 -94
- data/lib/scout/resource/software.rb +176 -0
- data/lib/scout/tsv/dumper.rb +107 -0
- data/lib/scout/tsv/index.rb +49 -0
- data/lib/scout/tsv/parser.rb +203 -30
- data/lib/scout/tsv/path.rb +13 -0
- data/lib/scout/tsv/persist/adapter.rb +348 -0
- data/lib/scout/tsv/persist/tokyocabinet.rb +113 -0
- data/lib/scout/tsv/persist.rb +15 -0
- data/lib/scout/tsv/traverse.rb +48 -0
- data/lib/scout/tsv/util.rb +24 -0
- data/lib/scout/tsv.rb +16 -3
- data/lib/scout/work_queue/worker.rb +3 -3
- data/lib/scout/work_queue.rb +22 -7
- data/lib/scout/workflow/definition.rb +93 -4
- data/lib/scout/workflow/step/config.rb +18 -0
- data/lib/scout/workflow/step/dependencies.rb +40 -0
- data/lib/scout/workflow/step/file.rb +15 -0
- data/lib/scout/workflow/step/info.rb +31 -4
- data/lib/scout/workflow/step/provenance.rb +148 -0
- data/lib/scout/workflow/step.rb +68 -19
- data/lib/scout/workflow/task.rb +3 -2
- data/lib/scout/workflow/usage.rb +1 -1
- data/lib/scout/workflow.rb +11 -3
- data/lib/scout-gear.rb +1 -0
- data/lib/scout.rb +1 -0
- data/scout-gear.gemspec +34 -3
- data/scout_commands/find +1 -1
- data/scout_commands/workflow/task +16 -10
- data/share/software/install_helpers +523 -0
- data/test/scout/log/test_progress.rb +0 -2
- data/test/scout/misc/test_system.rb +21 -0
- data/test/scout/open/test_stream.rb +159 -0
- data/test/scout/path/test_find.rb +14 -7
- data/test/scout/resource/test_software.rb +24 -0
- data/test/scout/test_config.rb +66 -0
- data/test/scout/test_meta_extension.rb +10 -0
- data/test/scout/test_named_array.rb +19 -0
- data/test/scout/test_persist.rb +35 -0
- data/test/scout/test_tmpfile.rb +2 -2
- data/test/scout/test_tsv.rb +41 -1
- data/test/scout/test_work_queue.rb +40 -13
- data/test/scout/tsv/persist/test_adapter.rb +34 -0
- data/test/scout/tsv/persist/test_tokyocabinet.rb +92 -0
- data/test/scout/tsv/test_dumper.rb +44 -0
- data/test/scout/tsv/test_index.rb +64 -0
- data/test/scout/tsv/test_parser.rb +86 -0
- data/test/scout/tsv/test_persist.rb +36 -0
- data/test/scout/tsv/test_traverse.rb +9 -0
- data/test/scout/tsv/test_util.rb +0 -0
- data/test/scout/work_queue/test_worker.rb +3 -3
- data/test/scout/workflow/step/test_dependencies.rb +25 -0
- data/test/scout/workflow/step/test_info.rb +15 -17
- data/test/scout/workflow/step/test_load.rb +16 -18
- data/test/scout/workflow/step/test_provenance.rb +25 -0
- data/test/scout/workflow/test_step.rb +206 -10
- data/test/scout/workflow/test_task.rb +0 -3
- data/test/test_helper.rb +6 -0
- metadata +33 -2
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'tokyocabinet'
|
2
|
+
require_relative 'adapter'
|
3
|
+
|
4
|
+
module ScoutCabinet
|
5
|
+
attr_accessor :persistence_path, :persistence_class
|
6
|
+
|
7
|
+
CONNECTIONS = {}
|
8
|
+
def self.open(path, write, tokyocabinet_class = TokyoCabinet::HDB)
|
9
|
+
if String === tokyocabinet_class && tokyocabinet_class.include?(":big")
|
10
|
+
big = true
|
11
|
+
tokyocabinet_class = tokyocabinet_class.split(":").first
|
12
|
+
else
|
13
|
+
big = false
|
14
|
+
end
|
15
|
+
|
16
|
+
dir = File.dirname(File.expand_path(path))
|
17
|
+
Open.mkdir(dir) unless File.exist?(dir)
|
18
|
+
|
19
|
+
tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
|
20
|
+
tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
|
21
|
+
|
22
|
+
database = CONNECTIONS[path] ||= tokyocabinet_class.new
|
23
|
+
|
24
|
+
if big and not Open.exists?(path)
|
25
|
+
database.tune(nil,nil,nil,tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
|
26
|
+
end
|
27
|
+
|
28
|
+
flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
|
29
|
+
database.close
|
30
|
+
|
31
|
+
if !database.open(path, flags)
|
32
|
+
ecode = database.ecode
|
33
|
+
raise "Open error: #{database.errmsg(ecode)}. Trying to open file #{path}"
|
34
|
+
end
|
35
|
+
|
36
|
+
database.extend ScoutCabinet
|
37
|
+
database.persistence_path ||= path
|
38
|
+
database.persistence_class = tokyocabinet_class
|
39
|
+
|
40
|
+
database.open(path, tokyocabinet_class::OREADER)
|
41
|
+
|
42
|
+
CONNECTIONS[path] = database
|
43
|
+
|
44
|
+
database
|
45
|
+
end
|
46
|
+
|
47
|
+
def close
|
48
|
+
@closed = true
|
49
|
+
@writable = false
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def read(force = false)
|
54
|
+
return if ! write? && ! closed && ! force
|
55
|
+
self.close
|
56
|
+
if !self.open(@persistence_path, persistence_class::OREADER)
|
57
|
+
ecode = self.ecode
|
58
|
+
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
59
|
+
end
|
60
|
+
|
61
|
+
@writable = false
|
62
|
+
@closed = false
|
63
|
+
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def write(force = true)
|
68
|
+
return if write? && ! closed && ! force
|
69
|
+
self.close
|
70
|
+
|
71
|
+
if !self.open(@persistence_path, persistence_class::OWRITER)
|
72
|
+
ecode = self.ecode
|
73
|
+
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
74
|
+
end
|
75
|
+
|
76
|
+
@writable = true
|
77
|
+
@closed = false
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
#def self.open_tokyocabinet(path, write, serializer = nil, tokyocabinet_class = TokyoCabinet::HDB)
|
83
|
+
# raise
|
84
|
+
# write = true unless File.exist? path
|
85
|
+
|
86
|
+
# FileUtils.mkdir_p File.dirname(path) unless File.exist?(File.dirname(path))
|
87
|
+
|
88
|
+
# database = Persist::TCAdapter.open(path, write, tokyocabinet_class)
|
89
|
+
|
90
|
+
# unless serializer == :clean
|
91
|
+
# TSV.setup database
|
92
|
+
# database.write_and_read do
|
93
|
+
# database.serializer = serializer
|
94
|
+
# end if serializer && database.serializer != serializer
|
95
|
+
# end
|
96
|
+
|
97
|
+
# database
|
98
|
+
#end
|
99
|
+
end
|
100
|
+
|
101
|
+
Persist.save_drivers[:HDB] = proc do |file, content|
|
102
|
+
data = ScoutCabinet.open(file, true, "HDB")
|
103
|
+
content.annotate(data)
|
104
|
+
data.extend TSVAdapter
|
105
|
+
data.merge!(content)
|
106
|
+
data
|
107
|
+
end
|
108
|
+
|
109
|
+
Persist.load_drivers[:HDB] = proc do |file|
|
110
|
+
data = ScoutCabinet.open(file, false, "HDB")
|
111
|
+
data.extend TSVAdapter unless TSVAdapter === data
|
112
|
+
data
|
113
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'persist/adapter'
|
2
|
+
require_relative 'persist/tokyocabinet'
|
3
|
+
|
4
|
+
Persist.save_drivers[:tsv] = proc do |file,content|
|
5
|
+
stream = if IO === content
|
6
|
+
content
|
7
|
+
elsif content.respond_to?(:get_stream)
|
8
|
+
content.get_stream
|
9
|
+
elsif content.respond_to?(:stream)
|
10
|
+
content.stream
|
11
|
+
end
|
12
|
+
Open.sensible_write(file, stream)
|
13
|
+
end
|
14
|
+
|
15
|
+
Persist.load_drivers[:tsv] = proc do |file| TSV.open file end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative 'parser'
|
2
|
+
module TSV
|
3
|
+
def self.traverse_add(into, res)
|
4
|
+
case into
|
5
|
+
when TSV::Dumper
|
6
|
+
into.add *res
|
7
|
+
when TSV, Hash
|
8
|
+
key, value = res
|
9
|
+
into[key] = value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.traverse(obj, into: nil, cpus: nil, bar: nil, **options, &block)
|
14
|
+
case obj
|
15
|
+
when TSV
|
16
|
+
self.traverse(obj.stream, into: into, cpus: cpus, bar: bar, **options, &block)
|
17
|
+
when String
|
18
|
+
f = Open.open(obj)
|
19
|
+
self.traverse(f, into: into, cpus: cpus, bar: bar, **options, &block)
|
20
|
+
when Step
|
21
|
+
self.traverse(obj.get_stream, into: into, cpus: cpus, bar: bar, **options, &block)
|
22
|
+
when IO
|
23
|
+
if into
|
24
|
+
into_thread = Thread.new do
|
25
|
+
Thread.current.report_on_exception = false
|
26
|
+
Thread.current["name"] = "Traverse into"
|
27
|
+
TSV.parse obj, **options do |k,v|
|
28
|
+
begin
|
29
|
+
res = block.call k, v
|
30
|
+
traverse_add into, res
|
31
|
+
rescue
|
32
|
+
into.abort $!
|
33
|
+
end
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
into.close if into.respond_to?(:close)
|
37
|
+
end
|
38
|
+
Thread.pass until into_thread
|
39
|
+
into
|
40
|
+
else
|
41
|
+
TSV.parse obj, **options do |k,v|
|
42
|
+
block.call k, v
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#require_relative '../../../modules/rbbt-util/lib/rbbt/tsv/manipulate'
|
2
|
+
#Log.warn "USING OLD RBBT CODE: #{__FILE__}"
|
3
|
+
module TSV
|
4
|
+
#[:each, :collect, :map].each do |method|
|
5
|
+
# define_method(method) do |*args,&block|
|
6
|
+
# super(*args) do |k,v|
|
7
|
+
# NamedArray.setup(v, @fields) unless @unnamed
|
8
|
+
# block.call k, v
|
9
|
+
# end
|
10
|
+
# end
|
11
|
+
#end
|
12
|
+
|
13
|
+
#[:select, :reject].each do |method|
|
14
|
+
# define_method(method) do |*args,&block|
|
15
|
+
# res = super(*args) do |k,v|
|
16
|
+
# NamedArray.setup(v, @fields) unless @unnamed
|
17
|
+
# block.call k, v
|
18
|
+
# end
|
19
|
+
# self.annotate(res)
|
20
|
+
# res
|
21
|
+
# end
|
22
|
+
#end
|
23
|
+
|
24
|
+
end
|
data/lib/scout/tsv.rb
CHANGED
@@ -1,14 +1,27 @@
|
|
1
1
|
require_relative 'meta_extension'
|
2
|
+
require_relative 'tsv/util'
|
2
3
|
require_relative 'tsv/parser'
|
4
|
+
require_relative 'tsv/dumper'
|
5
|
+
require_relative 'tsv/persist'
|
6
|
+
require_relative 'tsv/index'
|
7
|
+
require_relative 'tsv/path'
|
8
|
+
require_relative 'tsv/traverse'
|
3
9
|
|
4
10
|
module TSV
|
5
11
|
extend MetaExtension
|
6
|
-
extension_attr :key_field, :fields
|
12
|
+
extension_attr :key_field, :fields, :type, :filename, :namespace, :unnamed
|
7
13
|
|
8
14
|
def self.open(file, options = {})
|
9
|
-
|
10
|
-
|
15
|
+
persist, type = IndiferentHash.process_options options, :persist, :persist_type, :persist => false, :persist_type => "HDB"
|
16
|
+
Persist.persist(file, type, options.merge(:persist => persist)) do |filename|
|
17
|
+
data = filename ? ScoutCabinet.open(filename, true, type) : nil
|
18
|
+
options[:data] = data if data
|
19
|
+
options[:filename] = file
|
20
|
+
Open.open(file) do |f|
|
21
|
+
TSV.parse(f, **options)
|
22
|
+
end
|
11
23
|
end
|
12
24
|
end
|
25
|
+
|
13
26
|
end
|
14
27
|
|
@@ -21,7 +21,7 @@ class WorkQueue
|
|
21
21
|
raise obj
|
22
22
|
end
|
23
23
|
res = block.call obj
|
24
|
-
output.write res unless
|
24
|
+
output.write res unless ignore_ouput || res == :ignore
|
25
25
|
end
|
26
26
|
rescue DoneProcessing
|
27
27
|
rescue Interrupt
|
@@ -34,14 +34,14 @@ class WorkQueue
|
|
34
34
|
|
35
35
|
def abort
|
36
36
|
begin
|
37
|
-
Log.
|
37
|
+
Log.debug "Aborting worker #{@pid}"
|
38
38
|
Process.kill "INT", @pid
|
39
39
|
rescue Errno::ECHILD
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
def join
|
44
|
-
Log.
|
44
|
+
Log.debug "Joining worker #{@pid}"
|
45
45
|
Process.waitpid @pid
|
46
46
|
end
|
47
47
|
|
data/lib/scout/work_queue.rb
CHANGED
@@ -36,8 +36,12 @@ class WorkQueue
|
|
36
36
|
|
37
37
|
def remove_worker(pid)
|
38
38
|
@worker_mutex.synchronize do
|
39
|
-
@workers.
|
40
|
-
|
39
|
+
worker = @workers.index{|w| w.pid == pid}
|
40
|
+
if worker
|
41
|
+
Log.debug "Removed worker #{pid}"
|
42
|
+
@workers.delete_at(worker)
|
43
|
+
@removed_workers << pid
|
44
|
+
end
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
@@ -50,11 +54,13 @@ class WorkQueue
|
|
50
54
|
while true
|
51
55
|
obj = @output.read
|
52
56
|
if DoneProcessing === obj
|
57
|
+
|
53
58
|
done = @worker_mutex.synchronize do
|
54
59
|
Log.low "Worker #{obj.pid} done"
|
55
60
|
@done_workers << obj.pid
|
56
|
-
@done_workers.length == @removed_workers.length + @workers.length
|
61
|
+
@closed && @done_workers.length == @removed_workers.length + @workers.length
|
57
62
|
end
|
63
|
+
|
58
64
|
break if done
|
59
65
|
elsif Exception === obj
|
60
66
|
raise obj
|
@@ -65,9 +71,13 @@ class WorkQueue
|
|
65
71
|
rescue DoneProcessing
|
66
72
|
rescue Aborted
|
67
73
|
rescue WorkerException
|
68
|
-
Log.error "Exception in worker #{obj.pid} #{
|
74
|
+
Log.error "Exception in worker #{obj.pid} in queue #{Process.pid}: #{obj.message}"
|
69
75
|
self.abort
|
70
|
-
raise obj.
|
76
|
+
raise obj.worker_exception
|
77
|
+
rescue
|
78
|
+
Log.error "Exception processing output in queue #{Process.pid}: #{$!.message}"
|
79
|
+
self.abort
|
80
|
+
raise $!
|
71
81
|
end
|
72
82
|
end
|
73
83
|
|
@@ -84,11 +94,12 @@ class WorkQueue
|
|
84
94
|
while true
|
85
95
|
pid = Process.wait
|
86
96
|
remove_worker(pid)
|
87
|
-
break if workers.empty?
|
97
|
+
break if @worker_mutex.synchronize{ @workers.empty? }
|
88
98
|
end
|
89
99
|
end
|
90
100
|
end
|
91
101
|
|
102
|
+
Thread.pass until @worker_mutex.synchronize{ @workers.select{|w| w.pid.nil? }.empty? }
|
92
103
|
Thread.pass until @waiter["name"]
|
93
104
|
end
|
94
105
|
|
@@ -97,10 +108,14 @@ class WorkQueue
|
|
97
108
|
end
|
98
109
|
|
99
110
|
def abort
|
100
|
-
workers.
|
111
|
+
Log.low "Aborting #{@workers.length} workers in queue #{Process.pid}"
|
112
|
+
@worker_mutex.synchronize do
|
113
|
+
@workers.each{|w| w.abort }
|
114
|
+
end
|
101
115
|
end
|
102
116
|
|
103
117
|
def close
|
118
|
+
@closed = true
|
104
119
|
@worker_mutex.synchronize{ @workers.length }.times do
|
105
120
|
@input.write DoneProcessing.new()
|
106
121
|
end
|
@@ -2,7 +2,7 @@ require_relative '../meta_extension'
|
|
2
2
|
|
3
3
|
module Workflow
|
4
4
|
extend MetaExtension
|
5
|
-
extension_attr :name, :tasks
|
5
|
+
extension_attr :name, :tasks, :helpers
|
6
6
|
|
7
7
|
class << self
|
8
8
|
attr_accessor :directory
|
@@ -17,6 +17,32 @@ module Workflow
|
|
17
17
|
@name ||= self.to_s
|
18
18
|
end
|
19
19
|
|
20
|
+
def helpers
|
21
|
+
@helpers ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def helper(name, *args, &block)
|
25
|
+
if block_given?
|
26
|
+
helpers[name] = block
|
27
|
+
else
|
28
|
+
raise RbbtException, "helper #{name} unkown in #{self} workflow" unless helpers[name]
|
29
|
+
helpers[name].call(*args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def step_module
|
34
|
+
@_m ||= begin
|
35
|
+
m = Module.new
|
36
|
+
|
37
|
+
helpers.each do |name,block|
|
38
|
+
m.send(:define_method, name, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
m
|
42
|
+
end
|
43
|
+
@_m
|
44
|
+
end
|
45
|
+
|
20
46
|
attr_accessor :directory
|
21
47
|
def directory
|
22
48
|
@directory ||= Workflow.directory[name]
|
@@ -60,19 +86,82 @@ module Workflow
|
|
60
86
|
annotate_next_task(:inputs, args)
|
61
87
|
end
|
62
88
|
|
89
|
+
def desc(description)
|
90
|
+
annotate_next_task_single(:description, description)
|
91
|
+
end
|
92
|
+
|
93
|
+
def returns(type)
|
94
|
+
annotate_next_task_single(:returns, type)
|
95
|
+
end
|
96
|
+
|
97
|
+
def extension(extension)
|
98
|
+
annotate_next_task_single(:extension, extension)
|
99
|
+
end
|
100
|
+
|
63
101
|
def task(name_and_type, &block)
|
64
102
|
name, type = name_and_type.collect.first
|
65
103
|
@tasks ||= IndiferentHash.setup({})
|
66
104
|
begin
|
67
105
|
@annotate_next_task ||= {}
|
68
|
-
task = Task.setup(block, @annotate_next_task.merge(name: name, type: type, directory: directory[name]))
|
106
|
+
task = Task.setup(block, @annotate_next_task.merge(name: name, type: type, directory: directory[name], workflow: self))
|
69
107
|
@tasks[name] = task
|
70
108
|
ensure
|
71
109
|
@annotate_next_task = {}
|
72
110
|
end
|
73
111
|
end
|
74
112
|
|
75
|
-
def
|
76
|
-
|
113
|
+
def task_alias(name, workflow, oname, *rest, &block)
|
114
|
+
dep(workflow, oname, *rest, &block)
|
115
|
+
extension :dep_task unless @extension
|
116
|
+
returns workflow.tasks[oname].returns if workflow.tasks.include?(oname) unless @returns
|
117
|
+
task name => nil do
|
118
|
+
raise RbbtException, "dep_task does not have any dependencies" if dependencies.empty?
|
119
|
+
Step.wait_for_jobs dependencies.select{|d| d.streaming? }
|
120
|
+
dep = dependencies.last
|
121
|
+
dep.join
|
122
|
+
raise dep.get_exception if dep.error?
|
123
|
+
raise Aborted, "Aborted dependency #{dep.path}" if dep.aborted?
|
124
|
+
set_info :result_type, dep.info[:result_type]
|
125
|
+
forget = config :forget_dep_tasks, "forget_dep_tasks", :default => FORGET_DEP_TASKS
|
126
|
+
if forget
|
127
|
+
remove = config :remove_dep_tasks, "remove_dep_tasks", :default => REMOVE_DEP_TASKS
|
128
|
+
|
129
|
+
self.archive_deps
|
130
|
+
self.copy_files_dir
|
131
|
+
self.dependencies = self.dependencies - [dep]
|
132
|
+
Open.rm_rf self.files_dir if Open.exist? self.files_dir
|
133
|
+
FileUtils.cp_r dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
|
134
|
+
|
135
|
+
if dep.overriden || ! Workflow.job_path?(dep.path)
|
136
|
+
Open.link dep.path, self.tmp_path
|
137
|
+
else
|
138
|
+
Open.ln_h dep.path, self.tmp_path
|
139
|
+
|
140
|
+
case remove.to_s
|
141
|
+
when 'true'
|
142
|
+
dep.clean
|
143
|
+
when 'recursive'
|
144
|
+
(dep.dependencies + dep.rec_dependencies).uniq.each do |d|
|
145
|
+
next if d.overriden
|
146
|
+
d.clean unless config(:remove_dep, d.task_signature, d.task_name, d.workflow.to_s, :default => true).to_s == 'false'
|
147
|
+
end
|
148
|
+
dep.clean unless config(:remove_dep, dep.task_signature, dep.task_name, dep.workflow.to_s, :default => true).to_s == 'false'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
else
|
152
|
+
if Open.exists?(dep.files_dir)
|
153
|
+
Open.rm_rf self.files_dir
|
154
|
+
Open.link dep.files_dir, self.files_dir
|
155
|
+
end
|
156
|
+
if defined?(RemoteStep) && RemoteStep === dep
|
157
|
+
Open.write(self.tmp_path, Open.read(dep.path))
|
158
|
+
else
|
159
|
+
Open.link dep.path, self.path
|
160
|
+
end
|
161
|
+
end
|
162
|
+
nil
|
163
|
+
end
|
77
164
|
end
|
165
|
+
|
166
|
+
alias dep_task task_alias
|
78
167
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../../config'
|
2
|
+
|
3
|
+
class Step
|
4
|
+
def config(key, *tokens)
|
5
|
+
options = tokens.pop if Hash === tokens.last
|
6
|
+
options ||= {}
|
7
|
+
|
8
|
+
new_tokens = []
|
9
|
+
if workflow
|
10
|
+
workflow_name = workflow.to_s
|
11
|
+
new_tokens << ("workflow:" << workflow_name)
|
12
|
+
new_tokens << ("task:" << workflow_name << "#" << task_name.to_s)
|
13
|
+
end
|
14
|
+
new_tokens << ("task:" << task_name.to_s)
|
15
|
+
|
16
|
+
Scout::Config.get(key, tokens + new_tokens, options)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Step
|
2
|
+
def recursive_inputs
|
3
|
+
dependencies.inject(@inputs.annotate(@inputs.dup)) do |acc,dep|
|
4
|
+
acc.concat(dep.inputs) if dep.inputs
|
5
|
+
acc
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def input_dependencies
|
10
|
+
return [] unless inputs
|
11
|
+
inputs.select do |d|
|
12
|
+
Step === d
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_dependencies
|
17
|
+
inverse_dep = {}
|
18
|
+
dependencies.each{|dep|
|
19
|
+
next if dep.done?
|
20
|
+
if dep.dependencies
|
21
|
+
dep.dependencies.each do |d|
|
22
|
+
inverse_dep[d] ||= []
|
23
|
+
inverse_dep[d] << dep
|
24
|
+
end
|
25
|
+
end
|
26
|
+
input_dependencies.each do |d|
|
27
|
+
inverse_dep[d] ||= []
|
28
|
+
inverse_dep[d] << dep
|
29
|
+
end
|
30
|
+
}
|
31
|
+
inverse_dep.each do |dep,list|
|
32
|
+
dep.tee_copies = list.length
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def run_dependencies
|
37
|
+
dependencies.each{|dep| dep.run unless dep.running? || dep.done? }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Step
|
2
|
-
SERIALIZER = :
|
2
|
+
SERIALIZER = :marshal
|
3
3
|
def info_file
|
4
4
|
@info_file ||= begin
|
5
5
|
info_file = @path + ".info"
|
@@ -20,7 +20,11 @@ class Step
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def info
|
23
|
-
outdated =
|
23
|
+
outdated = begin
|
24
|
+
@info_load_time && (mtime = Open.mtime(info_file)) && mtime > @info_load_time
|
25
|
+
rescue
|
26
|
+
true
|
27
|
+
end
|
24
28
|
|
25
29
|
if @info.nil? || outdated
|
26
30
|
load_info
|
@@ -33,6 +37,19 @@ class Step
|
|
33
37
|
info = self.info
|
34
38
|
new_info.each do |key,value|
|
35
39
|
report_status new_info[:status], new_info[:message] if key == :status
|
40
|
+
if Exception === value
|
41
|
+
begin
|
42
|
+
Marshal.dump(value)
|
43
|
+
rescue TypeError
|
44
|
+
if ScoutException === value
|
45
|
+
new = ScoutException.new value.message
|
46
|
+
else
|
47
|
+
new = Exception.new value.message
|
48
|
+
end
|
49
|
+
new.set_backtrace(value.backtrace)
|
50
|
+
value = new
|
51
|
+
end
|
52
|
+
end
|
36
53
|
if info.include?(key)
|
37
54
|
case info[key]
|
38
55
|
when Array
|
@@ -62,7 +79,6 @@ class Step
|
|
62
79
|
end
|
63
80
|
|
64
81
|
def log(status, message = nil)
|
65
|
-
report_status status, message
|
66
82
|
if message
|
67
83
|
merge_info :status => status, :messages => [message]
|
68
84
|
else
|
@@ -71,7 +87,18 @@ class Step
|
|
71
87
|
end
|
72
88
|
|
73
89
|
def status
|
74
|
-
info[:status]
|
90
|
+
info[:status].tap{|s| s.nil? ? s : s.to_sym }
|
91
|
+
end
|
92
|
+
|
93
|
+
def error?
|
94
|
+
status == :error
|
75
95
|
end
|
76
96
|
|
97
|
+
def aborted?
|
98
|
+
status == :aborted
|
99
|
+
end
|
100
|
+
|
101
|
+
def running?
|
102
|
+
! done? && (info[:pid] && Misc.pid_alive?(info[:pid]))
|
103
|
+
end
|
77
104
|
end
|