rufus-tokyo 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,34 @@
2
2
  = rufus-tokyo CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-tokyo - 1.0.2 released 2009/11/01
6
+
7
+ - bug : HashMethods#to_a not working right with Ruby 1.9.1. Fixed.
8
+ - bug : REE problem with libXXXopen, had to switch from == 1 to != 0
9
+ - todo : added #counter_value to Cabinet/Tyrant
10
+ - todo : added default_proc / default value to Cabinet/Tyrant (not tables).
11
+ - todo : Table#delete_keys_with_prefix now using qry#searchout.
12
+ - todo : cleaned up 'no transactions for Tyrant [table]' code.
13
+ - todo : db#ldelete(k0, k1, ...) now OK.
14
+ - todo : minimal warnings when running with -w
15
+ - todo : db#mget(k0, k1, ...) now OK.
16
+ - added : class level open() for Table classes and Dystopia
17
+ - bug : the primary key is not stringified by get() for Table or TyrantTable
18
+ - bug : keys() crashes for Rufus::Edo::Cabinet.new('*.tcb')
19
+ - bug : keys() without :prefix returns duplicate keys for b-tree database
20
+ (Edo or Tokyo) due to iteration, while the underlying C code or even
21
+ calls with :prefix do not
22
+ - bug : specifying tuning parameters causes Rufus::Edo::Cabinet.new('*.tcf')
23
+ to raise an exception
24
+ - bug : keys() and each() don't work fixed-width database, due to fwmkeys()
25
+ not being supported (Edo and Tokyo)
26
+ - added : can set built-in or custom comparison functions for b-tree databases
27
+ (Edo interface only)
28
+ - todo : reenabled #copy for Tyrant (Edo and Tokyo)
29
+ - added : query_count() to match query_delete() for tables (Edo and Tokyo)
30
+ - todo : made iteration faster in most cases
31
+
32
+
5
33
  == rufus-tokyo - 1.0.1 released 2009/09/18
6
34
 
7
35
  - todo : add #putcat to Cabinet / Tyrant (Edo and Tokyo)
data/CREDITS.txt CHANGED
@@ -5,6 +5,7 @@
5
5
  == authors
6
6
 
7
7
  John Mettraux http://jmettraux.wordpress.com
8
+ James Edward Gray II http://blog.grayproductions.net/
8
9
  Zev Blut http://www.iknow.co.jp/users/zev
9
10
  Jeremy Hinegardner http://www.copiousfreetime.org/
10
11
 
@@ -24,7 +25,6 @@ Mark 'mebaran' http://github.com/mebaran
24
25
 
25
26
  == feedback / support
26
27
 
27
- James Edward Gray II http://blog.grayproductions.net/
28
28
  Alexandre Gravem
29
29
  Philippe Monnet http://blog.monnet-usa.com/
30
30
  Ilya Grigorik http://igvita.com
data/MIGRATED.txt ADDED
@@ -0,0 +1 @@
1
+ to gemcutter.org indeed :)
data/README.rdoc CHANGED
@@ -8,7 +8,7 @@ The 'abstract' and the 'table' API are covered for now.
8
8
 
9
9
  == installation
10
10
 
11
- sudo gem install rufus-tokyo
11
+ sudo gem install rufus-tokyo --source http://gemcutter.org
12
12
 
13
13
  (see after 'usage' for how to install Tokyo Cabinet (and Tyrant) if required)
14
14
 
@@ -31,11 +31,12 @@ the rdoc is at http://rufus.rubyforge.org/rufus-tokyo/
31
31
 
32
32
  this 'master' branch/version of rufus-tokyo works with
33
33
 
34
- ffi 0.3.1, 0.3.5, 0.4.0, 0.5.0
34
+ ffi 0.3.1, 0.3.5, 0.4.0, 0.5.0, 0.5.1
35
35
 
36
36
  ruby 1.8.6
37
37
  ruby 1.9.1p129
38
38
  jruby 1.1.6, 1.2.0, 1.3.1
39
+ ree 1.8.7 2009.10 (thanks to http://rvm.beginrescueend.com)
39
40
 
40
41
  TC 1.4.27 / 29 and TT 1.1.29 / 33
41
42
 
@@ -272,7 +273,7 @@ On the rufus-ruby list :
272
273
 
273
274
  http://groups.google.com/group/rufus-ruby
274
275
 
275
- Note : Flinn Muller started an english speaking mailing list for TC / TT / TD
276
+ Note : Flinn Mueller started an english speaking mailing list for TC / TT / TD
276
277
 
277
278
  http://groups.google.com/group/tokyocabinet-users
278
279
 
@@ -298,17 +299,23 @@ http://github.com/jmettraux/rufus-tokyo
298
299
 
299
300
  many thanks to the author of Tokyo Cabinet, Mikio Hirabayashi, and to the authors of ruby-ffi
300
301
 
301
- * http://tokyocabinet.sourceforge.net
302
- * http://kenai.com/projects/ruby-ffi
302
+ * http://1978th.net/tokyocabinet/
303
+ * http://1978th.net/tokyotyrant/
304
+ * http://1978th.net/tokyodystopia/
305
+
306
+ * http://wiki.github.com/ffi/ffi
303
307
 
304
308
  dystopia interface developed with and sponsored by Seven Scale <http://sevenscale.com/>,
305
309
  creators of Open Syslog.
306
310
 
311
+
307
312
  == authors
308
313
 
309
314
  * John Mettraux, jmettraux@gmail.com, http://jmettraux.wordpress.com
310
315
  * Zev Blut, http://www.iknow.co.jp/users/zev
311
316
  * Jeremy Hinegardner http://github.com/copiousfreetime (Tokyo Dystopia)
317
+ * James Edward Gray II http://blog.grayproductions.net/
318
+
312
319
 
313
320
  == the rest of Rufus
314
321
 
data/TODO.txt CHANGED
@@ -1,38 +1,37 @@
1
1
 
2
2
  [o] table : bench find(1) after set_index
3
3
  [o] table : bench insert(1) after set_index
4
-
5
4
  [o] align edo#new on tokyo#new
6
- [ ] horizontal (bdb hdb fdb) tests for tokyo and edo
7
-
8
5
  [o] rdoc unix socket for tyrant
9
6
  [o] edo : tran
10
7
  [x] bench ux socket
11
-
12
8
  [o] TT (TC) call [lua] function
13
9
  [o] queryout
14
-
15
10
  [o] impl lget/lput/ldelete in Rufus::Edo::Cabinet
16
-
17
11
  [x] maybe supported different libs for migrations...
18
12
  no, tctools are here for that.
19
-
20
- [ ] document ENV['TOKYO_TYRANT_LIB'] & _CABINET_ / LD_LIBRARY_PATH
21
-
13
+ [x] maybe Edo::Abort vs Tokyo::Abort
22
14
  [o] unify m/l raise trick for util map/list
23
-
24
15
  [o] misc calls (defrag) for Edo
25
- [ ] TT set master & co
26
-
27
16
  [o] drop 'backward compatibility' (post 0.1.14)
28
17
  [o] qgram, token, opt inverted index types
29
18
  [o] new query FTS conds
19
+ [o] document ENV['TOKYO_TYRANT_LIB'] & _CABINET_ / LD_LIBRARY_PATH
20
+ [o] first integration of Jeremy's work on Dystopia
21
+ [o] implement q.metasearch(q, u)
22
+ [o] table/delete_keys_with_prefix, use searchout
23
+ [o] default value / default_proc for cabinets
24
+ [o] self.open for tables
30
25
 
31
- [ ] table/delete_keys_with_prefix, use searchout
32
-
33
- [ ] first integration of Jeremy's work on Dystopia
26
+ [ ] ldelete for tables ?
34
27
 
35
- [ ] implement q.metasearch(q, u)
36
28
  [ ] kwic ?
37
- [x] maybe Edo::Abort vs Tokyo::Abort
29
+
30
+ [ ] TT set master & co
31
+
32
+ [ ] map/reduce ?
33
+
34
+ [ ] wire setmutex for Cabinet (and ?)
35
+
36
+ [ ] copy for tyrant tables ?
38
37
 
@@ -25,6 +25,7 @@
25
25
 
26
26
  require 'rufus/tokyo/hmethods'
27
27
  require 'rufus/tokyo/transactions'
28
+ require 'rufus/tokyo/openable'
28
29
 
29
30
 
30
31
  module Rufus::Edo
@@ -42,25 +43,9 @@ module Rufus::Edo
42
43
  include Rufus::Tokyo::HashMethods
43
44
  include Rufus::Tokyo::Transactions
44
45
 
45
- def self.included (target_module)
46
-
47
- target_module.module_eval do
48
- #
49
- # Same args as initialize, but can take a block form that will
50
- # close the db when done. Similar to File.open (via Zev)
51
- #
52
- def self.open (name, params={})
53
- db = self.new(name, params)
54
- if block_given?
55
- yield db
56
- nil
57
- else
58
- db
59
- end
60
- ensure
61
- db.close if block_given? && db
62
- end
63
- end
46
+ # Add the open() method to all Cabinet type classes.
47
+ def self.included(target)
48
+ target.extend(Rufus::Tokyo::Openable)
64
49
  end
65
50
 
66
51
  # Returns the path to this database.
@@ -193,25 +178,14 @@ module Rufus::Edo
193
178
  #
194
179
  def keys (options={})
195
180
 
196
- if pref = options[:prefix]
181
+ if @db.respond_to? :fwmkeys
182
+ pref = options.fetch(:prefix, "")
197
183
 
198
184
  @db.fwmkeys(pref, options[:limit] || -1)
199
-
185
+ elsif @db.respond_to? :range
186
+ @db.range("[min,max]", nil)
200
187
  else
201
-
202
- limit = options[:limit] || -1
203
- limit = nil if limit < 1
204
-
205
- l = []
206
-
207
- @db.iterinit
208
-
209
- while (k = @db.iternext)
210
- break if limit and l.size >= limit
211
- l << k
212
- end
213
-
214
- l
188
+ raise NotImplementedError, "Database does not support keys()"
215
189
  end
216
190
  end
217
191
 
@@ -235,9 +209,9 @@ module Rufus::Edo
235
209
  #
236
210
  # Warning : this is a naive (slow) implementation.
237
211
  #
238
- def lget (keys)
212
+ def lget (*keys)
239
213
 
240
- keys = keys.collect { |k| k.to_s }
214
+ keys = keys.flatten.collect { |k| k.to_s }
241
215
 
242
216
  # only ADB has the #misc method...
243
217
 
@@ -269,9 +243,9 @@ module Rufus::Edo
269
243
  #
270
244
  # Warning : this is a naive (slow) implementation.
271
245
  #
272
- def ldelete (keys)
246
+ def ldelete (*keys)
273
247
 
274
- keys = keys.collect { |k| k.to_s }
248
+ keys = keys.flatten.collect { |k| k.to_s }
275
249
 
276
250
  # only ADB has the #misc method...
277
251
 
@@ -287,6 +261,11 @@ module Rufus::Edo
287
261
  # Increments the value stored under the given key with the given increment
288
262
  # (defaults to 1 (integer)).
289
263
  #
264
+ # Warning : Tokyo Cabinet/Tyrant doesn't store counter values as regular
265
+ # strings (db['key'] won't yield something that replies properly to #to_i)
266
+ #
267
+ # Use #counter_value(k) to get the current value set for the counter.
268
+ #
290
269
  def incr (key, val=1)
291
270
 
292
271
  key = key.to_s
@@ -295,7 +274,7 @@ module Rufus::Edo
295
274
 
296
275
  raise(EdoError.new(
297
276
  "incr failed, there is probably already a string value set " +
298
- "for the key '#{key}'"
277
+ "for the key '#{key}'. Make sure there is no value before incrementing"
299
278
  )) unless v
300
279
 
301
280
  v
@@ -305,6 +284,15 @@ module Rufus::Edo
305
284
  alias :add_double :incr
306
285
  alias :add_int :incr
307
286
 
287
+ # Returns the current value for a counter (a float or an int).
288
+ #
289
+ # See #incr
290
+ #
291
+ def counter_value (key)
292
+
293
+ incr(key, 0.0) rescue incr(key, 0)
294
+ end
295
+
308
296
  # Triggers a defrag (TC >= 1.4.21 only)
309
297
  #
310
298
  def defrag
@@ -87,11 +87,29 @@ module Rufus::Edo
87
87
  # db = Rufus::Edo::Cabinet.new(
88
88
  # 'data', :type => :hash, :opts => 'ld', :mode => 'w')
89
89
  #
90
- # === mode
90
+ # === :mode
91
91
  #
92
92
  # * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
93
93
  # 'e' non locking, 'f' non blocking lock), default is 'wc'
94
94
  #
95
+ # === :default and :default_proc
96
+ #
97
+ # Much like a Ruby Hash, a Cabinet accepts a default value or a default_proc
98
+ #
99
+ # db = Rufus::Edo::Cabinet.new('data.tch', :default => 'xxx')
100
+ # db['fred'] = 'Astaire'
101
+ # p db['fred'] # => 'Astaire'
102
+ # p db['ginger'] # => 'xxx'
103
+ #
104
+ # db = Rufus::Edo::Cabinet.new(
105
+ # 'data.tch',
106
+ # :default_proc => lambda { |cab, key| "not found : '#{k}'" }
107
+ # p db['ginger'] # => "not found : 'ginger'"
108
+ #
109
+ # The first arg passed to the default_proc is the cabinet itself, so this
110
+ # opens up interesting possibilities.
111
+ #
112
+ #
95
113
  # === other parameters
96
114
  #
97
115
  # 'On-memory hash database supports "bnum", "capnum", and "capsiz".
@@ -99,7 +117,7 @@ module Rufus::Edo
99
117
  # Hash database supports "mode", "bnum", "apow", "fpow", "opts",
100
118
  # "rcnum", and "xmsiz".
101
119
  # B+ tree database supports "mode", "lmemb", "nmemb", "bnum", "apow",
102
- # "fpow", "opts", "lcnum", "ncnum", and "xmsiz".
120
+ # "fpow", "opts", "lcnum", "ncnum", "xmsiz", and "cmpfunc".
103
121
  # Fixed-length database supports "mode", "width", and "limsiz"'
104
122
  #
105
123
  # * :opts a set of chars ('l'arge, 'd'eflate, 'b'zip2, 't'cbs)
@@ -109,8 +127,6 @@ module Rufus::Edo
109
127
  # * :apow size of record alignment by power of 2 (defaults to 4)
110
128
  # * :fpow maximum number of elements of the free block pool by
111
129
  # power of 2 (defaults to 10)
112
- # * :mutex when set to true, makes sure only 1 thread at a time
113
- # accesses the table (well, Ruby, global thread lock, ...)
114
130
  #
115
131
  # * :rcnum specifies the maximum number of records to be cached.
116
132
  # If it is not more than 0, the record cache is disabled.
@@ -138,6 +154,12 @@ module Rufus::Edo
138
154
  # * :dfunit unit step number. If it is not more than 0,
139
155
  # the auto defragmentation is disabled. (Since TC 1.4.21)
140
156
  #
157
+ # * :cmpfunc the comparison function used to order a b-tree database. Can
158
+ # be set to :lexical (default), :decimal, or a Proc object that
159
+ # implements a <=>-like comparison function for the two keys it
160
+ # will be passed. Custom comparisons must be set each time the
161
+ # database is opened.
162
+ #
141
163
  #
142
164
  # = NOTE :
143
165
  #
@@ -166,7 +188,7 @@ module Rufus::Edo
166
188
  when :abstract then nil
167
189
  when :hash then [ :bnum, :apow, :fpow, :opts ]
168
190
  when :btree then [ :lmemb, :nmemb, :bnum, :apow, :fpow, :opts ]
169
- when :fixed then [ :bnum, :width, :limsiz ]
191
+ when :fixed then [ :width, :limsiz ]
170
192
  end
171
193
 
172
194
  @db.tune(*tuning_parameters.collect { |o| conf[o] }) \
@@ -197,6 +219,20 @@ module Rufus::Edo
197
219
  @db.setdfunit(conf[:dfunit]) \
198
220
  if @db.respond_to?(:setdfunit)
199
221
 
222
+ #
223
+ # set cmp_func
224
+
225
+ if @db.respond_to? :setcmpfunc
226
+ case conf[:cmpfunc]
227
+ when :lexical
228
+ @db.setcmpfunc(TokyoCabinet::BDB::CMPLEXICAL)
229
+ when :decimal
230
+ @db.setcmpfunc(TokyoCabinet::BDB::CMPDECIMAL)
231
+ when Proc
232
+ @db.setcmpfunc(conf[:cmpfunc])
233
+ end
234
+ end
235
+
200
236
  #
201
237
  # open
202
238
 
@@ -133,6 +133,11 @@ module Rufus::Edo
133
133
 
134
134
  @db.setdfunit(conf[:dfunit]) if @db.respond_to?(:setdfunit)
135
135
 
136
+ #
137
+ # no default
138
+
139
+ @default_proc = nil
140
+
136
141
  #
137
142
  # open
138
143
 
@@ -44,6 +44,7 @@ module Rufus::Edo
44
44
 
45
45
  include Rufus::Edo::CabinetCore
46
46
  include Rufus::Tokyo::TyrantCommons
47
+ include Rufus::Tokyo::NoTransactions
47
48
 
48
49
  attr_reader :host, :port
49
50
 
@@ -68,7 +69,26 @@ module Rufus::Edo
68
69
  #
69
70
  # t = Rufus::Edo::NetTyrant.new('127.0.0.1', 44001)
70
71
  #
71
- def initialize (host, port=0)
72
+ #
73
+ # == :default and :default_proc
74
+ #
75
+ # Much like a Ruby Hash, a Tyrant accepts a default value or a default_proc
76
+ #
77
+ # db = Rufus::Edo::NetTyrant.new('127.0.0.1', 1978, :default => 'xxx')
78
+ # db['fred'] = 'Astaire'
79
+ # p db['fred'] # => 'Astaire'
80
+ # p db['ginger'] # => 'xxx'
81
+ #
82
+ # db = Rufus::Edo::NetTyrant.new(
83
+ # '127.0.0.1',
84
+ # 1978,
85
+ # :default_proc => lambda { |cab, key| "not found : '#{k}'" }
86
+ # p db['ginger'] # => "not found : 'ginger'"
87
+ #
88
+ # The first arg passed to the default_proc is the tyrant itself, so this
89
+ # opens up interesting possibilities.
90
+ #
91
+ def initialize (host, port=0, params={})
72
92
 
73
93
  @host = host
74
94
  @port = port
@@ -84,6 +104,12 @@ module Rufus::Edo
84
104
  "tyrant at #{host}:#{port} is a table, " +
85
105
  "use Rufus::Edo::NetTyrantTable instead to access it.")
86
106
  end
107
+
108
+ #
109
+ # default value|proc
110
+
111
+ self.default = params[:default]
112
+ @default_proc ||= params[:default_proc]
87
113
  end
88
114
 
89
115
  # Returns the 'weight' of the db (in bytes)
@@ -93,14 +119,18 @@ module Rufus::Edo
93
119
  self.stat['size']
94
120
  end
95
121
 
96
- # isn't that a bit dangerous ? it creates a file on the server...
122
+ # Tells the Tyrant server to create a copy of itself at the given (remote)
123
+ # target_path.
97
124
  #
98
- # DISABLED.
125
+ # Returns true when successful.
126
+ #
127
+ # Note : if you started your ttserver with a path like "tyrants/data.tch"
128
+ # you have to provide a target path in the same subdir, like
129
+ # "tyrants/data_prime.tch".
99
130
  #
100
131
  def copy (target_path)
101
132
 
102
- #@db.copy(target_path)
103
- raise 'not allowed to create files on the server'
133
+ @db.copy(target_path) || raise_error
104
134
  end
105
135
 
106
136
  # Copies the current cabinet to a new file.
@@ -130,6 +160,7 @@ module Rufus::Edo
130
160
  protected
131
161
 
132
162
  def do_stat #:nodoc#
163
+
133
164
  @db.stat
134
165
  end
135
166
  end