metry 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +14 -69
  3. data/TODO +2 -3
  4. data/cucumber.yml +1 -0
  5. data/example/example.rb +1 -1
  6. data/features/psycho/dashboard.feature +17 -0
  7. data/features/psycho/goals.feature +24 -0
  8. data/features/psycho/visitor_tracking.feature +32 -0
  9. data/features/step_definitions/goals.rb +3 -0
  10. data/features/step_definitions/tracking.rb +1 -1
  11. data/features/step_definitions/web.rb +14 -2
  12. data/features/support/env.rb +4 -0
  13. data/lib/metry.rb +4 -6
  14. data/lib/metry/experiment.rb +6 -8
  15. data/lib/metry/psycho.rb +112 -0
  16. data/lib/metry/psycho/dashboard.erb +14 -0
  17. data/lib/metry/psycho/layout.erb +8 -0
  18. data/lib/metry/psycho/new_goal.erb +9 -0
  19. data/lib/metry/psycho/visitor.erb +7 -0
  20. data/lib/metry/rack/tracking.rb +17 -13
  21. data/lib/metry/storage.rb +116 -0
  22. data/radiant/example/features/metry.feature +8 -8
  23. data/radiant/example/features/psycho.feature +13 -0
  24. data/radiant/example/features/step_definitions/experiments.rb +2 -2
  25. data/radiant/example/features/step_definitions/tracking.rb +1 -1
  26. data/radiant/example/features/support/env.rb +3 -0
  27. data/radiant/extension/lib/metry_authenticator.rb +30 -0
  28. data/radiant/extension/lib/metry_tags.rb +2 -1
  29. data/radiant/extension/metry_extension.rb +1 -1
  30. data/test/{test_tokyo.rb → test_storage.rb} +3 -3
  31. metadata +17 -72
  32. data/lib/metry/memory.rb +0 -27
  33. data/lib/metry/tokyo.rb +0 -181
  34. data/vendor/rufus-tokyo/CHANGELOG.txt +0 -112
  35. data/vendor/rufus-tokyo/CREDITS.txt +0 -27
  36. data/vendor/rufus-tokyo/LICENSE.txt +0 -21
  37. data/vendor/rufus-tokyo/README.txt +0 -310
  38. data/vendor/rufus-tokyo/Rakefile +0 -118
  39. data/vendor/rufus-tokyo/TODO.txt +0 -25
  40. data/vendor/rufus-tokyo/doc/decision_table.numbers +0 -0
  41. data/vendor/rufus-tokyo/doc/rdoc-style.css +0 -320
  42. data/vendor/rufus-tokyo/lib/rufus-edo.rb +0 -3
  43. data/vendor/rufus-tokyo/lib/rufus-tokyo.rb +0 -3
  44. data/vendor/rufus-tokyo/lib/rufus/edo.rb +0 -39
  45. data/vendor/rufus-tokyo/lib/rufus/edo/README.txt +0 -106
  46. data/vendor/rufus-tokyo/lib/rufus/edo/cabcore.rb +0 -333
  47. data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/abstract.rb +0 -219
  48. data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/table.rb +0 -159
  49. data/vendor/rufus-tokyo/lib/rufus/edo/error.rb +0 -36
  50. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant.rb +0 -4
  51. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/abstract.rb +0 -137
  52. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/table.rb +0 -141
  53. data/vendor/rufus-tokyo/lib/rufus/edo/tabcore.rb +0 -567
  54. data/vendor/rufus-tokyo/lib/rufus/tokyo.rb +0 -58
  55. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/abstract.rb +0 -568
  56. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/lib.rb +0 -230
  57. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/table.rb +0 -753
  58. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/util.rb +0 -425
  59. data/vendor/rufus-tokyo/lib/rufus/tokyo/config.rb +0 -161
  60. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia.rb +0 -43
  61. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/lib.rb +0 -65
  62. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/words.rb +0 -71
  63. data/vendor/rufus-tokyo/lib/rufus/tokyo/hmethods.rb +0 -111
  64. data/vendor/rufus-tokyo/lib/rufus/tokyo/query.rb +0 -102
  65. data/vendor/rufus-tokyo/lib/rufus/tokyo/transactions.rb +0 -74
  66. data/vendor/rufus-tokyo/lib/rufus/tokyo/ttcommons.rb +0 -59
  67. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant.rb +0 -35
  68. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/abstract.rb +0 -146
  69. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/lib.rb +0 -153
  70. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/table.rb +0 -162
  71. data/vendor/rufus-tokyo/rufus-tokyo.gemspec +0 -25
  72. data/vendor/rufus-tokyo/spec/cabinet_spec.rb +0 -472
  73. data/vendor/rufus-tokyo/spec/cabinetconfig_spec.rb +0 -82
  74. data/vendor/rufus-tokyo/spec/edo_cabinet_spec.rb +0 -447
  75. data/vendor/rufus-tokyo/spec/edo_ntyrant_spec.rb +0 -299
  76. data/vendor/rufus-tokyo/spec/edo_ntyrant_table_spec.rb +0 -462
  77. data/vendor/rufus-tokyo/spec/edo_table_spec.rb +0 -560
  78. data/vendor/rufus-tokyo/spec/hmethods_spec.rb +0 -44
  79. data/vendor/rufus-tokyo/spec/incr.lua +0 -20
  80. data/vendor/rufus-tokyo/spec/spec.rb +0 -9
  81. data/vendor/rufus-tokyo/spec/spec_base.rb +0 -23
  82. data/vendor/rufus-tokyo/spec/start_tyrants.sh +0 -26
  83. data/vendor/rufus-tokyo/spec/stop_tyrants.sh +0 -9
  84. data/vendor/rufus-tokyo/spec/table_spec.rb +0 -567
  85. data/vendor/rufus-tokyo/spec/tyrant_spec.rb +0 -309
  86. data/vendor/rufus-tokyo/spec/tyrant_table_spec.rb +0 -479
  87. data/vendor/rufus-tokyo/spec/util_list_spec.rb +0 -200
  88. data/vendor/rufus-tokyo/spec/util_map_spec.rb +0 -132
  89. data/vendor/rufus-tokyo/tasks/dev.rb +0 -70
  90. data/vendor/rufus-tokyo/test/bm0.rb +0 -353
  91. data/vendor/rufus-tokyo/test/bm1_compression.rb +0 -54
  92. data/vendor/rufus-tokyo/test/con0.rb +0 -30
  93. data/vendor/rufus-tokyo/test/mem.rb +0 -49
  94. data/vendor/rufus-tokyo/test/mem1.rb +0 -44
  95. data/vendor/rufus-tokyo/test/readme0.rb +0 -17
  96. data/vendor/rufus-tokyo/test/readme1.rb +0 -21
  97. data/vendor/rufus-tokyo/test/readme2.rb +0 -15
  98. data/vendor/rufus-tokyo/test/readme3.rb +0 -24
  99. 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
-