scout-gear 7.2.0 → 8.0.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 +51 -6
- data/VERSION +1 -1
- data/bin/scout +6 -3
- data/lib/rbbt-scout.rb +1 -0
- data/lib/scout/cmd.rb +1 -1
- data/lib/scout/concurrent_stream.rb +33 -29
- data/lib/scout/config.rb +1 -1
- data/lib/scout/exceptions.rb +1 -0
- data/lib/scout/log/color.rb +4 -2
- data/lib/scout/log/progress/report.rb +1 -1
- data/lib/scout/log/progress/util.rb +71 -2
- data/lib/scout/log/progress.rb +1 -1
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +56 -21
- data/lib/scout/meta_extension.rb +13 -6
- data/lib/scout/misc/digest.rb +1 -1
- data/lib/scout/misc/format.rb +12 -0
- data/lib/scout/misc/helper.rb +31 -0
- data/lib/scout/misc/insist.rb +1 -1
- data/lib/scout/misc/monitor.rb +12 -1
- data/lib/scout/misc/system.rb +10 -0
- data/lib/scout/misc.rb +1 -0
- data/lib/scout/named_array.rb +65 -3
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +28 -2
- data/lib/scout/open/remote.rb +4 -0
- data/lib/scout/open/stream.rb +111 -42
- data/lib/scout/open/util.rb +13 -3
- data/lib/scout/path/find.rb +9 -1
- data/lib/scout/path/util.rb +35 -0
- data/lib/scout/persist/serialize.rb +18 -5
- data/lib/scout/persist.rb +60 -30
- data/lib/scout/resource/path.rb +53 -0
- data/lib/scout/resource/produce.rb +0 -8
- data/lib/scout/resource/util.rb +2 -1
- data/lib/scout/semaphore.rb +8 -1
- data/lib/scout/tmpfile.rb +7 -8
- data/lib/scout/tsv/attach.rb +177 -0
- data/lib/scout/tsv/change_id.rb +40 -0
- data/lib/scout/tsv/dumper.rb +85 -54
- data/lib/scout/tsv/index.rb +188 -20
- data/lib/scout/tsv/open.rb +182 -0
- data/lib/scout/tsv/parser.rb +200 -118
- data/lib/scout/tsv/path.rb +5 -6
- data/lib/scout/tsv/persist/adapter.rb +26 -37
- data/lib/scout/tsv/persist/fix_width_table.rb +327 -0
- data/lib/scout/tsv/persist/serialize.rb +117 -0
- data/lib/scout/tsv/persist/tokyocabinet.rb +6 -3
- data/lib/scout/tsv/persist.rb +4 -2
- data/lib/scout/tsv/transformer.rb +141 -0
- data/lib/scout/tsv/traverse.rb +136 -37
- data/lib/scout/tsv/util/filter.rb +312 -0
- data/lib/scout/tsv/util/process.rb +73 -0
- data/lib/scout/tsv/util/reorder.rb +81 -0
- data/lib/scout/tsv/util/select.rb +265 -0
- data/lib/scout/tsv/util/unzip.rb +86 -0
- data/lib/scout/tsv/util.rb +126 -19
- data/lib/scout/tsv.rb +28 -5
- data/lib/scout/work_queue/socket.rb +6 -1
- data/lib/scout/work_queue/worker.rb +5 -2
- data/lib/scout/work_queue.rb +15 -8
- data/lib/scout/workflow/definition.rb +29 -2
- data/lib/scout/workflow/step/dependencies.rb +24 -4
- data/lib/scout/workflow/step/info.rb +40 -5
- data/lib/scout/workflow/step/progress.rb +14 -0
- data/lib/scout/workflow/step/provenance.rb +8 -7
- data/lib/scout/workflow/step/status.rb +45 -0
- data/lib/scout/workflow/step.rb +104 -33
- data/lib/scout/workflow/task/inputs.rb +14 -20
- data/lib/scout/workflow/task.rb +86 -47
- data/lib/scout/workflow/usage.rb +10 -6
- data/scout-gear.gemspec +30 -3
- data/scout_commands/workflow/task +37 -9
- data/scout_commands/workflow/task_old +2 -2
- data/test/scout/open/test_stream.rb +61 -59
- data/test/scout/path/test_find.rb +10 -1
- data/test/scout/resource/test_produce.rb +15 -0
- data/test/scout/test_meta_extension.rb +25 -0
- data/test/scout/test_named_array.rb +18 -0
- data/test/scout/test_persist.rb +67 -0
- data/test/scout/test_tmpfile.rb +1 -1
- data/test/scout/test_tsv.rb +222 -3
- data/test/scout/test_work_queue.rb +21 -18
- data/test/scout/tsv/persist/test_adapter.rb +11 -1
- data/test/scout/tsv/persist/test_fix_width_table.rb +134 -0
- data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
- data/test/scout/tsv/test_attach.rb +227 -0
- data/test/scout/tsv/test_change_id.rb +98 -0
- data/test/scout/tsv/test_dumper.rb +1 -1
- data/test/scout/tsv/test_index.rb +127 -3
- data/test/scout/tsv/test_open.rb +167 -0
- data/test/scout/tsv/test_parser.rb +45 -3
- data/test/scout/tsv/test_persist.rb +9 -0
- data/test/scout/tsv/test_transformer.rb +108 -0
- data/test/scout/tsv/test_traverse.rb +195 -3
- data/test/scout/tsv/test_util.rb +24 -0
- data/test/scout/tsv/util/test_filter.rb +188 -0
- data/test/scout/tsv/util/test_process.rb +47 -0
- data/test/scout/tsv/util/test_reorder.rb +94 -0
- data/test/scout/tsv/util/test_select.rb +58 -0
- data/test/scout/tsv/util/test_unzip.rb +112 -0
- data/test/scout/work_queue/test_socket.rb +0 -1
- data/test/scout/work_queue/test_worker.rb +63 -6
- data/test/scout/workflow/step/test_load.rb +3 -3
- data/test/scout/workflow/step/test_status.rb +31 -0
- data/test/scout/workflow/task/test_inputs.rb +14 -14
- data/test/scout/workflow/test_step.rb +13 -13
- data/test/scout/workflow/test_task.rb +168 -32
- data/test/scout/workflow/test_usage.rb +33 -6
- data/test/test_helper.rb +3 -1
- metadata +29 -2
@@ -1,7 +1,9 @@
|
|
1
1
|
require_relative '../../open/lock'
|
2
|
+
require_relative '../../meta_extension'
|
3
|
+
require_relative 'serialize'
|
2
4
|
|
3
5
|
module TSVAdapter
|
4
|
-
attr_accessor :persistence_path, :persistence_class, :closed, :writable
|
6
|
+
attr_accessor :persistence_path, :persistence_class, :closed, :writable, :serializer
|
5
7
|
|
6
8
|
class << self
|
7
9
|
attr_accessor :lock_dir
|
@@ -13,20 +15,20 @@ module TSVAdapter
|
|
13
15
|
EXTENSION_ATTR_HASH_KEY = "__extension_attr_hash__"
|
14
16
|
EXTENSION_ATTR_HASH_SERIALIZER = Marshal
|
15
17
|
|
18
|
+
def serializer=(serializer)
|
19
|
+
@serializer = Symbol === serializer ? SERIALIZER_ALIAS[serializer] : serializer
|
20
|
+
end
|
21
|
+
|
16
22
|
def load_extension_attr_hash
|
17
|
-
EXTENSION_ATTR_HASH_SERIALIZER.load(self
|
23
|
+
EXTENSION_ATTR_HASH_SERIALIZER.load(StringIO.new(self.orig_get(EXTENSION_ATTR_HASH_KEY)))
|
18
24
|
end
|
19
25
|
|
20
26
|
def save_extension_attr_hash
|
21
|
-
self
|
27
|
+
self.orig_set(EXTENSION_ATTR_HASH_KEY, EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash))
|
22
28
|
end
|
23
29
|
|
24
30
|
def self.extended(base)
|
25
|
-
if base.
|
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
|
31
|
+
return if base.respond_to?(:orig_set)
|
30
32
|
|
31
33
|
class << base
|
32
34
|
alias orig_set []=
|
@@ -43,37 +45,24 @@ module TSVAdapter
|
|
43
45
|
super(key, save_value(value))
|
44
46
|
end
|
45
47
|
end
|
46
|
-
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
def load_value(value)
|
52
|
-
value
|
53
|
-
end
|
54
|
-
def save_value(value)
|
55
|
-
value
|
56
|
-
end
|
49
|
+
def load_value(str)
|
50
|
+
return nil if str.nil?
|
51
|
+
serializer.load(str)
|
57
52
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
53
|
+
|
54
|
+
def save_value(value)
|
55
|
+
serializer.dump(value)
|
75
56
|
end
|
76
57
|
end
|
58
|
+
|
59
|
+
if base.include?(EXTENSION_ATTR_HASH_KEY)
|
60
|
+
TSV.setup(base, base.load_extension_attr_hash)
|
61
|
+
else
|
62
|
+
base.instance_variable_get(:@extension_attrs).push :serializer
|
63
|
+
base.serializer = SERIALIZER_ALIAS[base.type] if base.serializer.nil?
|
64
|
+
base.save_extension_attr_hash
|
65
|
+
end
|
77
66
|
end
|
78
67
|
|
79
68
|
def keys(*args)
|
@@ -82,9 +71,9 @@ module TSVAdapter
|
|
82
71
|
end
|
83
72
|
|
84
73
|
if k[0] == EXTENSION_ATTR_HASH_KEY
|
85
|
-
k.slice(1,k.length
|
74
|
+
k.slice(1,k.length)
|
86
75
|
elsif k[-1] == EXTENSION_ATTR_HASH_KEY
|
87
|
-
k.slice(0,k.length-
|
76
|
+
k.slice(0,k.length-1)
|
88
77
|
else
|
89
78
|
k - [EXTENSION_ATTR_HASH_KEY]
|
90
79
|
end
|
@@ -0,0 +1,327 @@
|
|
1
|
+
class FixWidthTable
|
2
|
+
|
3
|
+
attr_accessor :filename, :file, :value_size, :record_size, :range, :size, :mask, :write
|
4
|
+
def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true)
|
5
|
+
filename = filename.find if Path === filename
|
6
|
+
@filename = filename
|
7
|
+
|
8
|
+
if update || %w(memory stringio).include?(filename.to_s.downcase) || ! File.exist?(filename)
|
9
|
+
Log.debug "FixWidthTable create: #{ filename }"
|
10
|
+
@value_size = value_size
|
11
|
+
@range = range
|
12
|
+
@record_size = @value_size + (@range ? 16 : 8)
|
13
|
+
@write = true
|
14
|
+
|
15
|
+
if %w(memory stringio).include?(filename.to_s.downcase)
|
16
|
+
@filename = :memory
|
17
|
+
@file = StringIO.new
|
18
|
+
else
|
19
|
+
FileUtils.rm @filename if File.exist? @filename
|
20
|
+
FileUtils.mkdir_p File.dirname(@filename) unless File.exist? @filename
|
21
|
+
@file = File.open(@filename, 'w:ASCII-8BIT')
|
22
|
+
end
|
23
|
+
|
24
|
+
@file.write [value_size].pack("L")
|
25
|
+
@file.write [@range ? 1 : 0 ].pack("C")
|
26
|
+
|
27
|
+
@size = 0
|
28
|
+
else
|
29
|
+
Log.debug "FixWidthTable up-to-date: #{ filename } - (in_memory:#{in_memory})"
|
30
|
+
if in_memory
|
31
|
+
@file = Open.open(@filename, :mode => 'r:ASCII-8BIT'){|f| StringIO.new f.read}
|
32
|
+
else
|
33
|
+
@file = File.open(@filename, 'r:ASCII-8BIT')
|
34
|
+
end
|
35
|
+
@value_size = @file.read(4).unpack("L").first
|
36
|
+
@range = @file.read(1).unpack("C").first == 1
|
37
|
+
@record_size = @value_size + (@range ? 16 : 8)
|
38
|
+
@write = false
|
39
|
+
|
40
|
+
@size = (File.size(@filename) - 5) / (@record_size)
|
41
|
+
end
|
42
|
+
|
43
|
+
@mask = "a#{@value_size}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def write?
|
47
|
+
@write
|
48
|
+
end
|
49
|
+
|
50
|
+
def persistence_path
|
51
|
+
@filename
|
52
|
+
end
|
53
|
+
|
54
|
+
def persistence_path=(value)
|
55
|
+
@filename=value
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.get(filename, value_size = nil, range = nil, update = false)
|
59
|
+
return self.new(filename, value_size, range, update) if filename == :memory
|
60
|
+
case
|
61
|
+
when (!File.exist?(filename) or update or not Persist::CONNECTIONS.include?(filename))
|
62
|
+
Persist::CONNECTIONS[filename] = self.new(filename, value_size, range, update)
|
63
|
+
end
|
64
|
+
|
65
|
+
Persist::CONNECTIONS[filename]
|
66
|
+
end
|
67
|
+
|
68
|
+
def format(pos, value)
|
69
|
+
padding = value_size - value.length
|
70
|
+
if @range
|
71
|
+
(pos + [padding, value + ("\0" * padding)]).pack("llll#{mask}")
|
72
|
+
else
|
73
|
+
[pos, padding, value + ("\0" * padding)].pack("ll#{mask}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add(pos, value)
|
78
|
+
format = format(pos, value)
|
79
|
+
@file.write format
|
80
|
+
|
81
|
+
@size += 1
|
82
|
+
end
|
83
|
+
|
84
|
+
def last_pos
|
85
|
+
pos(size - 1)
|
86
|
+
end
|
87
|
+
|
88
|
+
def idx_pos(index)
|
89
|
+
return nil if index < 0 or index >= size
|
90
|
+
@file.seek(5 + (record_size) * index, IO::SEEK_SET)
|
91
|
+
@file.read(4).unpack("l").first
|
92
|
+
end
|
93
|
+
|
94
|
+
def idx_pos_end(index)
|
95
|
+
return nil if index < 0 or index >= size
|
96
|
+
@file.seek(9 + (record_size) * index, IO::SEEK_SET)
|
97
|
+
@file.read(4).unpack("l").first
|
98
|
+
end
|
99
|
+
|
100
|
+
def idx_overlap(index)
|
101
|
+
return nil if index < 0 or index >= size
|
102
|
+
@file.seek(13 + (record_size) * index, IO::SEEK_SET)
|
103
|
+
@file.read(4).unpack("l").first
|
104
|
+
end
|
105
|
+
|
106
|
+
def idx_value(index)
|
107
|
+
return nil if index < 0 or index >= size
|
108
|
+
@file.seek((@range ? 17 : 9 ) + (record_size) * index, IO::SEEK_SET)
|
109
|
+
padding = @file.read(4).unpack("l").first+1
|
110
|
+
txt = @file.read(value_size)
|
111
|
+
str = txt.unpack(mask).first
|
112
|
+
padding > 1 ? str[0..-padding] : str
|
113
|
+
end
|
114
|
+
|
115
|
+
def read(force = false)
|
116
|
+
return if @filename == :memory
|
117
|
+
@write = false
|
118
|
+
@file.close unless @file.closed?
|
119
|
+
@file = File.open(filename, 'r:ASCII-8BIT')
|
120
|
+
end
|
121
|
+
|
122
|
+
def close
|
123
|
+
@write = false
|
124
|
+
@file.close
|
125
|
+
end
|
126
|
+
|
127
|
+
def dump
|
128
|
+
read
|
129
|
+
@file.rewind
|
130
|
+
@file.read
|
131
|
+
end
|
132
|
+
|
133
|
+
#{{{ Adding data
|
134
|
+
|
135
|
+
def add_point(data)
|
136
|
+
data.sort_by{|value,pos| pos }.each do |value, pos|
|
137
|
+
add pos, value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_range_point(pos, value)
|
142
|
+
@latest ||= []
|
143
|
+
while @latest.any? and @latest[0] < pos[0]
|
144
|
+
@latest.shift
|
145
|
+
end
|
146
|
+
overlap = @latest.length
|
147
|
+
add pos + [overlap], value
|
148
|
+
@latest << pos[1]
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_range(data)
|
152
|
+
@latest = []
|
153
|
+
data.sort_by{|value, pos| pos[0] }.each do |value, pos|
|
154
|
+
add_range_point(pos, value)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#{{{ Searching
|
159
|
+
|
160
|
+
def closest(pos)
|
161
|
+
upper = size - 1
|
162
|
+
lower = 0
|
163
|
+
|
164
|
+
return -1 if upper < lower
|
165
|
+
|
166
|
+
while(upper >= lower) do
|
167
|
+
idx = lower + (upper - lower) / 2
|
168
|
+
pos_idx = idx_pos(idx)
|
169
|
+
|
170
|
+
case pos <=> pos_idx
|
171
|
+
when 0
|
172
|
+
break
|
173
|
+
when -1
|
174
|
+
upper = idx - 1
|
175
|
+
when 1
|
176
|
+
lower = idx + 1
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
if pos_idx > pos
|
181
|
+
idx = idx - 1
|
182
|
+
end
|
183
|
+
|
184
|
+
idx.to_i
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_range(pos, return_idx = false)
|
188
|
+
case pos
|
189
|
+
when Range
|
190
|
+
r_start = pos.begin
|
191
|
+
r_end = pos.end
|
192
|
+
when Array
|
193
|
+
r_start, r_end = pos
|
194
|
+
else
|
195
|
+
r_start, r_end = pos, pos
|
196
|
+
end
|
197
|
+
|
198
|
+
idx = closest(r_start)
|
199
|
+
|
200
|
+
return [] if idx >= size
|
201
|
+
return [] if idx < 0 and r_start == r_end
|
202
|
+
|
203
|
+
idx = 0 if idx < 0
|
204
|
+
|
205
|
+
overlap = idx_overlap(idx)
|
206
|
+
|
207
|
+
idx -= overlap unless overlap.nil?
|
208
|
+
|
209
|
+
values = []
|
210
|
+
l_start = idx_pos(idx)
|
211
|
+
l_end = idx_pos_end(idx)
|
212
|
+
|
213
|
+
if return_idx
|
214
|
+
while l_start <= r_end
|
215
|
+
values << idx if l_end >= r_start
|
216
|
+
idx += 1
|
217
|
+
break if idx >= size
|
218
|
+
l_start = idx_pos(idx)
|
219
|
+
l_end = idx_pos_end(idx)
|
220
|
+
end
|
221
|
+
else
|
222
|
+
while l_start <= r_end
|
223
|
+
values << idx_value(idx) if l_end >= r_start
|
224
|
+
idx += 1
|
225
|
+
break if idx >= size
|
226
|
+
l_start = idx_pos(idx)
|
227
|
+
l_end = idx_pos_end(idx)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
values
|
232
|
+
end
|
233
|
+
|
234
|
+
def get_point(pos, return_idx = false)
|
235
|
+
if Range === pos
|
236
|
+
r_start = pos.begin
|
237
|
+
r_end = pos.end
|
238
|
+
else
|
239
|
+
r_start = pos.to_i
|
240
|
+
r_end = pos.to_i
|
241
|
+
end
|
242
|
+
|
243
|
+
idx = closest(r_start)
|
244
|
+
|
245
|
+
return [] if idx >= size
|
246
|
+
return [] if idx < 0 and r_start == r_end
|
247
|
+
|
248
|
+
idx = 0 if idx < 0
|
249
|
+
|
250
|
+
idx += 1 unless idx_pos(idx) >= r_start
|
251
|
+
|
252
|
+
return [] if idx >= size
|
253
|
+
|
254
|
+
values = []
|
255
|
+
l_start = idx_pos(idx)
|
256
|
+
l_end = idx_pos_end(idx)
|
257
|
+
if return_idx
|
258
|
+
while l_start <= r_end
|
259
|
+
values << idx
|
260
|
+
idx += 1
|
261
|
+
break if idx >= size
|
262
|
+
l_start = idx_pos(idx)
|
263
|
+
l_end = idx_pos_end(idx)
|
264
|
+
end
|
265
|
+
else
|
266
|
+
while l_start <= r_end
|
267
|
+
values << idx_value(idx)
|
268
|
+
idx += 1
|
269
|
+
break if idx >= size
|
270
|
+
l_start = idx_pos(idx)
|
271
|
+
l_end = idx_pos_end(idx)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
values
|
276
|
+
end
|
277
|
+
|
278
|
+
def [](pos)
|
279
|
+
return [] if size == 0
|
280
|
+
self.read
|
281
|
+
if @range
|
282
|
+
get_range(pos)
|
283
|
+
else
|
284
|
+
get_point(pos)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def overlaps(pos, value = false)
|
289
|
+
return [] if size == 0
|
290
|
+
idxs = if @range
|
291
|
+
get_range(pos, true)
|
292
|
+
else
|
293
|
+
get_point(pos, true)
|
294
|
+
end
|
295
|
+
if value
|
296
|
+
idxs.collect{|idx| [idx_pos(idx), idx_pos_end(idx), idx_value(idx)] * ":"}
|
297
|
+
else
|
298
|
+
idxs.collect{|idx| [idx_pos(idx), idx_pos_end(idx)] * ":"}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
def values_at(*list)
|
304
|
+
list.collect{|pos|
|
305
|
+
self[pos]
|
306
|
+
}
|
307
|
+
end
|
308
|
+
|
309
|
+
def chunked_values_at(keys, max = 5000)
|
310
|
+
Misc.ordered_divide(keys, max).inject([]) do |acc,c|
|
311
|
+
new = self.values_at(*c)
|
312
|
+
new.annotate acc if new.respond_to? :annotate and acc.empty?
|
313
|
+
acc.concat(new)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
alias length size
|
318
|
+
end
|
319
|
+
|
320
|
+
Persist.save_drivers[:fwt] = proc do |file, content|
|
321
|
+
content.file.seek 0
|
322
|
+
Misc.sensiblewrite(file, content.file.read)
|
323
|
+
end
|
324
|
+
|
325
|
+
Persist.load_drivers[:fwt] = proc do |file|
|
326
|
+
FixWidthTable.new file
|
327
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'base64'
|
2
|
+
module TSVAdapter
|
3
|
+
|
4
|
+
class CleanSerializer
|
5
|
+
def self.dump(o); o end
|
6
|
+
def self.load(o); o end
|
7
|
+
end
|
8
|
+
|
9
|
+
class BinarySerializer
|
10
|
+
def self.dump(o); [o].pack('m'); end
|
11
|
+
def self.load(str); str.unpack('m').first; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class IntegerSerializer
|
15
|
+
def self.dump(i); [i].pack("l"); end
|
16
|
+
def self.load(str); str.unpack("l").first; end
|
17
|
+
end
|
18
|
+
|
19
|
+
class FloatSerializer
|
20
|
+
def self.dump(i); [i].pack("d"); end
|
21
|
+
def self.load(str); str.unpack("d").first; end
|
22
|
+
end
|
23
|
+
|
24
|
+
class StrictIntegerArraySerializer
|
25
|
+
def self.dump(a); a.pack("l*"); end
|
26
|
+
def self.load(str); a = str.unpack("l*"); end
|
27
|
+
end
|
28
|
+
|
29
|
+
class StrictFloatArraySerializer
|
30
|
+
def self.dump(a); a.pack("d*"); end
|
31
|
+
def self.load(str); a = str.unpack("d*"); end
|
32
|
+
end
|
33
|
+
|
34
|
+
class IntegerArraySerializer
|
35
|
+
NIL_INT = -999
|
36
|
+
def self.dump(a); a.collect{|v| v || NIL_INT}.pack("l*"); end
|
37
|
+
def self.load(str); a = str.unpack("l*"); a.collect{|v| v == NIL_INT ? nil : v}; end
|
38
|
+
end
|
39
|
+
|
40
|
+
class FloatArraySerializer
|
41
|
+
NIL_FLOAT = -999.999
|
42
|
+
def self.dump(a); a.collect{|v| v || NIL_FLOAT}.pack("d*"); end
|
43
|
+
def self.load(str); a = str.unpack("d*"); a.collect{|v| v == NIL_FLOAT ? nil : v}; end
|
44
|
+
end
|
45
|
+
|
46
|
+
class StringSerializer
|
47
|
+
def self.dump(str); str.to_s; end
|
48
|
+
def self.load(str); str.dup; end
|
49
|
+
end
|
50
|
+
|
51
|
+
class StringArraySerializer
|
52
|
+
def self.dump(array)
|
53
|
+
array.collect{|a| a.to_s} * "\t"
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.load(string)
|
57
|
+
return nil if string.nil? or string == 'nil'
|
58
|
+
return [] if string.empty?
|
59
|
+
string.split("\t", -1)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class StringDoubleArraySerializer
|
64
|
+
def self.dump(array)
|
65
|
+
begin
|
66
|
+
array.collect{|a| a.collect{|a| a.to_s } * "|"} * "\t"
|
67
|
+
rescue Encoding::CompatibilityError
|
68
|
+
array.collect{|a| a.collect{|a| a.to_s.force_encoding('UTF-8')} * "|"} * "\t"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.load(string)
|
73
|
+
return [] if string.nil?
|
74
|
+
string.split("\t", -1).collect{|l| l.split("|", -1)}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class TSVMarshalSerializer
|
79
|
+
def self.dump(tsv)
|
80
|
+
Marshal.dump(tsv.dup)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.load(string)
|
84
|
+
TSV.setup Marshal.load(string)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class TSVSerializer
|
89
|
+
def self.dump(tsv)
|
90
|
+
tsv.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.load(string)
|
94
|
+
TSV.open StringIO.new(string)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
SERIALIZER_ALIAS = {
|
99
|
+
:single => StringSerializer,
|
100
|
+
:list => StringArraySerializer,
|
101
|
+
:flat => StringArraySerializer,
|
102
|
+
:double => StringDoubleArraySerializer,
|
103
|
+
:clean => CleanSerializer,
|
104
|
+
:integer => IntegerSerializer,
|
105
|
+
:float => FloatSerializer,
|
106
|
+
:integer_array => IntegerArraySerializer,
|
107
|
+
:float_array => FloatArraySerializer,
|
108
|
+
:strict_integer_array => StrictIntegerArraySerializer,
|
109
|
+
:strict_float_array => StrictFloatArraySerializer,
|
110
|
+
:marshal => Marshal,
|
111
|
+
:string => StringSerializer,
|
112
|
+
:binary => BinarySerializer,
|
113
|
+
:tsv => TSVSerializer,
|
114
|
+
:marshal_tsv => TSVMarshalSerializer
|
115
|
+
}
|
116
|
+
|
117
|
+
end
|
@@ -4,8 +4,8 @@ require_relative 'adapter'
|
|
4
4
|
module ScoutCabinet
|
5
5
|
attr_accessor :persistence_path, :persistence_class
|
6
6
|
|
7
|
-
CONNECTIONS = {}
|
8
7
|
def self.open(path, write, tokyocabinet_class = TokyoCabinet::HDB)
|
8
|
+
path = path.find if Path === path
|
9
9
|
if String === tokyocabinet_class && tokyocabinet_class.include?(":big")
|
10
10
|
big = true
|
11
11
|
tokyocabinet_class = tokyocabinet_class.split(":").first
|
@@ -16,10 +16,13 @@ module ScoutCabinet
|
|
16
16
|
dir = File.dirname(File.expand_path(path))
|
17
17
|
Open.mkdir(dir) unless File.exist?(dir)
|
18
18
|
|
19
|
+
tokyocabinet_class = tokyocabinet_class.to_s if Symbol === tokyocabinet_class
|
19
20
|
tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
|
20
21
|
tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
|
21
22
|
|
22
|
-
|
23
|
+
# Hack - Ignore warning: undefining the allocator of T_DATA class
|
24
|
+
# TokyoCabinet::HDB_data
|
25
|
+
database = Log.ignore_stderr do Persist::CONNECTIONS[path] ||= tokyocabinet_class.new end
|
23
26
|
|
24
27
|
if big and not Open.exists?(path)
|
25
28
|
database.tune(nil,nil,nil,tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
|
@@ -39,7 +42,7 @@ module ScoutCabinet
|
|
39
42
|
|
40
43
|
database.open(path, tokyocabinet_class::OREADER)
|
41
44
|
|
42
|
-
CONNECTIONS[path] = database
|
45
|
+
Persist::CONNECTIONS[path] = database
|
43
46
|
|
44
47
|
database
|
45
48
|
end
|
data/lib/scout/tsv/persist.rb
CHANGED
@@ -4,10 +4,12 @@ require_relative 'persist/tokyocabinet'
|
|
4
4
|
Persist.save_drivers[:tsv] = proc do |file,content|
|
5
5
|
stream = if IO === content
|
6
6
|
content
|
7
|
-
elsif content.respond_to?(:get_stream)
|
8
|
-
content.get_stream
|
9
7
|
elsif content.respond_to?(:stream)
|
10
8
|
content.stream
|
9
|
+
elsif content.respond_to?(:dumper_stream)
|
10
|
+
content.dumper_stream
|
11
|
+
else
|
12
|
+
content
|
11
13
|
end
|
12
14
|
Open.sensible_write(file, stream)
|
13
15
|
end
|