rufus-tokyo 1.0.1 → 1.0.2
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.
- data/CHANGELOG.txt +28 -0
- data/CREDITS.txt +1 -1
- data/MIGRATED.txt +1 -0
- data/README.rdoc +12 -5
- data/TODO.txt +16 -17
- data/lib/rufus/edo/cabcore.rb +28 -40
- data/lib/rufus/edo/cabinet/abstract.rb +41 -5
- data/lib/rufus/edo/cabinet/table.rb +5 -0
- data/lib/rufus/edo/ntyrant/abstract.rb +36 -5
- data/lib/rufus/edo/ntyrant/table.rb +5 -18
- data/lib/rufus/edo/tabcore.rb +28 -35
- data/lib/rufus/tokyo.rb +1 -1
- data/lib/rufus/tokyo/cabinet/abstract.rb +83 -59
- data/lib/rufus/tokyo/cabinet/lib.rb +7 -0
- data/lib/rufus/tokyo/cabinet/table.rb +45 -51
- data/lib/rufus/tokyo/cabinet/util.rb +3 -1
- data/lib/rufus/tokyo/config.rb +5 -4
- data/lib/rufus/tokyo/dystopia/core.rb +3 -0
- data/lib/rufus/tokyo/dystopia/lib.rb +5 -5
- data/lib/rufus/tokyo/hmethods.rb +50 -8
- data/lib/rufus/tokyo/openable.rb +23 -0
- data/lib/rufus/tokyo/transactions.rb +44 -0
- data/lib/rufus/tokyo/tyrant/abstract.rb +54 -7
- data/lib/rufus/tokyo/tyrant/lib.rb +4 -1
- data/lib/rufus/tokyo/tyrant/table.rb +4 -23
- metadata +17 -17
@@ -49,6 +49,7 @@ module Rufus::Edo
|
|
49
49
|
|
50
50
|
include Rufus::Edo::TableCore
|
51
51
|
include Rufus::Tokyo::TyrantCommons
|
52
|
+
include Rufus::Tokyo::NoTransactions
|
52
53
|
|
53
54
|
attr_reader :host, :port
|
54
55
|
|
@@ -87,6 +88,8 @@ module Rufus::Edo
|
|
87
88
|
@db = TokyoTyrant::RDBTBL.new
|
88
89
|
@db.open(host, port) || raise_error
|
89
90
|
|
91
|
+
@default_proc = nil
|
92
|
+
|
90
93
|
if self.stat['type'] != 'table'
|
91
94
|
|
92
95
|
@db.close
|
@@ -99,9 +102,9 @@ module Rufus::Edo
|
|
99
102
|
|
100
103
|
# Gets multiple records in one sweep.
|
101
104
|
#
|
102
|
-
def lget (keys)
|
105
|
+
def lget (*keys)
|
103
106
|
|
104
|
-
h = keys.inject({}) { |
|
107
|
+
h = keys.flatten.inject({}) { |hh, k| hh[k] = nil; hh }
|
105
108
|
r = @db.mget(h)
|
106
109
|
|
107
110
|
raise 'lget failure' if r == -1
|
@@ -111,22 +114,6 @@ module Rufus::Edo
|
|
111
114
|
|
112
115
|
alias :mget :lget
|
113
116
|
|
114
|
-
def transaction #:nodoc#
|
115
|
-
raise NoMethodError.new("NetTyrant : transactions not supported")
|
116
|
-
end
|
117
|
-
def abort #:nodoc#
|
118
|
-
raise NoMethodError.new("NetTyrant : transactions not supported")
|
119
|
-
end
|
120
|
-
def tranbegin #:nodoc#
|
121
|
-
raise NoMethodError.new("NetTyrant : transactions not supported")
|
122
|
-
end
|
123
|
-
def trancommit #:nodoc#
|
124
|
-
raise NoMethodError.new("NetTyrant : transactions not supported")
|
125
|
-
end
|
126
|
-
def tranabort #:nodoc#
|
127
|
-
raise NoMethodError.new("NetTyrant : transactions not supported")
|
128
|
-
end
|
129
|
-
|
130
117
|
# Calls a lua embedded function
|
131
118
|
# (http://tokyocabinet.sourceforge.net/tyrantdoc/#luaext)
|
132
119
|
#
|
data/lib/rufus/edo/tabcore.rb
CHANGED
@@ -26,12 +26,13 @@
|
|
26
26
|
require 'rufus/tokyo/utils'
|
27
27
|
require 'rufus/tokyo/query'
|
28
28
|
require 'rufus/tokyo/transactions'
|
29
|
+
require 'rufus/tokyo/openable'
|
29
30
|
|
30
31
|
|
31
32
|
module Rufus::Edo
|
32
33
|
|
33
34
|
#
|
34
|
-
# Methods common to the two table classes (
|
35
|
+
# Methods common to the two table classes (table + ntyrant) found in
|
35
36
|
# Rufus::Edo
|
36
37
|
#
|
37
38
|
module TableCore
|
@@ -39,6 +40,11 @@ module Rufus::Edo
|
|
39
40
|
include Rufus::Tokyo::HashMethods
|
40
41
|
include Rufus::Tokyo::Transactions
|
41
42
|
|
43
|
+
# Add the open() method to all Table type classes.
|
44
|
+
def self.included(target)
|
45
|
+
target.extend(Rufus::Tokyo::Openable)
|
46
|
+
end
|
47
|
+
|
42
48
|
# Closes the table (and frees the datastructure allocated for it),
|
43
49
|
# raises an exception in case of failure.
|
44
50
|
#
|
@@ -88,7 +94,7 @@ module Rufus::Edo
|
|
88
94
|
|
89
95
|
column_name = column_name == :pk ? '' : column_name.to_s
|
90
96
|
|
91
|
-
i = types.inject(0) { |
|
97
|
+
i = types.inject(0) { |ii, t| ii | INDEX_TYPES[t] }
|
92
98
|
|
93
99
|
@db.setindex(column_name, i) || raise_error
|
94
100
|
end
|
@@ -154,46 +160,24 @@ module Rufus::Edo
|
|
154
160
|
#
|
155
161
|
def keys (options={})
|
156
162
|
|
157
|
-
|
158
|
-
|
159
|
-
@db.fwmkeys(pref, options[:limit] || -1)
|
160
|
-
|
161
|
-
else
|
162
|
-
|
163
|
-
limit = options[:limit] || -1
|
164
|
-
limit = nil if limit < 1
|
163
|
+
pref = options.fetch(:prefix, "")
|
165
164
|
|
166
|
-
|
167
|
-
|
168
|
-
l = []
|
169
|
-
|
170
|
-
while (k = @db.iternext)
|
171
|
-
break if limit and l.size >= limit
|
172
|
-
l << k
|
173
|
-
end
|
174
|
-
|
175
|
-
l
|
176
|
-
end
|
165
|
+
@db.fwmkeys(pref, options[:limit] || -1)
|
177
166
|
end
|
178
167
|
|
179
168
|
# Deletes all the entries whose key begin with the given prefix.
|
180
169
|
#
|
181
170
|
def delete_keys_with_prefix (prefix)
|
182
171
|
|
183
|
-
|
184
|
-
@db.misc('outlist', @db.fwmkeys(prefix, -1))
|
185
|
-
else
|
186
|
-
ks = @db.fwmkeys(prefix, -1) # -1 for no limit
|
187
|
-
ks.each { |k| self.delete(k) }
|
188
|
-
end
|
172
|
+
query_delete { |q| q.add('', :strbw, prefix) }
|
189
173
|
end
|
190
174
|
|
191
175
|
# Returns a hash { key => record } of all the records matching the
|
192
176
|
# given keys.
|
193
177
|
#
|
194
|
-
def lget (keys)
|
178
|
+
def lget (*keys)
|
195
179
|
|
196
|
-
keys = Rufus::Tokyo::h_or_a_to_s(keys)
|
180
|
+
keys = Rufus::Tokyo::h_or_a_to_s(keys.flatten)
|
197
181
|
|
198
182
|
if @db.respond_to?(:mget)
|
199
183
|
@db.mget(keys)
|
@@ -236,6 +220,15 @@ module Rufus::Edo
|
|
236
220
|
prepare_query(&block).delete
|
237
221
|
end
|
238
222
|
|
223
|
+
# Prepares, runs AND counts all the matching records.
|
224
|
+
#
|
225
|
+
def query_count (&block)
|
226
|
+
|
227
|
+
prepare_query { |q|
|
228
|
+
q.pk_only # improve efficiency, since we have to do the query
|
229
|
+
}.count
|
230
|
+
end
|
231
|
+
|
239
232
|
# Warning : this method is low-level, you probably only need
|
240
233
|
# to use #transaction and a block.
|
241
234
|
#
|
@@ -443,10 +436,10 @@ module Rufus::Edo
|
|
443
436
|
#
|
444
437
|
def initialize (query_class, table)
|
445
438
|
|
446
|
-
@table
|
447
|
-
@query
|
448
|
-
|
449
|
-
@
|
439
|
+
@table = table
|
440
|
+
@query = query_class.new(table.original)
|
441
|
+
@opts = {}
|
442
|
+
@has_run = false
|
450
443
|
end
|
451
444
|
|
452
445
|
# Returns the original, underlying RDBQUERY instance.
|
@@ -624,7 +617,7 @@ module Rufus::Edo
|
|
624
617
|
# Runs this query (returns a TableResultSet instance)
|
625
618
|
#
|
626
619
|
def run
|
627
|
-
|
620
|
+
@has_run = true
|
628
621
|
@last_resultset = TableResultSet.new(@table, @query.search, @opts)
|
629
622
|
end
|
630
623
|
|
@@ -642,7 +635,7 @@ module Rufus::Edo
|
|
642
635
|
|
643
636
|
#@query.count
|
644
637
|
# not yet implemented by Hirabayashi-san
|
645
|
-
|
638
|
+
run.free unless @has_run
|
646
639
|
@last_resultset ? @last_resultset.size : 0
|
647
640
|
end
|
648
641
|
|
data/lib/rufus/tokyo.rb
CHANGED
@@ -25,6 +25,8 @@
|
|
25
25
|
|
26
26
|
require 'rufus/tokyo/transactions'
|
27
27
|
require 'rufus/tokyo/outlen'
|
28
|
+
#require 'rufus/tokyo/config'
|
29
|
+
require 'rufus/tokyo/openable'
|
28
30
|
|
29
31
|
|
30
32
|
module Rufus::Tokyo
|
@@ -54,6 +56,8 @@ module Rufus::Tokyo
|
|
54
56
|
include HashMethods
|
55
57
|
include Transactions
|
56
58
|
include Outlen
|
59
|
+
#include CabinetConfig
|
60
|
+
extend Openable
|
57
61
|
|
58
62
|
# Creates/opens the cabinet, raises an exception in case of
|
59
63
|
# creation/opening failure.
|
@@ -124,11 +128,29 @@ module Rufus::Tokyo
|
|
124
128
|
# db = Rufus::Tokyo::Cabinet.new(
|
125
129
|
# 'data', :type => :hash, :opts => 'ld', :mode => 'w')
|
126
130
|
#
|
127
|
-
# === mode
|
131
|
+
# === :mode
|
128
132
|
#
|
129
133
|
# * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
|
130
134
|
# 'e' non locking, 'f' non blocking lock), default is 'wc'
|
131
135
|
#
|
136
|
+
# === :default and :default_proc
|
137
|
+
#
|
138
|
+
# Much like a Ruby Hash, a Cabinet accepts a default value or a default_proc
|
139
|
+
#
|
140
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tch', :default => 'xxx')
|
141
|
+
# db['fred'] = 'Astaire'
|
142
|
+
# p db['fred'] # => 'Astaire'
|
143
|
+
# p db['ginger'] # => 'xxx'
|
144
|
+
#
|
145
|
+
# db = Rufus::Tokyo::Cabinet.new(
|
146
|
+
# 'data.tch',
|
147
|
+
# :default_proc => lambda { |cab, key| "not found : '#{k}'" }
|
148
|
+
# p db['ginger'] # => "not found : 'ginger'"
|
149
|
+
#
|
150
|
+
# The first arg passed to the default_proc is the cabinet itself, so this
|
151
|
+
# opens up interesting possibilities.
|
152
|
+
#
|
153
|
+
#
|
132
154
|
# === other parameters
|
133
155
|
#
|
134
156
|
# 'On-memory hash database supports "bnum", "capnum", and "capsiz".
|
@@ -178,6 +200,9 @@ module Rufus::Tokyo
|
|
178
200
|
#
|
179
201
|
def initialize (name, params={})
|
180
202
|
|
203
|
+
#conf = determine_conf(path, params)
|
204
|
+
# not using it
|
205
|
+
|
181
206
|
@db = lib.tcadbnew
|
182
207
|
|
183
208
|
name = '*' if name == :mem_hash # in memory hash database
|
@@ -188,35 +213,20 @@ module Rufus::Tokyo
|
|
188
213
|
end
|
189
214
|
|
190
215
|
@path = name
|
216
|
+
@type = File.extname(@path)[1..-1]
|
191
217
|
|
192
218
|
name = name + params.collect { |k, v| "##{k}=#{v}" }.join('')
|
193
219
|
|
194
|
-
(lib.tcadbopen(@db, name)
|
220
|
+
(lib.tcadbopen(@db, name) != 0) || raise(
|
195
221
|
TokyoError.new("failed to open/create db '#{name}' #{params.inspect}"))
|
196
222
|
|
223
|
+
#
|
224
|
+
# default value|proc
|
225
|
+
|
197
226
|
self.default = params[:default]
|
198
227
|
@default_proc ||= params[:default_proc]
|
199
228
|
end
|
200
229
|
|
201
|
-
# Same args as initialize, but can take a block form that will
|
202
|
-
# close the db when done. Similar to File.open
|
203
|
-
#
|
204
|
-
def self.open (name, params={})
|
205
|
-
|
206
|
-
db = self.new(name, params)
|
207
|
-
|
208
|
-
if block_given?
|
209
|
-
yield db
|
210
|
-
nil
|
211
|
-
else
|
212
|
-
db
|
213
|
-
end
|
214
|
-
|
215
|
-
ensure
|
216
|
-
|
217
|
-
db.close if block_given? && db
|
218
|
-
end
|
219
|
-
|
220
230
|
# Returns a new in-memory hash. Accepts the same optional params hash
|
221
231
|
# as new().
|
222
232
|
#
|
@@ -382,41 +392,20 @@ module Rufus::Tokyo
|
|
382
392
|
#
|
383
393
|
def keys (options={})
|
384
394
|
|
385
|
-
|
386
|
-
|
387
|
-
|
395
|
+
if @type == "tcf"
|
396
|
+
min, max = "min", "max"
|
397
|
+
l = lib.tcfdbrange2( as_fixed, min, Rufus::Tokyo.blen(min),
|
398
|
+
max, Rufus::Tokyo.blen(max), -1)
|
399
|
+
else
|
400
|
+
pre = options.fetch(:prefix, "")
|
388
401
|
|
389
402
|
l = lib.abs_fwmkeys(
|
390
403
|
@db, pre, Rufus::Tokyo.blen(pre), options[:limit] || -1)
|
391
|
-
|
392
|
-
l = Rufus::Tokyo::List.new(l)
|
393
|
-
|
394
|
-
options[:native] ? l : l.release
|
395
|
-
|
396
|
-
else
|
397
|
-
|
398
|
-
limit = options[:limit] || -1
|
399
|
-
limit = nil if limit < 1
|
400
|
-
|
401
|
-
l = options[:native] ? Rufus::Tokyo::List.new : []
|
402
|
-
|
403
|
-
lib.abs_iterinit(@db)
|
404
|
-
|
405
|
-
outlen = FFI::MemoryPointer.new(:int)
|
406
|
-
|
407
|
-
loop do
|
408
|
-
break if limit and l.size >= limit
|
409
|
-
out = lib.abs_iternext(@db, outlen)
|
410
|
-
break if out.address == 0
|
411
|
-
l << out.get_bytes(0, outlen.get_int(0))
|
412
|
-
end
|
413
|
-
|
414
|
-
l
|
415
404
|
end
|
416
405
|
|
417
|
-
|
406
|
+
l = Rufus::Tokyo::List.new(l)
|
418
407
|
|
419
|
-
|
408
|
+
options[:native] ? l : l.release
|
420
409
|
end
|
421
410
|
|
422
411
|
# Deletes all the entries whose keys begin with the given prefix
|
@@ -433,9 +422,9 @@ module Rufus::Tokyo
|
|
433
422
|
# Given a list of keys, returns a Hash { key => value } of the
|
434
423
|
# matching entries (in one sweep).
|
435
424
|
#
|
436
|
-
def lget (keys)
|
425
|
+
def lget (*keys)
|
437
426
|
|
438
|
-
keys = keys.collect { |k| k.to_s }
|
427
|
+
keys = keys.flatten.collect { |k| k.to_s }
|
439
428
|
|
440
429
|
Hash[*call_misc('getlist', Rufus::Tokyo::List.new(keys))]
|
441
430
|
end
|
@@ -460,11 +449,11 @@ module Rufus::Tokyo
|
|
460
449
|
|
461
450
|
# Given a list of keys, deletes all the matching entries (in one sweep).
|
462
451
|
#
|
463
|
-
def ldelete (keys)
|
452
|
+
def ldelete (*keys)
|
464
453
|
|
465
|
-
|
466
|
-
|
467
|
-
|
454
|
+
call_misc(
|
455
|
+
'outlist',
|
456
|
+
Rufus::Tokyo::List.new(keys.flatten.collect { |k| k.to_s }))
|
468
457
|
end
|
469
458
|
|
470
459
|
# Increments the value stored under the given key with the given increment
|
@@ -472,6 +461,11 @@ module Rufus::Tokyo
|
|
472
461
|
#
|
473
462
|
# Accepts an integer or a double value.
|
474
463
|
#
|
464
|
+
# Warning : Tokyo Cabinet/Tyrant doesn't store counter values as regular
|
465
|
+
# strings (db['key'] won't yield something that replies properly to #to_i)
|
466
|
+
#
|
467
|
+
# Use #counter_value(k) to get the current value set for the counter.
|
468
|
+
#
|
475
469
|
def incr (key, inc=1)
|
476
470
|
|
477
471
|
key = key.to_s
|
@@ -482,7 +476,7 @@ module Rufus::Tokyo
|
|
482
476
|
|
483
477
|
raise(TokyoError.new(
|
484
478
|
"incr failed, there is probably already a string value set " +
|
485
|
-
"for the key '#{key}'"
|
479
|
+
"for the key '#{key}'. Make sure there is no value before incrementing"
|
486
480
|
)) if v == Rufus::Tokyo::INT_MIN || (v.respond_to?(:nan?) && v.nan?)
|
487
481
|
|
488
482
|
v
|
@@ -492,6 +486,15 @@ module Rufus::Tokyo
|
|
492
486
|
alias :add_int :incr
|
493
487
|
alias :add_double :incr
|
494
488
|
|
489
|
+
# Returns the current value for a counter (a float or an int).
|
490
|
+
#
|
491
|
+
# See #incr
|
492
|
+
#
|
493
|
+
def counter_value (key)
|
494
|
+
|
495
|
+
incr(key, 0.0) rescue incr(key, 0)
|
496
|
+
end
|
497
|
+
|
495
498
|
# Triggers a defrag run (TC >= 1.4.21 only)
|
496
499
|
#
|
497
500
|
def defrag
|
@@ -581,6 +584,27 @@ module Rufus::Tokyo
|
|
581
584
|
lib.tcadbreveal(@db)
|
582
585
|
end
|
583
586
|
|
587
|
+
# Returns the pointer to the fixed-width database hiding behind the
|
588
|
+
# abstract structure.
|
589
|
+
#
|
590
|
+
# Will raise an argument error if the structure behind the abstract db
|
591
|
+
# is not a fixed-width structure.
|
592
|
+
#
|
593
|
+
def as_fixed
|
594
|
+
|
595
|
+
raise(NoMethodError.new("cannot call Fixed-width function on #{@path}")) \
|
596
|
+
if ! @path.match(/\.tcf$/)
|
597
|
+
|
598
|
+
lib.tcadbreveal(@db)
|
599
|
+
end
|
600
|
+
|
601
|
+
# Advanced function. Initially added to uncover tc{b|f|h}dbsetmutex().
|
602
|
+
#
|
603
|
+
def call_non_abstract_function (funcname, *args)
|
604
|
+
|
605
|
+
lib.send(lib.tcadbreveal(@db), "#{@type}#{funcname}", *args)
|
606
|
+
end
|
607
|
+
|
584
608
|
#--
|
585
609
|
#def check_transaction_support
|
586
610
|
# raise(TokyoError.new(
|
@@ -616,8 +640,8 @@ module Rufus::Tokyo
|
|
616
640
|
|
617
641
|
def libcall (lib_method, *args)
|
618
642
|
|
619
|
-
(
|
620
|
-
|
643
|
+
raise TokyoError.new("call to #{lib_method} failed") \
|
644
|
+
unless lib.send(lib_method, @db, *args) == 1
|
621
645
|
end
|
622
646
|
|
623
647
|
end
|
@@ -198,6 +198,13 @@ module Rufus::Tokyo
|
|
198
198
|
attfunc :tcbdbputdup, [ :pointer, :pointer, :int, :pointer, :int ], :int
|
199
199
|
attfunc :tcbdbget4, [ :pointer, :pointer, :int ], :pointer
|
200
200
|
|
201
|
+
#
|
202
|
+
# tcfdb functions
|
203
|
+
#
|
204
|
+
# http://tokyocabinet.sourceforge.net/spex-en.html#tcfdbapi
|
205
|
+
|
206
|
+
attfunc :tcfdbrange2, [ :pointer, :pointer, :int, :pointer, :int, :int ], :pointer
|
207
|
+
|
201
208
|
#
|
202
209
|
# tcmap functions
|
203
210
|
#
|