rufus-tokyo 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,13 @@
2
2
  = rufus-tokyo CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-tokyo - 0.1.8 released 2009/02/27
6
+
7
+ - added : support for Hirabayashi-san 'native' Ruby classes via Rufus::Edo
8
+ - todo : implemented #delete_keys_with_prefix (naive impl for tables)
9
+ - added : lget/ldelete and merge! to Rufus::Tokyo::Cabinet and ::Tyrant
10
+
11
+
5
12
  == rufus-tokyo - 0.1.7 released 2009/02/19
6
13
 
7
14
  - todo : Rufus::Tokyo::Cabinet.new('filename', :type => :hash) now OK (Zev)
@@ -5,10 +5,14 @@
5
5
  == authors
6
6
 
7
7
  John Mettraux http://jmettraux.wordpress.com
8
- Justin Reagor http://blog.kineticweb.com/
9
8
  Zev Blut http://www.iknow.co.jp/users/zev
10
9
 
11
10
 
11
+ == contributors
12
+
13
+ Justin Reagor http://blog.kineticweb.com/
14
+
15
+
12
16
  == finally
13
17
 
14
18
  many thanks to the author of Tokyo Cabinet (Mikio Hirabayashi) and
data/README.txt CHANGED
@@ -13,6 +13,13 @@ The 'abstract' and the 'table' API are covered for now.
13
13
  (see after 'usage' for how to install Tokyo Cabinet (and Tyrant) if required)
14
14
 
15
15
 
16
+ == Rufus::Edo
17
+
18
+ Note : Rufus::Tokyo focuses on leveraging Hirabayashi-san's C libraries via ruby-ffi, but the gem rufus-tokyo also contains Rufus::Edo which wraps the Tokyo Cabinet/Tyrant author's [native] C bindings :
19
+
20
+ http://github.com/jmettraux/rufus-tokyo/tree/master/lib/rufus/edo
21
+
22
+
16
23
  == usage
17
24
 
18
25
  hereafter TC references Tokyo Cabinet, while TT references Tokyo Tyrant.
@@ -48,7 +55,7 @@ http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
48
55
  require 'rubygems'
49
56
  require 'rufus/tokyo'
50
57
 
51
- t = Rufus::Tokyo::Table.new('table.tdb')
58
+ t = Rufus::Tokyo::Table.new('table.tct')
52
59
 
53
60
  t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
54
61
  t['pk1'] = { 'name' => 'bob', 'age' => '18' }
@@ -123,6 +130,19 @@ Rufus::Tokyo::Tyrant instances have a #stat method :
123
130
  # fd => 7
124
131
 
125
132
 
133
+ Note that it's also OK to make a Tokyo Tyrant server listen on a unix socket :
134
+
135
+ ttserver -host /tmp/ttsocket -port 0 data.tch
136
+
137
+ and then :
138
+
139
+ require 'rubygems'
140
+ require 'rufus/tokyo/tyrant'
141
+ db = Rufus::Tokyo::Tyrant.new('/tmp/ttsocket')
142
+ db['a'] = 'alpha'
143
+ db.close
144
+
145
+
126
146
  === TT remote table
127
147
 
128
148
  to start a ttserver (backed by a table), on the command line :
@@ -172,6 +192,19 @@ Rufus::Tokyo::TyrantTable instances have a #stat method :
172
192
  # fd => 10
173
193
 
174
194
 
195
+ Note that it's also OK to make a Tokyo Tyrant server listen on a unix socket :
196
+
197
+ ttserver -host /tmp/tttsocket -port 0 data.tct
198
+
199
+ and then :
200
+
201
+ require 'rubygems'
202
+ require 'rufus/tokyo/tyrant'
203
+ t = Rufus::Tokyo::TyrantTable.new('/tmp/tttsocket')
204
+ t['customer0'] = { 'name' => 'Heike no Kyomori', 'age' => '75' }
205
+ t.close
206
+
207
+
175
208
  == rdoc
176
209
 
177
210
  more in the rdoc
@@ -239,7 +272,6 @@ many thanks to the author of Tokyo Cabinet, Mikio Hirabayashi, and to the author
239
272
  == authors
240
273
 
241
274
  John Mettraux, jmettraux@gmail.com, http://jmettraux.wordpress.com
242
- Justin Reagor, http://blog.kineticweb.com/
243
275
  Zev Blut, http://www.iknow.co.jp/users/zev
244
276
 
245
277
 
data/TODO.txt CHANGED
@@ -1,5 +1,14 @@
1
1
 
2
- [ ] implement keys and values
3
- [ ] wire optimize()
2
+ [ ] table : bench find(1) after set_index
3
+ [ ] table : bench insert(1) after set_index
4
+
5
+ [x] align edo#new on tokyo#new
6
+ [ ] horizontal (bdb hdb fdb) tests for tokyo and edo
7
+
8
+ [x] rdoc unix socket for tyrant
9
+ [x] edo : tran
10
+ [ ] bench ux socket
11
+ [ ] impl lget/lput/ldelete in Rufus::Edo::Cabinet
12
+
4
13
  [ ] maybe supported different libs for migrations...
5
14
 
@@ -0,0 +1,3 @@
1
+
2
+ require 'rufus/edo'
3
+
@@ -0,0 +1,44 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ begin
32
+
33
+ require 'tokyocabinet'
34
+
35
+ rescue LoadError
36
+
37
+ raise LoadError.new(
38
+ "tokyocabinet 'native' C bindings not present on your system, " +
39
+ "see http://github.com/jmettraux/rufus-tokyo/tree/master/lib/rufus/edo")
40
+ end
41
+
42
+ require 'rufus/edo/cabinet/abstract'
43
+ require 'rufus/edo/cabinet/table'
44
+
@@ -0,0 +1,292 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ require 'rufus/tokyo/hmethods'
32
+ require 'rufus/tokyo/transactions'
33
+
34
+
35
+ module Rufus::Edo
36
+
37
+ #
38
+ # The base cabinet methods are gathered here. They focus on wrapping
39
+ # Hirabayashi-san's methods.
40
+ #
41
+ # This module is included by Edo::Cabinet and Edo::NTyrant. Placing the
42
+ # methods in this module avoids having to load 'TokyoCabinet' when using
43
+ # only rufus/edo/ntyrant.
44
+ #
45
+ module CabinetCore
46
+
47
+ include Rufus::Tokyo::HashMethods
48
+ include Rufus::Tokyo::Transactions
49
+
50
+ def self.included (target_module)
51
+
52
+ target_module.module_eval do
53
+ #
54
+ # Same args as initialize, but can take a block form that will
55
+ # close the db when done. Similar to File.open (via Zev)
56
+ #
57
+ def self.open (name, params={})
58
+ db = self.new(name, params)
59
+ if block_given?
60
+ yield db
61
+ nil
62
+ else
63
+ db
64
+ end
65
+ ensure
66
+ db.close if block_given? && db
67
+ end
68
+ end
69
+ end
70
+
71
+ #
72
+ # No comment
73
+ #
74
+ def []= (k, v)
75
+ @db.put(k, v) || raise_error
76
+ end
77
+
78
+ #
79
+ # (The actual #[] method is provided by HashMethods
80
+ #
81
+ def get (k)
82
+ @db.get(k)
83
+ end
84
+ protected :get
85
+
86
+ #
87
+ # Removes a record from the cabinet, returns the value if successful
88
+ # else nil.
89
+ #
90
+ def delete (k)
91
+ v = self[k]
92
+ @db.out(k) ? v : nil
93
+ end
94
+
95
+ #
96
+ # Returns the number of records in the 'cabinet'
97
+ #
98
+ def size
99
+ @db.rnum
100
+ end
101
+
102
+ #
103
+ # Removes all the records in the cabinet (use with care)
104
+ #
105
+ # Returns self (like Ruby's Hash does).
106
+ #
107
+ def clear
108
+ @db.vanish || raise_error
109
+ self
110
+ end
111
+
112
+ #
113
+ # Returns the 'weight' of the db (in bytes)
114
+ #
115
+ def weight
116
+ @db.fsiz
117
+ end
118
+
119
+ #
120
+ # Closes the cabinet (and frees the datastructure allocated for it),
121
+ # returns true in case of success.
122
+ #
123
+ def close
124
+ @db.close || raise_error
125
+ end
126
+
127
+ #
128
+ # Copies the current cabinet to a new file.
129
+ #
130
+ # Returns true if it was successful.
131
+ #
132
+ def copy (target_path)
133
+ @db.copy(target_path)
134
+ end
135
+
136
+ #
137
+ # Copies the current cabinet to a new file.
138
+ #
139
+ # Does it by copying each entry afresh to the target file. Spares some
140
+ # space, hence the 'compact' label...
141
+ #
142
+ def compact_copy (target_path)
143
+ @other_db = self.class.new(target_path)
144
+ self.each { |k, v| @other_db[k] = v }
145
+ @other_db.close
146
+ end
147
+
148
+ #
149
+ # "synchronize updated contents of an abstract database object with
150
+ # the file and the device"
151
+ #
152
+ def sync
153
+ @db.sync || raise_error
154
+ end
155
+
156
+ #
157
+ # Returns an array of all the primary keys in the db.
158
+ #
159
+ # With no options given, this method will return all the keys (strings)
160
+ # in a Ruby array.
161
+ #
162
+ # :prefix --> returns only the keys who match a given string prefix
163
+ #
164
+ # :limit --> returns a limited number of keys
165
+ #
166
+ def keys (options={})
167
+
168
+ if pref = options[:prefix]
169
+
170
+ @db.fwmkeys(pref, options[:limit] || -1)
171
+
172
+ else
173
+
174
+ limit = options[:limit] || -1
175
+ limit = nil if limit < 1
176
+
177
+ l = []
178
+
179
+ @db.iterinit
180
+
181
+ while (k = @db.iternext)
182
+ break if limit and l.size >= limit
183
+ l << k
184
+ end
185
+
186
+ l
187
+ end
188
+ end
189
+
190
+ #
191
+ # Deletes all the entries whose keys begin with the given prefix
192
+ #
193
+ def delete_keys_with_prefix (prefix)
194
+
195
+ #call_misc('outlist', lib.abs_fwmkeys2(@db, prefix, -1))
196
+ # # -1 for no limits
197
+ @db.fwmkeys(prefix, -1).each { |k| self.delete(k) }
198
+ nil
199
+ end
200
+
201
+ #
202
+ # Given a list of keys, returns a Hash { key => value } of the
203
+ # matching entries (in one sweep).
204
+ #
205
+ # Warning : this is a naive (slow) implementation.
206
+ #
207
+ def lget (keys)
208
+
209
+ #Hash[*call_misc('getlist', Rufus::Tokyo::List.new(keys))]
210
+ keys.inject({}) { |h, k| v = self[k]; h[k] = v if v; h }
211
+ end
212
+
213
+ #--
214
+ # default impl provided by HashMethods
215
+ #
216
+ #def merge! (hash)
217
+ # call_misc(
218
+ # 'putlist',
219
+ # hash.inject(Rufus::Tokyo::List.new) { |l, (k, v)| l << k; l << v; l })
220
+ # self
221
+ #end
222
+ #++
223
+ alias :lput :merge!
224
+
225
+ #
226
+ # Given a list of keys, deletes all the matching entries (in one sweep).
227
+ #
228
+ # Warning : this is a naive (slow) implementation.
229
+ #
230
+ def ldelete (keys)
231
+
232
+ #call_misc('outlist', Rufus::Tokyo::List.new(keys))
233
+ keys.each { |k| self.delete(k) }
234
+ nil
235
+ end
236
+
237
+ #
238
+ # Returns the underlying 'native' Ruby object (of the class devised by
239
+ # Hirabayashi-san)
240
+ #
241
+ def original
242
+ @db
243
+ end
244
+
245
+ #
246
+ # This is rather low-level, you'd better use #transaction like in
247
+ #
248
+ # db.transaction do
249
+ # db['a'] = 'alpha'
250
+ # db['b'] = 'bravo'
251
+ # db.abort if something_went_wrong?
252
+ # end
253
+ #
254
+ # Note that fixed-length dbs do not support transactions. It will result
255
+ # in a NoMethodError.
256
+ #
257
+ def tranbegin
258
+ @db.tranbegin
259
+ end
260
+
261
+ #
262
+ # This is rather low-level use #transaction and a block for a higher-level
263
+ # technique.
264
+ #
265
+ # Note that fixed-length dbs do not support transactions. It will result
266
+ # in a NoMethodError.
267
+ #
268
+ def trancommit
269
+ @db.trancommit
270
+ end
271
+
272
+ #
273
+ # This is rather low-level use #transaction and a block for a higher-level
274
+ # technique.
275
+ #
276
+ # Note that fixed-length dbs do not support transactions. It will result
277
+ # in a NoMethodError.
278
+ #
279
+ def tranabort
280
+ @db.tranabort
281
+ end
282
+
283
+ protected
284
+
285
+ def raise_error
286
+ code = @db.ecode
287
+ message = @db.errmsg(code)
288
+ raise EdoError.new("(err #{code}) #{message}")
289
+ end
290
+ end
291
+ end
292
+