rufus-tokyo 0.1.6 → 0.1.7
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 +11 -0
- data/CREDITS.txt +5 -3
- data/README.txt +1 -0
- data/lib/rufus/tokyo.rb +7 -5
- data/lib/rufus/tokyo/cabinet/abstract.rb +144 -22
- data/lib/rufus/tokyo/cabinet/lib.rb +8 -0
- data/lib/rufus/tokyo/cabinet/table.rb +178 -65
- data/lib/rufus/tokyo/cabinet/util.rb +12 -1
- data/lib/rufus/tokyo/tyrant/lib.rb +4 -0
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
= rufus-tokyo CHANGELOG.txt
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
== rufus-tokyo - 0.1.7 released 2009/02/19
|
|
6
|
+
|
|
7
|
+
- todo : Rufus::Tokyo::Cabinet.new('filename', :type => :hash) now OK (Zev)
|
|
8
|
+
- todo : more documentation for Rufus::Tokyo::Cabinet#new
|
|
9
|
+
- added : Rufus::Tokyo::Cabinet has a open method that takes a block like
|
|
10
|
+
File.open (Zev)
|
|
11
|
+
- todo : aligned Rufus::Tokyo::Table#new on ::Cabinet#new
|
|
12
|
+
- todo : added opts (:prefix, :limit, :native) to Rufus::Tokyo::Cabinet#keys,
|
|
13
|
+
Rufus::Tokyo::Table#keys and the corresponding Tyrant classes
|
|
14
|
+
|
|
15
|
+
|
|
5
16
|
== rufus-tokyo - 0.1.6 released 2009/02/16
|
|
6
17
|
|
|
7
18
|
- todo : Tyrant and TyrantTable now complain when used in lieu of each other
|
data/CREDITS.txt
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
== authors
|
|
6
6
|
|
|
7
|
-
John Mettraux
|
|
8
|
-
Justin Reagor
|
|
7
|
+
John Mettraux http://jmettraux.wordpress.com
|
|
8
|
+
Justin Reagor http://blog.kineticweb.com/
|
|
9
|
+
Zev Blut http://www.iknow.co.jp/users/zev
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
== finally
|
|
12
13
|
|
|
13
|
-
many thanks to the author of Tokyo Cabinet (Mikio Hirabayashi) and
|
|
14
|
+
many thanks to the author of Tokyo Cabinet (Mikio Hirabayashi) and
|
|
15
|
+
the authors of ruby-ffi
|
|
14
16
|
|
|
15
17
|
http://tokyocabinet.sourceforge.net
|
|
16
18
|
http://kenai.com/projects/ruby-ffi
|
data/README.txt
CHANGED
|
@@ -240,6 +240,7 @@ many thanks to the author of Tokyo Cabinet, Mikio Hirabayashi, and to the author
|
|
|
240
240
|
|
|
241
241
|
John Mettraux, jmettraux@gmail.com, http://jmettraux.wordpress.com
|
|
242
242
|
Justin Reagor, http://blog.kineticweb.com/
|
|
243
|
+
Zev Blut, http://www.iknow.co.jp/users/zev
|
|
243
244
|
|
|
244
245
|
|
|
245
246
|
== the rest of Rufus
|
data/lib/rufus/tokyo.rb
CHANGED
|
@@ -22,13 +22,19 @@
|
|
|
22
22
|
#++
|
|
23
23
|
#
|
|
24
24
|
|
|
25
|
+
#
|
|
26
|
+
# "made in Japan"
|
|
27
|
+
#
|
|
28
|
+
# jmettraux@gmail.com
|
|
29
|
+
#
|
|
30
|
+
|
|
25
31
|
require 'ffi' # sudo gem install ffi
|
|
26
32
|
|
|
27
33
|
|
|
28
34
|
module Rufus
|
|
29
35
|
module Tokyo
|
|
30
36
|
|
|
31
|
-
VERSION = '0.1.
|
|
37
|
+
VERSION = '0.1.7'
|
|
32
38
|
|
|
33
39
|
#
|
|
34
40
|
# A common error class
|
|
@@ -40,7 +46,3 @@ end
|
|
|
40
46
|
|
|
41
47
|
require 'rufus/tokyo/cabinet'
|
|
42
48
|
|
|
43
|
-
# TODO : do not include me
|
|
44
|
-
#require 'rufus/tokyo/tyrant'
|
|
45
|
-
#require 'rufus/tokyo/dystopia'
|
|
46
|
-
|
|
@@ -74,48 +74,140 @@ module Rufus
|
|
|
74
74
|
# 'casket.tch' with a bucket number of 100000 and the 'large' and
|
|
75
75
|
# 'deflate' options (opts) turned on.
|
|
76
76
|
#
|
|
77
|
-
#
|
|
77
|
+
# Note that there is an #open method similar to File#open for openening
|
|
78
|
+
# a db and closing it when it's no longer needed :
|
|
78
79
|
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
80
|
+
# Rufus::Tokyo::Cabinet.new('data.tch') do |db|
|
|
81
|
+
# db['key'] = value
|
|
82
|
+
# end
|
|
81
83
|
#
|
|
82
|
-
# ==
|
|
84
|
+
# == database name
|
|
83
85
|
#
|
|
84
|
-
#
|
|
85
|
-
# options, thus
|
|
86
|
+
# From http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi :
|
|
86
87
|
#
|
|
87
|
-
#
|
|
88
|
+
# 'If it is "*", the database will be an on-memory hash database. If it is
|
|
89
|
+
# "+", the database will be an on-memory tree database. If its suffix is
|
|
90
|
+
# ".tch", the database will be a hash database. If its suffix is ".tcb",
|
|
91
|
+
# the database will be a B+ tree database. If its suffix is ".tcf", the
|
|
92
|
+
# database will be a fixed-length database. If its suffix is ".tct", the
|
|
93
|
+
# database will be a table database.'
|
|
94
|
+
#
|
|
95
|
+
# You're supposed to give a path to the database file you want to use and
|
|
96
|
+
# Cabinet expects you to give the proper prefix.
|
|
97
|
+
#
|
|
98
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tch') # hash database
|
|
99
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tcb') # B+ tree db
|
|
100
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tcf') # fixed-length db
|
|
101
|
+
#
|
|
102
|
+
# will result with the same file names :
|
|
103
|
+
#
|
|
104
|
+
# db = Rufus::Tokyo::Cabinet.new('data', :type => :hash) # hash database
|
|
105
|
+
# db = Rufus::Tokyo::Cabinet.new('data', :type => :btree) # B+ tree db
|
|
106
|
+
# db = Rufus::Tokyo::Cabinet.new('data', :type => :fixed) # fixed-length db
|
|
107
|
+
#
|
|
108
|
+
# You can open an in-memory hash and an in-memory B+ tree with :
|
|
109
|
+
#
|
|
110
|
+
# h = Rufus::Tokyo::Cabinet.new(:mem_hash) # or
|
|
111
|
+
# h = Rufus::Tokyo::Cabinet.new('*')
|
|
112
|
+
#
|
|
113
|
+
# t = Rufus::Tokyo::Cabinet.new(:mem_tree) # or
|
|
114
|
+
# t = Rufus::Tokyo::Cabinet.new('+')
|
|
115
|
+
#
|
|
116
|
+
# == parameters
|
|
88
117
|
#
|
|
89
|
-
#
|
|
118
|
+
# There are two ways to pass parameters at the opening of a db :
|
|
119
|
+
#
|
|
120
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tch#opts=ld#mode=w') # or
|
|
121
|
+
# db = Rufus::Tokyo::Cabinet.new('data.tch', :opts => 'ld', :mode => 'w')
|
|
122
|
+
#
|
|
123
|
+
# most verbose :
|
|
90
124
|
#
|
|
91
125
|
# db = Rufus::Tokyo::Cabinet.new(
|
|
92
|
-
# '
|
|
126
|
+
# 'data', :type => :hash, :opts => 'ld', :mode => 'w')
|
|
127
|
+
#
|
|
128
|
+
# === mode
|
|
129
|
+
#
|
|
130
|
+
# * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
|
|
131
|
+
# 'e' non locking, 'f' non blocking lock), default is 'wc'
|
|
132
|
+
#
|
|
133
|
+
# === other parameters
|
|
134
|
+
#
|
|
135
|
+
# 'On-memory hash database supports "bnum", "capnum", and "capsiz".
|
|
136
|
+
# On-memory tree database supports "capnum" and "capsiz".
|
|
137
|
+
# Hash database supports "mode", "bnum", "apow", "fpow", "opts",
|
|
138
|
+
# "rcnum", and "xmsiz".
|
|
139
|
+
# B+ tree database supports "mode", "lmemb", "nmemb", "bnum", "apow",
|
|
140
|
+
# "fpow", "opts", "lcnum", "ncnum", and "xmsiz".
|
|
141
|
+
# Fixed-length database supports "mode", "width", and "limsiz"'
|
|
142
|
+
#
|
|
143
|
+
# * :opts a set of chars ('l'arge, 'd'eflate, 'b'zip2, 't'cbs)
|
|
144
|
+
# (usually empty or something like 'ld' or 'lb')
|
|
145
|
+
#
|
|
146
|
+
# * :bnum number of elements of the bucket array
|
|
147
|
+
# * :apow size of record alignment by power of 2 (defaults to 4)
|
|
148
|
+
# * :fpow maximum number of elements of the free block pool by
|
|
149
|
+
# power of 2 (defaults to 10)
|
|
150
|
+
# * :mutex when set to true, makes sure only 1 thread at a time
|
|
151
|
+
# accesses the table (well, Ruby, global thread lock, ...)
|
|
93
152
|
#
|
|
94
|
-
#
|
|
153
|
+
# * :rcnum specifies the maximum number of records to be cached.
|
|
154
|
+
# If it is not more than 0, the record cache is disabled.
|
|
155
|
+
# It is disabled by default.
|
|
156
|
+
# * :lcnum specifies the maximum number of leaf nodes to be cached.
|
|
157
|
+
# If it is not more than 0, the default value is specified.
|
|
158
|
+
# The default value is 2048.
|
|
159
|
+
# * :ncnum specifies the maximum number of non-leaf nodes to be
|
|
160
|
+
# cached. If it is not more than 0, the default value is
|
|
161
|
+
# specified. The default value is 512.
|
|
95
162
|
#
|
|
96
|
-
#
|
|
163
|
+
# * :xmsiz specifies the size of the extra mapped memory. If it is
|
|
164
|
+
# not more than 0, the extra mapped memory is disabled.
|
|
165
|
+
# The default size is 67108864.
|
|
97
166
|
#
|
|
98
|
-
#
|
|
167
|
+
# * :capnum specifies the capacity number of records.
|
|
168
|
+
# * :capsiz specifies the capacity size of using memory.
|
|
99
169
|
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
170
|
+
#
|
|
171
|
+
# = NOTE :
|
|
172
|
+
#
|
|
173
|
+
# On reopening a file, Cabinet will tend to stick to the parameters as
|
|
174
|
+
# set when the file was opened. To change that, have a look at the
|
|
175
|
+
# man pages of the various command line tools coming with Tokyo Cabinet.
|
|
102
176
|
#
|
|
103
177
|
def initialize (name, params={})
|
|
104
178
|
|
|
105
179
|
@db = lib.tcadbnew
|
|
106
180
|
|
|
107
|
-
name = '*' if name == :
|
|
108
|
-
name = '+' if name == :
|
|
181
|
+
name = '*' if name == :mem_hash # in memory hash database
|
|
182
|
+
name = '+' if name == :mem_tree # in memory B+ tree database
|
|
183
|
+
|
|
184
|
+
if type = params.delete(:type)
|
|
185
|
+
name += { :hash => '.tch', :btree => '.tcb', :fixed => '.tcf' }[type]
|
|
186
|
+
end
|
|
109
187
|
|
|
110
188
|
name = name + params.collect { |k, v| "##{k}=#{v}" }.join('')
|
|
111
189
|
|
|
112
190
|
(lib.tcadbopen(@db, name) == 1) ||
|
|
113
|
-
raise("failed to open/create db '#{name}'")
|
|
191
|
+
raise("failed to open/create db '#{name}' #{params.inspect}")
|
|
114
192
|
|
|
115
193
|
self.default = params[:default]
|
|
116
194
|
@default_proc ||= params[:default_proc]
|
|
117
195
|
end
|
|
118
196
|
|
|
197
|
+
# Same args as initialize, but can take a block form that will
|
|
198
|
+
# close the db when done. Similar to File.open
|
|
199
|
+
def self.open (name, params={})
|
|
200
|
+
db = self.new(name, params)
|
|
201
|
+
if block_given?
|
|
202
|
+
yield db
|
|
203
|
+
nil
|
|
204
|
+
else
|
|
205
|
+
db
|
|
206
|
+
end
|
|
207
|
+
ensure
|
|
208
|
+
db.close if block_given? && db
|
|
209
|
+
end
|
|
210
|
+
|
|
119
211
|
#
|
|
120
212
|
# Returns a new in-memory hash. Accepts the same optional params hash
|
|
121
213
|
# as new().
|
|
@@ -229,11 +321,41 @@ module Rufus
|
|
|
229
321
|
#
|
|
230
322
|
# Returns an array with all the keys in the databse
|
|
231
323
|
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
324
|
+
# With no options given, this method will return all the keys (strings)
|
|
325
|
+
# in a Ruby array.
|
|
326
|
+
#
|
|
327
|
+
# :prefix --> returns only the keys who match a given string prefix
|
|
328
|
+
#
|
|
329
|
+
# :limit --> returns a limited number of keys
|
|
330
|
+
#
|
|
331
|
+
# :native --> returns an instance of Rufus::Tokyo::List instead of
|
|
332
|
+
# a Ruby Hash, you have to call #free on that List when done with it !
|
|
333
|
+
# Else you're exposing yourself to a memory leak.
|
|
334
|
+
#
|
|
335
|
+
def keys (options={})
|
|
336
|
+
|
|
337
|
+
if pref = options[:prefix]
|
|
338
|
+
|
|
339
|
+
l = lib.abs_fwmkeys2(@db, pref, options[:limit] || -1)
|
|
340
|
+
l = Rufus::Tokyo::List.new(l)
|
|
341
|
+
options[:native] ? l : l.release
|
|
342
|
+
|
|
343
|
+
else
|
|
344
|
+
|
|
345
|
+
limit = options[:limit] || -1
|
|
346
|
+
limit = nil if limit < 1
|
|
347
|
+
|
|
348
|
+
l = options[:native] ? Rufus::Tokyo::List.new : []
|
|
349
|
+
|
|
350
|
+
lib.abs_iterinit(@db)
|
|
351
|
+
|
|
352
|
+
while (k = (lib.abs_iternext2(@db) rescue nil))
|
|
353
|
+
break if limit and l.size >= limit
|
|
354
|
+
l << k
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
l
|
|
358
|
+
end
|
|
237
359
|
end
|
|
238
360
|
end
|
|
239
361
|
|
|
@@ -97,12 +97,18 @@ module Rufus
|
|
|
97
97
|
attfunc :abs_sync, :tcadbsync, [ :pointer ], :int
|
|
98
98
|
attfunc :abs_copy, :tcadbcopy, [ :pointer, :string ], :int
|
|
99
99
|
|
|
100
|
+
attfunc :abs_fwmkeys2, :tcadbfwmkeys2, [ :pointer, :string, :int ], :pointer
|
|
101
|
+
|
|
100
102
|
#
|
|
101
103
|
# tctdb functions
|
|
102
104
|
#
|
|
103
105
|
# http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
|
|
104
106
|
|
|
105
107
|
attfunc :tctdbnew, [], :pointer
|
|
108
|
+
attfunc :tctdbsetmutex, [ :pointer ], :int
|
|
109
|
+
attfunc :tctdbtune, [ :pointer, :uint64, :uint8, :uint8, :uint8 ], :int
|
|
110
|
+
attfunc :tctdbsetcache, [ :pointer, :uint32, :uint32, :uint32 ], :int
|
|
111
|
+
attfunc :tctdbsetxmsiz, [ :pointer, :uint64 ], :int
|
|
106
112
|
|
|
107
113
|
attfunc :tctdbopen, [ :pointer, :string, :int ], :int
|
|
108
114
|
|
|
@@ -137,6 +143,8 @@ module Rufus
|
|
|
137
143
|
attfunc :tctdbtrancommit, [ :pointer ], :int
|
|
138
144
|
attfunc :tctdbtranabort, [ :pointer ], :int
|
|
139
145
|
|
|
146
|
+
attfunc :tab_fwmkeys2, :tctdbfwmkeys2, [ :pointer, :string, :int ], :pointer
|
|
147
|
+
|
|
140
148
|
#
|
|
141
149
|
# tctdbqry functions
|
|
142
150
|
#
|
|
@@ -31,61 +31,94 @@
|
|
|
31
31
|
module Rufus
|
|
32
32
|
module Tokyo
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
#
|
|
35
|
+
# Methods for setting up / tuning a Cabinet.
|
|
36
|
+
#
|
|
37
|
+
# Gets included into Table.
|
|
38
|
+
#
|
|
39
|
+
module CabinetConfig
|
|
40
|
+
|
|
41
|
+
protected
|
|
35
42
|
|
|
36
43
|
#
|
|
37
|
-
#
|
|
44
|
+
# Given a path, a hash of parameters and a suffix,
|
|
45
|
+
#
|
|
46
|
+
# a) makes sure that the path has the given suffix or raises an exception
|
|
47
|
+
# b) gathers params found in the path (#) or in params
|
|
48
|
+
# c) determines the config as set by the parameters
|
|
49
|
+
#
|
|
50
|
+
def determine_conf (path, params, suffix)
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
OWRITER = 1 << 1 # open as a writer
|
|
41
|
-
OCREAT = 1 << 2 # writer creating
|
|
42
|
-
OTRUNC = 1 << 3 # writer truncating
|
|
43
|
-
ONOLCK = 1 << 4 # open without locking
|
|
44
|
-
OLCKNB = 1 << 5 # lock without blocking
|
|
52
|
+
if path.index('#')
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
ss = path.split('#')
|
|
55
|
+
path = ss.shift
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
ss.each { |p| pp = p.split('='); params[pp[0]] = pp[1] }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
raise "path '#{path}' must be suffixed with #{suffix}" \
|
|
61
|
+
unless path[-suffix.length..-1] == suffix
|
|
62
|
+
|
|
63
|
+
params = params.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
params
|
|
56
|
-
|
|
65
|
+
conf = {
|
|
66
|
+
:params => params,
|
|
67
|
+
:path => path,
|
|
68
|
+
:mode => determine_open_mode(params),
|
|
69
|
+
:mutex => (params[:mutex].to_s == 'true'),
|
|
70
|
+
#:indexes => params[:idx] || params[:indexes],
|
|
71
|
+
:xmsiz => (params[:xmsiz] || 67108864).to_i
|
|
72
|
+
}
|
|
73
|
+
conf.merge!(determine_tuning_values(params))
|
|
74
|
+
conf.merge(determine_cache_values(params))
|
|
57
75
|
end
|
|
58
76
|
|
|
59
|
-
#
|
|
60
|
-
# Given params (array or hash), computes the open mode (an int)
|
|
61
|
-
# for the Tokyo Cabinet object.
|
|
62
|
-
#
|
|
63
|
-
def compute_open_mode (params)
|
|
77
|
+
def determine_open_mode (params) #:nodoc#
|
|
64
78
|
|
|
65
|
-
|
|
79
|
+
mode = params[:mode].to_s
|
|
80
|
+
mode = 'wc' if mode.size < 1
|
|
66
81
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
:lock_no_block => OLCKNB,
|
|
76
|
-
:sync_every => OTSYNC
|
|
82
|
+
{
|
|
83
|
+
'r' => (1 << 0), # open as a reader
|
|
84
|
+
'w' => (1 << 1), # open as a writer
|
|
85
|
+
'c' => (1 << 2), # writer creating
|
|
86
|
+
't' => (1 << 3), # writer truncating
|
|
87
|
+
'e' => (1 << 4), # open without locking
|
|
88
|
+
'f' => (1 << 5), # lock without blocking
|
|
89
|
+
's' => (1 << 6), # synchronize every transaction (tctdb.h)
|
|
77
90
|
|
|
78
|
-
}.inject(0) { |r, (
|
|
91
|
+
}.inject(0) { |r, (c, v)|
|
|
79
92
|
|
|
80
|
-
r = r | v if
|
|
93
|
+
r = r | v if mode.index(c); r
|
|
81
94
|
}
|
|
95
|
+
end
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
def determine_tuning_values (params) #:nodoc#
|
|
98
|
+
|
|
99
|
+
bnum = (params[:bnum] || 131071).to_i
|
|
100
|
+
apow = (params[:apow] || 4).to_i
|
|
101
|
+
fpow = (params[:fpow] || 10).to_i
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
o = params[:opts] || ''
|
|
104
|
+
o = {
|
|
105
|
+
'l' => 1 << 0, # large
|
|
106
|
+
'd' => 1 << 1, # deflate
|
|
107
|
+
'b' => 1 << 2, # bzip2
|
|
108
|
+
't' => 1 << 3, # tcbs
|
|
109
|
+
'x' => 1 << 4
|
|
110
|
+
}.inject(0) { |i, (k, v)| i = i | v if o.index(k); i }
|
|
111
|
+
|
|
112
|
+
{ :bnum => bnum, :apow => apow, :fpow => fpow, :opts => o }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def determine_cache_values (params) #:nodoc#
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
:rcnum => params[:rcnum].to_i,
|
|
119
|
+
:lcnum => (params[:lcnum] || 2048).to_i,
|
|
120
|
+
:ncnum => (params[:ncnum] || 512).to_i
|
|
121
|
+
}
|
|
89
122
|
end
|
|
90
123
|
end
|
|
91
124
|
|
|
@@ -122,31 +155,82 @@ module Rufus
|
|
|
122
155
|
class Table
|
|
123
156
|
|
|
124
157
|
include HashMethods
|
|
125
|
-
include
|
|
158
|
+
include CabinetConfig
|
|
126
159
|
|
|
127
160
|
#
|
|
128
161
|
# Creates a Table instance (creates or opens it depending on the args)
|
|
129
162
|
#
|
|
130
163
|
# For example,
|
|
131
164
|
#
|
|
132
|
-
# t = Rufus::Tokyo::Table.new('table.tdb'
|
|
165
|
+
# t = Rufus::Tokyo::Table.new('table.tdb')
|
|
133
166
|
# # '.tdb' suffix is a must
|
|
134
167
|
#
|
|
135
168
|
# will create the table.tdb (or simply open it if already present)
|
|
136
169
|
# and make sure we have write access to it.
|
|
137
|
-
# Note that the suffix (.tdc) is relevant to Tokyo Cabinet, using another
|
|
138
|
-
# will result in a Tokyo Cabinet error.
|
|
139
170
|
#
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
# == parameters
|
|
172
|
+
#
|
|
173
|
+
# Parameters can be set in the path or via the optional params hash (like
|
|
174
|
+
# in Rufus::Tokyo::Cabinet)
|
|
175
|
+
#
|
|
176
|
+
# * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
|
|
177
|
+
# 'e' non locking, 'f' non blocking lock), default is 'wc'
|
|
178
|
+
# * :opts a set of chars ('l'arge, 'd'eflate, 'b'zip2, 't'cbs)
|
|
179
|
+
# (usually empty or something like 'ld' or 'lb')
|
|
180
|
+
#
|
|
181
|
+
# * :bnum number of elements of the bucket array
|
|
182
|
+
# * :apow size of record alignment by power of 2 (defaults to 4)
|
|
183
|
+
# * :fpow maximum number of elements of the free block pool by
|
|
184
|
+
# power of 2 (defaults to 10)
|
|
185
|
+
# * :mutex when set to true, makes sure only 1 thread at a time
|
|
186
|
+
# accesses the table (well, Ruby, global thread lock, ...)
|
|
187
|
+
#
|
|
188
|
+
# * :rcnum specifies the maximum number of records to be cached.
|
|
189
|
+
# If it is not more than 0, the record cache is disabled.
|
|
190
|
+
# It is disabled by default.
|
|
191
|
+
# * :lcnum specifies the maximum number of leaf nodes to be cached.
|
|
192
|
+
# If it is not more than 0, the default value is specified.
|
|
193
|
+
# The default value is 2048.
|
|
194
|
+
# * :ncnum specifies the maximum number of non-leaf nodes to be
|
|
195
|
+
# cached. If it is not more than 0, the default value is
|
|
196
|
+
# specified. The default value is 512.
|
|
197
|
+
#
|
|
198
|
+
# * :xmsiz specifies the size of the extra mapped memory. If it is
|
|
199
|
+
# not more than 0, the extra mapped memory is disabled.
|
|
200
|
+
# The default size is 67108864.
|
|
201
|
+
#
|
|
202
|
+
# Some examples :
|
|
203
|
+
#
|
|
204
|
+
# t = Rufus::Tokyo::Table.new('table.tdb')
|
|
205
|
+
# t = Rufus::Tokyo::Table.new('table.tdb#mode=r')
|
|
206
|
+
# t = Rufus::Tokyo::Table.new('table.tdb', :mode => 'r')
|
|
207
|
+
# t = Rufus::Tokyo::Table.new('table.tdb#opts=ld#mode=r')
|
|
208
|
+
# t = Rufus::Tokyo::Table.new('table.tdb', :opts => 'ld', :mode => 'r')
|
|
209
|
+
#
|
|
210
|
+
def initialize (path, params={})
|
|
144
211
|
|
|
145
|
-
|
|
212
|
+
conf = determine_conf(path, params, '.tdb')
|
|
146
213
|
|
|
147
214
|
@db = lib.tctdbnew
|
|
148
215
|
|
|
149
|
-
|
|
216
|
+
#
|
|
217
|
+
# tune table
|
|
218
|
+
|
|
219
|
+
libcall(:tctdbsetmutex) if conf[:mutex]
|
|
220
|
+
|
|
221
|
+
libcall(:tctdbtune, conf[:bnum], conf[:apow], conf[:fpow], conf[:opts])
|
|
222
|
+
|
|
223
|
+
# TODO : set indexes here... well, there is already #set_index
|
|
224
|
+
#conf[:indexes]...
|
|
225
|
+
|
|
226
|
+
libcall(:tctdbsetcache, conf[:rcnum], conf[:lcnum], conf[:ncnum])
|
|
227
|
+
|
|
228
|
+
libcall(:tctdbsetxmsiz, conf[:xmsiz])
|
|
229
|
+
|
|
230
|
+
#
|
|
231
|
+
# open table
|
|
232
|
+
|
|
233
|
+
libcall(:tctdbopen, conf[:path], conf[:mode])
|
|
150
234
|
end
|
|
151
235
|
|
|
152
236
|
#
|
|
@@ -245,25 +329,43 @@ module Rufus
|
|
|
245
329
|
end
|
|
246
330
|
|
|
247
331
|
#
|
|
248
|
-
# Returns
|
|
332
|
+
# Returns an array of all the primary keys in the table
|
|
249
333
|
#
|
|
250
|
-
#
|
|
334
|
+
# With no options given, this method will return all the keys (strings)
|
|
335
|
+
# in a Ruby array.
|
|
251
336
|
#
|
|
252
|
-
|
|
253
|
-
m = lib.tab_get(@db, k, CabinetLib.strlen(k))
|
|
254
|
-
return nil if m.address == 0 # :( too bad, but it works
|
|
255
|
-
Map.to_h(m) # which frees the map
|
|
256
|
-
end
|
|
257
|
-
protected :get
|
|
258
|
-
|
|
337
|
+
# :prefix --> returns only the keys who match a given string prefix
|
|
259
338
|
#
|
|
260
|
-
#
|
|
339
|
+
# :limit --> returns a limited number of keys
|
|
261
340
|
#
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
341
|
+
# :native --> returns an instance of Rufus::Tokyo::List instead of
|
|
342
|
+
# a Ruby Hash, you have to call #free on that List when done with it !
|
|
343
|
+
# Else you're exposing yourself to a memory leak.
|
|
344
|
+
#
|
|
345
|
+
def keys (options={})
|
|
346
|
+
|
|
347
|
+
if pref = options[:prefix]
|
|
348
|
+
|
|
349
|
+
l = lib.tab_fwmkeys2(@db, pref, options[:limit] || -1)
|
|
350
|
+
l = Rufus::Tokyo::List.new(l)
|
|
351
|
+
options[:native] ? l : l.release
|
|
352
|
+
|
|
353
|
+
else
|
|
354
|
+
|
|
355
|
+
limit = options[:limit] || -1
|
|
356
|
+
limit = nil if limit < 1
|
|
357
|
+
|
|
358
|
+
l = options[:native] ? Rufus::Tokyo::List.new : []
|
|
359
|
+
|
|
360
|
+
lib.tab_iterinit(@db)
|
|
361
|
+
|
|
362
|
+
while (k = (lib.tab_iternext2(@db) rescue nil))
|
|
363
|
+
break if limit and l.size >= limit
|
|
364
|
+
l << k
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
l
|
|
368
|
+
end
|
|
267
369
|
end
|
|
268
370
|
|
|
269
371
|
#
|
|
@@ -377,6 +479,17 @@ module Rufus
|
|
|
377
479
|
|
|
378
480
|
protected
|
|
379
481
|
|
|
482
|
+
#
|
|
483
|
+
# Returns the value (as a Ruby Hash) else nil
|
|
484
|
+
#
|
|
485
|
+
# (the actual #[] method is provided by HashMethods)
|
|
486
|
+
#
|
|
487
|
+
def get (k)
|
|
488
|
+
m = lib.tab_get(@db, k, CabinetLib.strlen(k))
|
|
489
|
+
return nil if m.address == 0 # :( too bad, but it works
|
|
490
|
+
Map.to_h(m) # which frees the map
|
|
491
|
+
end
|
|
492
|
+
|
|
380
493
|
def libcall (lib_method, *args)
|
|
381
494
|
|
|
382
495
|
#(lib.send(lib_method, @db, *args) == 1) or raise_error
|
|
@@ -179,7 +179,7 @@ module Rufus
|
|
|
179
179
|
# (by passing a list pointer, one can wrap an existing list pointer
|
|
180
180
|
# into a handy instance of this class)
|
|
181
181
|
#
|
|
182
|
-
def initialize (list_pointer
|
|
182
|
+
def initialize (list_pointer=nil)
|
|
183
183
|
@list = list_pointer || clib.tclistnew
|
|
184
184
|
end
|
|
185
185
|
|
|
@@ -333,6 +333,17 @@ module Rufus
|
|
|
333
333
|
alias :free :close
|
|
334
334
|
alias :destroy :close
|
|
335
335
|
|
|
336
|
+
#
|
|
337
|
+
# Closes (frees memory from it) this list and returns the ruby version
|
|
338
|
+
# of it
|
|
339
|
+
#
|
|
340
|
+
def release
|
|
341
|
+
|
|
342
|
+
a = self.to_a
|
|
343
|
+
self.close
|
|
344
|
+
a
|
|
345
|
+
end
|
|
346
|
+
|
|
336
347
|
protected
|
|
337
348
|
|
|
338
349
|
#
|
|
@@ -84,6 +84,8 @@ module Rufus
|
|
|
84
84
|
attfunc :abs_sync, :tcrdbsync, [ :pointer ], :int
|
|
85
85
|
attfunc :abs_copy, :tcrdbcopy, [ :pointer, :string ], :int
|
|
86
86
|
|
|
87
|
+
attfunc :abs_fwmkeys2, :tcrdbfwmkeys2, [ :pointer, :string, :int ], :pointer
|
|
88
|
+
|
|
87
89
|
#
|
|
88
90
|
# table functions
|
|
89
91
|
|
|
@@ -111,6 +113,8 @@ module Rufus
|
|
|
111
113
|
|
|
112
114
|
attfunc :tab_setindex, :tcrdbtblsetindex, [ :pointer, :string, :int ], :int
|
|
113
115
|
|
|
116
|
+
attfunc :tab_fwmkeys2, :tcrdbfwmkeys2, [ :pointer, :string, :int ], :pointer
|
|
117
|
+
|
|
114
118
|
#
|
|
115
119
|
# qry functions
|
|
116
120
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rufus-tokyo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Mettraux
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2009-02-
|
|
13
|
+
date: 2009-02-19 00:00:00 +09:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|