rufus-tokyo 0.1.2 → 0.1.3

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
@@ -1,6 +1,14 @@
1
1
 
2
2
  = rufus-tokyo CHANGELOG.txt
3
3
 
4
+ == rufus-tokyo - 0.1.3 released 2009/01/29
5
+
6
+ - todo : implemented Rufus::Tokyo::Table (and query)
7
+ - todo : implemented Rufus::Tokyo::List
8
+ - todo : implemented Rufus::Tokyo::Map
9
+ - todo : implemented Cabinet#compact_copy
10
+ - todo : implemented Cabinet#copy
11
+
4
12
 
5
13
  == rufus-tokyo - 0.1.2 released 2009/01/23
6
14
 
data/CREDITS.txt CHANGED
@@ -1,7 +1,20 @@
1
1
 
2
2
  = CREDITS.txt rufus-tokyo gem
3
3
 
4
- many thanks to the authors of Tokyo Cabinet and ruby-ffi
4
+
5
+ == authors
6
+
7
+ John Mettraux http://jmettraux.wordpress.com
8
+
9
+
10
+ == contributors
11
+
12
+ Justin Reagor http://blog.kineticweb.com/
13
+
14
+
15
+ == finally
16
+
17
+ many thanks to the author of Tokyo Cabinet (Mikio Hirabayashi) and of ruby-ffi
5
18
 
6
19
  http://tokyocabinet.sourceforge.net
7
20
  http://kenai.com/projects/ruby-ffi
data/README.txt CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  ruby-ffi based interface to Tokyo Cabinet.
5
5
 
6
- It focuses on the abstract API for now (http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi)
6
+ The 'abstract' and the 'table' API are covered for now.
7
7
 
8
8
 
9
9
  == installation
@@ -15,6 +15,10 @@ It focuses on the abstract API for now (http://tokyocabinet.sourceforge.net/spex
15
15
 
16
16
  == usage
17
17
 
18
+ === Abstract API
19
+
20
+ http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
21
+
18
22
  to create a hash (file named 'data.tch')
19
23
 
20
24
  require 'rubygems'
@@ -34,14 +38,41 @@ to create a hash (file named 'data.tch')
34
38
  db.close
35
39
 
36
40
 
41
+ === Table API
42
+
43
+ http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
44
+
45
+ require 'rubygems'
46
+ require 'rufus/tokyo/cabinet/table'
47
+
48
+ t = Rufus::Tokyo::Table.new('table.tdb', :create, :write)
49
+
50
+ t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
51
+ t['pk1'] = { 'name' => 'bob', 'age' => '18' }
52
+ t['pk2'] = { 'name' => 'charly', 'age' => '45' }
53
+ t['pk3'] = { 'name' => 'doug', 'age' => '77' }
54
+ t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }
55
+
56
+ p t.query { |q|
57
+ q.add_condition 'age', :numge, '32'
58
+ q.order_by 'age'
59
+ }
60
+ # => [ {"name"=>"ephrem", :pk=>"pk4", "age"=>"32"},
61
+ # {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]
62
+
63
+ t.close
64
+
65
+
37
66
  more in the rdoc
38
67
 
39
68
  http://rufus.rubyforge.org/rufus-tokyo/
40
69
  http://rufus.rubyforge.org/rufus-tokyo/classes/Rufus/Tokyo/Cabinet.html
70
+ http://rufus.rubyforge.org/rufus-tokyo/classes/Rufus/Tokyo/Table.html
41
71
 
42
72
  or directly in the source
43
73
 
44
- http://github.com/jmettraux/rufus-tokyo/blob/master/lib/rufus/tokyo.rb
74
+ http://github.com/jmettraux/rufus-tokyo/blob/master/lib/rufus/tokyo/cabinet/abstract.rb
75
+ http://github.com/jmettraux/rufus-tokyo/blob/master/lib/rufus/tokyo/cabinet/table.rb
45
76
 
46
77
 
47
78
  == Tokyo Cabinet install
@@ -55,12 +86,9 @@ If you don't have Tokyo Cabinet on your system, you can get it and compile it :
55
86
 
56
87
  git clone git://github.com/etrepum/tokyo-cabinet.git
57
88
  cd tokyo-cabinet
58
- git checkout 1.4.1
89
+ git checkout 1.4.2
59
90
  ./configure
60
91
  make
61
-
62
- eventually
63
-
64
92
  sudo make install
65
93
 
66
94
 
@@ -95,7 +123,7 @@ http://github.com/jmettraux/rufus-tokyo
95
123
 
96
124
  == credits
97
125
 
98
- many thanks to the authors of Tokyo Cabinet and to the authors of ruby-ffi
126
+ many thanks to the author of Tokyo Cabinet, Mikio Hirabayashi, and to the authors of ruby-ffi
99
127
 
100
128
  http://tokyocabinet.sourceforge.net
101
129
  http://kenai.com/projects/ruby-ffi
data/lib/rufus/tokyo.rb CHANGED
@@ -22,249 +22,6 @@
22
22
  #++
23
23
  #
24
24
 
25
- #
26
- # "made in Japan"
27
- #
28
- # jmettraux@gmail.com
29
- #
30
-
31
- require 'rubygems'
32
- require 'ffi'
33
-
34
- module Rufus
35
- module Tokyo
36
-
37
- VERSION = '0.1.2'
38
-
39
- module Func #:nodoc#
40
- extend FFI::Library
41
-
42
- #
43
- # find Tokyo Cabinet lib
44
-
45
- paths = Array(ENV['TOKYO_CABINET_LIB'] || %w{
46
- /opt/local/lib/libtokyocabinet.dylib
47
- /usr/local/lib/libtokyocabinet.dylib
48
- /usr/local/lib/libtokyocabinet.so
49
- })
50
-
51
- paths.each do |path|
52
- if File.exist?(path)
53
- ffi_lib(path)
54
- @lib = path
55
- break
56
- end
57
- end
58
-
59
- attach_function :tcadbnew, [], :pointer
60
-
61
- attach_function :tcadbopen, [ :pointer, :string ], :int
62
- attach_function :tcadbclose, [ :pointer ], :int
63
-
64
- attach_function :tcadbdel, [ :pointer ], :void
65
-
66
- attach_function :tcadbrnum, [ :pointer ], :uint64
67
- attach_function :tcadbsize, [ :pointer ], :uint64
68
-
69
- attach_function :tcadbput2, [ :pointer, :string, :string ], :int
70
- attach_function :tcadbget2, [ :pointer, :string ], :string
71
- attach_function :tcadbout2, [ :pointer, :string ], :int
72
-
73
- attach_function :tcadbiterinit, [ :pointer ], :int
74
- attach_function :tcadbiternext2, [ :pointer ], :string
75
-
76
- attach_function :tcadbvanish, [ :pointer ], :int
77
-
78
-
79
- #def self.method_missing (m, *args)
80
- # mm = "tcadb#{m}"
81
- # self.respond_to?(mm) ? self.send(mm, *args) : super
82
- #end
83
- #
84
- # makes JRuby unhappy, forget it.
85
- end
86
-
87
- #
88
- # Returns the path to the Tokyo Cabinet dynamic library currently in use
89
- #
90
- def self.lib
91
- Rufus::Tokyo::Func.instance_variable_get(:@lib)
92
- end
93
-
94
- #
95
- # A 'cabinet', ie a Tokyo Cabinet database.
96
- #
97
- # Follows the abstract API described at :
98
- #
99
- # http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
100
- #
101
- # An usage example :
102
- #
103
- # db = Rufus::Tokyo::Cabinet.new('test_data.tch')
104
- # db['pillow'] = 'Shonagon'
105
- #
106
- # db.size # => 1
107
- # db['pillow'] # => 'Shonagon'
108
- #
109
- # db.delete('pillow') # => 'Shonagon'
110
- # db.size # => 0
111
- #
112
- # db.close
113
- #
114
- class Cabinet
115
- include Enumerable
116
-
117
- #
118
- # Creates/opens the cabinet, raises an exception in case of
119
- # creation/opening failure.
120
- #
121
- # This method accepts a 'name' parameter and an optional 'params' hash
122
- # parameter.
123
- #
124
- # 'name' follows the syntax described at
125
- #
126
- # http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
127
- #
128
- # under tcadbopen(). For example :
129
- #
130
- # db = Rufus::Tokyo::Cabinet.new('casket.tch#bnum=100000#opts=ld')
131
- #
132
- # will open (eventually create) a hash database backed in the file
133
- # 'casket.tch' with a bucket number of 100000 and the 'large' and
134
- # 'deflate' options (opts) turned on.
135
- #
136
- # == :hash or :tree
137
- #
138
- # Setting the name to :hash or :tree simply will create a in-memory hash
139
- # or tree respectively (see #new_tree and #new_hash).
140
- #
141
- # == tuning parameters
142
- #
143
- # It's ok to use the optional params hash to pass tuning parameters and
144
- # options, thus
145
- #
146
- # db = Rufus::Tokyo::Cabinet.new('casket.tch#bnum=100000#opts=ld')
147
- #
148
- # and
149
- #
150
- # db = Rufus::Tokyo::Cabinet.new(
151
- # 'casket.tch', :bnum => 100000, :opts => 'ld')
152
- #
153
- # are equivalent.
154
- #
155
- # == mode
156
- #
157
- # To open a db in read-only mode :
158
- #
159
- # db = Rufus::Tokyo::Cabinet.new('casket.tch#mode=r')
160
- # db = Rufus::Tokyo::Cabinet.new('casket.tch', :mode => 'r')
161
- #
162
- def initialize (name, params={})
163
-
164
- @db = Rufus::Tokyo::Func.tcadbnew
165
-
166
- name = '*' if name == :hash # in memory hash database
167
- name = '+' if name == :tree # in memory B+ tree database
168
-
169
- name = name + params.collect { |k, v| "##{k}=#{v}" }.join('')
170
-
171
- (Rufus::Tokyo::Func.tcadbopen(@db, name) == 1) ||
172
- raise("failed to open/create db '#{name}'")
173
- end
174
-
175
- #
176
- # Returns a new in-memory hash. Accepts the same optional params hash
177
- # as new().
178
- #
179
- def self.new_hash (params={})
180
- self.new(:hash, params)
181
- end
182
-
183
- #
184
- # Returns a new in-memory B+ tree. Accepts the same optional params hash
185
- # as new().
186
- #
187
- def self.new_tree (params={})
188
- self.new(:tree, params)
189
- end
190
-
191
- def []= (k, v)
192
- Rufus::Tokyo::Func.tcadbput2(@db, k, v)
193
- end
194
-
195
- def [] (k)
196
- Rufus::Tokyo::Func.tcadbget2(@db, k) rescue nil
197
- end
198
-
199
- #
200
- # Removes a record from the cabinet, returns the value if successful
201
- # else nil.
202
- #
203
- def delete (k)
204
- v = self[k]
205
- (Rufus::Tokyo::Func.tcadbout2(@db, k) == 1) ? v : nil
206
- end
207
-
208
- #
209
- # Returns the number of records in the 'cabinet'
210
- #
211
- def size
212
- Rufus::Tokyo::Func.tcadbrnum(@db)
213
- end
214
-
215
- #
216
- # Removes all the records in the cabinet (use with care)
217
- #
218
- # Returns self (like Ruby's Hash does).
219
- #
220
- def clear
221
- Rufus::Tokyo::Func.tcadbvanish(@db)
222
- self
223
- end
224
-
225
- #
226
- # Returns the 'weight' of the db (in bytes)
227
- #
228
- def weight
229
- Rufus::Tokyo::Func.tcadbsize(@db)
230
- end
231
-
232
- #
233
- # Closes the cabinet (and frees the datastructure allocated for it),
234
- # returns true in case of success.
235
- #
236
- def close
237
- result = Rufus::Tokyo::Func.tcadbclose(@db)
238
- Rufus::Tokyo::Func.tcadbdel(@db)
239
- (result == 1)
240
- end
241
-
242
- #
243
- # Returns an array with all the keys in the databse
244
- #
245
- def keys
246
- a = []
247
- Rufus::Tokyo::Func.tcadbiterinit(@db)
248
- while (k = (Rufus::Tokyo::Func.tcadbiternext2(@db) rescue nil))
249
- a << k
250
- end
251
- a
252
- end
253
-
254
- #
255
- # Returns an array with all the values in the database (heavy...)
256
- #
257
- def values
258
- collect { |k, v| v }
259
- end
260
-
261
- #
262
- # The classical Ruby each (unlocks the power of the Enumerable mixin)
263
- #
264
- def each
265
- keys.each { |k| yield(k, self[k]) }
266
- end
267
- end
268
- end
269
- end
25
+ require File.dirname(__FILE__) + '/tokyo/cabinet'
26
+ #require 'rufus/tokyo/cabinet'
270
27
 
@@ -0,0 +1,123 @@
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
+ unless defined?(FFI)
26
+ #
27
+ # don't require rubygems if not necessary
28
+ #
29
+ require 'rubygems'
30
+ require 'ffi'
31
+ end
32
+
33
+ module Rufus
34
+ module Tokyo
35
+
36
+ VERSION = '0.1.3'
37
+
38
+ #
39
+ # A common error class
40
+ #
41
+ class TokyoError < RuntimeError; end
42
+
43
+ #
44
+ # Some constants shared by most of Tokyo Cabinet APIs
45
+ #
46
+ # (Used only by rufus/tokyo/cabinet/table for now)
47
+ #
48
+ module TokyoContainerMixin
49
+
50
+ #
51
+ # some Tokyo constants
52
+
53
+ OREADER = 1 << 0 # open as a reader
54
+ OWRITER = 1 << 1 # open as a writer
55
+ OCREAT = 1 << 2 # writer creating
56
+ OTRUNC = 1 << 3 # writer truncating
57
+ ONOLCK = 1 << 4 # open without locking
58
+ OLCKNB = 1 << 5 # lock without blocking
59
+
60
+ OTSYNC = 1 << 6 # synchronize every transaction (tctdb.h)
61
+
62
+ #
63
+ # Makes sure that a set of parameters is a hash (will transform an
64
+ # array into a hash if necessary)
65
+ #
66
+ def params_to_h (params)
67
+
68
+ params.is_a?(Hash) ?
69
+ params :
70
+ Array(params).inject({}) { |h, e| h[e] = true; h }
71
+ end
72
+
73
+ #
74
+ # Given params (array or hash), computes the open mode (an int)
75
+ # for the Tokyo Cabinet object.
76
+ #
77
+ def compute_open_mode (params)
78
+
79
+ params = params_to_h(params)
80
+
81
+ {
82
+ :read => OREADER,
83
+ :reader => OREADER,
84
+ :write => OWRITER,
85
+ :writer => OWRITER,
86
+ :create => OCREAT,
87
+ :truncate => OTRUNC,
88
+ :no_lock => ONOLCK,
89
+ :lock_no_block => OLCKNB,
90
+ :sync_every => OTSYNC
91
+
92
+ }.inject(0) { |r, (k, v)|
93
+
94
+ r = r | v if params[k]; r
95
+ }
96
+ end
97
+ end
98
+
99
+ #
100
+ # Generates a lib mixin from a FFI module.
101
+ #
102
+ # Including this mixin will simply bind two #lib methods (call and instance)
103
+ # returning the FFI module.
104
+ #
105
+ def self.generate_lib_mixin (lib_module)
106
+ eval %{
107
+ module #{lib_module}Mixin
108
+ def self.included (target)
109
+ target.class_eval do
110
+ def self.lib
111
+ #{lib_module}
112
+ end
113
+ def lib
114
+ self.class.lib
115
+ end
116
+ end
117
+ end
118
+ end
119
+ }
120
+ end
121
+ end
122
+ end
123
+