rbbt-util 5.27.2 → 5.27.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 258aa01482866ef7b940790ad6f10d077a0cd721b972cbb939412c3691595acc
4
- data.tar.gz: 9adb68a2c9ddfa77a3be419dd106e4083e11933dd6653b4d6e0bfa921edab187
3
+ metadata.gz: 6551d632ae1f2289805a53ceaf9db01d0c0a029ea6c76176aed419e4d6a2a485
4
+ data.tar.gz: 72562729535554e718451adb87338503ff40a81874a9e0fed6f8eaf4e6aa0edc
5
5
  SHA512:
6
- metadata.gz: 4df9dcbc8280023faa1e6c2e6a9393a9ae66e4513a95cdeae94256f5fc61f0e6691e114cd1d40a900041e1769988b2a69751f282fc95c0c134acb44cac3ed40c
7
- data.tar.gz: b72bd064835be7c5dcfcf180ff87d6e22fced3f8833d9479f607ab64760594c7d7d25d84cd828b33f0a7d72208983b8c89e26d8924e91afc81ba5e5943ef462d
6
+ metadata.gz: 0d8c3ff2861dd4bbd835e3e41826f5fd6452bdd0b40fbd8378737effdffa6da051ce221e24f4bbacaf952725ccf7da09b533c8c414a7fd10480369ae528a4259
7
+ data.tar.gz: 1790b8f38f91dfbb582a394d86953156d90351a8d724fb9535a3bc72ebac5fbbfe24e88fe10cf943e2ed91ff059af68cf581bac333f5480096f85cf6e29b8018
@@ -4,20 +4,21 @@ class FixWidthTable
4
4
  def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true)
5
5
  @filename = filename
6
6
 
7
- if update or %w(memory stringio).include?(filename.to_s.downcase) or not File.exist?(filename)
7
+ if update || %w(memory stringio).include?(filename.to_s.downcase) || ! File.exist?(filename)
8
8
  Log.debug "FixWidthTable create: #{ filename }"
9
9
  @value_size = value_size
10
10
  @range = range
11
11
  @record_size = @value_size + (@range ? 16 : 8)
12
12
  @write = true
13
13
 
14
- if %w(memory stringio).include? filename.to_s.downcase
14
+ if %w(memory stringio).include?(filename.to_s.downcase)
15
15
  @filename = :memory
16
16
  @file = StringIO.new
17
17
  else
18
18
  FileUtils.rm @filename if File.exist? @filename
19
19
  FileUtils.mkdir_p File.dirname(@filename) unless File.exist? @filename
20
- @file = File.open(@filename, 'wb')
20
+ #@file = File.open(@filename, 'wb')
21
+ @file = File.open(@filename, 'w:ASCII-8BIT')
21
22
  end
22
23
 
23
24
  @file.write [value_size].pack("L")
@@ -25,9 +26,9 @@ class FixWidthTable
25
26
 
26
27
  @size = 0
27
28
  else
28
- Log.debug "FixWidthTable up-to-date: #{ filename }"
29
+ Log.debug "FixWidthTable up-to-date: #{ filename } - (in_memory:#{in_memory})"
29
30
  if in_memory
30
- @file = StringIO.new(Open.read(@filename, :mode => 'r:ASCII-8BIT'), 'r')
31
+ @file = Open.open(@filename, :mode => 'r:ASCII-ASCII'){|f| StringIO.new f.read}
31
32
  else
32
33
  @file = File.open(@filename, 'r:ASCII-8BIT')
33
34
  end
@@ -148,13 +148,13 @@ module Persist
148
148
 
149
149
  data.write_and_read do
150
150
  yield data
151
- end
152
151
 
153
- FileUtils.mv data.persistence_path, path if File.exist? data.persistence_path and not File.exist? path
154
- tsv = CONNECTIONS[path] = CONNECTIONS.delete tmp_path
155
- tsv.persistence_path = path
152
+ FileUtils.mv data.persistence_path, path if File.exist? data.persistence_path and not File.exist? path
153
+ tsv = CONNECTIONS[path] = CONNECTIONS.delete tmp_path
154
+ tsv.persistence_path = path
156
155
 
157
- tsv.fix_io if tsv.respond_to? :fix_io
156
+ tsv.fix_io if tsv.respond_to? :fix_io
157
+ end
158
158
 
159
159
  data
160
160
  rescue Exception
@@ -9,25 +9,10 @@ module Persist
9
9
  @mutex ||= Mutex.new
10
10
  end
11
11
 
12
- def prefix(key)
13
- range(key, 1, key + MAX_CHAR, 1)
14
- end
15
-
16
- def get_prefix(key)
17
- keys = prefix(key)
18
- select(:key => keys)
19
- end
20
-
21
12
  def closed?
22
13
  @closed
23
14
  end
24
15
 
25
- def close
26
- @closed = true
27
- super
28
- self
29
- end
30
-
31
16
  def write?
32
17
  @writable
33
18
  end
@@ -47,8 +32,10 @@ module Persist
47
32
  def close(*args)
48
33
  begin
49
34
  super(*args)
35
+ @closed = true
50
36
  rescue NoMethodError
51
37
  end
38
+ self
52
39
  end
53
40
 
54
41
  def read(*args)
@@ -58,25 +45,14 @@ module Persist
58
45
  end
59
46
  end
60
47
 
61
- def collect
62
- res = []
63
- each do |key, value|
64
- res << if block_given?
65
- yield key, value
66
- else
67
- [key, value]
68
- end
69
- end
70
- res
71
- end
72
-
73
48
  def delete(key)
74
49
  out(key)
75
50
  end
76
51
 
77
52
  def lock
78
- #return yield if @locked
53
+ return yield if @locked
79
54
  lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
55
+ Log.stack caller if $LOG
80
56
  Misc.lock(lock_filename) do
81
57
  begin
82
58
  @locked = true
@@ -87,6 +63,16 @@ module Persist
87
63
  end
88
64
  end
89
65
 
66
+ def lock_and_close
67
+ lock do
68
+ begin
69
+ yield
70
+ ensure
71
+ close
72
+ end
73
+ end
74
+ end
75
+
90
76
  def write_and_read
91
77
  if write?
92
78
  begin
@@ -97,7 +83,7 @@ module Persist
97
83
  end
98
84
 
99
85
  lock do
100
- write true if closed? or not write?
86
+ write(true) if closed? || !write?
101
87
  begin
102
88
  yield
103
89
  ensure
@@ -111,12 +97,12 @@ module Persist
111
97
  begin
112
98
  return yield
113
99
  ensure
114
- close
100
+ close unless @locked
115
101
  end
116
102
  end
117
103
 
118
104
  lock do
119
- write true if closed? || ! write?
105
+ write(true) if closed? || ! write?
120
106
  res = begin
121
107
  yield
122
108
  rescue Exception
@@ -130,11 +116,12 @@ module Persist
130
116
  end
131
117
 
132
118
  def read_and_close
133
- if read?
119
+ #return yield if @locked
120
+ if read? || write?
134
121
  begin
135
122
  return yield
136
123
  ensure
137
- close
124
+ close unless @locked
138
125
  end
139
126
  end
140
127
 
@@ -148,21 +135,85 @@ module Persist
148
135
  end
149
136
  end
150
137
 
151
-
152
138
  def merge!(hash)
153
139
  hash.each do |key,values|
154
140
  self[key] = values
155
141
  end
156
142
  end
157
143
 
158
-
159
144
  def range(*args)
160
- super(*args) #- TSV::ENTRY_KEYS.to_a
145
+ self.read_and_close do
146
+ super(*args)
147
+ end
161
148
  end
162
149
 
163
150
  def include?(*args)
164
- read if closed?
165
- super(*args) #- TSV::ENTRY_KEYS.to_a
151
+ self.read_and_close do
152
+ super(*args) #- TSV::ENTRY_KEYS.to_a
153
+ end
154
+ end
155
+
156
+ def [](*args)
157
+ self.read_and_close do
158
+ super(*args) #- TSV::ENTRY_KEYS.to_a
159
+ end
160
+ end
161
+
162
+ def []=(*args)
163
+ self.write_and_close do
164
+ super(*args) #- TSV::ENTRY_KEYS.to_a
165
+ end
166
+ end
167
+
168
+ def keys(*args)
169
+ self.read_and_close do
170
+ super(*args)
171
+ end
172
+ end
173
+
174
+
175
+ def prefix(key)
176
+ self.read_and_close do
177
+ range(key, 1, key + MAX_CHAR, 1)
178
+ end
179
+ end
180
+
181
+ def get_prefix(key)
182
+ keys = prefix(key)
183
+ select(:key => keys)
184
+ end
185
+
186
+
187
+ def size(*args)
188
+ self.read_and_close do
189
+ super(*args)
190
+ end
191
+ end
192
+
193
+ def each(*args, &block)
194
+ self.read_and_close do
195
+ super(*args, &block)
196
+ end
197
+ end
198
+
199
+ def collect
200
+ res = []
201
+ each do |key, value|
202
+ res << if block_given?
203
+ yield key, value
204
+ else
205
+ [key, value]
206
+ end
207
+ end
208
+ res
209
+ end
210
+
211
+ def values_at(*keys)
212
+ self.read_and_close do
213
+ keys.collect do |k|
214
+ self[k]
215
+ end
216
+ end
166
217
  end
167
218
  end
168
219
  end
@@ -16,7 +16,7 @@ module Persist
16
16
  end
17
17
 
18
18
  dir = File.dirname(File.expand_path(path))
19
- Open.mkdir(dir) unless Open.exists?(dir)
19
+ File.mkdir(dir) unless File.exists?(dir)
20
20
 
21
21
  tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
22
22
  tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
@@ -87,13 +87,15 @@ module Persist
87
87
  def self.open_tokyocabinet(path, write, serializer = nil, tokyocabinet_class = TokyoCabinet::HDB)
88
88
  write = true unless File.exist? path
89
89
 
90
- FileUtils.mkdir_p File.dirname(path) unless Open.exist?(File.dirname(path))
90
+ FileUtils.mkdir_p File.dirname(path) unless File.exist?(File.dirname(path))
91
91
 
92
92
  database = Persist::TCAdapter.open(path, write, tokyocabinet_class)
93
93
 
94
94
  unless serializer == :clean
95
95
  TSV.setup database
96
- database.serializer = serializer || database.serializer
96
+ database.write_and_read do
97
+ database.serializer = serializer
98
+ end if serializer && database.serializer != serializer
97
99
  end
98
100
 
99
101
  database
@@ -170,10 +170,12 @@ module Resource
170
170
  if type and not File.exist?(final_path) or force
171
171
  Log.medium "Producing: #{ final_path }"
172
172
  lock_filename = Persist.persistence_path(final_path, {:dir => Resource.lock_dir})
173
+
173
174
  Misc.lock lock_filename do
174
175
  FileUtils.rm_rf final_path if force and File.exist? final_path
175
- if not File.exist?(final_path) or force
176
- (remote_server and get_from_server(path, final_path)) or
176
+
177
+ if ! File.exist?(final_path) || force
178
+
177
179
  begin
178
180
  case type
179
181
  when :string
@@ -291,7 +293,7 @@ url='#{url}'
291
293
  rescue
292
294
  FileUtils.rm_rf final_path if File.exist? final_path
293
295
  raise $!
294
- end
296
+ end unless (remote_server && get_from_server(path, final_path))
295
297
  end
296
298
  end
297
299
  end
@@ -304,11 +306,12 @@ url='#{url}'
304
306
  resource ||= Rbbt
305
307
  (Path::STANDARD_SEARCH + resource.search_order + resource.search_paths.keys).uniq.each do |name|
306
308
  pattern = resource.search_paths[name]
307
- next if patterns.nil?
309
+ next if pattern.nil?
310
+ pattern = pattern.sub('{PWD}', Dir.pwd)
308
311
  if String === pattern and pattern.include?('{')
309
312
  regexp = "^" + pattern.gsub(/{([^}]+)}/,'(?<\1>[^/]+)') + "(?:/(?<REST>.*))?/?$"
310
313
  if m = path.match(regexp)
311
- if m["PKGDIR"] == resource.pkgdir
314
+ if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == resource.pkgdir
312
315
  return self[m["TOPLEVEL"]][m["SUBPATH"]][m["REST"]]
313
316
  end
314
317
  end
@@ -199,7 +199,7 @@ module Path
199
199
  next if res
200
200
  next unless paths.include? w
201
201
  path = find(w, caller_lib, paths)
202
- res = path if File.exist? path
202
+ res = path if File.exist?(path)
203
203
  end if res.nil?
204
204
 
205
205
  (paths.keys - STANDARD_SEARCH - search_order).each do |w|
@@ -241,8 +241,8 @@ module Path
241
241
  sub('{REMOVE}/', '').
242
242
  sub('{REMOVE}', '')
243
243
 
244
- path = path + '.gz' if File.exist? path + '.gz'
245
- path = path + '.bgz' if File.exist? path + '.bgz'
244
+ path = path + '.gz' if File.exist?(path + '.gz')
245
+ path = path + '.bgz' if File.exist?(path + '.bgz')
246
246
 
247
247
  self.annotate path
248
248
 
@@ -243,7 +243,7 @@ module TSV
243
243
  end
244
244
 
245
245
  def []=(key, value, clean = false)
246
- return super(key, value) if clean or value.nil? or TSV::CleanSerializer == self.serializer_module
246
+ return super(key, value) if clean || value.nil? || TSV::CleanSerializer == self.serializer_module
247
247
  super(key, @serializer_module.dump(value))
248
248
  end
249
249
 
@@ -366,11 +366,11 @@ module TSV
366
366
  keys.length
367
367
  end
368
368
 
369
- def values_at(*keys)
370
- keys.collect do |key|
371
- self[key]
372
- end
373
- end
369
+ #def _values_at(*keys)
370
+ # keys.collect do |key|
371
+ # self[key]
372
+ # end
373
+ #end
374
374
 
375
375
  def chunked_values_at(keys, max = 5000)
376
376
  Misc.ordered_divide(keys, max).inject([]) do |acc,c|
@@ -10,7 +10,8 @@ module TSV
10
10
 
11
11
  identifiers = Organism.identifiers(tsv.namespace) if identifiers.nil? and tsv.namespace
12
12
 
13
- if not tsv.fields.include? format
13
+
14
+ if ! tsv.fields.include?(format)
14
15
  new = {}
15
16
  tsv.each do |k,v|
16
17
  if v === String or v === Array
@@ -32,6 +33,7 @@ module TSV
32
33
  tsv = tsv.attach identifiers, :fields => [format], :persist_input => true
33
34
  end
34
35
 
36
+
35
37
  tsv = tsv.reorder(format, tsv.fields[0..-2])
36
38
 
37
39
  tsv = tsv.to_flat if orig_type == :flat
@@ -89,6 +89,7 @@ module TSV
89
89
  stream
90
90
  end
91
91
 
92
+ all_fields = fields
92
93
  key_field = key_fields.compact.first
93
94
  if same_fields
94
95
  fields = fields.first
@@ -15,6 +15,14 @@ end
15
15
  class Aborted < StandardError; end
16
16
 
17
17
  class TryAgain < StandardError; end
18
+
19
+ class TryThis < StandardError
20
+ attr_accessor :payload
21
+ def initialize(payload = nil)
22
+ @payload = payload
23
+ end
24
+ end
25
+
18
26
  class SemaphoreInterrupted < TryAgain; end
19
27
  class LockInterrupted < TryAgain; end
20
28
 
@@ -18,6 +18,8 @@ module Misc
18
18
 
19
19
  BLOCK_SIZE=1024 * 8
20
20
 
21
+ SKIP_TAG="[SKIP TAG]"
22
+
21
23
  PIPE_MUTEX = Mutex.new
22
24
 
23
25
  OPEN_PIPE_IN = []
@@ -29,7 +31,7 @@ module Misc
29
31
 
30
32
  [sout, sin]
31
33
  end
32
- Log.debug{"Creating pipe #{[res.last.inspect,res.first.inspect] * " => "}"}
34
+ Log.debug{"Creating pipe #{[res.last.inspect, res.first.inspect] * " => "}"}
33
35
  res
34
36
  end
35
37
 
@@ -255,6 +257,11 @@ module Misc
255
257
  end
256
258
  tee1, *rest = Misc.tee_stream stream_dup, num + 1
257
259
  stream.reopen(tee1)
260
+
261
+ #ToDo: I can't explain why the @threads variable appears with the value of
262
+ # @filename
263
+ stream.instance_variable_set(:@threads, nil) if stream.instance_variables.include?(:@threads)
264
+
258
265
  tee1.annotate(stream)
259
266
  rest
260
267
  end
@@ -537,18 +544,29 @@ module Misc
537
544
  end
538
545
  end
539
546
 
547
+ def self.buffer_stream(stream)
548
+ sout, sin = Misc.pipe
549
+ Misc.consume_stream(stream, true, sin)
550
+ sout
551
+ end
552
+
540
553
  def self._paste_streams(streams, output, lines = nil, sep = "\t", header = nil, &block)
541
554
  output.puts header if header
542
555
  streams = streams.collect do |stream|
543
556
  if defined? Step and Step === stream
544
- stream.get_stream || stream.join.path.open
557
+ io = stream.get_stream
558
+ if io
559
+ buffer_stream(io)
560
+ else
561
+ stream.join.path.open
562
+ end
545
563
  else
546
564
  stream
547
565
  end
548
566
  end
549
567
 
550
568
  begin
551
- done_streams = []
569
+
552
570
  lines ||= streams.collect{|s| s.gets }
553
571
  keys = []
554
572
  parts = []
@@ -564,6 +582,7 @@ module Misc
564
582
  end
565
583
  sizes = parts.collect{|p| p.nil? ? 0 : p.length }
566
584
  last_min = nil
585
+
567
586
  while lines.compact.any?
568
587
  if block_given?
569
588
  min = keys.compact.sort(&block).first
@@ -571,14 +590,23 @@ module Misc
571
590
  min = keys.compact.sort.first
572
591
  end
573
592
  str = []
593
+ threads = []
574
594
  keys.each_with_index do |key,i|
575
595
  case key
576
596
  when min
577
- str << [parts[i] * sep]
597
+ if parts[i] == [SKIP_TAG]
598
+ str << [sep * (sizes[i]-1)] if sizes[i] > 0
599
+ else
600
+ str << [parts[i] * sep]
601
+ end
602
+
578
603
  line = lines[i] = streams[i].gets
579
- if line.nil?
604
+
605
+ if line.nil?
580
606
  keys[i] = nil
581
607
  parts[i] = nil
608
+ streams[i].close unless streams[i].closed?
609
+ streams[i].join if streams[i].respond_to?(:join)
582
610
  else
583
611
  k, *p = line.chomp.split(sep, -1)
584
612
  keys[i] = k
@@ -589,10 +617,12 @@ module Misc
589
617
  end
590
618
  end
591
619
 
592
- output.puts [min, str*sep] * sep
620
+ output.puts [min, str.flatten*sep] * sep
593
621
  end
622
+
594
623
  streams.each do |stream|
595
- stream.join if stream.respond_to? :join
624
+ stream.close unless stream.closed?
625
+ stream.join if stream.respond_to?(:join)
596
626
  end
597
627
  rescue
598
628
  Log.exception $!
@@ -607,7 +607,7 @@ module Workflow
607
607
  end
608
608
 
609
609
  def self.load_step(path)
610
- Path.setup(path) unless Path === path
610
+ path = Path.setup(path.dup) unless Path === path
611
611
  path = path.find
612
612
 
613
613
  begin
@@ -35,6 +35,7 @@ module Workflow
35
35
  input_use = rec_input_use(name)
36
36
  input_defaults = rec_input_defaults(name)
37
37
  input_options = rec_input_options(name)
38
+ extension = task.extension
38
39
  export = case
39
40
  when (synchronous_exports.include?(name.to_sym) or synchronous_exports.include?(name.to_s))
40
41
  :synchronous
@@ -60,7 +61,8 @@ module Workflow
60
61
  :input_use => input_use,
61
62
  :result_type => result_type,
62
63
  :result_description => result_description,
63
- :dependencies => dependencies
64
+ :dependencies => dependencies,
65
+ :extension => extension
64
66
  }
65
67
  end
66
68
  end
@@ -18,6 +18,7 @@ module Workflow
18
18
  :description => "",
19
19
  :result_type => nil,
20
20
  :result_description => "",
21
+ :resumable => false,
21
22
  :extension => nil)
22
23
 
23
24
 
@@ -33,6 +34,10 @@ module Workflow
33
34
  @extension = extension
34
35
  end
35
36
 
37
+ def resumable
38
+ @resumable = true
39
+ end
40
+
36
41
  def returns(description)
37
42
  @result_description = description
38
43
  end
@@ -118,6 +123,7 @@ module Workflow
118
123
  :input_descriptions => consume_input_descriptions,
119
124
  :required_inputs => consume_required_inputs,
120
125
  :extension => consume_extension,
126
+ :resumable => consume_resumable,
121
127
  :input_options => consume_input_options
122
128
  }
123
129
 
@@ -137,13 +137,15 @@ class RemoteWorkflow
137
137
 
138
138
  post_thread = Thread.new(Thread.current) do |parent|
139
139
  bl = lambda do |rok|
140
- if Net::HTTPOK === rok
140
+ if Net::HTTPOK === rok
141
141
  _url = rok["RBBT-STREAMING-JOB-URL"]
142
142
  @url = File.join(task_url, File.basename(_url)) if _url
143
143
  rok.read_body do |c,_a, _b|
144
144
  sin.write c
145
145
  end
146
146
  sin.close
147
+ elsif Net::HTTPSeeOther === rok
148
+ raise TryThis.new(rok)
147
149
  else
148
150
  err = StringIO.new
149
151
  rok.read_body do |c,_a, _b|
@@ -156,7 +158,7 @@ class RemoteWorkflow
156
158
  err.rewind
157
159
  err.read
158
160
  end
159
- ne = @adaptor.parse_exception text
161
+ ne = RemoteWorkflow.parse_exception text
160
162
  case ne
161
163
  when String
162
164
  parent.raise e.class, ne
@@ -173,7 +175,11 @@ class RemoteWorkflow
173
175
  end
174
176
 
175
177
  Log.debug{ "RestClient execute: #{ task_url } - #{Misc.fingerprint task_params}" }
176
- RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
178
+ begin
179
+ RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
180
+ rescue TryThis
181
+ RestClient::Request.execute(:method => :get, :url => $!.payload.header[:location], :block_response => bl)
182
+ end
177
183
  end
178
184
 
179
185
  # It seems like now response body are now decoded by Net::HTTP after 2.1
@@ -25,8 +25,13 @@ class RemoteStep < Step
25
25
  end
26
26
 
27
27
  def cache_file
28
- digest = Misc.obj2digest([base_url, task, base_name, inputs])
29
- Rbbt.var.cache.REST[[task, clean_name, digest] * "."].find
28
+ begin
29
+ digest = Misc.obj2digest([base_url, task, base_name, inputs])
30
+ Rbbt.var.cache.REST[[task, clean_name, digest].compact * "."].find
31
+ rescue
32
+ Log.exception $!
33
+ raise $!
34
+ end
30
35
  end
31
36
 
32
37
  def cache_files
@@ -62,7 +67,6 @@ class RemoteStep < Step
62
67
  no_load ? Misc.add_GET_param(path, "_format", "raw") : @result
63
68
  end
64
69
 
65
-
66
70
  def self.get_streams(inputs, stream_input = nil)
67
71
  new_inputs = {}
68
72
  inputs.each do |k,v|
@@ -240,6 +244,7 @@ class RemoteStep < Step
240
244
  return true if cache_files.any?
241
245
  init_job unless @url
242
246
  Log.debug{ "Joining RemoteStep: #{path}" }
247
+
243
248
  if IO === @result
244
249
  res = @result
245
250
  @result = nil
@@ -253,6 +258,7 @@ class RemoteStep < Step
253
258
  sleep 1 unless self.done? || self.aborted? || self.error?
254
259
  while not (self.done? || self.aborted? || self.error?)
255
260
  sleep 3
261
+ iif [self.done?, self.status, self.info]
256
262
  end
257
263
  end
258
264
 
@@ -129,7 +129,7 @@ class RemoteStep
129
129
  end
130
130
  end
131
131
 
132
- def _run_job(cache_type = :async)
132
+ def _run_job(cache_type = :asynchronous)
133
133
  get_streams
134
134
 
135
135
  task_url = URI.encode(File.join(base_url, task.to_s))
@@ -142,7 +142,13 @@ class RemoteStep
142
142
  else
143
143
  @adaptor.execute_job(base_url, task, task_params, cache_type)
144
144
  end
145
+ end
146
+
145
147
 
148
+ def produce(*args)
149
+ @started = true
150
+ _run_job
146
151
  end
152
+
147
153
  end
148
154
  end
@@ -612,6 +612,10 @@ class Step
612
612
  provenance
613
613
  end
614
614
 
615
+ def resumable?
616
+ task && task.resumable
617
+ end
618
+
615
619
  def config(key, *tokens)
616
620
  options = tokens.pop if Hash === tokens.last
617
621
  options ||= {}
@@ -92,7 +92,7 @@ class Step
92
92
  (job.done? && job.dirty?) || (job.error? && job.dirty?) ||
93
93
  (!(job.noinfo? || job.done? || job.error? || job.aborted? || job.running?))
94
94
 
95
- job.clean
95
+ job.clean unless job.resumable? && (job.updated? && ! job.dirty?)
96
96
  job.set_info :status, :cleaned
97
97
  end
98
98
 
@@ -144,14 +144,18 @@ class Step
144
144
 
145
145
  dependency.status_lock.synchronize do
146
146
  if dependency.aborted? || (dependency.error? && dependency.recoverable_error? && ! canfail_paths.include?(dependency.path) && ! already_failed.include?(dependency.path)) || (!Open.remote?(dependency.path) && dependency.missing?)
147
- Log.warn "Cleaning dep. on exec #{Log.color :blue, dependency.path} (missing: #{dependency.missing?}; error #{dependency.error?})"
148
- dependency.clean
149
- already_failed << dependency.path
150
- raise TryAgain
147
+ if dependency.resumable?
148
+ dependency.status = :resume
149
+ else
150
+ Log.warn "Cleaning dep. on exec #{Log.color :blue, dependency.path} (missing: #{dependency.missing?}; error #{dependency.error?})"
151
+ dependency.clean
152
+ already_failed << dependency.path
153
+ raise TryAgain
154
+ end
151
155
  end
152
156
  end
153
157
 
154
- if ! (dependency.started? || dependency.error?)
158
+ if dependency.status == :resume || ! (dependency.started? || dependency.error?)
155
159
  log_dependency_exec(dependency, :starting)
156
160
  dependency.run(true)
157
161
  raise TryAgain
@@ -362,7 +366,7 @@ class Step
362
366
  (step.dependencies + step.input_dependencies).each do |step_dep|
363
367
  next if step_dep.done? or step_dep.running? or (ComputeDependency === step_dep and (step_dep.compute == :nodup or step_dep.compute == :ignore))
364
368
  dep_step[step_dep.path] ||= []
365
- dep_step[step_dep.path] << step_dep
369
+ dep_step[step_dep.path] << step
366
370
  end
367
371
  end
368
372
 
@@ -610,7 +610,7 @@ class Step
610
610
  end
611
611
 
612
612
  def _clean_finished
613
- if Open.exists? path and not status == :done
613
+ if Open.exists?(path) && status != :done
614
614
  Log.warn "Aborted job had finished. Removing result -- #{ path }"
615
615
  begin
616
616
  Open.rm path
@@ -2,7 +2,7 @@ require 'rbbt/util/misc'
2
2
  require 'rbbt/persist'
3
3
 
4
4
  module Task
5
- attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :required_inputs, :description, :name, :result_description, :extension, :workflow
5
+ attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :required_inputs, :description, :name, :result_description, :extension, :workflow, :resumable
6
6
 
7
7
  def self.setup(options = {}, &block)
8
8
  block.extend Task
@@ -125,6 +125,7 @@ class Step
125
125
  def self.migrate(path, search_path, options = {})
126
126
  resource=Rbbt
127
127
 
128
+ orig_path = path
128
129
  other_rsync_args = options[:rsync]
129
130
 
130
131
  recursive = options[:recursive]
@@ -154,6 +155,7 @@ puts files * "\n"
154
155
  else
155
156
  if File.exists?(path)
156
157
  path = resource.identify(path)
158
+ raise "Resource #{resource} could not identify #{orig_path}" if path.nil?
157
159
  else
158
160
  path = Path.setup(path)
159
161
  end
@@ -178,7 +180,7 @@ puts resource[path].find(search_path)
178
180
  subpath_files = {}
179
181
  paths.sort.each do |path|
180
182
  parts = path.split("/")
181
- subpath = parts[0..-4] * "/"
183
+ subpath = parts[0..-4] * "/" + "/"
182
184
 
183
185
  if subpath_files.keys.any? && subpath.start_with?(subpath_files.keys.last)
184
186
  subpath = subpath_files.keys.last
@@ -190,6 +192,7 @@ puts resource[path].find(search_path)
190
192
  subpath_files[subpath] << source
191
193
  end
192
194
 
195
+ synced_files = []
193
196
  subpath_files.each do |subpath, files|
194
197
  if options[:target]
195
198
  CMD.cmd("ssh #{options[:target]} mkdir -p '#{File.dirname(target)}'")
@@ -204,11 +207,15 @@ puts resource[path].find(search_path)
204
207
  end
205
208
  target = [options[:target], target] * ":" if options[:target]
206
209
 
210
+ next if File.exists?(source) && File.exists?(target) && File.expand_path(source) == File.expand_path(target)
211
+
207
212
  files_and_dirs = Set.new( files )
208
213
  files.each do |file|
214
+ synced_files << File.join(subpath, file)
215
+
209
216
  parts = file.split("/")[0..-2].reject{|p| p.empty?}
210
217
  while parts.any?
211
- files_and_dirs << parts * "/"
218
+ files_and_dirs << parts * "/"
212
219
  parts.pop
213
220
  end
214
221
  end
@@ -218,8 +225,7 @@ puts resource[path].find(search_path)
218
225
 
219
226
  cmd = "rsync #{MAIN_RSYNC_ARGS} --progress #{test_str} --files-from='#{tmp_include_file}' #{source}/ #{target}/ #{other_rsync_args}"
220
227
 
221
- cmd << " && rm -Rf #{source}" if options[:delete]
222
-
228
+ #cmd << " && rm -Rf #{source}" if options[:delete]
223
229
  if options[:print]
224
230
  ppp Open.read(tmp_include_file)
225
231
  puts cmd
@@ -228,6 +234,26 @@ puts resource[path].find(search_path)
228
234
  end
229
235
  end
230
236
  end
237
+
238
+ if options[:delete] && synced_files.any?
239
+ puts Log.color :magenta, "About to erase these files:"
240
+ synced_files.each do |p|
241
+ puts Log.color :red, p
242
+ end
243
+
244
+ if options[:non_interactive]
245
+ response = 'yes'
246
+ else
247
+ puts Log.color :magenta, "Type 'yes' if you are sure:"
248
+ response = STDIN.gets.chomp
249
+ end
250
+
251
+ if response == 'yes'
252
+ synced_files.each do |p|
253
+ Open.rm p
254
+ end
255
+ end
256
+ end
231
257
  end
232
258
 
233
259
  def self.purge(path, recursive = false)
@@ -71,7 +71,7 @@ get_pkg(){
71
71
  local url="$2"
72
72
 
73
73
  if [ ! -f "$OPT_SRC_DIR/$name.pkg" ]; then
74
- wget "$url" -O "$OPT_SRC_DIR/$name.pkg" || wget "$url" -O "$OPT_SRC_DIR/$name.pkg" --no-check-certificate
74
+ wget "$url" -O "$OPT_SRC_DIR/$name.pkg" || wget "$url" -O "$OPT_SRC_DIR/$name.pkg" --no-check-certificate || (rm -f "$OPT_SRC_DIR/$name.pkg"; echo "Error downloading"; exit -1)
75
75
  fi
76
76
  }
77
77
 
@@ -85,7 +85,7 @@ uncompress_pkg(){
85
85
  mkdir -p "$OPT_BUILD_DIR"
86
86
  cd "$OPT_BUILD_DIR"
87
87
 
88
- (tar xvfz $pkg || tar xvfJ $pkg || tar xvfj $pkg || unzip $pkg || echo "Error decompressing") 2> /dev/null
88
+ (tar xvfz $pkg || tar xvfJ $pkg || tar xvfj $pkg || unzip $pkg || (echo "Error decompressing" & cd & rmdir "$OPT_BUILD_DIR" & exit -1 ) ) 2> /dev/null
89
89
 
90
90
  cd "$old_pwd"
91
91
  }
@@ -207,6 +207,8 @@ prepare_make(){
207
207
 
208
208
  [ -d src -a ! -e CMakeLists.txt -a ! -e Makefile -a ! -e configure ] && cd src
209
209
 
210
+ [ -f bootstrap ] && (./bootstrap || exit -1)
211
+
210
212
  if [ -f config/m4 ]; then
211
213
  libtoolize --force
212
214
  aclocal
@@ -275,6 +277,8 @@ build_make(){
275
277
  setup "$name"
276
278
  clean_build
277
279
  fi
280
+
281
+ cd "$old_pwd"
278
282
  }
279
283
 
280
284
  buid_cmake(){
@@ -489,7 +493,7 @@ install_jar(){
489
493
  local url="$2"
490
494
 
491
495
  [ -d "$OPT_DIR/$name/" ] || mkdir -p "$OPT_DIR/$name/"
492
- wget "$url" -O "$OPT_DIR/$name/$name.jar" --no-check-certificate
496
+ wget "$url" -O "$OPT_DIR/jars/$name.jar" || wget "$url" -O "$OPT_DIR/jars/$name.jar" --no-check-certificate || (rm "$OPT_DIR/jars/$name.jar"; exit -1)
493
497
  link "$OPT_DIR/$name/$name.jar" "$OPT_JAR_DIR/$name.jar"
494
498
  }
495
499
 
@@ -3,7 +3,7 @@
3
3
  require 'rbbt-util'
4
4
  require 'rbbt/util/simpleopt'
5
5
  require 'rbbt/workflow'
6
- require 'rbbt/workflow/remote/ssh/get'
6
+ require 'rbbt/workflow/remote_workflow'
7
7
 
8
8
  $0 = "rbbt #{$previous_commands*""} #{ File.basename(__FILE__) }" if $previous_commands
9
9
 
@@ -34,4 +34,6 @@ end
34
34
 
35
35
  path, search_path, _sep, *other = ARGV
36
36
 
37
+ search_path = 'user' if search_path.nil?
38
+
37
39
  Step.migrate(path, search_path, options)
@@ -187,7 +187,7 @@ workflows.sort.each do |workflow,tasks|
187
187
  if info_fields and info_fields.any?
188
188
  info = begin
189
189
  Open.open(i[:info_file]) do |f|
190
- Step::INFO_SERIALIAZER.load(f)
190
+ Step::INFO_SERIALIZER.load(f)
191
191
  end
192
192
  rescue
193
193
  {:status => :noinfo}
@@ -198,9 +198,10 @@ workflows.sort.each do |workflow,tasks|
198
198
  else
199
199
  info = begin
200
200
  Open.open(i[:info_file]) do |f|
201
- Step::INFO_SERIALIAZER.load(f)
201
+ Step::INFO_SERIALIZER.load(f)
202
202
  end
203
203
  rescue
204
+ Log.exception $!
204
205
  {:status => :noinfo}
205
206
  end
206
207
  IndiferentHash.setup(info)
@@ -41,7 +41,7 @@ def list_jobs(options)
41
41
  clean_file = file.sub('.info','')
42
42
  begin
43
43
  next if File.exist? clean_file and $quick
44
- info = Step::INFO_SERIALIAZER.load(Open.read(file, :mode => 'rb'))
44
+ info = Step::INFO_SERIALIZER.load(Open.read(file, :mode => 'rb'))
45
45
  next if (File.exist?(clean_file) or info[:status] == :done) and (info[:children_pids].nil? or info[:children_done] or info[:children_pids].select{|pid| Misc.pid_exists? pid}.empty?)
46
46
  rescue Exception
47
47
  puts "Error parsing info file: #{ file }"
@@ -86,7 +86,7 @@ def clean_jobs(options)
86
86
  info = nil
87
87
  next if File.exist? clean_file
88
88
  begin
89
- info = Step::INFO_SERIALIAZER.load(Open.read(file, :mode => 'rb'))
89
+ info = Step::INFO_SERIALIZER.load(Open.read(file, :mode => 'rb'))
90
90
  rescue Exception
91
91
  Log.debug "Error process #{ file }"
92
92
  remove_job file if options[:errors]
@@ -117,7 +117,7 @@ begin
117
117
  end
118
118
  else
119
119
  if options[:file]
120
- info = Step::INFO_SERIALIAZER.load(Open.read(options[:file], :mode => 'rb'))
120
+ info = Step::INFO_SERIALIZER.load(Open.read(options[:file], :mode => 'rb'))
121
121
  print_job options[:file], info
122
122
  else
123
123
  list_jobs options
@@ -4,6 +4,7 @@ require 'rbbt/tsv/stream'
4
4
  require 'rbbt'
5
5
 
6
6
  class TestStream < Test::Unit::TestCase
7
+
7
8
  def test_collapse_stream
8
9
  text=<<-EOF
9
10
  #: :sep=" "
@@ -65,7 +66,7 @@ row3 AAA BBB CCC
65
66
 
66
67
  text2=<<-EOF
67
68
  #: :sep=" "
68
- #Row Labela Labelb
69
+ #Row Labela Labelb
69
70
  row1 a b
70
71
  row3 aaa bbb
71
72
  row2 aa bb
@@ -100,7 +101,7 @@ row1 A B C
100
101
 
101
102
  text2=<<-EOF
102
103
  #: :sep=" "
103
- #Row Labela Labelb
104
+ #Row Labela Labelb
104
105
  row2 aa bb
105
106
  EOF
106
107
 
@@ -132,7 +133,7 @@ row1 A B C
132
133
 
133
134
  text2=<<-EOF
134
135
  #: :sep=" "
135
- #Row Labela Labelb
136
+ #Row Labela Labelb
136
137
  row2 aa bb
137
138
  EOF
138
139
 
@@ -285,7 +285,7 @@ line4
285
285
  begin
286
286
  Misc.consume_stream(sio, false, STDOUT)
287
287
  rescue
288
- Log.exception $!
288
+ raise $!
289
289
  end
290
290
  end
291
291
  end
@@ -4,6 +4,27 @@ require 'rbbt/workflow'
4
4
  module DepWorkflow
5
5
  extend Workflow
6
6
 
7
+ input :input_file, :file, "Input file", nil, :stream => true
8
+ task :s1 => :array do |input_file|
9
+ TSV.traverse input_file, :type => :array, :into => :stream, :bar => "Task1" do |line|
10
+ line + "\t" << "Task1"
11
+ end
12
+ end
13
+
14
+ dep :s1
15
+ task :s2 => :array do |input_file|
16
+ TSV.traverse step(:s1), :type => :array, :into => :stream, :bar => "Task2" do |line|
17
+ next [line.split("\t").first, Misc::SKIP_TAG] * "\t" if rand < 0.9
18
+ line + "\t" << "Task2"
19
+ end
20
+ end
21
+
22
+ dep :s1
23
+ dep :s2
24
+ task :s3 => :array do |input_file|
25
+ Misc.paste_streams(dependencies.reverse)
26
+ end
27
+
7
28
  input :input_file, :file, "Input file", nil, :stream => true
8
29
  task :task1 => :array do |input_file|
9
30
  TSV.traverse input_file, :type => :array, :into => :stream, :bar => "Task1" do |line|
@@ -28,9 +49,7 @@ module DepWorkflow
28
49
  dep :task2
29
50
  dep :task3
30
51
  task :task4 => :array do
31
- s1 = TSV.get_stream step(:task2)
32
- s2 = TSV.get_stream step(:task3)
33
- Misc.paste_streams([s1, s2])
52
+ Misc.paste_streams(dependencies)
34
53
  end
35
54
 
36
55
  dep :task4
@@ -43,9 +62,7 @@ module DepWorkflow
43
62
  dep :task2
44
63
  dep :task5
45
64
  task :task6 => :array do
46
- s1 = TSV.get_stream step(:task2)
47
- s2 = TSV.get_stream step(:task5)
48
- Misc.paste_streams([s1, s2])
65
+ Misc.paste_streams(dependencies)
49
66
  end
50
67
 
51
68
  input :stream_file, :file, "Streamed file", nil, :stream => true
@@ -81,6 +98,26 @@ module ComputeWorkflow
81
98
 
82
99
  end
83
100
 
101
+ module ResumeWorkflow
102
+ extend Workflow
103
+
104
+ resumable
105
+ task :resume => :string do
106
+ if file('foo').exists?
107
+ 'done'
108
+ else
109
+ Open.mkdir files_dir
110
+ Open.touch(file('foo'))
111
+ raise
112
+ end
113
+ end
114
+
115
+ dep :resume
116
+ task :reverse => :string do
117
+ step(:resume).load.reverse
118
+ end
119
+ end
120
+
84
121
  class TestWorkflowDependency < Test::Unit::TestCase
85
122
  def test_task1
86
123
  size = 10000
@@ -114,8 +151,25 @@ class TestWorkflowDependency < Test::Unit::TestCase
114
151
  end
115
152
  end
116
153
 
154
+ def test_task3
155
+ size = 100000
156
+ content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
157
+ TmpFile.with_file(content) do |input_file|
158
+ job = DepWorkflow.job(:task3, "TEST", :input_file => input_file)
159
+ io = TSV.get_stream job.run(:stream)
160
+ last_line = nil
161
+ while line = io.gets
162
+ last_line = line.strip
163
+ end
164
+ io.join
165
+
166
+ assert_equal "Line #{size}\tTask1\tTask3", last_line
167
+ end
168
+ end
169
+
117
170
  def test_task4
118
- size = 1000
171
+ size = 100000
172
+ Log.severity = 0
119
173
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
120
174
  last_line = nil
121
175
  TmpFile.with_file(content) do |input_file|
@@ -131,7 +185,7 @@ class TestWorkflowDependency < Test::Unit::TestCase
131
185
  end
132
186
 
133
187
  def test_task5
134
- size = 1000
188
+ size = 10000
135
189
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
136
190
  last_line = nil
137
191
  TmpFile.with_file(content) do |input_file|
@@ -145,20 +199,44 @@ class TestWorkflowDependency < Test::Unit::TestCase
145
199
  assert_equal "Line #{size}\tTask1\tTask2\tTask1\tTask3\tTask5", last_line
146
200
  end
147
201
 
148
- def test_task6
202
+ def test_s3
149
203
  size = 100000
150
- content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
204
+ content = (1..size).to_a.collect{|num| "Line #{num}" } * "\n"
151
205
  last_line = nil
152
206
  Log.severity = 0
153
207
  TmpFile.with_file(content) do |input_file|
154
208
  begin
155
- job = DepWorkflow.job(:task6, "TEST", :input_file => input_file)
156
- job.run(:stream)
157
- io = TSV.get_stream job
158
- while line = io.gets
159
- last_line = line.strip
209
+ job = DepWorkflow.job(:s3, "TEST", :input_file => input_file)
210
+ job.recursive_clean
211
+ job.run(:stream)
212
+ io = TSV.get_stream job
213
+ while line = io.gets
214
+ last_line = line.strip
215
+ end
216
+ io.join if io.respond_to? :join
217
+ rescue Exception
218
+ job.abort
219
+ raise $!
160
220
  end
161
- io.join
221
+ end
222
+ assert last_line.include? "Line #{size}"
223
+ end
224
+
225
+ def test_task6
226
+ size = 100000
227
+ content = (1..size).to_a.collect{|num| "Line #{num}" } * "\n"
228
+ last_line = nil
229
+ Log.severity = 0
230
+ TmpFile.with_file(content) do |input_file|
231
+ begin
232
+ job = DepWorkflow.job(:task6, "TEST", :input_file => input_file)
233
+ job.recursive_clean
234
+ job.run(:stream)
235
+ io = TSV.get_stream job
236
+ while line = io.gets
237
+ last_line = line.strip
238
+ end
239
+ io.join
162
240
  rescue Exception
163
241
  job.abort
164
242
  raise $!
@@ -168,7 +246,7 @@ class TestWorkflowDependency < Test::Unit::TestCase
168
246
  end
169
247
 
170
248
  def test_task8
171
- size = 100000
249
+ size = 10000
172
250
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
173
251
  last_line = nil
174
252
  Log.severity = 0
@@ -204,5 +282,16 @@ class TestWorkflowDependency < Test::Unit::TestCase
204
282
  assert_equal "Line #{size}\tTask1\tTask2", last_line
205
283
  end
206
284
  end
285
+
286
+ def test_resume
287
+ Log.severity = 0
288
+ job = ResumeWorkflow.job(:reverse)
289
+ job.recursive_clean
290
+ assert_raise do
291
+ job.run
292
+ end
293
+ assert job.dependencies.first.file('foo').exists?
294
+ assert_equal 'done'.reverse, job.run
295
+ end
207
296
  end
208
297
 
@@ -61,6 +61,18 @@ class TestRemoteWorkflow < Test::Unit::TestCase
61
61
  def test_rest
62
62
  Log.with_severity 0 do
63
63
 
64
+ remote_workflow_server(TestWFRest) do |client|
65
+ job = client.job(:hi, nil, {})
66
+ job.clean
67
+ job = client.job(:hi, nil, {})
68
+ assert ! job.done?
69
+ job.run
70
+ job.produce
71
+ job = client.job(:hi, nil, {})
72
+ assert job.done?
73
+ sleep 1
74
+ end
75
+
64
76
  remote_workflow_server(TestWFRest) do |client|
65
77
  assert_equal "Hello World", client.job(:hi, nil, {}).run.chomp
66
78
  assert_equal "Hello Miguel", client.job(:hi, nil, {:name => :Miguel}).run.chomp
@@ -78,7 +90,7 @@ class TestRemoteWorkflow < Test::Unit::TestCase
78
90
 
79
91
  def _test_ssh
80
92
  Log.severity = 0
81
- client = RemoteWorkflow.new "ssh://turbo:Translation", "Translation"
93
+ client = RemoteWorkflow.new "ssh://#{ENV["HOSTNAME"]}:Translation", "Translation"
82
94
  job = client.job("translate", "SSH-TEST-1", :genes => ["TP53","KRAS"])
83
95
  assert_equal 2, job.run.select{|l| l =~ /ENSG/}.length
84
96
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbbt-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.27.2
4
+ version: 5.27.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-29 00:00:00.000000000 Z
11
+ date: 2020-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake