scout-gear 7.1.0 → 7.2.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.
- 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
|