rbbt-util 5.28.14 → 5.30.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rbbt/persist.rb CHANGED
@@ -110,6 +110,8 @@ module Persist
110
110
  def self.load_file(path, type)
111
111
  begin
112
112
  case (type || :marshal).to_sym
113
+ when :path
114
+ path
113
115
  when :nil
114
116
  nil
115
117
  when :boolean
@@ -167,6 +169,8 @@ module Persist
167
169
  end
168
170
 
169
171
  case (type || :marshal).to_sym
172
+ when :path
173
+ nil
170
174
  when :nil
171
175
  nil
172
176
  when :boolean
@@ -104,9 +104,6 @@ module Persist
104
104
  write(true) if closed? || ! write?
105
105
  res = begin
106
106
  yield
107
- rescue Exception
108
- Log.exception $!
109
- raise $!
110
107
  ensure
111
108
  close
112
109
  end
@@ -115,7 +112,6 @@ module Persist
115
112
  end
116
113
 
117
114
  def read_and_close
118
- #return yield if @locked
119
115
  if read? || write?
120
116
  begin
121
117
  return yield
@@ -134,6 +130,45 @@ module Persist
134
130
  end
135
131
  end
136
132
 
133
+ def read_lock
134
+ read if closed?
135
+ if read?
136
+ begin
137
+ return yield
138
+ ensure
139
+ close
140
+ end
141
+ end
142
+
143
+ lock do
144
+ close
145
+ read true
146
+ begin
147
+ yield
148
+ end
149
+ end
150
+ end
151
+
152
+ def write_lock
153
+ write if closed?
154
+ if write?
155
+ begin
156
+ return yield
157
+ ensure
158
+ close
159
+ end
160
+ end
161
+
162
+ lock do
163
+ close
164
+ write true
165
+ begin
166
+ yield
167
+ end
168
+ end
169
+ end
170
+
171
+
137
172
  def merge!(hash)
138
173
  hash.each do |key,values|
139
174
  self[key] = values
@@ -141,38 +176,38 @@ module Persist
141
176
  end
142
177
 
143
178
  def range(*args)
144
- self.read_and_close do
179
+ self.read_lock do
145
180
  super(*args)
146
181
  end
147
182
  end
148
183
 
149
184
  def include?(*args)
150
- self.read_and_close do
185
+ self.read_lock do
151
186
  super(*args) #- TSV::ENTRY_KEYS.to_a
152
187
  end
153
188
  end
154
189
 
155
190
  def [](*args)
156
- self.read_and_close do
191
+ self.read_lock do
157
192
  super(*args) #- TSV::ENTRY_KEYS.to_a
158
193
  end
159
194
  end
160
195
 
161
196
  def []=(*args)
162
- self.write_and_close do
197
+ self.write_lock do
163
198
  super(*args) #- TSV::ENTRY_KEYS.to_a
164
199
  end
165
200
  end
166
201
 
167
202
  def keys(*args)
168
- self.read_and_close do
203
+ self.read_lock do
169
204
  super(*args)
170
205
  end
171
206
  end
172
207
 
173
208
 
174
209
  def prefix(key)
175
- self.read_and_close do
210
+ self.read_lock do
176
211
  range(key, 1, key + MAX_CHAR, 1)
177
212
  end
178
213
  end
@@ -184,13 +219,13 @@ module Persist
184
219
 
185
220
 
186
221
  def size(*args)
187
- self.read_and_close do
222
+ self.read_lock do
188
223
  super(*args)
189
224
  end
190
225
  end
191
226
 
192
227
  def each(*args, &block)
193
- self.read_and_close do
228
+ self.read_lock do
194
229
  super(*args, &block)
195
230
  end
196
231
  end
@@ -208,7 +243,7 @@ module Persist
208
243
  end
209
244
 
210
245
  def values_at(*keys)
211
- self.read_and_close do
246
+ self.read_lock do
212
247
  keys.collect do |k|
213
248
  self[k]
214
249
  end
data/lib/rbbt/util/cmd.rb CHANGED
@@ -217,7 +217,7 @@ module CMD
217
217
  end
218
218
  end
219
219
 
220
- def self.cmd_log(*args)
220
+ def self.cmd_pid(*args)
221
221
  all_args = *args
222
222
 
223
223
  all_args << {} unless Hash === all_args.last
@@ -248,4 +248,9 @@ module CMD
248
248
  nil
249
249
  end
250
250
 
251
+ def self.cmd_log(*args)
252
+ cmd_pid(*args)
253
+ nil
254
+ end
255
+
251
256
  end
@@ -287,7 +287,9 @@ module Misc
287
287
  when Symbol
288
288
  obj.to_s
289
289
  when (defined?(Path) and Path)
290
- if Step === obj.resource
290
+ if defined?(Step) && Open.exists?(Step.info_file(obj))
291
+ obj2str(Workflow.load_step(obj))
292
+ elsif defined?(Step) && Step === obj.resource
291
293
  "Step file: " + obj
292
294
  else
293
295
  if obj.exists?
@@ -322,7 +324,11 @@ module Misc
322
324
  remove_long_items(obj)
323
325
  when File
324
326
  if obj.respond_to? :filename and obj.filename
325
- "<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
326
332
  else
327
333
  "<IO:" << obj.path << "--" << mtime_str(obj.path) << ">"
328
334
  end
@@ -330,7 +336,11 @@ module Misc
330
336
  "<IO:" << obj.short_path << ">"
331
337
  when IO
332
338
  if obj.respond_to? :filename and obj.filename
333
- "<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
334
344
  else
335
345
 
336
346
  if obj.respond_to? :obj2str
@@ -242,48 +242,6 @@ module Misc
242
242
 
243
243
  return options
244
244
 
245
- options = {}
246
- string.split(/#/).each do |str|
247
- if str.match(/(.*)=(.*)/)
248
- option, value = $1, $2
249
- else
250
- option, value = str, true
251
- end
252
-
253
- option = option.sub(":",'').to_sym if option.chars.first == ':'
254
- value = value.sub(":",'').to_sym if String === value and value.chars.first == ':'
255
-
256
- if value == true
257
- options[option] = option.to_s.chars.first != '!'
258
- else
259
- options[option] = Thread.start do
260
- $SAFE = 0;
261
- case
262
- when value =~ /^(?:true|T)$/i
263
- true
264
- when value =~ /^(?:false|F)$/i
265
- false
266
- when Symbol === value
267
- value
268
- when (String === value and value =~ /^\/(.*)\/$/)
269
- Regexp.new /#{$1}/
270
- else
271
- begin
272
- Kernel.const_get value
273
- rescue
274
- begin
275
- raise if value =~ /[a-z]/ and defined? value
276
- eval(value)
277
- rescue Exception
278
- value
279
- end
280
- end
281
- end
282
- end.value
283
- end
284
- end
285
-
286
- options
287
245
  end
288
246
 
289
247
  end
@@ -0,0 +1,49 @@
1
+ require 'rbbt/util/cmd'
2
+ module ProcPath
3
+ CMD.tool :procpath do
4
+ 'pip install procpath'
5
+ end
6
+
7
+ def self.record(pid, path, options = {})
8
+ IndiferentHash.setup(options)
9
+ options = Misc.add_defaults options, "interval" => 30
10
+
11
+ cmd_options = %w(interval recnum reevalnum).inject({}){|acc,k| acc[k] = options[k]; acc}
12
+
13
+ Log.debug "ProcPath recording #{pid} in #{path} (#{Misc.fingerprint options})"
14
+ procpath_thread = Thread.new do
15
+ begin
16
+ procpath_pid = CMD.cmd_pid(:procpath, "record --database-file '#{path}' '$..children[?(@.stat.pid == #{pid})]'", cmd_options.merge(:nofail => true, :add_option_dashes => true))
17
+ rescue Exception
18
+ Log.exceptions $!
19
+ Process.kill "INT", procpath_pid
20
+ end
21
+ end
22
+
23
+ procpath_thread.report_on_exception = false
24
+
25
+ Process.wait pid.to_i
26
+ procpath_thread.raise Interrupt
27
+ end
28
+
29
+ def self.plot(path, output, options = {})
30
+ IndiferentHash.setup(options)
31
+ options = Misc.add_defaults options, "query-name" => 'rss', 'epsilon' => 0.5, "moving-average-window" => 10
32
+
33
+ cmd_options = %w(query-name epsilon monitor-average-window title logarithmic after before custom-query-file custom-value-expr).inject({}){|acc,k| acc[k] = options[k]; acc}
34
+ CMD.cmd_log(:procpath, "plot --database-file '#{path}' --plot-file '#{output}' ", cmd_options.merge(:nofail => true, :add_option_dashes => true))
35
+ end
36
+
37
+ def self.monitor(pid, path)
38
+ database, options_str = path.split("#")
39
+ options = options_str.nil? ? {} : Misc.string2hash(options_str)
40
+
41
+ database = File.expand_path database
42
+ Log.low "ProcPath monitor #{pid} in #{database} (#{Misc.fingerprint options})"
43
+
44
+ ProcPath.record(pid, database + '.sqlite3', options)
45
+ ProcPath.plot(database + '.sqlite3', database + '.cpu.svg', options.merge("query-name" => 'cpu'))
46
+ ProcPath.plot(database + '.sqlite3', database + '.rss.svg', options.merge("query-name" => 'rss'))
47
+ end
48
+ end
49
+
data/lib/rbbt/workflow.rb CHANGED
@@ -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
 
@@ -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,7 @@ 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
15
16
 
16
17
  RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
17
18
 
@@ -145,11 +146,13 @@ class Step
145
146
  seen = []
146
147
  while path = deps.pop
147
148
  dep_info = archived_info[path]
148
- dep_info[:inputs].each do |k,v|
149
- all_inputs[k] = v unless all_inputs.include?(k)
150
- end if dep_info[:inputs]
151
- deps.concat(dep_info[:dependencies].collect{|p| p.last } - seen) if dep_info[:dependencies]
152
- 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
153
156
  seen << path
154
157
  end
155
158
 
@@ -93,18 +93,22 @@ class Step
93
93
 
94
94
  Log.debug "Saving job input #{name} (#{type}) into #{path}"
95
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
96
104
  when Array === value
97
- Open.write(path, value * "\n")
105
+ Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
98
106
  when IO === value
99
- Open.write(path, value)
100
- when type == "file"
101
- if String === value && File.exists?(value)
102
- Open.link(value, path)
107
+ if value.filename && String === value.filename && File.exists?(value.filename)
108
+ Open.ln_s(value.filename, path)
103
109
  else
104
- Open.write(path + '.read', value.to_s)
110
+ Open.write(path, value)
105
111
  end
106
- when Step === value
107
- value = value.produce.load
108
112
  else
109
113
  Open.write(path, value.to_s)
110
114
  end
@@ -114,18 +118,24 @@ class Step
114
118
  def self.save_job_inputs(job, dir, options = nil)
115
119
  options = IndiferentHash.setup options.dup if options
116
120
 
117
- task_name = job.task_name
121
+ task_name = Symbol === job.overriden ? job.overriden : job.task_name
118
122
  workflow = job.workflow
119
123
  workflow = Kernel.const_get workflow if String === workflow
120
- task_info = workflow.task_info(task_name)
121
- input_types = task_info[:input_types]
122
- task_inputs = task_info[:inputs]
123
- 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
124
132
 
125
133
  inputs = {}
134
+ real_inputs = job.real_inputs || job.info[:real_inputs]
126
135
  job.recursive_inputs.zip(job.recursive_inputs.fields).each do |value,name|
127
136
  next unless task_inputs.include? name.to_sym
128
- next if options and ! options.include?(name)
137
+ next unless real_inputs.include? name.to_sym
138
+ next if options && ! options.include?(name)
129
139
  next if value.nil?
130
140
  next if input_defaults[name] == value
131
141
  inputs[name] = value
@@ -222,7 +232,7 @@ class Step
222
232
  def init_info(force = false)
223
233
  return nil if @exec || info_file.nil? || (Open.exists?(info_file) && ! force)
224
234
  Open.lock(info_file, :lock => info_lock) do
225
- i = {:status => :waiting, :pid => Process.pid, :path => path}
235
+ i = {:status => :waiting, :pid => Process.pid, :path => path, :real_inputs => real_inputs}
226
236
  i[:dependencies] = dependencies.collect{|dep| [dep.task_name, dep.name, dep.path]} if dependencies
227
237
  Misc.sensiblewrite(info_file, Step.serialize_info(i), :force => true, :lock => false)
228
238
  @info_cache = IndiferentHash.setup(i)
@@ -495,8 +505,8 @@ class Step
495
505
 
496
506
  def running?
497
507
  return false if ! (started? || status == :ending)
498
- pid = info[:pid]
499
- return nil if pid.nil?
508
+ return nil unless Open.exist?(self.pid_file)
509
+ pid = Open.read(self.pid_file).to_i
500
510
 
501
511
  return false if done? or error? or aborted?
502
512
 
@@ -520,8 +530,7 @@ class Step
520
530
  end
521
531
 
522
532
  def nopid?
523
- pid = info[:pid] || Open.exists?(pid_file)
524
- ! pid && ! (status.nil? || status == :aborted || status == :done || status == :error || status == :cleaned)
533
+ ! Open.exists?(pid_file) && ! (status.nil? || status == :aborted || status == :done || status == :error || status == :cleaned)
525
534
  end
526
535
 
527
536
  def aborted?