scout-gear 7.2.0 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|