scout-gear 6.0.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 +465 -432
- 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 +9 -0
- data/lib/scout/indiferent_hash/options.rb +1 -0
- data/lib/scout/indiferent_hash.rb +4 -2
- data/lib/scout/log/color.rb +31 -2
- data/lib/scout/log/progress/report.rb +1 -0
- data/lib/scout/log/progress/util.rb +3 -1
- data/lib/scout/log/progress.rb +7 -3
- data/lib/scout/log.rb +8 -3
- data/lib/scout/misc/digest.rb +1 -3
- 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 +58 -26
- 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 +317 -0
- 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 +27 -0
- data/lib/scout/work_queue/worker.rb +16 -11
- data/lib/scout/work_queue.rb +63 -21
- 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 +33 -6
- data/lib/scout/workflow/step/provenance.rb +148 -0
- data/lib/scout/workflow/step.rb +70 -20
- data/lib/scout/workflow/task.rb +5 -4
- 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 +38 -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 +160 -1
- 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_semaphore.rb +1 -1
- data/test/scout/test_tmpfile.rb +2 -2
- data/test/scout/test_tsv.rb +74 -0
- data/test/scout/test_work_queue.rb +63 -8
- 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 +173 -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 +49 -1
- 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 +37 -2
@@ -0,0 +1,348 @@
|
|
1
|
+
require_relative '../../open/lock'
|
2
|
+
|
3
|
+
module TSVAdapter
|
4
|
+
attr_accessor :persistence_path, :persistence_class, :closed, :writable
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :lock_dir
|
8
|
+
def lock_dir
|
9
|
+
@lock_dir ||= Path.setup('tmp/tsv_locks')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
EXTENSION_ATTR_HASH_KEY = "__extension_attr_hash__"
|
14
|
+
EXTENSION_ATTR_HASH_SERIALIZER = Marshal
|
15
|
+
|
16
|
+
def load_extension_attr_hash
|
17
|
+
EXTENSION_ATTR_HASH_SERIALIZER.load(self[EXTENSION_ATTR_HASH_KEY])
|
18
|
+
end
|
19
|
+
|
20
|
+
def save_extension_attr_hash
|
21
|
+
self[EXTENSION_ATTR_HASH_KEY]= EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.extended(base)
|
25
|
+
if base.include?(EXTENSION_ATTR_HASH_KEY)
|
26
|
+
TSV.setup(base, base.load_extension_attr_hash)
|
27
|
+
elsif TSV === base
|
28
|
+
base[EXTENSION_ATTR_HASH_KEY] = EXTENSION_ATTR_HASH_SERIALIZER.dump(base.extension_attr_hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
class << base
|
32
|
+
alias orig_set []=
|
33
|
+
alias orig_get []
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
self.read_lock do
|
37
|
+
load_value(super(key))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def []=(key, value)
|
42
|
+
self.write_lock do
|
43
|
+
super(key, save_value(value))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
case base.type
|
49
|
+
when :single
|
50
|
+
class << base
|
51
|
+
def load_value(value)
|
52
|
+
value
|
53
|
+
end
|
54
|
+
def save_value(value)
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
when :list, :flat
|
59
|
+
class << base
|
60
|
+
def load_value(value)
|
61
|
+
value.nil? ? nil : value.split("\t")
|
62
|
+
end
|
63
|
+
def save_value(value)
|
64
|
+
value * "\t"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
when :double
|
68
|
+
class << base
|
69
|
+
def load_value(value)
|
70
|
+
value.nil? ? nil : value.split("\t").collect{|v| v.split("|") }
|
71
|
+
end
|
72
|
+
def save_value(value)
|
73
|
+
value.collect{|v| v * "|" } * "\t"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def keys(*args)
|
80
|
+
k = self.read_lock do
|
81
|
+
super(*args)
|
82
|
+
end
|
83
|
+
|
84
|
+
if k[0] == EXTENSION_ATTR_HASH_KEY
|
85
|
+
k.slice(1,k.length-1)
|
86
|
+
elsif k[-1] == EXTENSION_ATTR_HASH_KEY
|
87
|
+
k.slice(0,k.length-2)
|
88
|
+
else
|
89
|
+
k - [EXTENSION_ATTR_HASH_KEY]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def each(&block)
|
94
|
+
self.read_lock do
|
95
|
+
super do |k,v|
|
96
|
+
next if k == EXTENSION_ATTR_HASH_KEY
|
97
|
+
yield(k, load_value(v))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def collect(&block)
|
103
|
+
res = []
|
104
|
+
if block_given?
|
105
|
+
each do |k,v|
|
106
|
+
res << yield(k, v)
|
107
|
+
end
|
108
|
+
else
|
109
|
+
each do |k,v|
|
110
|
+
res << [k, v]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
res
|
114
|
+
end
|
115
|
+
|
116
|
+
def values
|
117
|
+
collect{|k,v| v }
|
118
|
+
end
|
119
|
+
|
120
|
+
alias map collect
|
121
|
+
|
122
|
+
def closed?
|
123
|
+
@closed
|
124
|
+
end
|
125
|
+
|
126
|
+
def write?
|
127
|
+
@writable
|
128
|
+
end
|
129
|
+
|
130
|
+
def read?
|
131
|
+
! (write? || closed?)
|
132
|
+
end
|
133
|
+
|
134
|
+
def write(*args)
|
135
|
+
begin
|
136
|
+
super(*args)
|
137
|
+
@writable = true
|
138
|
+
rescue NoMethodError
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def close(*args)
|
143
|
+
begin
|
144
|
+
super(*args)
|
145
|
+
@closed = true
|
146
|
+
rescue NoMethodError
|
147
|
+
end
|
148
|
+
self
|
149
|
+
end
|
150
|
+
|
151
|
+
def read(*args)
|
152
|
+
begin
|
153
|
+
super(*args)
|
154
|
+
rescue NoMethodError
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def delete(key)
|
159
|
+
self.write_lock do
|
160
|
+
out(key)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def lock
|
165
|
+
return yield if @locked
|
166
|
+
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSVAdapter.lock_dir})
|
167
|
+
Open.lock(lock_filename) do
|
168
|
+
begin
|
169
|
+
@locked = true
|
170
|
+
yield
|
171
|
+
ensure
|
172
|
+
@locked = false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def lock_and_close
|
178
|
+
lock do
|
179
|
+
begin
|
180
|
+
yield
|
181
|
+
ensure
|
182
|
+
close
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def write_and_read
|
188
|
+
if write?
|
189
|
+
begin
|
190
|
+
return yield
|
191
|
+
ensure
|
192
|
+
read
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
lock do
|
197
|
+
write(true) if closed? || !write?
|
198
|
+
begin
|
199
|
+
yield
|
200
|
+
ensure
|
201
|
+
read
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def write_and_close
|
207
|
+
if write?
|
208
|
+
begin
|
209
|
+
return yield
|
210
|
+
ensure
|
211
|
+
close unless @locked
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
lock do
|
216
|
+
write(true) if closed? || ! write?
|
217
|
+
res = begin
|
218
|
+
yield
|
219
|
+
ensure
|
220
|
+
close
|
221
|
+
end
|
222
|
+
res
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def with_read(&block)
|
227
|
+
if read? || write?
|
228
|
+
return yield
|
229
|
+
else
|
230
|
+
read_and_close &block
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def with_write(&block)
|
235
|
+
if write?
|
236
|
+
return yield
|
237
|
+
else
|
238
|
+
if self.read?
|
239
|
+
self.write_and_read do
|
240
|
+
return yield
|
241
|
+
end
|
242
|
+
else
|
243
|
+
self.write_and_close do
|
244
|
+
return yield
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
def read_and_close
|
252
|
+
if read? || write?
|
253
|
+
begin
|
254
|
+
return yield
|
255
|
+
ensure
|
256
|
+
close unless @locked
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
lock do
|
261
|
+
read true if closed? || ! read?
|
262
|
+
begin
|
263
|
+
yield
|
264
|
+
ensure
|
265
|
+
close
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def read_lock
|
271
|
+
read if closed?
|
272
|
+
if read? || write?
|
273
|
+
return yield
|
274
|
+
end
|
275
|
+
|
276
|
+
lock do
|
277
|
+
close
|
278
|
+
read true
|
279
|
+
begin
|
280
|
+
yield
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def write_lock
|
286
|
+
write if closed?
|
287
|
+
if write?
|
288
|
+
return yield
|
289
|
+
end
|
290
|
+
|
291
|
+
lock do
|
292
|
+
close
|
293
|
+
write true
|
294
|
+
begin
|
295
|
+
yield
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def merge!(hash)
|
301
|
+
hash.each do |key,values|
|
302
|
+
self[key] = values
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def range(*args)
|
307
|
+
begin
|
308
|
+
self.read_lock do
|
309
|
+
super(*args)
|
310
|
+
end
|
311
|
+
rescue
|
312
|
+
[]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def include?(*args)
|
317
|
+
self.read_lock do
|
318
|
+
super(*args) #- TSV::ENTRY_KEYS.to_a
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
MAX_CHAR = 255.chr
|
323
|
+
|
324
|
+
def prefix(key)
|
325
|
+
self.read_lock do
|
326
|
+
range(key, 1, key + MAX_CHAR, 1)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def get_prefix(key)
|
331
|
+
keys = prefix(key)
|
332
|
+
select(:key => keys)
|
333
|
+
end
|
334
|
+
|
335
|
+
def size(*args)
|
336
|
+
self.read_lock do
|
337
|
+
super(*args)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def values_at(*keys)
|
342
|
+
self.read_lock do
|
343
|
+
keys.collect do |k|
|
344
|
+
self[k]
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -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
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'meta_extension'
|
2
|
+
require_relative 'tsv/util'
|
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'
|
9
|
+
|
10
|
+
module TSV
|
11
|
+
extend MetaExtension
|
12
|
+
extension_attr :key_field, :fields, :type, :filename, :namespace, :unnamed
|
13
|
+
|
14
|
+
def self.open(file, options = {})
|
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
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
@@ -1,16 +1,18 @@
|
|
1
1
|
class WorkQueue
|
2
2
|
class Worker
|
3
3
|
attr_accessor :pid, :ignore_ouput
|
4
|
-
def initialize
|
4
|
+
def initialize(ignore_ouput = false)
|
5
|
+
@ignore_output = ignore_ouput
|
5
6
|
end
|
6
7
|
|
7
8
|
def run
|
8
9
|
@pid = Process.fork do
|
10
|
+
Log.debug "Worker start with #{Process.pid}"
|
9
11
|
yield
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
|
-
def process(input, output, &block)
|
15
|
+
def process(input, output = nil, &block)
|
14
16
|
run do
|
15
17
|
begin
|
16
18
|
while obj = input.read
|
@@ -22,21 +24,25 @@ class WorkQueue
|
|
22
24
|
output.write res unless ignore_ouput || res == :ignore
|
23
25
|
end
|
24
26
|
rescue DoneProcessing
|
25
|
-
|
27
|
+
rescue Interrupt
|
26
28
|
rescue Exception
|
27
|
-
|
29
|
+
output.write WorkerException.new($!, Process.pid)
|
28
30
|
exit -1
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
35
|
+
def abort
|
36
|
+
begin
|
37
|
+
Log.debug "Aborting worker #{@pid}"
|
38
|
+
Process.kill "INT", @pid
|
39
|
+
rescue Errno::ECHILD
|
40
|
+
end
|
36
41
|
end
|
37
42
|
|
38
|
-
def
|
39
|
-
Log.
|
43
|
+
def join
|
44
|
+
Log.debug "Joining worker #{@pid}"
|
45
|
+
Process.waitpid @pid
|
40
46
|
end
|
41
47
|
|
42
48
|
def self.join(workers)
|
@@ -44,8 +50,7 @@ class WorkQueue
|
|
44
50
|
begin
|
45
51
|
while pid = Process.wait
|
46
52
|
status = $?
|
47
|
-
|
48
|
-
worker.exit status.exitstatus if worker
|
53
|
+
worker = workers.select{|w| w.pid == pid }.first
|
49
54
|
end
|
50
55
|
rescue Errno::ECHILD
|
51
56
|
end
|