SciMed-bj 1.2.4

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.
@@ -0,0 +1,86 @@
1
+ class Hash
2
+ begin
3
+ method "to_options"
4
+ rescue
5
+ def to_options
6
+ inject(Hash.new){|h, kv| h.update kv.first.to_s.to_sym => kv.last}
7
+ end
8
+ def to_options!
9
+ replace to_options
10
+ end
11
+ end
12
+
13
+ begin
14
+ method "to_string_options"
15
+ rescue
16
+ def to_string_options
17
+ inject(Hash.new){|h, kv| h.update kv.first.to_s => kv.last}
18
+ end
19
+ def to_string_options!
20
+ replace to_string_options
21
+ end
22
+ end
23
+
24
+ begin
25
+ method "reverse_merge"
26
+ rescue
27
+ def reverse_merge other
28
+ other.merge self
29
+ end
30
+ def reverse_merge! other
31
+ replace reverse_merge(other)
32
+ end
33
+ end
34
+
35
+ begin
36
+ method "slice"
37
+ rescue
38
+ def slice(*keys)
39
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
40
+ reject { |key,| !allowed.include?(key) }
41
+ end
42
+ end
43
+
44
+ begin
45
+ method "slice!"
46
+ rescue
47
+ def slice!(*keys)
48
+ replace(slice(*keys))
49
+ end
50
+ end
51
+ end
52
+
53
+ class Object
54
+ begin
55
+ method "returning"
56
+ rescue
57
+ def returning value, &block
58
+ block.call value
59
+ value
60
+ end
61
+ end
62
+ end
63
+
64
+ class Object
65
+ def singleton_class &block
66
+ @singleton_class ||=
67
+ class << self
68
+ self
69
+ end
70
+ block ? @singleton_class.module_eval(&block) : @singleton_class
71
+ end
72
+ end
73
+
74
+ class String
75
+ begin
76
+ method 'underscore'
77
+ rescue
78
+ def underscore
79
+ gsub(/::/, '/').
80
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
81
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
82
+ tr("-", "_").
83
+ downcase
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,426 @@
1
+ class Bj
2
+ #
3
+ # table base class
4
+ #
5
+ class Table < ActiveRecord::Base
6
+ module ClassMethods
7
+ fattr("list"){ Array.new }
8
+ fattr("migration"){}
9
+
10
+ def migration_code classname = "BjMigration"
11
+ <<-code
12
+ class #{ classname } < ActiveRecord::Migration
13
+ def self.up
14
+ Bj::Table.each{|table| table.up}
15
+ end
16
+ def self.down
17
+ Bj::Table.reverse_each{|table| table.down}
18
+ end
19
+ end
20
+ code
21
+ end
22
+
23
+ def up
24
+ migration_class.up
25
+ end
26
+
27
+ def down
28
+ migration_class.down
29
+ end
30
+
31
+ def migration_class
32
+ table = self
33
+ @migration_class ||=
34
+ Class.new(ActiveRecord::Migration) do
35
+ sc =
36
+ class << self
37
+ self
38
+ end
39
+ sc.module_eval{ fattr :table => table }
40
+ sc.module_eval &table.migration
41
+ end
42
+ end
43
+
44
+ def content_column_names
45
+ @content_column_names = content_columns.map{|column| column.name}
46
+ end
47
+
48
+ def create_hash_for options
49
+ options.to_options!
50
+ hash = {}
51
+ content_column_names.each do |key|
52
+ key = key.to_s.to_sym
53
+ hash[key] = options[key]
54
+ end
55
+ hash
56
+ end
57
+
58
+ def each *a, &b
59
+ list.each *a, &b
60
+ end
61
+
62
+ def reverse_each *a, &b
63
+ list.reverse.each *a, &b
64
+ end
65
+ end
66
+ send :extend, ClassMethods
67
+
68
+ module InstanceMethods
69
+ def to_hash
70
+ oh = OrderedHash.new
71
+ self.class.content_column_names.each{|c| oh[c] = self[c]}
72
+ oh
73
+ end
74
+ end
75
+ send :include, InstanceMethods
76
+
77
+ module RecursivelyInherited
78
+ def inherited other
79
+ super
80
+ ensure
81
+ (Table.list << other).uniq!
82
+ basename = other.name.split(%r/::/).last.underscore
83
+ Table.singleton_class{ fattr basename => other }
84
+ other.send :extend, RecursivelyInherited
85
+ end
86
+ end
87
+ send :extend, RecursivelyInherited
88
+
89
+ #
90
+ # table classes
91
+ #
92
+ class Job < Table
93
+ set_table_name "bj_job"
94
+ set_primary_key "#{ table_name }_id"
95
+
96
+ migration {
97
+ define_method :up do
98
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
99
+ t.column "command" , :text
100
+
101
+ t.column "state" , :text
102
+ t.column "priority" , :integer
103
+ t.column "tag" , :text
104
+ t.column "is_restartable" , :integer
105
+
106
+ t.column "submitter" , :text
107
+ t.column "runner" , :text
108
+ t.column "pid" , :integer
109
+
110
+ t.column "submitted_at" , :datetime
111
+ t.column "started_at" , :datetime
112
+ t.column "finished_at" , :datetime
113
+
114
+ t.column "env" , :text
115
+ t.column "stdin" , :text
116
+ t.column "stdout" , :text
117
+ t.column "stderr" , :text
118
+ t.column "exit_status" , :integer
119
+ end
120
+ end
121
+
122
+ define_method :down do
123
+ drop_table table.table_name
124
+ end
125
+ }
126
+
127
+ module ClassMethods
128
+ def submit jobs, options = {}, &block
129
+ jobs = Joblist.for jobs, options
130
+ returned = []
131
+ transaction do
132
+ jobs.each do |job|
133
+ job = create_hash_for(job.reverse_merge(submit_defaults))
134
+ job = create! job
135
+ returned << (block ? block.call(job) : job)
136
+ end
137
+ end
138
+ returned
139
+ end
140
+
141
+ def submit_defaults
142
+ {
143
+ :state => "pending",
144
+ :priority => 0,
145
+ :tag => "",
146
+ :is_restartable => true,
147
+ :submitter => Bj.hostname,
148
+ :submitted_at => Time.now,
149
+ }
150
+ end
151
+ end
152
+ send :extend, ClassMethods
153
+
154
+ module InstanceMethods
155
+ def title
156
+ "job[#{ id }](#{ command })"
157
+ end
158
+
159
+ def finished
160
+ reload
161
+ exit_status
162
+ end
163
+ alias_method "finished?", "finished"
164
+
165
+ def run! options = {}
166
+ job = self
167
+ thread = nil
168
+
169
+ command = job.command
170
+ env = job.env ? YAML.load(job.env) : {}
171
+ stdin = job.stdin || ''
172
+ stdout = job.stdout || ''
173
+ stderr = job.stderr || ''
174
+ started_at = Time.now
175
+
176
+ job.state = "starting"
177
+ job.save!
178
+
179
+ thread = Util.start command, :cwd=>Bj.rails_root, :env=>env, :stdin=>stdin, :stdout=>stdout, :stderr=>stderr
180
+
181
+ job.state = "running"
182
+ job.runner = Bj.hostname
183
+ job.pid = thread.pid
184
+ job.started_at = started_at
185
+
186
+ Bj.transaction(options) do
187
+ job.save!
188
+ job.reload
189
+ end
190
+
191
+ exit_status = thread.value
192
+
193
+ job.state = "finished"
194
+ job.finished_at = Time.now
195
+ job.stdout = stdout
196
+ job.stderr = stderr
197
+ job.exit_status = exit_status
198
+
199
+ Bj.transaction(options) do
200
+ job.save!
201
+ job.reload
202
+ end
203
+
204
+ job
205
+ end
206
+ end
207
+ send :include, InstanceMethods
208
+ end
209
+
210
+ class JobArchive < Job
211
+ set_table_name "bj_job_archive"
212
+ set_primary_key "#{ table_name }_id"
213
+
214
+ migration {
215
+ define_method(:up) do
216
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
217
+ t.column "command" , :text
218
+
219
+ t.column "state" , :text
220
+ t.column "priority" , :integer
221
+ t.column "tag" , :text
222
+ t.column "is_restartable" , :integer
223
+
224
+ t.column "submitter" , :text
225
+ t.column "runner" , :text
226
+ t.column "pid" , :integer
227
+
228
+ t.column "submitted_at" , :datetime
229
+ t.column "started_at" , :datetime
230
+ t.column "finished_at" , :datetime
231
+ t.column "archived_at" , :datetime
232
+
233
+ t.column "env" , :text
234
+ t.column "stdin" , :text
235
+ t.column "stdout" , :text
236
+ t.column "stderr" , :text
237
+ t.column "exit_status" , :integer
238
+ end
239
+ end
240
+
241
+ define_method(:down) do
242
+ drop_table table.table_name
243
+ end
244
+ }
245
+ end
246
+
247
+ class Config < Table
248
+ set_table_name "bj_config"
249
+ set_primary_key "#{ table_name }_id"
250
+
251
+ migration {
252
+ define_method(:up) do
253
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
254
+ t.column "hostname" , :text
255
+ t.column "key" , :text
256
+ t.column "value" , :text
257
+ t.column "cast" , :text
258
+ end
259
+
260
+ begin
261
+ add_index table.table_name, %w[ hostname key ], :unique => true
262
+ rescue Exception
263
+ STDERR.puts "WARNING: your database is sucking and does not support unique indexes on text fields!?"
264
+ end
265
+ end
266
+
267
+ define_method(:down) do
268
+ begin
269
+ remove_index table.table_name, :column => %w[ hostname key ]
270
+ rescue Exception
271
+ end
272
+ drop_table table.table_name
273
+ end
274
+ }
275
+
276
+ module ClassMethods
277
+ def [] key
278
+ get key
279
+ end
280
+
281
+ def get key, options = {}
282
+ transaction do
283
+ options.to_options!
284
+ hostname = options[:hostname] || Bj.hostname
285
+ record = find :first, :conditions => conditions(:key => key, :hostname => hostname)
286
+ record ? record.value : default_for(key)
287
+ end
288
+ end
289
+
290
+ def conditions options = {}
291
+ options.to_options!
292
+ options.reverse_merge!(
293
+ :hostname => Bj.hostname
294
+ )
295
+ options
296
+ end
297
+
298
+ def default_for key
299
+ record = find :first, :conditions => conditions(:key => key, :hostname => '*')
300
+ record ? record.value : nil
301
+ end
302
+
303
+ def []= key, value
304
+ set key, value
305
+ end
306
+
307
+ def set key, value, options = {}
308
+ transaction do
309
+ options.to_options!
310
+ hostname = options[:hostname] || Bj.hostname
311
+ record = find :first, :conditions => conditions(:key => key, :hostname => hostname), :lock => true
312
+ cast = options[:cast] || cast_for(value)
313
+ key = key.to_s
314
+ value = value.to_s
315
+ if record
316
+ record["value"] = value
317
+ record["cast"] = cast
318
+ record.save!
319
+ else
320
+ create! :hostname => hostname, :key => key, :value => value, :cast => cast
321
+ end
322
+ value
323
+ end
324
+ end
325
+
326
+ def delete key
327
+ transaction do
328
+ record = find :first, :conditions => conditions(:key => key), :lock => true
329
+ if record
330
+ record.destroy
331
+ record
332
+ else
333
+ nil
334
+ end
335
+ end
336
+ end
337
+
338
+ def has_key? key
339
+ record = find :first, :conditions => conditions(:key => key)
340
+ record ? record : false
341
+ end
342
+ alias_method "has_key", "has_key?"
343
+
344
+ def keys
345
+ find(:all, :conditions => conditions).map(&:key)
346
+ end
347
+
348
+ def values
349
+ find(:all, :conditions => conditions).map(&:value)
350
+ end
351
+
352
+ def for options = {}
353
+ oh = OrderedHash.new
354
+ find(:all, :conditions => conditions(options)).each do |record|
355
+ oh[record.key] = record.value
356
+ end
357
+ oh
358
+ end
359
+
360
+ def cast_for value
361
+ case value
362
+ when TrueClass, FalseClass
363
+ 'to_bool'
364
+ when NilClass
365
+ 'to_nil'
366
+ when Fixnum, Bignum
367
+ 'to_i'
368
+ when Float
369
+ 'to_f'
370
+ when Time
371
+ 'to_time'
372
+ when Symbol
373
+ 'to_sym'
374
+ else
375
+ case value.to_s
376
+ when %r/^\d+$/
377
+ 'to_i'
378
+ when %r/^\d+\.\d+$/
379
+ 'to_f'
380
+ when %r/^nil$|^$/
381
+ 'to_nil'
382
+ when %r/^true|false$/
383
+ 'to_bool'
384
+ else
385
+ 'to_s'
386
+ end
387
+ end
388
+ end
389
+
390
+ def casts
391
+ @casts ||= {
392
+ 'to_bool' => lambda do |value|
393
+ value.to_s =~ %r/^true$/i ? true : false
394
+ end,
395
+ 'to_i' => lambda do |value|
396
+ Integer value.to_s.gsub(%r/^(-)?0*/,'\1')
397
+ end,
398
+ 'to_f' => lambda do |value|
399
+ Float value.to_s.gsub(%r/^0*/,'')
400
+ end,
401
+ 'to_time' => lambda do |value|
402
+ Time.parse(value.to_s)
403
+ end,
404
+ 'to_sym' => lambda do |value|
405
+ value.to_s.to_sym
406
+ end,
407
+ 'to_nil' => lambda do |value|
408
+ value.to_s =~ %r/^nil$|^$/i ? nil : value.to_s
409
+ end,
410
+ 'to_s' => lambda do |value|
411
+ value.to_s
412
+ end,
413
+ }
414
+ end
415
+ end
416
+ send :extend, ClassMethods
417
+
418
+ module InstanceMethods
419
+ def value
420
+ self.class.casts[cast][self["value"]]
421
+ end
422
+ end
423
+ send :include, InstanceMethods
424
+ end
425
+ end
426
+ end