rbbt-util 3.2.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/run_workflow.rb +118 -0
- data/lib/rbbt-util.rb +0 -3
- data/lib/rbbt/util/fix_width_table.rb +7 -0
- data/lib/rbbt/util/misc.rb +20 -4
- data/lib/rbbt/util/persistence.rb +51 -28
- data/lib/rbbt/util/resource.rb +1 -0
- data/lib/rbbt/util/task.rb +11 -0
- data/lib/rbbt/util/task/job.rb +3 -1
- data/lib/rbbt/util/tc_hash.rb +89 -20
- data/lib/rbbt/util/tsv.rb +23 -8
- data/lib/rbbt/util/tsv/accessor.rb +8 -5
- data/lib/rbbt/util/tsv/filters.rb +68 -20
- data/lib/rbbt/util/tsv/index.rb +115 -92
- data/lib/rbbt/util/tsv/manipulate.rb +10 -13
- data/lib/rbbt/util/tsv/parse.rb +1 -1
- data/lib/rbbt/util/tsv/resource.rb +8 -0
- data/lib/rbbt/util/workflow.rb +26 -8
- data/share/lib/R/util.R +71 -1
- data/test/rbbt/util/test_misc.rb +17 -0
- data/test/rbbt/util/test_persistence.rb +32 -0
- data/test/rbbt/util/test_resource.rb +1 -0
- data/test/rbbt/util/test_task.rb +14 -0
- data/test/rbbt/util/test_tc_hash.rb +16 -0
- data/test/rbbt/util/tsv/test_accessor.rb +0 -1
- data/test/rbbt/util/tsv/test_filters.rb +26 -0
- data/test/rbbt/util/tsv/test_index.rb +78 -26
- data/test/rbbt/util/tsv/test_manipulate.rb +1 -1
- metadata +10 -14
- data/bin/workflow.rb +0 -24
- data/lib/rbbt/util/bed.rb +0 -325
- data/lib/rbbt/util/cachehelper.rb +0 -100
- data/test/rbbt/util/test_bed.rb +0 -136
data/bin/run_workflow.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rbbt-util'
|
4
|
+
require 'rbbt/util/simpleopt'
|
5
|
+
require 'rbbt/util/workflow'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
def usage(task)
|
9
|
+
puts task.usage
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
def SOPT_options(task)
|
14
|
+
sopt_options = []
|
15
|
+
task.option_summary.flatten.each do |info|
|
16
|
+
name = info[:name]
|
17
|
+
short = name.to_s.chars.first
|
18
|
+
boolean = info[:type] == :boolean
|
19
|
+
|
20
|
+
sopt_options << "-#{short}--#{name}#{boolean ? '' : '*'}"
|
21
|
+
end
|
22
|
+
|
23
|
+
sopt_options * ":"
|
24
|
+
end
|
25
|
+
|
26
|
+
def fix_options(task, job_options)
|
27
|
+
option_types = task.option_summary.flatten.inject({}){|types, new| types[new[:name]] = new[:type]; types}
|
28
|
+
|
29
|
+
job_options_cleaned = {}
|
30
|
+
|
31
|
+
job_options.each do |name, value|
|
32
|
+
value = case
|
33
|
+
when option_types[name] == :float
|
34
|
+
value.to_f
|
35
|
+
when option_types[name] == :integer
|
36
|
+
value.to_i
|
37
|
+
when option_types[name] == :array
|
38
|
+
value.split(/[,|]/)
|
39
|
+
when option_types[name] == :tsv
|
40
|
+
begin
|
41
|
+
if value == '-'
|
42
|
+
TSV.new(STDIN).to_s :sort
|
43
|
+
else
|
44
|
+
TSV.new(value).to_s :sort
|
45
|
+
end
|
46
|
+
rescue
|
47
|
+
value
|
48
|
+
end
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
job_options_cleaned[name] = value
|
53
|
+
end
|
54
|
+
|
55
|
+
job_options_cleaned
|
56
|
+
end
|
57
|
+
|
58
|
+
options = SOPT.get "-t--task*:-l--log*:-h--help:-n--name:-cl--clean:-rcl-recursive_clean"
|
59
|
+
|
60
|
+
# Set log, fork, clean, recursive_clean and help
|
61
|
+
Log.severity = options[:log].to_i if options.include? :log
|
62
|
+
help = !!options.delete(:help)
|
63
|
+
do_fork = !!options.delete(:fork)
|
64
|
+
clean = !!options.delete(:clean)
|
65
|
+
recursive_clean = !!options.delete(:recursive_clean)
|
66
|
+
|
67
|
+
# Get workflow
|
68
|
+
workflow = ARGV.first
|
69
|
+
WorkFlow.require_workflow workflow
|
70
|
+
|
71
|
+
# Set task
|
72
|
+
namespace, task = nil, nil
|
73
|
+
|
74
|
+
case
|
75
|
+
when (not options[:task])
|
76
|
+
workflow_usage if help
|
77
|
+
task = self.last_task
|
78
|
+
namespace = self
|
79
|
+
when (options[:task] =~ /\./)
|
80
|
+
namespace, task = options.delete(:task).split('.')
|
81
|
+
namespace = Misc.string2const(namespace)
|
82
|
+
else
|
83
|
+
task_name = options.delete(:task)
|
84
|
+
task = self.tasks[task_name]
|
85
|
+
end
|
86
|
+
|
87
|
+
usage(task) if help
|
88
|
+
|
89
|
+
name = options.delete(:name) || "Default"
|
90
|
+
|
91
|
+
# get job args
|
92
|
+
sopt_option_string = SOPT_options(task)
|
93
|
+
job_options = SOPT.get sopt_option_string
|
94
|
+
job_options = fix_options(task, job_options)
|
95
|
+
|
96
|
+
#- get job
|
97
|
+
job = task.job(name, job_options)
|
98
|
+
|
99
|
+
# clean job
|
100
|
+
job.clean if clean
|
101
|
+
job.recursive_clean if recursive_clean
|
102
|
+
|
103
|
+
# run
|
104
|
+
if do_fork
|
105
|
+
job.fork
|
106
|
+
while not job.done?
|
107
|
+
puts "#{job.step}: #{job.messages.last}"
|
108
|
+
sleep 2
|
109
|
+
end
|
110
|
+
else
|
111
|
+
job.run
|
112
|
+
end
|
113
|
+
|
114
|
+
#- error
|
115
|
+
raise job.messages.last if job.error?
|
116
|
+
|
117
|
+
#print
|
118
|
+
pp job.load
|
data/lib/rbbt-util.rb
CHANGED
@@ -5,12 +5,9 @@ require 'rbbt/util/tmpfile'
|
|
5
5
|
require 'rbbt/util/filecache'
|
6
6
|
require 'rbbt/util/tsv'
|
7
7
|
require 'rbbt/util/persistence'
|
8
|
-
require 'rbbt/util/bed'
|
9
|
-
require 'rbbt/util/cachehelper'
|
10
8
|
require 'rbbt/util/misc'
|
11
9
|
|
12
10
|
FileCache.cachedir = Rbbt.var.cache.filecache.find :user
|
13
11
|
Open.cachedir = Rbbt.var.cache["open-remote"].find :user
|
14
12
|
TmpFile.tmpdir = Rbbt.tmp.find :user
|
15
13
|
Persistence.cachedir = Rbbt.var.cache.persistence.find :user
|
16
|
-
Bed.cachedir = Rbbt.var.cache["bed-persistence"].find :user
|
@@ -11,6 +11,7 @@ class FixWidthTable
|
|
11
11
|
@record_size = @value_size + (@range ? 12 : 4)
|
12
12
|
|
13
13
|
if %w(memory stringio).include? filename.to_s.downcase
|
14
|
+
@filename = :memory
|
14
15
|
@file = StringIO.new
|
15
16
|
else
|
16
17
|
FileUtils.rm @filename if File.exists? @filename
|
@@ -104,6 +105,12 @@ class FixWidthTable
|
|
104
105
|
@file.close
|
105
106
|
end
|
106
107
|
|
108
|
+
def dump
|
109
|
+
read
|
110
|
+
@file.rewind
|
111
|
+
@file.read
|
112
|
+
end
|
113
|
+
|
107
114
|
#{{{ Adding data
|
108
115
|
|
109
116
|
def add_point(data)
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -33,6 +33,16 @@ end
|
|
33
33
|
module Misc
|
34
34
|
class FieldNotFoundError < StandardError;end
|
35
35
|
|
36
|
+
def self.in_dir(dir)
|
37
|
+
old_pwd = FileUtils.pwd
|
38
|
+
begin
|
39
|
+
FileUtils.cd dir
|
40
|
+
yield
|
41
|
+
ensure
|
42
|
+
FileUtils.cd old_pwd
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
36
46
|
def self.intersect_sorted_arrays(a1, a2)
|
37
47
|
e1, e2 = a1.shift, a2.shift
|
38
48
|
intersect = []
|
@@ -98,6 +108,7 @@ module Misc
|
|
98
108
|
end
|
99
109
|
|
100
110
|
def self.redefine_method(object, old_method, new_method_name, &block)
|
111
|
+
return if object.respond_to? new_method_name
|
101
112
|
metaclass = class << object; self end
|
102
113
|
metaclass.send :alias_method, new_method_name, old_method
|
103
114
|
metaclass.send :define_method, old_method, &block
|
@@ -376,13 +387,16 @@ module Misc
|
|
376
387
|
chunks
|
377
388
|
end
|
378
389
|
|
390
|
+
def self.merge2hash(list1, list2)
|
391
|
+
hash = {}
|
392
|
+
list1.zip(list2).each do |k,v| hash[k] = v end
|
393
|
+
hash
|
394
|
+
end
|
379
395
|
|
380
396
|
|
381
397
|
def self.process_to_hash(list)
|
382
398
|
result = yield list
|
383
|
-
|
384
|
-
list.zip(result).each do |k,v| hash[k] = v end
|
385
|
-
hash
|
399
|
+
merge2hash(list, result)
|
386
400
|
end
|
387
401
|
|
388
402
|
IUPAC2BASE = {
|
@@ -424,7 +438,9 @@ module PDF2Text
|
|
424
438
|
require 'rbbt/util/open'
|
425
439
|
|
426
440
|
|
427
|
-
|
441
|
+
TmpFile.with_file(Open.open(filename, :nocache => true).read) do |pdf_file|
|
442
|
+
CMD.cmd("pdftotext #{pdf_file} -", :pipe => false, :stderr => true)
|
443
|
+
end
|
428
444
|
end
|
429
445
|
end
|
430
446
|
|
@@ -23,6 +23,13 @@ module Persistence
|
|
23
23
|
def self.get_persistence_file(file, prefix, options = {})
|
24
24
|
persistence_dir = Misc.process_options options, :persistence_dir
|
25
25
|
persistence_dir ||= CACHEDIR
|
26
|
+
|
27
|
+
if options.include? :filters
|
28
|
+
options[:filters].each do |match,value|
|
29
|
+
file = file + "&F[#{match}=#{Misc.digest(value.inspect)}]"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
26
33
|
name = prefix.to_s.dup << ":" << file.to_s << ":"
|
27
34
|
|
28
35
|
options_md5 = Misc.hash2md5 options
|
@@ -171,22 +178,28 @@ module Persistence
|
|
171
178
|
Log.debug "Creating #{ persistence_file }. Prefix = #{prefix}"
|
172
179
|
|
173
180
|
res = yield file, options, filename, persistence_file
|
181
|
+
|
174
182
|
serializer = tsv_serializer res
|
175
183
|
|
176
|
-
if
|
177
|
-
|
178
|
-
|
179
|
-
end
|
184
|
+
if TCHash === res
|
185
|
+
per = res
|
186
|
+
else
|
180
187
|
|
181
|
-
|
182
|
-
|
188
|
+
if File.exists? persistence_file
|
189
|
+
Log.debug "Erasing old #{ persistence_file }. Prefix = #{prefix}"
|
190
|
+
FileUtils.rm persistence_file
|
191
|
+
end
|
183
192
|
|
184
|
-
|
185
|
-
|
193
|
+
Log.debug "Dump data into '#{persistence_file}'"
|
194
|
+
per = Persistence::TSV.get persistence_file, true, serializer
|
186
195
|
|
187
|
-
|
188
|
-
|
189
|
-
|
196
|
+
per.write
|
197
|
+
per.merge! res
|
198
|
+
|
199
|
+
Persistence::TSV::FIELD_INFO_ENTRIES.keys.each do |key|
|
200
|
+
if res.respond_to?(key.to_sym) and per.respond_to?("#{key}=".to_sym)
|
201
|
+
per.send "#{key}=".to_sym, res.send(key.to_sym)
|
202
|
+
end
|
190
203
|
end
|
191
204
|
end
|
192
205
|
|
@@ -293,27 +306,36 @@ module Persistence
|
|
293
306
|
FileUtils.rm persistence_file
|
294
307
|
end
|
295
308
|
|
296
|
-
max_length = res.collect{|k,v| k.length}.max
|
297
309
|
|
298
|
-
if
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
FileUtils.rm persistence_file if File.exists? persistence_file
|
304
|
-
raise $!
|
305
|
-
end
|
310
|
+
if FixWidthTable === res and res.filename == :memory
|
311
|
+
Log.debug "Dumping memory FWT into #{ persistence_file }. Prefix = #{prefix}"
|
312
|
+
FileUtils.mkdir_p File.dirname(persistence_file) unless File.exists? File.dirname(persistence_file)
|
313
|
+
Open.write(persistence_file, res.dump)
|
314
|
+
fwt = FixWidthTable.get persistence_file
|
306
315
|
else
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
316
|
+
|
317
|
+
max_length = res.collect{|k,v| k.length}.max
|
318
|
+
|
319
|
+
if range
|
320
|
+
begin
|
321
|
+
fwt = FixWidthTable.get persistence_file, max_length, true
|
322
|
+
fwt.add_range res
|
323
|
+
rescue
|
324
|
+
FileUtils.rm persistence_file if File.exists? persistence_file
|
325
|
+
raise $!
|
326
|
+
end
|
327
|
+
else
|
328
|
+
begin
|
329
|
+
fwt = FixWidthTable.get persistence_file, max_length, false
|
330
|
+
fwt.add_point res
|
331
|
+
rescue
|
332
|
+
FileUtils.rm persistence_file
|
333
|
+
raise $!
|
334
|
+
end
|
313
335
|
end
|
314
|
-
end
|
315
336
|
|
316
|
-
|
337
|
+
fwt.read
|
338
|
+
end
|
317
339
|
|
318
340
|
fwt
|
319
341
|
else
|
@@ -327,6 +349,7 @@ module Persistence
|
|
327
349
|
|
328
350
|
def self.persist(file, prefix = "", persistence_type = :string, options = {}, &block)
|
329
351
|
options = Misc.add_defaults options, :persistence => true
|
352
|
+
|
330
353
|
persistence =
|
331
354
|
Misc.process_options options, :persistence
|
332
355
|
|
data/lib/rbbt/util/resource.rb
CHANGED
data/lib/rbbt/util/task.rb
CHANGED
@@ -55,10 +55,20 @@ class Task
|
|
55
55
|
[run_options, args, optional_args]
|
56
56
|
end
|
57
57
|
|
58
|
+
def pull_from_hash(args, optional_args)
|
59
|
+
option_summary.first.each do |info|
|
60
|
+
name = info[:name]
|
61
|
+
if optional_args.include? name
|
62
|
+
args.push optional_args.delete name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
58
67
|
def setup(jobname, args, optional_args, dependencies)
|
59
68
|
previous_jobs = []
|
60
69
|
required_files = []
|
61
70
|
|
71
|
+
pull_from_hash(args, optional_args)
|
62
72
|
run_options, args, optional_args = process_options args, optional_args
|
63
73
|
|
64
74
|
dependencies.each do |dependency|
|
@@ -89,6 +99,7 @@ class Task
|
|
89
99
|
optional_args = {}
|
90
100
|
end
|
91
101
|
|
102
|
+
|
92
103
|
previous_jobs, required_files, run_options = setup(jobname, args, optional_args, dependencies)
|
93
104
|
|
94
105
|
job_id = self.job_id jobname, run_options, previous_jobs
|
data/lib/rbbt/util/task/job.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rbbt/util/misc'
|
|
2
2
|
|
3
3
|
class Task
|
4
4
|
class Job
|
5
|
-
attr_accessor :task, :id, :name, :options, :
|
5
|
+
attr_accessor :task, :id, :name, :options, :previous_jobs, :required_files, :pid, :path, :previous_jobs, :input
|
6
6
|
|
7
7
|
IDSEP = "_"
|
8
8
|
|
@@ -285,6 +285,8 @@ class Task
|
|
285
285
|
Marshal.load(Open.read(path))
|
286
286
|
when :yaml
|
287
287
|
YAML.load(Open.read(path))
|
288
|
+
when nil
|
289
|
+
nil
|
288
290
|
end
|
289
291
|
end
|
290
292
|
|
data/lib/rbbt/util/tc_hash.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rbbt/util/misc'
|
2
2
|
require 'tokyocabinet'
|
3
|
+
require 'set'
|
3
4
|
|
4
5
|
class TCHash < TokyoCabinet::HDB
|
5
6
|
class OpenError < StandardError;end
|
@@ -10,6 +11,11 @@ class TCHash < TokyoCabinet::HDB
|
|
10
11
|
def self.load(str); str.unpack("l").first; end
|
11
12
|
end
|
12
13
|
|
14
|
+
class FloatSerializer
|
15
|
+
def self.dump(i); [i].pack("d"); end
|
16
|
+
def self.load(str); str.unpack("d").first; end
|
17
|
+
end
|
18
|
+
|
13
19
|
class IntegerArraySerializer
|
14
20
|
def self.dump(a); a.pack("l*"); end
|
15
21
|
def self.load(str); str.unpack("l*"); end
|
@@ -40,8 +46,29 @@ class TCHash < TokyoCabinet::HDB
|
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
49
|
+
class TSVSerializer
|
50
|
+
def self.dump(tsv)
|
51
|
+
tsv.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.load(string)
|
55
|
+
TSV.new StringIO.new(string)
|
56
|
+
end
|
57
|
+
end
|
43
58
|
|
44
|
-
|
59
|
+
|
60
|
+
|
61
|
+
ALIAS = {
|
62
|
+
:integer => IntegerSerializer,
|
63
|
+
:float => FloatSerializer,
|
64
|
+
:integer_array => IntegerArraySerializer,
|
65
|
+
:marshal => Marshal,
|
66
|
+
:single => StringSerializer,
|
67
|
+
:string => StringSerializer,
|
68
|
+
:list => StringArraySerializer,
|
69
|
+
:double => StringDoubleArraySerializer,
|
70
|
+
:tsv => TSVSerializer
|
71
|
+
}
|
45
72
|
|
46
73
|
CONNECTIONS = {}
|
47
74
|
|
@@ -49,7 +76,6 @@ class TCHash < TokyoCabinet::HDB
|
|
49
76
|
:type => '__tokyocabinet_hash_type',
|
50
77
|
:serializer => '__tokyocabinet_hash_serializer',
|
51
78
|
:identifiers => '__tokyocabinet_hash_identifiers',
|
52
|
-
:datadir => '__tokyocabinet_hash_datadir',
|
53
79
|
:fields => '__tokyocabinet_hash_fields',
|
54
80
|
:key_field => '__tokyocabinet_hash_key_field',
|
55
81
|
:filename => '__tokyocabinet_hash_filename',
|
@@ -74,7 +100,13 @@ class TCHash < TokyoCabinet::HDB
|
|
74
100
|
out(key) or raise "Not deleted"
|
75
101
|
end
|
76
102
|
|
77
|
-
|
103
|
+
alias original_include? include?
|
104
|
+
def include?(key)
|
105
|
+
return nil unless String === key
|
106
|
+
original_include? key
|
107
|
+
end
|
108
|
+
|
109
|
+
attr_accessor :serializer, :path_to_db
|
78
110
|
def serializer=(serializer)
|
79
111
|
|
80
112
|
if ALIAS.include? serializer.to_sym
|
@@ -97,17 +129,20 @@ class TCHash < TokyoCabinet::HDB
|
|
97
129
|
|
98
130
|
@write = write
|
99
131
|
|
100
|
-
if
|
101
|
-
serializer_str = self.original_get_brackets(FIELD_INFO_ENTRIES[:serializer])
|
132
|
+
if @serializer.nil?
|
102
133
|
|
103
|
-
|
104
|
-
|
134
|
+
if self.include? FIELD_INFO_ENTRIES[:serializer]
|
135
|
+
serializer_str = self.original_get_brackets(FIELD_INFO_ENTRIES[:serializer])
|
105
136
|
|
106
|
-
|
107
|
-
|
137
|
+
mod = Misc.string2const serializer_str
|
138
|
+
@serializer = mod
|
108
139
|
|
109
|
-
|
110
|
-
|
140
|
+
else
|
141
|
+
raise "No serializer specified" if (serializer || @serializer).nil?
|
142
|
+
|
143
|
+
self.original_set_brackets(FIELD_INFO_ENTRIES[:serializer], serializer.to_s) unless self.include? FIELD_INFO_ENTRIES[:serializer]
|
144
|
+
@serializer = serializer
|
145
|
+
end
|
111
146
|
end
|
112
147
|
end
|
113
148
|
|
@@ -116,31 +151,44 @@ class TCHash < TokyoCabinet::HDB
|
|
116
151
|
end
|
117
152
|
|
118
153
|
def write
|
154
|
+
self.sync
|
119
155
|
self.close
|
120
156
|
self.open(true)
|
121
157
|
end
|
122
158
|
|
123
159
|
def read
|
160
|
+
self.sync
|
124
161
|
self.close
|
125
162
|
self.open(false)
|
126
163
|
end
|
127
164
|
|
128
|
-
def initialize(path, write = false, serializer =
|
165
|
+
def initialize(path, write = false, serializer = nil)
|
129
166
|
super()
|
130
167
|
|
131
|
-
|
168
|
+
if ALIAS.include? serializer
|
169
|
+
@serializer = ALIAS[serializer]
|
170
|
+
else
|
171
|
+
@serializer = serializer
|
172
|
+
end
|
132
173
|
|
133
174
|
@path_to_db = path
|
134
175
|
|
135
176
|
if write || ! File.exists?(@path_to_db)
|
177
|
+
@serializer = Marshal if @serializer.nil?
|
136
178
|
self.setcache(100000) or raise "Error setting cache"
|
137
|
-
self.open(true, serializer)
|
179
|
+
self.open(true, @serializer)
|
180
|
+
self.original_set_brackets(FIELD_INFO_ENTRIES[:serializer], @serializer.to_s)
|
138
181
|
else
|
139
182
|
self.open(false)
|
140
183
|
end
|
141
184
|
end
|
142
185
|
|
143
|
-
def self.get(path, write = false, serializer =
|
186
|
+
def self.get(path, write = false, serializer = nil)
|
187
|
+
if not (TrueClass === write or FalseClass === write) and serializer.nil?
|
188
|
+
serializer = write
|
189
|
+
write = false
|
190
|
+
end
|
191
|
+
|
144
192
|
if ALIAS.include? serializer
|
145
193
|
serializer = ALIAS[serializer]
|
146
194
|
else
|
@@ -213,6 +261,7 @@ class TCHash < TokyoCabinet::HDB
|
|
213
261
|
values.collect{|v| serializer.load(v)}
|
214
262
|
end
|
215
263
|
|
264
|
+
alias real_original_each each
|
216
265
|
# This version of each fixes a problem in ruby 1.9. It also
|
217
266
|
# removes the special entries
|
218
267
|
def each(&block)
|
@@ -224,17 +273,26 @@ class TCHash < TokyoCabinet::HDB
|
|
224
273
|
keys.zip(values.collect{|v| serializer.load v}).each &block
|
225
274
|
end
|
226
275
|
|
276
|
+
def each(&block)
|
277
|
+
skippable = Set.new(FIELD_INFO_ENTRIES.values)
|
278
|
+
real_original_each do |key, value|
|
279
|
+
block.call(key, serializer.load(value)) unless skippable.include? key
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
227
283
|
alias original_each each
|
228
284
|
|
229
|
-
def collect
|
285
|
+
def collect(&block)
|
286
|
+
skippable = Set.new(FIELD_INFO_ENTRIES.values)
|
230
287
|
res = []
|
231
|
-
|
288
|
+
real_original_each do |key,value|
|
289
|
+
next if skippable.include? key
|
232
290
|
if block_given?
|
233
|
-
|
291
|
+
block.call(key, serializer.load(value))
|
234
292
|
else
|
235
|
-
res << [
|
293
|
+
res << [key, value]
|
236
294
|
end
|
237
|
-
|
295
|
+
end
|
238
296
|
res
|
239
297
|
end
|
240
298
|
|
@@ -251,5 +309,16 @@ class TCHash < TokyoCabinet::HDB
|
|
251
309
|
raise "Transaction cannot initiate"
|
252
310
|
end
|
253
311
|
end
|
312
|
+
|
313
|
+
def clear
|
314
|
+
special_values = FIELD_INFO_ENTRIES.values.sort.collect{|k| self.original_get_brackets(k)}
|
315
|
+
restore = ! write?
|
316
|
+
write if restore
|
317
|
+
vanish
|
318
|
+
FIELD_INFO_ENTRIES.values.sort.zip(special_values).each{|k,v|
|
319
|
+
self.original_set_brackets(k,v) unless v.nil?
|
320
|
+
}
|
321
|
+
read if restore
|
322
|
+
end
|
254
323
|
|
255
324
|
end
|