rufus-tokyo 0.1.7 → 0.1.8

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.
@@ -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
+