rbbt-util 5.28.10 → 5.29.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,12 +26,17 @@ module Persist
26
26
  MAX_FILE_LENGTH = 150
27
27
 
28
28
  # Is 'file' newer than 'path'? return non-true if path is newer than file
29
- def self.newer?(path, file)
29
+ def self.newer?(path, file, by_link = false)
30
30
  return true if not Open.exists?(file)
31
31
  path = path.find if Path === path
32
32
  file = file.find if Path === file
33
- patht = Open.mtime(path)
34
- filet = Open.mtime(file)
33
+ if by_link
34
+ patht = File.exists?(path) ? File.lstat(path).mtime : nil
35
+ filet = File.exists?(file) ? File.lstat(file).mtime : nil
36
+ else
37
+ patht = Open.mtime(path)
38
+ filet = Open.mtime(file)
39
+ end
35
40
  return true if patht.nil? || filet.nil?
36
41
  diff = patht - filet
37
42
  return diff if diff < 0
@@ -112,13 +112,19 @@ module Resource
112
112
  end
113
113
  when Net::HTTPRedirection, Net::HTTPFound
114
114
  location = response['location']
115
- Log.debug("Feching directory from: #{location}. Into: #{final_path}")
116
- FileUtils.mkdir_p final_path unless File.exist? final_path
117
- TmpFile.with_file do |tmp_dir|
118
- Misc.in_dir tmp_dir do
119
- CMD.cmd('tar xvfz -', :in => Open.open(location, :nocache => true))
115
+ if location.include? 'get_directory'
116
+ Log.debug("Feching directory from: #{location}. Into: #{final_path}")
117
+ FileUtils.mkdir_p final_path unless File.exist? final_path
118
+ TmpFile.with_file do |tmp_dir|
119
+ Misc.in_dir tmp_dir do
120
+ CMD.cmd('tar xvfz -', :in => Open.open(location, :nocache => true))
121
+ end
122
+ FileUtils.mv tmp_dir, final_path
123
+ end
124
+ else
125
+ Open.open(location, :nocache => true) do |s|
126
+ Misc.sensiblewrite(final_path, s)
120
127
  end
121
- FileUtils.mv tmp_dir, final_path
122
128
  end
123
129
  when Net::HTTPInternalServerError
124
130
  @server_missing_resource_cache << url
@@ -297,7 +297,7 @@ module Path
297
297
 
298
298
  raise "No resource defined to produce file: #{ self }" if resource.nil?
299
299
 
300
- resource.produce self, force
300
+ resource.produce self, force if Resource === resource
301
301
 
302
302
  self
303
303
  end
@@ -243,6 +243,7 @@ module TSV
243
243
  Log.debug("Attachment of fields:#{Misc.fingerprint fields } from #{other.filename.inspect} finished.")
244
244
 
245
245
  if complete
246
+ Log.warn "Attaching through index and completing empty rows; keys with wrong format may appear (#{other.key_field} insted of #{self.key_field})" if index
246
247
  fill = TrueClass === complete ? nil : complete
247
248
  field_length = self.fields.length
248
249
  common_fields = (other.fields & self.fields)
@@ -255,11 +256,11 @@ module TSV
255
256
  case type
256
257
  when :single
257
258
  missing.each do |k|
258
- self[k] = nil
259
+ self[k] = fill
259
260
  end
260
261
  when :list
261
262
  missing.each do |k|
262
- values = [nil] * field_length
263
+ values = [fill] * field_length
263
264
  other_values = other[k]
264
265
  other_common_pos.zip(this_common_pos).each do |o,t|
265
266
  values[t] = other_values[o]
@@ -267,8 +268,9 @@ module TSV
267
268
  self[k] = values
268
269
  end
269
270
  when :double
271
+ fill = [] if fill.nil?
270
272
  missing.each do |k|
271
- values = [[]] * field_length
273
+ values = [fill] * field_length
272
274
  other_values = other[k]
273
275
  other_common_pos.zip(this_common_pos).each do |o,t|
274
276
  values[t] = other_values[o]
@@ -276,8 +278,9 @@ module TSV
276
278
  self[k] = values
277
279
  end
278
280
  when :flat
281
+ fill = [] if fill.nil?
279
282
  missing.each do |k|
280
- self[k] = []
283
+ self[k] = fill
281
284
  end
282
285
  end
283
286
  end
@@ -2,6 +2,3 @@ require 'rbbt/util/concurrency'
2
2
 
3
3
  require 'rbbt/tsv/parallel/through'
4
4
  require 'rbbt/tsv/parallel/traverse'
5
-
6
- module TSV
7
- end
@@ -41,7 +41,7 @@ source('#{UTIL}');
41
41
 
42
42
  if monitor
43
43
  #io = CMD.cmd('R --no-save --quiet', options.merge(:in => cmd, :pipe => true, :log => true))
44
- io = CMD.cmd('R --no-save --quiet', options.merge(:in => cmd, :pipe => true, :log => true))
44
+ io = CMD.cmd('R --no-save --quiet', options.merge(:in => cmd, :pipe => true, :log => true, :xvfb => true))
45
45
  while line = io.gets
46
46
  case monitor
47
47
  when Proc
@@ -52,7 +52,7 @@ source('#{UTIL}');
52
52
  end
53
53
  nil
54
54
  else
55
- CMD.cmd('R --no-save --slave --quiet', options.merge(:in => cmd))
55
+ CMD.cmd('R --no-save --slave --quiet', options.merge(:in => cmd, :xvfb => true))
56
56
  end
57
57
  end
58
58
 
@@ -100,6 +100,7 @@ module CMD
100
100
  no_fail = options.delete(:no_fail)
101
101
  no_fail = options.delete(:nofail) if no_fail.nil?
102
102
  no_wait = options.delete(:no_wait)
103
+ xvfb = options.delete(:xvfb)
103
104
 
104
105
  dont_close_in = options.delete(:dont_close_in)
105
106
 
@@ -117,6 +118,14 @@ module CMD
117
118
 
118
119
  end
119
120
 
121
+ case xvfb
122
+ when TrueClass
123
+ cmd = "xvfb-run --server-args='-screen 0 1024x768x24' --auto-servernum #{cmd}"
124
+ when String
125
+ cmd = "xvfb-run --server-args='#{xvfb}' --auto-servernum --server-num=1 #{cmd}"
126
+ when String
127
+ end
128
+
120
129
  if stderr == true
121
130
  stderr = Log::HIGH
122
131
  end
@@ -61,6 +61,14 @@ module IndiferentHash
61
61
  super(key)
62
62
  end
63
63
  end
64
+
65
+ def clean_version
66
+ clean = {}
67
+ each do |k,v|
68
+ clean[k.to_s] = v unless clean.include? k.to_s
69
+ end
70
+ clean
71
+ end
64
72
  end
65
73
 
66
74
  module CaseInsensitiveHash
@@ -287,15 +287,21 @@ module Misc
287
287
  when Symbol
288
288
  obj.to_s
289
289
  when (defined?(Path) and Path)
290
- if obj.exists?
291
- if obj.directory?
292
- files = obj.glob("**/*")
293
- "directory: #{Misc.fingerprint(files)}"
290
+ if defined?(Step) && Open.exists?(Step.info_file(obj))
291
+ obj2str(Workflow.load_step(obj))
292
+ elsif defined?(Step) && Step === obj.resource
293
+ "Step file: " + obj
294
+ else
295
+ if obj.exists?
296
+ if obj.directory?
297
+ files = obj.glob("**/*")
298
+ "directory: #{Misc.fingerprint(files)}"
299
+ else
300
+ "file: " << Open.realpath(obj) << "--" << mtime_str(obj)
301
+ end
294
302
  else
295
- "file: " << Open.realpath(obj) << "--" << mtime_str(obj)
303
+ obj + " (file missing)"
296
304
  end
297
- else
298
- obj + " (file missing)"
299
305
  end
300
306
  when String
301
307
  if Misc.is_filename?(obj) and ! %w(. ..).include?(obj)
@@ -318,7 +324,11 @@ module Misc
318
324
  remove_long_items(obj)
319
325
  when File
320
326
  if obj.respond_to? :filename and obj.filename
321
- "<IO:" << obj.filename << "--" << mtime_str(obj.filename) << ">"
327
+ if defined?(Step) && Open.exists?(Step.info_file(obj.filename))
328
+ obj2str(Workflow.load_step(obj.filename))
329
+ else
330
+ "<IO:" << obj.filename << "--" << mtime_str(obj.filename) << ">"
331
+ end
322
332
  else
323
333
  "<IO:" << obj.path << "--" << mtime_str(obj.path) << ">"
324
334
  end
@@ -326,7 +336,11 @@ module Misc
326
336
  "<IO:" << obj.short_path << ">"
327
337
  when IO
328
338
  if obj.respond_to? :filename and obj.filename
329
- "<IO:" << obj.filename << "--" << mtime_str(obj.filename) << ">"
339
+ if defined?(Step) && Open.exists?(Step.info_file(obj.filename))
340
+ obj2str(Workflow.load_step(obj.filename))
341
+ else
342
+ "<IO:" << obj.filename << "--" << mtime_str(obj.filename) << ">"
343
+ end
330
344
  else
331
345
 
332
346
  if obj.respond_to? :obj2str
@@ -385,7 +385,7 @@ module Workflow
385
385
  next if default == v
386
386
  next if (String === default and Symbol === v and v.to_s == default)
387
387
  next if (Symbol === default and String === v and v == default.to_s)
388
- real_inputs[k] = v
388
+ real_inputs[k.to_sym] = v
389
389
  end
390
390
 
391
391
  jobname_input_value = inputs[jobname_input] || all_defaults[jobname_input]
@@ -410,6 +410,7 @@ module Workflow
410
410
  job.workflow = self
411
411
  job.clean_name = jobname
412
412
  job.overriden = overriden
413
+ job.real_inputs = real_inputs.keys
413
414
  job
414
415
  end
415
416
 
@@ -16,6 +16,10 @@ end
16
16
 
17
17
  module Workflow
18
18
 
19
+ def self.job_path?(path)
20
+ path.split("/")[-4] == "jobs"
21
+ end
22
+
19
23
  def log(status, message = nil, &block)
20
24
  Step.log(status, message, nil, &block)
21
25
  end
@@ -301,7 +305,9 @@ module Workflow
301
305
 
302
306
  def setup_override_dependency(dep, workflow, task_name)
303
307
  dep = Step === dep ? dep : Workflow.load_step(dep)
308
+ dep.workflow = workflow
304
309
  dep.info[:name] = dep.name
310
+ dep.original_task_name ||= dep.task_name if dep.workflow
305
311
  begin
306
312
  workflow = Kernel.const_get workflow if String === workflow
307
313
  dep.task = workflow.tasks[task_name] if dep.task.nil? && workflow.tasks.include?(task_name)
@@ -309,7 +315,7 @@ module Workflow
309
315
  Log.exception $!
310
316
  end
311
317
  dep.task_name = task_name
312
- dep.overriden = true
318
+ dep.overriden = dep.original_task_name.to_sym
313
319
  dep
314
320
  end
315
321
 
@@ -360,7 +366,7 @@ module Workflow
360
366
  compute = options[:compute]
361
367
 
362
368
  options = IndiferentHash.setup(options.dup)
363
- dep = dependency.call jobname, options.merge(_inputs), real_dependencies
369
+ dep = dependency.call jobname, _inputs.merge(options), real_dependencies
364
370
 
365
371
  dep = [dep] unless Array === dep
366
372
 
@@ -77,6 +77,7 @@ module Workflow
77
77
  task name do
78
78
  raise RbbtException, "dependency not found in dep_task" if dependencies.empty?
79
79
  dep = dependencies.last.join
80
+ raise dep.get_exception if dep.error?
80
81
  set_info :result_type, dep.info[:result_type]
81
82
  forget = config :forget_dep_tasks, :forget_dep_tasks, :default => FORGET_DEP_TASKS
82
83
  if forget
@@ -50,8 +50,8 @@ module Workflow
50
50
  case input_types[input]
51
51
  when :file
52
52
  Log.debug "Pointing #{ input } to #{file}"
53
- if file =~ /\.read$/
54
- inputs[input.to_sym] = Open.read(file)
53
+ if file =~ /\.yaml/
54
+ inputs[input.to_sym] = YAML.load(Open.read(file))
55
55
  else
56
56
  inputs[input.to_sym] = Open.realpath(file)
57
57
  end
@@ -12,6 +12,9 @@ class Step
12
12
  attr_accessor :exec
13
13
  attr_accessor :relocated
14
14
  attr_accessor :result, :mutex, :seen
15
+ attr_accessor :real_inputs, :original_task_name
16
+
17
+ RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
15
18
 
16
19
  class << self
17
20
  attr_accessor :lock_dir
@@ -143,11 +146,13 @@ class Step
143
146
  seen = []
144
147
  while path = deps.pop
145
148
  dep_info = archived_info[path]
146
- dep_info[:inputs].each do |k,v|
147
- all_inputs[k] = v unless all_inputs.include?(k)
148
- end if dep_info[:inputs]
149
- deps.concat(dep_info[:dependencies].collect{|p| p.last } - seen) if dep_info[:dependencies]
150
- deps.concat(dep_info[:archived_dependencies].collect{|p| p.last } - seen) if dep_info[:archived_dependencies]
149
+ if dep_info
150
+ dep_info[:inputs].each do |k,v|
151
+ all_inputs[k] = v unless all_inputs.include?(k)
152
+ end if dep_info[:inputs]
153
+ deps.concat(dep_info[:dependencies].collect{|p| p.last } - seen) if dep_info[:dependencies]
154
+ deps.concat(dep_info[:archived_dependencies].collect{|p| p.last } - seen) if dep_info[:archived_dependencies]
155
+ end
151
156
  seen << path
152
157
  end
153
158
 
@@ -156,7 +161,7 @@ class Step
156
161
 
157
162
  def dependencies=(dependencies)
158
163
  @dependencies = dependencies
159
- set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]}
164
+ set_info :dependencies, dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
160
165
  end
161
166
 
162
167
  def recursive_inputs
@@ -454,6 +459,7 @@ class Step
454
459
  status << "not running" if ! done? && ! running?
455
460
  status.unshift " " if status.any?
456
461
  Log.high "Cleaning step: #{path}#{status * " "}"
462
+ Log.stack caller if RBBT_DEBUG_CLEAN
457
463
  abort if ! done? && running?
458
464
  Step.clean(path)
459
465
  self
@@ -8,6 +8,16 @@ class Step
8
8
  end
9
9
  end
10
10
 
11
+ def self.serialize_info(info)
12
+ info = info.clean_version if IndiferentHash === info
13
+ INFO_SERIALIZER.dump(info)
14
+ end
15
+
16
+ def self.load_serialized_info(io)
17
+ IndiferentHash.setup(INFO_SERIALIZER.load(io))
18
+ end
19
+
20
+
11
21
  def self.wait_for_jobs(jobs)
12
22
  jobs = [jobs] if Step === jobs
13
23
  begin
@@ -59,7 +69,7 @@ class Step
59
69
  def self.step_info(path)
60
70
  begin
61
71
  Open.open(info_file(path), :mode => 'rb') do |f|
62
- INFO_SERIALIZER.load(f)
72
+ self.load_serialized_info(f)
63
73
  end
64
74
  rescue Exception
65
75
  Log.exception $!
@@ -83,18 +93,22 @@ class Step
83
93
 
84
94
  Log.debug "Saving job input #{name} (#{type}) into #{path}"
85
95
  case
96
+ when Step === value
97
+ Open.ln_s(value.path, path)
98
+ when type.to_s == "file"
99
+ if String === value && File.exists?(value)
100
+ Open.ln_s(value, path)
101
+ else
102
+ Open.write(path + '.yaml', value.to_yaml)
103
+ end
86
104
  when Array === value
87
- Open.write(path, value * "\n")
105
+ Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
88
106
  when IO === value
89
- Open.write(path, value)
90
- when type == "file"
91
- if String === value && File.exists?(value)
92
- Open.link(value, path)
107
+ if value.filename && String === value.filename && File.exists?(value.filename)
108
+ Open.ln_s(value.filename, path)
93
109
  else
94
- Open.write(path + '.read', value.to_s)
110
+ Open.write(path, value)
95
111
  end
96
- when Step === value
97
- value = value.produce.load
98
112
  else
99
113
  Open.write(path, value.to_s)
100
114
  end
@@ -104,18 +118,24 @@ class Step
104
118
  def self.save_job_inputs(job, dir, options = nil)
105
119
  options = IndiferentHash.setup options.dup if options
106
120
 
107
- task_name = job.task_name
121
+ task_name = Symbol === job.overriden ? job.overriden : job.task_name
108
122
  workflow = job.workflow
109
123
  workflow = Kernel.const_get workflow if String === workflow
110
- task_info = workflow.task_info(task_name)
111
- input_types = task_info[:input_types]
112
- task_inputs = task_info[:inputs]
113
- input_defaults = task_info[:input_defaults]
124
+ if workflow
125
+ task_info = workflow.task_info(task_name)
126
+ input_types = task_info[:input_types]
127
+ task_inputs = task_info[:inputs]
128
+ input_defaults = task_info[:input_defaults]
129
+ else
130
+ task_info = input_types = task_inputs = input_defaults = {}
131
+ end
114
132
 
115
133
  inputs = {}
134
+ real_inputs = job.real_inputs || job.info[:real_inputs]
116
135
  job.recursive_inputs.zip(job.recursive_inputs.fields).each do |value,name|
117
136
  next unless task_inputs.include? name.to_sym
118
- next if options and ! options.include?(name)
137
+ next unless real_inputs.include? name.to_sym
138
+ next if options && ! options.include?(name)
119
139
  next if value.nil?
120
140
  next if input_defaults[name] == value
121
141
  inputs[name] = value
@@ -188,7 +208,7 @@ class Step
188
208
  info_lock.lock if check_lock and false
189
209
  begin
190
210
  Open.open(info_file, :mode => 'rb') do |file|
191
- INFO_SERIALIZER.load(file) #|| {}
211
+ Step.load_serialized_info(file)
192
212
  end
193
213
  ensure
194
214
  info_lock.unlock if check_lock and false
@@ -204,7 +224,7 @@ class Step
204
224
  Log.debug{"Error loading info file: " + info_file}
205
225
  Log.exception $!
206
226
  Open.rm info_file
207
- Misc.sensiblewrite(info_file, INFO_SERIALIZER.dump({:status => :error, :messages => ["Info file lost"]}))
227
+ Misc.sensiblewrite(info_file, Step.serialize_info({:status => :error, :messages => ["Info file lost"]}))
208
228
  raise $!
209
229
  end
210
230
  end
@@ -212,10 +232,10 @@ class Step
212
232
  def init_info(force = false)
213
233
  return nil if @exec || info_file.nil? || (Open.exists?(info_file) && ! force)
214
234
  Open.lock(info_file, :lock => info_lock) do
215
- i = {:status => :waiting, :pid => Process.pid, :path => path}
235
+ i = {:status => :waiting, :pid => Process.pid, :path => path, :real_inputs => real_inputs}
216
236
  i[:dependencies] = dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
217
- @info_cache = i
218
- Misc.sensiblewrite(info_file, INFO_SERIALIZER.dump(i), :force => true, :lock => false)
237
+ Misc.sensiblewrite(info_file, Step.serialize_info(i), :force => true, :lock => false)
238
+ @info_cache = IndiferentHash.setup(i)
219
239
  @info_cache_time = Time.now
220
240
  end
221
241
  end
@@ -227,9 +247,9 @@ class Step
227
247
  Open.lock(info_file, :lock => info_lock) do
228
248
  i = info(false).dup
229
249
  i[key] = value
230
- @info_cache = i
231
- dump = INFO_SERIALIZER.dump(i)
232
- Misc.sensiblewrite(info_file, dump, :force => true, :lock => false)
250
+ dump = Step.serialize_info(i)
251
+ @info_cache = IndiferentHash.setup(i)
252
+ Misc.sensiblewrite(info_file, dump, :force => true, :lock => false) if Open.exists?(info_file)
233
253
  @info_cache_time = Time.now
234
254
  value
235
255
  end
@@ -242,9 +262,9 @@ class Step
242
262
  Open.lock(info_file, :lock => info_lock) do
243
263
  i = info(false)
244
264
  i.merge! hash
245
- @info_cache = i
246
- dump = INFO_SERIALIZER.dump(i)
247
- Misc.sensiblewrite(info_file, dump, :force => true, :lock => false)
265
+ dump = Step.serialize_info(i)
266
+ @info_cache = IndiferentHash.setup(i)
267
+ Misc.sensiblewrite(info_file, dump, :force => true, :lock => false) if Open.exists?(info_file)
248
268
  @info_cache_time = Time.now
249
269
  value
250
270
  end
@@ -537,7 +557,7 @@ class Step
537
557
  end
538
558
 
539
559
  def file(name)
540
- Path.setup(File.join(files_dir, name.to_s))
560
+ Path.setup(File.join(files_dir, name.to_s), workflow, self)
541
561
  end
542
562
 
543
563
  def save_file(name, content)