rufus-tokyo 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
+