rufus-tokyo 0.1.12 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +9 -0
- data/CREDITS.txt +1 -0
- data/README.txt +6 -1
- data/TODO.txt +11 -7
- data/lib/rufus/edo/cabcore.rb +31 -16
- data/lib/rufus/edo/cabinet/abstract.rb +11 -2
- data/lib/rufus/edo/cabinet/table.rb +19 -2
- data/lib/rufus/edo/ntyrant/table.rb +13 -0
- data/lib/rufus/edo/tabcore.rb +10 -29
- data/lib/rufus/tokyo.rb +13 -1
- data/lib/rufus/tokyo/cabinet/abstract.rb +123 -31
- data/lib/rufus/tokyo/cabinet/lib.rb +32 -30
- data/lib/rufus/tokyo/cabinet/table.rb +77 -44
- data/lib/rufus/tokyo/cabinet/util.rb +130 -93
- data/lib/rufus/tokyo/config.rb +5 -2
- data/lib/rufus/tokyo/hmethods.rb +14 -7
- data/lib/rufus/tokyo/tyrant/abstract.rb +16 -3
- data/lib/rufus/tokyo/tyrant/lib.rb +16 -10
- data/lib/rufus/tokyo/tyrant/table.rb +0 -2
- metadata +6 -4
data/lib/rufus/tokyo.rb
CHANGED
@@ -29,13 +29,25 @@ require 'ffi' # sudo gem install ffi
|
|
29
29
|
module Rufus
|
30
30
|
module Tokyo
|
31
31
|
|
32
|
-
VERSION = '0.1.
|
32
|
+
VERSION = '0.1.13'
|
33
33
|
|
34
34
|
#
|
35
35
|
# A common error class
|
36
36
|
#
|
37
37
|
class TokyoError < RuntimeError; end
|
38
38
|
|
39
|
+
#
|
40
|
+
# Grumpf, this is not elegant...
|
41
|
+
#
|
42
|
+
INT_MIN = -2147483648
|
43
|
+
|
44
|
+
# Returns 'bytesize' of the string (Ruby 1.9.1 for everyone).
|
45
|
+
#
|
46
|
+
def self.blen (s)
|
47
|
+
|
48
|
+
s.respond_to?(:bytesize) ? s.bytesize : s.size
|
49
|
+
end
|
50
|
+
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
@@ -53,7 +53,6 @@ module Rufus::Tokyo
|
|
53
53
|
include HashMethods
|
54
54
|
include Transactions
|
55
55
|
|
56
|
-
#
|
57
56
|
# Creates/opens the cabinet, raises an exception in case of
|
58
57
|
# creation/opening failure.
|
59
58
|
#
|
@@ -165,6 +164,9 @@ module Rufus::Tokyo
|
|
165
164
|
# * :capnum specifies the capacity number of records.
|
166
165
|
# * :capsiz specifies the capacity size of using memory.
|
167
166
|
#
|
167
|
+
# * :dfunit unit step number. If it is not more than 0,
|
168
|
+
# the auto defragmentation is disabled. (Since TC 1.4.21)
|
169
|
+
#
|
168
170
|
#
|
169
171
|
# = NOTE :
|
170
172
|
#
|
@@ -183,6 +185,8 @@ module Rufus::Tokyo
|
|
183
185
|
name += { :hash => '.tch', :btree => '.tcb', :fixed => '.tcf' }[type]
|
184
186
|
end
|
185
187
|
|
188
|
+
@path = name
|
189
|
+
|
186
190
|
name = name + params.collect { |k, v| "##{k}=#{v}" }.join('')
|
187
191
|
|
188
192
|
(lib.tcadbopen(@db, name) == 1) ||
|
@@ -193,130 +197,153 @@ module Rufus::Tokyo
|
|
193
197
|
end
|
194
198
|
|
195
199
|
# Same args as initialize, but can take a block form that will
|
196
|
-
# close the db when done.
|
200
|
+
# close the db when done. Similar to File.open
|
201
|
+
#
|
197
202
|
def self.open (name, params={})
|
203
|
+
|
198
204
|
db = self.new(name, params)
|
205
|
+
|
199
206
|
if block_given?
|
200
207
|
yield db
|
201
208
|
nil
|
202
209
|
else
|
203
210
|
db
|
204
211
|
end
|
212
|
+
|
205
213
|
ensure
|
214
|
+
|
206
215
|
db.close if block_given? && db
|
207
216
|
end
|
208
217
|
|
209
|
-
#
|
210
218
|
# Returns a new in-memory hash. Accepts the same optional params hash
|
211
219
|
# as new().
|
212
220
|
#
|
213
221
|
def self.new_hash (params={})
|
222
|
+
|
214
223
|
self.new(:hash, params)
|
215
224
|
end
|
216
225
|
|
217
|
-
#
|
218
226
|
# Returns a new in-memory B+ tree. Accepts the same optional params hash
|
219
227
|
# as new().
|
220
228
|
#
|
221
229
|
def self.new_tree (params={})
|
230
|
+
|
222
231
|
self.new(:tree, params)
|
223
232
|
end
|
224
233
|
|
225
|
-
#
|
226
|
-
# using the cabinet lib
|
234
|
+
# Using the cabinet lib
|
227
235
|
#
|
228
236
|
def lib
|
237
|
+
|
229
238
|
CabinetLib
|
230
239
|
end
|
231
240
|
|
241
|
+
# Returns the path to this database.
|
232
242
|
#
|
243
|
+
def path
|
244
|
+
|
245
|
+
@path
|
246
|
+
end
|
247
|
+
|
233
248
|
# No comment
|
234
249
|
#
|
235
250
|
def []= (k, v)
|
236
|
-
|
251
|
+
|
252
|
+
lib.abs_put(@db, k, Rufus::Tokyo.blen(k), v, Rufus::Tokyo.blen(v))
|
237
253
|
end
|
238
254
|
|
255
|
+
# Like #put but doesn't overwrite the value if already set. Returns true
|
256
|
+
# only if there no previous entry for k.
|
239
257
|
#
|
258
|
+
def putkeep (k, v)
|
259
|
+
|
260
|
+
(lib.abs_putkeep(
|
261
|
+
@db, k, Rufus::Tokyo.blen(k), v, Rufus::Tokyo.blen(v)) == 1)
|
262
|
+
end
|
263
|
+
|
240
264
|
# (The actual #[] method is provided by HashMethods
|
241
265
|
#
|
242
266
|
def get (k)
|
243
|
-
|
267
|
+
|
268
|
+
outlen_op(:abs_get, k, Rufus::Tokyo.blen(k))
|
244
269
|
end
|
245
270
|
protected :get
|
246
271
|
|
247
|
-
#
|
248
272
|
# Removes a record from the cabinet, returns the value if successful
|
249
273
|
# else nil.
|
250
274
|
#
|
251
275
|
def delete (k)
|
276
|
+
|
252
277
|
v = self[k]
|
253
|
-
|
278
|
+
|
279
|
+
(lib.abs_out(@db, k, Rufus::Tokyo.blen(k)) == 1) ? v : nil
|
254
280
|
end
|
255
281
|
|
256
|
-
#
|
257
282
|
# Returns the number of records in the 'cabinet'
|
258
283
|
#
|
259
284
|
def size
|
285
|
+
|
260
286
|
lib.abs_rnum(@db)
|
261
287
|
end
|
262
288
|
|
263
|
-
#
|
264
289
|
# Removes all the records in the cabinet (use with care)
|
265
290
|
#
|
266
291
|
# Returns self (like Ruby's Hash does).
|
267
292
|
#
|
268
293
|
def clear
|
294
|
+
|
269
295
|
lib.abs_vanish(@db)
|
296
|
+
|
270
297
|
self
|
271
298
|
end
|
272
299
|
|
273
|
-
#
|
274
300
|
# Returns the 'weight' of the db (in bytes)
|
275
301
|
#
|
276
302
|
def weight
|
303
|
+
|
277
304
|
lib.abs_size(@db)
|
278
305
|
end
|
279
306
|
|
280
|
-
#
|
281
307
|
# Closes the cabinet (and frees the datastructure allocated for it),
|
282
308
|
# returns true in case of success.
|
283
309
|
#
|
284
310
|
def close
|
311
|
+
|
285
312
|
result = lib.abs_close(@db)
|
286
313
|
lib.abs_del(@db)
|
314
|
+
|
287
315
|
(result == 1)
|
288
316
|
end
|
289
317
|
|
290
|
-
#
|
291
318
|
# Copies the current cabinet to a new file.
|
292
319
|
#
|
293
320
|
# Returns true if it was successful.
|
294
321
|
#
|
295
322
|
def copy (target_path)
|
323
|
+
|
296
324
|
(lib.abs_copy(@db, target_path) == 1)
|
297
325
|
end
|
298
326
|
|
299
|
-
#
|
300
327
|
# Copies the current cabinet to a new file.
|
301
328
|
#
|
302
329
|
# Does it by copying each entry afresh to the target file. Spares some
|
303
330
|
# space, hence the 'compact' label...
|
304
331
|
#
|
305
332
|
def compact_copy (target_path)
|
333
|
+
|
306
334
|
@other_db = Cabinet.new(target_path)
|
307
335
|
self.each { |k, v| @other_db[k] = v }
|
308
336
|
@other_db.close
|
309
337
|
end
|
310
338
|
|
311
|
-
#
|
312
339
|
# "synchronize updated contents of an abstract database object with
|
313
340
|
# the file and the device"
|
314
341
|
#
|
315
342
|
def sync
|
343
|
+
|
316
344
|
(lib.abs_sync(@db) == 1)
|
317
345
|
end
|
318
346
|
|
319
|
-
#
|
320
347
|
# Returns an array with all the keys in the databse
|
321
348
|
#
|
322
349
|
# With no options given, this method will return all the keys (strings)
|
@@ -332,10 +359,15 @@ module Rufus::Tokyo
|
|
332
359
|
#
|
333
360
|
def keys (options={})
|
334
361
|
|
335
|
-
|
362
|
+
outlen = nil
|
363
|
+
|
364
|
+
if pre = options[:prefix]
|
365
|
+
|
366
|
+
l = lib.abs_fwmkeys(
|
367
|
+
@db, pre, Rufus::Tokyo.blen(pre), options[:limit] || -1)
|
336
368
|
|
337
|
-
l = lib.abs_fwmkeys2(@db, pref, options[:limit] || -1)
|
338
369
|
l = Rufus::Tokyo::List.new(l)
|
370
|
+
|
339
371
|
options[:native] ? l : l.release
|
340
372
|
|
341
373
|
else
|
@@ -347,26 +379,34 @@ module Rufus::Tokyo
|
|
347
379
|
|
348
380
|
lib.abs_iterinit(@db)
|
349
381
|
|
350
|
-
|
382
|
+
outlen = FFI::MemoryPointer.new(:int)
|
383
|
+
|
384
|
+
loop do
|
351
385
|
break if limit and l.size >= limit
|
352
|
-
|
386
|
+
out = lib.abs_iternext(@db, outlen)
|
387
|
+
break if out.address == 0
|
388
|
+
l << out.get_bytes(0, outlen.get_int(0))
|
353
389
|
end
|
354
390
|
|
355
391
|
l
|
356
392
|
end
|
393
|
+
|
394
|
+
ensure
|
395
|
+
|
396
|
+
outlen.free if outlen
|
357
397
|
end
|
358
398
|
|
359
|
-
#
|
360
399
|
# Deletes all the entries whose keys begin with the given prefix
|
361
400
|
#
|
362
401
|
def delete_keys_with_prefix (prefix)
|
363
402
|
|
364
|
-
call_misc(
|
365
|
-
|
403
|
+
call_misc(
|
404
|
+
'outlist', lib.abs_fwmkeys(@db, prefix, Rufus::Tokyo.blen(prefix), -1))
|
405
|
+
# -1 for no limits
|
406
|
+
|
366
407
|
nil
|
367
408
|
end
|
368
409
|
|
369
|
-
#
|
370
410
|
# Given a list of keys, returns a Hash { key => value } of the
|
371
411
|
# matching entries (in one sweep).
|
372
412
|
#
|
@@ -375,7 +415,6 @@ module Rufus::Tokyo
|
|
375
415
|
Hash[*call_misc('getlist', Rufus::Tokyo::List.new(keys))]
|
376
416
|
end
|
377
417
|
|
378
|
-
#
|
379
418
|
# Merges the given hash into this Cabinet (or Tyrant) and returns self.
|
380
419
|
#
|
381
420
|
def merge! (hash)
|
@@ -387,7 +426,6 @@ module Rufus::Tokyo
|
|
387
426
|
end
|
388
427
|
alias :lput :merge!
|
389
428
|
|
390
|
-
#
|
391
429
|
# Given a list of keys, deletes all the matching entries (in one sweep).
|
392
430
|
#
|
393
431
|
def ldelete (keys)
|
@@ -395,6 +433,29 @@ module Rufus::Tokyo
|
|
395
433
|
call_misc('outlist', Rufus::Tokyo::List.new(keys))
|
396
434
|
end
|
397
435
|
|
436
|
+
# Increments the value stored under the given key with the given increment
|
437
|
+
# (defaults to 1 (integer)).
|
438
|
+
#
|
439
|
+
# Accepts an integer or a double value.
|
440
|
+
#
|
441
|
+
def incr (key, inc=1)
|
442
|
+
|
443
|
+
v = inc.is_a?(Fixnum) ?
|
444
|
+
lib.addint(@db, key, Rufus::Tokyo.blen(key), inc) :
|
445
|
+
lib.adddouble(@db, key, Rufus::Tokyo.blen(key), inc)
|
446
|
+
|
447
|
+
raise(TokyoError.new(
|
448
|
+
"incr failed, there is probably already a string value set " +
|
449
|
+
"for the key '#{key}'"
|
450
|
+
)) if v == Rufus::Tokyo::INT_MIN || (v.respond_to?(:nan?) && v.nan?)
|
451
|
+
|
452
|
+
v
|
453
|
+
end
|
454
|
+
alias :addint :incr
|
455
|
+
alias :adddouble :incr
|
456
|
+
alias :add_int :incr
|
457
|
+
alias :add_double :incr
|
458
|
+
|
398
459
|
# Warning : this method is low-level, you probably only need
|
399
460
|
# to use #transaction and a block.
|
400
461
|
#
|
@@ -407,6 +468,18 @@ module Rufus::Tokyo
|
|
407
468
|
libcall(:tcadbtranbegin)
|
408
469
|
end
|
409
470
|
|
471
|
+
# Triggers a defrag run (TC >= 1.4.21 only)
|
472
|
+
#
|
473
|
+
def defrag
|
474
|
+
|
475
|
+
raise(NotImplementedError.new(
|
476
|
+
"method defrag is supported since Tokyo Cabinet 1.4.21. " +
|
477
|
+
"your TC version doesn't support it"
|
478
|
+
)) unless lib.respond_to?(:tctdbsetdfunit)
|
479
|
+
|
480
|
+
call_misc('defrag', Rufus::Tokyo::List.new)
|
481
|
+
end
|
482
|
+
|
410
483
|
# Warning : this method is low-level, you probably only need
|
411
484
|
# to use #transaction and a block.
|
412
485
|
#
|
@@ -441,8 +514,7 @@ module Rufus::Tokyo
|
|
441
514
|
) unless lib.respond_to?(:tcadbtranbegin)
|
442
515
|
end
|
443
516
|
|
444
|
-
#
|
445
|
-
# wrapping tcadbmisc or tcrdbmisc
|
517
|
+
# Wrapping tcadbmisc or tcrdbmisc
|
446
518
|
# (and taking care of freeing the list_pointer)
|
447
519
|
#
|
448
520
|
def call_misc (function, list_pointer)
|
@@ -459,7 +531,7 @@ module Rufus::Tokyo
|
|
459
531
|
end
|
460
532
|
end
|
461
533
|
|
462
|
-
#
|
534
|
+
# Calls the tcadbmisc function
|
463
535
|
#
|
464
536
|
def do_call_misc (function, list_pointer)
|
465
537
|
|
@@ -471,6 +543,26 @@ module Rufus::Tokyo
|
|
471
543
|
(eval(%{ lib.#{lib_method}(@db, *args) }) == 1) or \
|
472
544
|
raise TokyoError.new("call to #{lib_method} failed")
|
473
545
|
end
|
546
|
+
|
547
|
+
# A wrapper for library returning a string (binary data potentially)
|
548
|
+
#
|
549
|
+
def outlen_op (method, *args)
|
550
|
+
|
551
|
+
args.unshift(@db)
|
552
|
+
|
553
|
+
outlen = FFI::MemoryPointer.new(:int)
|
554
|
+
args << outlen
|
555
|
+
|
556
|
+
out = lib.send(method, *args)
|
557
|
+
|
558
|
+
return nil if out.address == 0
|
559
|
+
|
560
|
+
return out.get_bytes(0, outlen.get_int(0))
|
561
|
+
|
562
|
+
ensure
|
563
|
+
|
564
|
+
outlen.free
|
565
|
+
end
|
474
566
|
end
|
475
567
|
end
|
476
568
|
|
@@ -84,22 +84,29 @@ module Rufus::Tokyo
|
|
84
84
|
attfunc :abs_rnum, :tcadbrnum, [ :pointer ], :uint64
|
85
85
|
attfunc :abs_size, :tcadbsize, [ :pointer ], :uint64
|
86
86
|
|
87
|
-
attfunc :
|
88
|
-
|
89
|
-
attfunc :
|
87
|
+
attfunc :abs_put, :tcadbput, [ :pointer, :pointer, :int, :pointer, :int ], :int
|
88
|
+
|
89
|
+
attfunc :abs_get, :tcadbget, [ :pointer, :pointer, :int, :pointer ], :pointer
|
90
|
+
|
91
|
+
attfunc :abs_out, :tcadbout, [ :pointer, :pointer, :int ], :int
|
92
|
+
|
93
|
+
attfunc :abs_putkeep, :tcadbputkeep, [ :pointer, :pointer, :int, :pointer, :int ], :int
|
90
94
|
|
91
95
|
attfunc :abs_iterinit, :tcadbiterinit, [ :pointer ], :int
|
92
|
-
attfunc :
|
96
|
+
attfunc :abs_iternext, :tcadbiternext, [ :pointer, :pointer ], :pointer
|
93
97
|
|
94
98
|
attfunc :abs_vanish, :tcadbvanish, [ :pointer ], :int
|
95
99
|
|
96
100
|
attfunc :abs_sync, :tcadbsync, [ :pointer ], :int
|
97
101
|
attfunc :abs_copy, :tcadbcopy, [ :pointer, :string ], :int
|
98
102
|
|
99
|
-
attfunc :
|
103
|
+
attfunc :abs_fwmkeys, :tcadbfwmkeys, [ :pointer, :pointer, :int, :int ], :pointer
|
100
104
|
|
101
105
|
attfunc :tcadbmisc, [ :pointer, :string, :pointer ], :pointer
|
102
106
|
|
107
|
+
attfunc :addint, :tcadbaddint, [ :pointer, :string, :int, :int ], :int
|
108
|
+
attfunc :adddouble, :tcadbadddouble, [ :pointer, :string, :int, :double ], :double
|
109
|
+
|
103
110
|
begin # since TC 1.4.13
|
104
111
|
attfunc :tcadbtranbegin, [ :pointer ], :int
|
105
112
|
attfunc :tcadbtrancommit, [ :pointer ], :int
|
@@ -118,18 +125,23 @@ module Rufus::Tokyo
|
|
118
125
|
attfunc :tctdbsetcache, [ :pointer, :uint32, :uint32, :uint32 ], :int
|
119
126
|
attfunc :tctdbsetxmsiz, [ :pointer, :uint64 ], :int
|
120
127
|
|
128
|
+
begin # since TC 1.4.21
|
129
|
+
attfunc :tctdbsetdfunit, [ :pointer, :uint32 ], :int
|
130
|
+
rescue FFI::NotFoundError => nfe
|
131
|
+
end
|
132
|
+
|
121
133
|
attfunc :tctdbopen, [ :pointer, :string, :int ], :int
|
122
134
|
|
123
135
|
attfunc :tab_close, :tctdbclose, [ :pointer ], :int
|
124
136
|
|
125
137
|
attfunc :tab_genuid, :tctdbgenuid, [ :pointer ], :int64
|
126
138
|
|
127
|
-
attfunc :tab_get, :tctdbget, [ :pointer, :
|
139
|
+
attfunc :tab_get, :tctdbget, [ :pointer, :pointer, :int ], :pointer
|
128
140
|
|
129
141
|
attfunc :tab_iterinit, :tctdbiterinit, [ :pointer ], :int
|
130
|
-
attfunc :
|
142
|
+
attfunc :tab_iternext, :tctdbiternext, [ :pointer, :pointer ], :pointer
|
131
143
|
|
132
|
-
attfunc :tab_put, :tctdbput, [ :pointer, :
|
144
|
+
attfunc :tab_put, :tctdbput, [ :pointer, :pointer, :int, :pointer ], :int
|
133
145
|
|
134
146
|
#attfunc :tctdbput3, [ :pointer, :string, :string ], :int
|
135
147
|
# not using it anymore, Ruby can turn an array into a hash so easily
|
@@ -151,7 +163,7 @@ module Rufus::Tokyo
|
|
151
163
|
attfunc :tctdbtrancommit, [ :pointer ], :int
|
152
164
|
attfunc :tctdbtranabort, [ :pointer ], :int
|
153
165
|
|
154
|
-
attfunc :
|
166
|
+
attfunc :tab_fwmkeys, :tctdbfwmkeys, [ :pointer, :pointer, :int, :int ], :pointer
|
155
167
|
|
156
168
|
#
|
157
169
|
# tctdbqry functions
|
@@ -183,18 +195,13 @@ module Rufus::Tokyo
|
|
183
195
|
# http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
|
184
196
|
|
185
197
|
attfunc :tcmapnew, [], :pointer
|
186
|
-
|
187
|
-
attfunc :
|
188
|
-
attfunc :tcmapout2, [ :pointer, :string ], :int
|
198
|
+
attfunc :tcmapput, [ :pointer, :pointer, :int, :pointer, :int ], :void
|
199
|
+
attfunc :tcmapout, [ :pointer, :pointer, :int ], :int
|
189
200
|
attfunc :tcmapclear, [ :pointer ], :void
|
190
|
-
|
191
201
|
attfunc :tcmapdel, [ :pointer ], :void
|
192
|
-
|
193
|
-
attfunc :tcmapget2, [ :pointer, :string ], :string
|
194
|
-
|
202
|
+
attfunc :tcmapget, [ :pointer, :pointer, :int, :pointer ], :pointer
|
195
203
|
attfunc :tcmapiterinit, [ :pointer ], :void
|
196
|
-
attfunc :
|
197
|
-
|
204
|
+
attfunc :tcmapiternext, [ :pointer, :pointer ], :pointer
|
198
205
|
attfunc :tcmaprnum, [ :pointer ], :uint64
|
199
206
|
|
200
207
|
#
|
@@ -203,19 +210,14 @@ module Rufus::Tokyo
|
|
203
210
|
# http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
|
204
211
|
|
205
212
|
attfunc :tclistnew, [], :pointer
|
206
|
-
|
207
213
|
attfunc :tclistnum, [ :pointer ], :int
|
208
|
-
attfunc :
|
209
|
-
|
210
|
-
attfunc :
|
211
|
-
attfunc :
|
212
|
-
attfunc :
|
213
|
-
attfunc :
|
214
|
-
attfunc :
|
215
|
-
|
216
|
-
attfunc :tclistremove2, [ :pointer, :int ], :string
|
217
|
-
# beware, seems like have to free the return string self
|
218
|
-
|
214
|
+
attfunc :tclistval, [ :pointer, :int, :pointer ], :pointer
|
215
|
+
attfunc :tclistpush, [ :pointer, :pointer, :int ], :void
|
216
|
+
attfunc :tclistpop, [ :pointer, :pointer ], :pointer
|
217
|
+
attfunc :tclistshift, [ :pointer, :pointer ], :pointer
|
218
|
+
attfunc :tclistunshift, [ :pointer, :pointer, :int ], :void
|
219
|
+
attfunc :tclistover, [ :pointer, :int, :pointer, :int ], :void
|
220
|
+
attfunc :tclistremove, [ :pointer, :int, :pointer ], :pointer
|
219
221
|
attfunc :tclistdel, [ :pointer ], :void
|
220
222
|
end
|
221
223
|
|