metry 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +14 -69
- data/TODO +2 -3
- data/cucumber.yml +1 -0
- data/example/example.rb +1 -1
- data/features/psycho/dashboard.feature +17 -0
- data/features/psycho/goals.feature +24 -0
- data/features/psycho/visitor_tracking.feature +32 -0
- data/features/step_definitions/goals.rb +3 -0
- data/features/step_definitions/tracking.rb +1 -1
- data/features/step_definitions/web.rb +14 -2
- data/features/support/env.rb +4 -0
- data/lib/metry.rb +4 -6
- data/lib/metry/experiment.rb +6 -8
- data/lib/metry/psycho.rb +112 -0
- data/lib/metry/psycho/dashboard.erb +14 -0
- data/lib/metry/psycho/layout.erb +8 -0
- data/lib/metry/psycho/new_goal.erb +9 -0
- data/lib/metry/psycho/visitor.erb +7 -0
- data/lib/metry/rack/tracking.rb +17 -13
- data/lib/metry/storage.rb +116 -0
- data/radiant/example/features/metry.feature +8 -8
- data/radiant/example/features/psycho.feature +13 -0
- data/radiant/example/features/step_definitions/experiments.rb +2 -2
- data/radiant/example/features/step_definitions/tracking.rb +1 -1
- data/radiant/example/features/support/env.rb +3 -0
- data/radiant/extension/lib/metry_authenticator.rb +30 -0
- data/radiant/extension/lib/metry_tags.rb +2 -1
- data/radiant/extension/metry_extension.rb +1 -1
- data/test/{test_tokyo.rb → test_storage.rb} +3 -3
- metadata +17 -72
- data/lib/metry/memory.rb +0 -27
- data/lib/metry/tokyo.rb +0 -181
- data/vendor/rufus-tokyo/CHANGELOG.txt +0 -112
- data/vendor/rufus-tokyo/CREDITS.txt +0 -27
- data/vendor/rufus-tokyo/LICENSE.txt +0 -21
- data/vendor/rufus-tokyo/README.txt +0 -310
- data/vendor/rufus-tokyo/Rakefile +0 -118
- data/vendor/rufus-tokyo/TODO.txt +0 -25
- data/vendor/rufus-tokyo/doc/decision_table.numbers +0 -0
- data/vendor/rufus-tokyo/doc/rdoc-style.css +0 -320
- data/vendor/rufus-tokyo/lib/rufus-edo.rb +0 -3
- data/vendor/rufus-tokyo/lib/rufus-tokyo.rb +0 -3
- data/vendor/rufus-tokyo/lib/rufus/edo.rb +0 -39
- data/vendor/rufus-tokyo/lib/rufus/edo/README.txt +0 -106
- data/vendor/rufus-tokyo/lib/rufus/edo/cabcore.rb +0 -333
- data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/abstract.rb +0 -219
- data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/table.rb +0 -159
- data/vendor/rufus-tokyo/lib/rufus/edo/error.rb +0 -36
- data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant.rb +0 -4
- data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/abstract.rb +0 -137
- data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/table.rb +0 -141
- data/vendor/rufus-tokyo/lib/rufus/edo/tabcore.rb +0 -567
- data/vendor/rufus-tokyo/lib/rufus/tokyo.rb +0 -58
- data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/abstract.rb +0 -568
- data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/lib.rb +0 -230
- data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/table.rb +0 -753
- data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/util.rb +0 -425
- data/vendor/rufus-tokyo/lib/rufus/tokyo/config.rb +0 -161
- data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia.rb +0 -43
- data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/lib.rb +0 -65
- data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/words.rb +0 -71
- data/vendor/rufus-tokyo/lib/rufus/tokyo/hmethods.rb +0 -111
- data/vendor/rufus-tokyo/lib/rufus/tokyo/query.rb +0 -102
- data/vendor/rufus-tokyo/lib/rufus/tokyo/transactions.rb +0 -74
- data/vendor/rufus-tokyo/lib/rufus/tokyo/ttcommons.rb +0 -59
- data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant.rb +0 -35
- data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/abstract.rb +0 -146
- data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/lib.rb +0 -153
- data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/table.rb +0 -162
- data/vendor/rufus-tokyo/rufus-tokyo.gemspec +0 -25
- data/vendor/rufus-tokyo/spec/cabinet_spec.rb +0 -472
- data/vendor/rufus-tokyo/spec/cabinetconfig_spec.rb +0 -82
- data/vendor/rufus-tokyo/spec/edo_cabinet_spec.rb +0 -447
- data/vendor/rufus-tokyo/spec/edo_ntyrant_spec.rb +0 -299
- data/vendor/rufus-tokyo/spec/edo_ntyrant_table_spec.rb +0 -462
- data/vendor/rufus-tokyo/spec/edo_table_spec.rb +0 -560
- data/vendor/rufus-tokyo/spec/hmethods_spec.rb +0 -44
- data/vendor/rufus-tokyo/spec/incr.lua +0 -20
- data/vendor/rufus-tokyo/spec/spec.rb +0 -9
- data/vendor/rufus-tokyo/spec/spec_base.rb +0 -23
- data/vendor/rufus-tokyo/spec/start_tyrants.sh +0 -26
- data/vendor/rufus-tokyo/spec/stop_tyrants.sh +0 -9
- data/vendor/rufus-tokyo/spec/table_spec.rb +0 -567
- data/vendor/rufus-tokyo/spec/tyrant_spec.rb +0 -309
- data/vendor/rufus-tokyo/spec/tyrant_table_spec.rb +0 -479
- data/vendor/rufus-tokyo/spec/util_list_spec.rb +0 -200
- data/vendor/rufus-tokyo/spec/util_map_spec.rb +0 -132
- data/vendor/rufus-tokyo/tasks/dev.rb +0 -70
- data/vendor/rufus-tokyo/test/bm0.rb +0 -353
- data/vendor/rufus-tokyo/test/bm1_compression.rb +0 -54
- data/vendor/rufus-tokyo/test/con0.rb +0 -30
- data/vendor/rufus-tokyo/test/mem.rb +0 -49
- data/vendor/rufus-tokyo/test/mem1.rb +0 -44
- data/vendor/rufus-tokyo/test/readme0.rb +0 -17
- data/vendor/rufus-tokyo/test/readme1.rb +0 -21
- data/vendor/rufus-tokyo/test/readme2.rb +0 -15
- data/vendor/rufus-tokyo/test/readme3.rb +0 -24
- data/vendor/rufus-tokyo/test/readmes_test.sh +0 -17
@@ -1,58 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
-
# of this software and associated documentation files (the "Software"), to deal
|
6
|
-
# in the Software without restriction, including without limitation the rights
|
7
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
# copies of the Software, and to permit persons to whom the Software is
|
9
|
-
# furnished to do so, subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in
|
12
|
-
# all copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
-
# THE SOFTWARE.
|
21
|
-
#
|
22
|
-
# Made in Japan.
|
23
|
-
#++
|
24
|
-
|
25
|
-
|
26
|
-
require 'ffi' # sudo gem install ffi
|
27
|
-
|
28
|
-
|
29
|
-
module Rufus
|
30
|
-
module Tokyo
|
31
|
-
|
32
|
-
VERSION = '0.1.14'
|
33
|
-
|
34
|
-
#
|
35
|
-
# A common error class
|
36
|
-
#
|
37
|
-
class TokyoError < RuntimeError; end
|
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
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
require 'rufus/tokyo/cabinet/lib'
|
55
|
-
require 'rufus/tokyo/cabinet/util'
|
56
|
-
require 'rufus/tokyo/cabinet/abstract'
|
57
|
-
require 'rufus/tokyo/cabinet/table'
|
58
|
-
|
@@ -1,568 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
-
# of this software and associated documentation files (the "Software"), to deal
|
6
|
-
# in the Software without restriction, including without limitation the rights
|
7
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
# copies of the Software, and to permit persons to whom the Software is
|
9
|
-
# furnished to do so, subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in
|
12
|
-
# all copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
-
# THE SOFTWARE.
|
21
|
-
#
|
22
|
-
# Made in Japan.
|
23
|
-
#++
|
24
|
-
|
25
|
-
|
26
|
-
require 'rufus/tokyo/transactions'
|
27
|
-
|
28
|
-
|
29
|
-
module Rufus::Tokyo
|
30
|
-
|
31
|
-
#
|
32
|
-
# A 'cabinet', ie a Tokyo Cabinet [abstract] database.
|
33
|
-
#
|
34
|
-
# Follows the abstract API described at :
|
35
|
-
#
|
36
|
-
# http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
|
37
|
-
#
|
38
|
-
# An usage example :
|
39
|
-
#
|
40
|
-
# db = Rufus::Tokyo::Cabinet.new('test_data.tch')
|
41
|
-
# db['pillow'] = 'Shonagon'
|
42
|
-
#
|
43
|
-
# db.size # => 1
|
44
|
-
# db['pillow'] # => 'Shonagon'
|
45
|
-
#
|
46
|
-
# db.delete('pillow') # => 'Shonagon'
|
47
|
-
# db.size # => 0
|
48
|
-
#
|
49
|
-
# db.close
|
50
|
-
#
|
51
|
-
class Cabinet
|
52
|
-
|
53
|
-
include HashMethods
|
54
|
-
include Transactions
|
55
|
-
|
56
|
-
# Creates/opens the cabinet, raises an exception in case of
|
57
|
-
# creation/opening failure.
|
58
|
-
#
|
59
|
-
# This method accepts a 'name' parameter and an optional 'params' hash
|
60
|
-
# parameter.
|
61
|
-
#
|
62
|
-
# 'name' follows the syntax described at
|
63
|
-
#
|
64
|
-
# http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
|
65
|
-
#
|
66
|
-
# under tcadbopen(). For example :
|
67
|
-
#
|
68
|
-
# db = Rufus::Tokyo::Cabinet.new('casket.tch#bnum=100000#opts=ld')
|
69
|
-
#
|
70
|
-
# will open (eventually create) a hash database backed in the file
|
71
|
-
# 'casket.tch' with a bucket number of 100000 and the 'large' and
|
72
|
-
# 'deflate' options (opts) turned on.
|
73
|
-
#
|
74
|
-
# Note that there is an #open method similar to File#open for openening
|
75
|
-
# a db and closing it when it's no longer needed :
|
76
|
-
#
|
77
|
-
# Rufus::Tokyo::Cabinet.new('data.tch') do |db|
|
78
|
-
# db['key'] = value
|
79
|
-
# end
|
80
|
-
#
|
81
|
-
# == database name
|
82
|
-
#
|
83
|
-
# From http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi :
|
84
|
-
#
|
85
|
-
# 'If it is "*", the database will be an on-memory hash database. If it is
|
86
|
-
# "+", the database will be an on-memory tree database. If its suffix is
|
87
|
-
# ".tch", the database will be a hash database. If its suffix is ".tcb",
|
88
|
-
# the database will be a B+ tree database. If its suffix is ".tcf", the
|
89
|
-
# database will be a fixed-length database. If its suffix is ".tct", the
|
90
|
-
# database will be a table database.'
|
91
|
-
#
|
92
|
-
# You're supposed to give a path to the database file you want to use and
|
93
|
-
# Cabinet expects you to give the proper prefix.
|
94
|
-
#
|
95
|
-
# db = Rufus::Tokyo::Cabinet.new('data.tch') # hash database
|
96
|
-
# db = Rufus::Tokyo::Cabinet.new('data.tcb') # B+ tree db
|
97
|
-
# db = Rufus::Tokyo::Cabinet.new('data.tcf') # fixed-length db
|
98
|
-
#
|
99
|
-
# will result with the same file names :
|
100
|
-
#
|
101
|
-
# db = Rufus::Tokyo::Cabinet.new('data', :type => :hash) # hash database
|
102
|
-
# db = Rufus::Tokyo::Cabinet.new('data', :type => :btree) # B+ tree db
|
103
|
-
# db = Rufus::Tokyo::Cabinet.new('data', :type => :fixed) # fixed-length db
|
104
|
-
#
|
105
|
-
# You can open an in-memory hash and an in-memory B+ tree with :
|
106
|
-
#
|
107
|
-
# h = Rufus::Tokyo::Cabinet.new(:mem_hash) # or
|
108
|
-
# h = Rufus::Tokyo::Cabinet.new('*')
|
109
|
-
#
|
110
|
-
# t = Rufus::Tokyo::Cabinet.new(:mem_tree) # or
|
111
|
-
# t = Rufus::Tokyo::Cabinet.new('+')
|
112
|
-
#
|
113
|
-
# == parameters
|
114
|
-
#
|
115
|
-
# There are two ways to pass parameters at the opening of a db :
|
116
|
-
#
|
117
|
-
# db = Rufus::Tokyo::Cabinet.new('data.tch#opts=ld#mode=w') # or
|
118
|
-
# db = Rufus::Tokyo::Cabinet.new('data.tch', :opts => 'ld', :mode => 'w')
|
119
|
-
#
|
120
|
-
# most verbose :
|
121
|
-
#
|
122
|
-
# db = Rufus::Tokyo::Cabinet.new(
|
123
|
-
# 'data', :type => :hash, :opts => 'ld', :mode => 'w')
|
124
|
-
#
|
125
|
-
# === mode
|
126
|
-
#
|
127
|
-
# * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
|
128
|
-
# 'e' non locking, 'f' non blocking lock), default is 'wc'
|
129
|
-
#
|
130
|
-
# === other parameters
|
131
|
-
#
|
132
|
-
# 'On-memory hash database supports "bnum", "capnum", and "capsiz".
|
133
|
-
# On-memory tree database supports "capnum" and "capsiz".
|
134
|
-
# Hash database supports "mode", "bnum", "apow", "fpow", "opts",
|
135
|
-
# "rcnum", and "xmsiz".
|
136
|
-
# B+ tree database supports "mode", "lmemb", "nmemb", "bnum", "apow",
|
137
|
-
# "fpow", "opts", "lcnum", "ncnum", and "xmsiz".
|
138
|
-
# Fixed-length database supports "mode", "width", and "limsiz"'
|
139
|
-
#
|
140
|
-
# * :opts a set of chars ('l'arge, 'd'eflate, 'b'zip2, 't'cbs)
|
141
|
-
# (usually empty or something like 'ld' or 'lb')
|
142
|
-
#
|
143
|
-
# * :bnum number of elements of the bucket array
|
144
|
-
# * :apow size of record alignment by power of 2 (defaults to 4)
|
145
|
-
# * :fpow maximum number of elements of the free block pool by
|
146
|
-
# power of 2 (defaults to 10)
|
147
|
-
# * :mutex when set to true, makes sure only 1 thread at a time
|
148
|
-
# accesses the table (well, Ruby, global thread lock, ...)
|
149
|
-
#
|
150
|
-
# * :rcnum specifies the maximum number of records to be cached.
|
151
|
-
# If it is not more than 0, the record cache is disabled.
|
152
|
-
# It is disabled by default.
|
153
|
-
# * :lcnum specifies the maximum number of leaf nodes to be cached.
|
154
|
-
# If it is not more than 0, the default value is specified.
|
155
|
-
# The default value is 2048.
|
156
|
-
# * :ncnum specifies the maximum number of non-leaf nodes to be
|
157
|
-
# cached. If it is not more than 0, the default value is
|
158
|
-
# specified. The default value is 512.
|
159
|
-
#
|
160
|
-
# * :xmsiz specifies the size of the extra mapped memory. If it is
|
161
|
-
# not more than 0, the extra mapped memory is disabled.
|
162
|
-
# The default size is 67108864.
|
163
|
-
#
|
164
|
-
# * :capnum specifies the capacity number of records.
|
165
|
-
# * :capsiz specifies the capacity size of using memory.
|
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
|
-
#
|
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.
|
176
|
-
#
|
177
|
-
def initialize (name, params={})
|
178
|
-
|
179
|
-
@db = lib.tcadbnew
|
180
|
-
|
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
|
187
|
-
|
188
|
-
@path = name
|
189
|
-
|
190
|
-
name = name + params.collect { |k, v| "##{k}=#{v}" }.join('')
|
191
|
-
|
192
|
-
(lib.tcadbopen(@db, name) == 1) ||
|
193
|
-
raise("failed to open/create db '#{name}' #{params.inspect}")
|
194
|
-
|
195
|
-
self.default = params[:default]
|
196
|
-
@default_proc ||= params[:default_proc]
|
197
|
-
end
|
198
|
-
|
199
|
-
# Same args as initialize, but can take a block form that will
|
200
|
-
# close the db when done. Similar to File.open
|
201
|
-
#
|
202
|
-
def self.open (name, params={})
|
203
|
-
|
204
|
-
db = self.new(name, params)
|
205
|
-
|
206
|
-
if block_given?
|
207
|
-
yield db
|
208
|
-
nil
|
209
|
-
else
|
210
|
-
db
|
211
|
-
end
|
212
|
-
|
213
|
-
ensure
|
214
|
-
|
215
|
-
db.close if block_given? && db
|
216
|
-
end
|
217
|
-
|
218
|
-
# Returns a new in-memory hash. Accepts the same optional params hash
|
219
|
-
# as new().
|
220
|
-
#
|
221
|
-
def self.new_hash (params={})
|
222
|
-
|
223
|
-
self.new(:hash, params)
|
224
|
-
end
|
225
|
-
|
226
|
-
# Returns a new in-memory B+ tree. Accepts the same optional params hash
|
227
|
-
# as new().
|
228
|
-
#
|
229
|
-
def self.new_tree (params={})
|
230
|
-
|
231
|
-
self.new(:tree, params)
|
232
|
-
end
|
233
|
-
|
234
|
-
# Using the cabinet lib
|
235
|
-
#
|
236
|
-
def lib
|
237
|
-
|
238
|
-
CabinetLib
|
239
|
-
end
|
240
|
-
|
241
|
-
# Returns the path to this database.
|
242
|
-
#
|
243
|
-
def path
|
244
|
-
|
245
|
-
@path
|
246
|
-
end
|
247
|
-
|
248
|
-
# No comment
|
249
|
-
#
|
250
|
-
def []= (k, v)
|
251
|
-
|
252
|
-
lib.abs_put(@db, k, Rufus::Tokyo.blen(k), v, Rufus::Tokyo.blen(v))
|
253
|
-
end
|
254
|
-
|
255
|
-
# Like #put but doesn't overwrite the value if already set. Returns true
|
256
|
-
# only if there no previous entry for k.
|
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
|
-
|
264
|
-
# (The actual #[] method is provided by HashMethods
|
265
|
-
#
|
266
|
-
def get (k)
|
267
|
-
|
268
|
-
outlen_op(:abs_get, k, Rufus::Tokyo.blen(k))
|
269
|
-
end
|
270
|
-
protected :get
|
271
|
-
|
272
|
-
# Removes a record from the cabinet, returns the value if successful
|
273
|
-
# else nil.
|
274
|
-
#
|
275
|
-
def delete (k)
|
276
|
-
|
277
|
-
v = self[k]
|
278
|
-
|
279
|
-
(lib.abs_out(@db, k, Rufus::Tokyo.blen(k)) == 1) ? v : nil
|
280
|
-
end
|
281
|
-
|
282
|
-
# Returns the number of records in the 'cabinet'
|
283
|
-
#
|
284
|
-
def size
|
285
|
-
|
286
|
-
lib.abs_rnum(@db)
|
287
|
-
end
|
288
|
-
|
289
|
-
# Removes all the records in the cabinet (use with care)
|
290
|
-
#
|
291
|
-
# Returns self (like Ruby's Hash does).
|
292
|
-
#
|
293
|
-
def clear
|
294
|
-
|
295
|
-
lib.abs_vanish(@db)
|
296
|
-
|
297
|
-
self
|
298
|
-
end
|
299
|
-
|
300
|
-
# Returns the 'weight' of the db (in bytes)
|
301
|
-
#
|
302
|
-
def weight
|
303
|
-
|
304
|
-
lib.abs_size(@db)
|
305
|
-
end
|
306
|
-
|
307
|
-
# Closes the cabinet (and frees the datastructure allocated for it),
|
308
|
-
# returns true in case of success.
|
309
|
-
#
|
310
|
-
def close
|
311
|
-
|
312
|
-
result = lib.abs_close(@db)
|
313
|
-
lib.abs_del(@db)
|
314
|
-
|
315
|
-
(result == 1)
|
316
|
-
end
|
317
|
-
|
318
|
-
# Copies the current cabinet to a new file.
|
319
|
-
#
|
320
|
-
# Returns true if it was successful.
|
321
|
-
#
|
322
|
-
def copy (target_path)
|
323
|
-
|
324
|
-
(lib.abs_copy(@db, target_path) == 1)
|
325
|
-
end
|
326
|
-
|
327
|
-
# Copies the current cabinet to a new file.
|
328
|
-
#
|
329
|
-
# Does it by copying each entry afresh to the target file. Spares some
|
330
|
-
# space, hence the 'compact' label...
|
331
|
-
#
|
332
|
-
def compact_copy (target_path)
|
333
|
-
|
334
|
-
@other_db = Cabinet.new(target_path)
|
335
|
-
self.each { |k, v| @other_db[k] = v }
|
336
|
-
@other_db.close
|
337
|
-
end
|
338
|
-
|
339
|
-
# "synchronize updated contents of an abstract database object with
|
340
|
-
# the file and the device"
|
341
|
-
#
|
342
|
-
def sync
|
343
|
-
|
344
|
-
(lib.abs_sync(@db) == 1)
|
345
|
-
end
|
346
|
-
|
347
|
-
# Returns an array with all the keys in the databse
|
348
|
-
#
|
349
|
-
# With no options given, this method will return all the keys (strings)
|
350
|
-
# in a Ruby array.
|
351
|
-
#
|
352
|
-
# :prefix --> returns only the keys who match a given string prefix
|
353
|
-
#
|
354
|
-
# :limit --> returns a limited number of keys
|
355
|
-
#
|
356
|
-
# :native --> returns an instance of Rufus::Tokyo::List instead of
|
357
|
-
# a Ruby Hash, you have to call #free on that List when done with it !
|
358
|
-
# Else you're exposing yourself to a memory leak.
|
359
|
-
#
|
360
|
-
def keys (options={})
|
361
|
-
|
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)
|
368
|
-
|
369
|
-
l = Rufus::Tokyo::List.new(l)
|
370
|
-
|
371
|
-
options[:native] ? l : l.release
|
372
|
-
|
373
|
-
else
|
374
|
-
|
375
|
-
limit = options[:limit] || -1
|
376
|
-
limit = nil if limit < 1
|
377
|
-
|
378
|
-
l = options[:native] ? Rufus::Tokyo::List.new : []
|
379
|
-
|
380
|
-
lib.abs_iterinit(@db)
|
381
|
-
|
382
|
-
outlen = FFI::MemoryPointer.new(:int)
|
383
|
-
|
384
|
-
loop do
|
385
|
-
break if limit and l.size >= limit
|
386
|
-
out = lib.abs_iternext(@db, outlen)
|
387
|
-
break if out.address == 0
|
388
|
-
l << out.get_bytes(0, outlen.get_int(0))
|
389
|
-
end
|
390
|
-
|
391
|
-
l
|
392
|
-
end
|
393
|
-
|
394
|
-
ensure
|
395
|
-
|
396
|
-
outlen.free if outlen
|
397
|
-
end
|
398
|
-
|
399
|
-
# Deletes all the entries whose keys begin with the given prefix
|
400
|
-
#
|
401
|
-
def delete_keys_with_prefix (prefix)
|
402
|
-
|
403
|
-
call_misc(
|
404
|
-
'outlist', lib.abs_fwmkeys(@db, prefix, Rufus::Tokyo.blen(prefix), -1))
|
405
|
-
# -1 for no limits
|
406
|
-
|
407
|
-
nil
|
408
|
-
end
|
409
|
-
|
410
|
-
# Given a list of keys, returns a Hash { key => value } of the
|
411
|
-
# matching entries (in one sweep).
|
412
|
-
#
|
413
|
-
def lget (keys)
|
414
|
-
|
415
|
-
Hash[*call_misc('getlist', Rufus::Tokyo::List.new(keys))]
|
416
|
-
end
|
417
|
-
|
418
|
-
# Merges the given hash into this Cabinet (or Tyrant) and returns self.
|
419
|
-
#
|
420
|
-
def merge! (hash)
|
421
|
-
|
422
|
-
call_misc(
|
423
|
-
'putlist',
|
424
|
-
hash.inject(Rufus::Tokyo::List.new) { |l, (k, v)| l << k; l << v; l })
|
425
|
-
self
|
426
|
-
end
|
427
|
-
alias :lput :merge!
|
428
|
-
|
429
|
-
# Given a list of keys, deletes all the matching entries (in one sweep).
|
430
|
-
#
|
431
|
-
def ldelete (keys)
|
432
|
-
|
433
|
-
call_misc('outlist', Rufus::Tokyo::List.new(keys))
|
434
|
-
end
|
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
|
-
|
459
|
-
# Triggers a defrag run (TC >= 1.4.21 only)
|
460
|
-
#
|
461
|
-
def defrag
|
462
|
-
|
463
|
-
raise(NotImplementedError.new(
|
464
|
-
"method defrag is supported since Tokyo Cabinet 1.4.21. " +
|
465
|
-
"your TC version doesn't support it"
|
466
|
-
)) unless lib.respond_to?(:tctdbsetdfunit)
|
467
|
-
|
468
|
-
call_misc('defrag', Rufus::Tokyo::List.new)
|
469
|
-
end
|
470
|
-
|
471
|
-
# Warning : this method is low-level, you probably only need
|
472
|
-
# to use #transaction and a block.
|
473
|
-
#
|
474
|
-
# Direct call for 'transaction begin'.
|
475
|
-
#
|
476
|
-
def tranbegin
|
477
|
-
|
478
|
-
check_transaction_support
|
479
|
-
|
480
|
-
libcall(:tcadbtranbegin)
|
481
|
-
end
|
482
|
-
|
483
|
-
# Warning : this method is low-level, you probably only need
|
484
|
-
# to use #transaction and a block.
|
485
|
-
#
|
486
|
-
# Direct call for 'transaction commit'.
|
487
|
-
#
|
488
|
-
def trancommit
|
489
|
-
|
490
|
-
check_transaction_support
|
491
|
-
|
492
|
-
libcall(:tcadbtrancommit)
|
493
|
-
end
|
494
|
-
|
495
|
-
# Warning : this method is low-level, you probably only need
|
496
|
-
# to use #transaction and a block.
|
497
|
-
#
|
498
|
-
# Direct call for 'transaction abort'.
|
499
|
-
#
|
500
|
-
def tranabort
|
501
|
-
|
502
|
-
check_transaction_support
|
503
|
-
|
504
|
-
libcall(:tcadbtranabort)
|
505
|
-
end
|
506
|
-
|
507
|
-
protected
|
508
|
-
|
509
|
-
def check_transaction_support
|
510
|
-
|
511
|
-
raise(TokyoError.new(
|
512
|
-
"The version of Tokyo Cabinet you're using doesn't support " +
|
513
|
-
"transactions for non-table structures. Upgrade to TC >= 1.4.13.")
|
514
|
-
) unless lib.respond_to?(:tcadbtranbegin)
|
515
|
-
end
|
516
|
-
|
517
|
-
# Wrapping tcadbmisc or tcrdbmisc
|
518
|
-
# (and taking care of freeing the list_pointer)
|
519
|
-
#
|
520
|
-
def call_misc (function, list_pointer)
|
521
|
-
|
522
|
-
list_pointer = list_pointer.pointer \
|
523
|
-
if list_pointer.is_a?(Rufus::Tokyo::List)
|
524
|
-
|
525
|
-
begin
|
526
|
-
l = do_call_misc(function, list_pointer)
|
527
|
-
raise "function '#{function}' failed" unless l
|
528
|
-
Rufus::Tokyo::List.new(l).release
|
529
|
-
ensure
|
530
|
-
Rufus::Tokyo::List.free(list_pointer)
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
# Calls the tcadbmisc function
|
535
|
-
#
|
536
|
-
def do_call_misc (function, list_pointer)
|
537
|
-
|
538
|
-
lib.tcadbmisc(@db, function, list_pointer)
|
539
|
-
end
|
540
|
-
|
541
|
-
def libcall (lib_method, *args)
|
542
|
-
|
543
|
-
(eval(%{ lib.#{lib_method}(@db, *args) }) == 1) or \
|
544
|
-
raise TokyoError.new("call to #{lib_method} failed")
|
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
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|