rufus-tokyo 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,18 @@
2
2
  = rufus-tokyo CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-tokyo - 0.1.6 released 2009/02/16
6
+
7
+ - todo : Tyrant and TyrantTable now complain when used in lieu of each other
8
+ - todo : implemented Tyrant and TyrantTable #stat
9
+ - todo : made tran begin/abort/commit directly available (framework builders)
10
+ - todo : implemented Rufus::Tokyo::Table#transaction
11
+ - bug : JRuby support back in
12
+ - todo : implemented Rufus::Tokyo::Map#[] (class method)
13
+ - todo : simplified Table and TyrantTable #[]=
14
+ - bug : preventing table#[]= from segfaulting on bad input (Justin)
15
+
16
+
5
17
  == rufus-tokyo - 0.1.5 released 2009/02/13
6
18
 
7
19
  - todo : implemented set_index (cabinet / tyrant tables)
data/README.txt CHANGED
@@ -47,32 +47,54 @@ http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
47
47
 
48
48
  require 'rubygems'
49
49
  require 'rufus/tokyo'
50
-
51
- t = Rufus::Tokyo::Table.new('table.tdb', :create, :write)
52
-
50
+
51
+ t = Rufus::Tokyo::Table.new('table.tdb')
52
+
53
53
  t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
54
54
  t['pk1'] = { 'name' => 'bob', 'age' => '18' }
55
55
  t['pk2'] = { 'name' => 'charly', 'age' => '45' }
56
56
  t['pk3'] = { 'name' => 'doug', 'age' => '77' }
57
57
  t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }
58
-
58
+
59
59
  p t.query { |q|
60
60
  q.add_condition 'age', :numge, '32'
61
61
  q.order_by 'age'
62
62
  }
63
63
  # => [ {"name"=>"ephrem", :pk=>"pk4", "age"=>"32"},
64
64
  # {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]
65
-
65
+
66
66
  t.close
67
67
 
68
+ Note that the Tokyo Cabinet Table API does support transactions :
69
+
70
+ p t.size
71
+ # => 0
72
+
73
+ t.transaction do
74
+ t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
75
+ t['pk1'] = { 'name' => 'bob', 'age' => '18' }
76
+ t.abort
77
+ end
78
+
79
+ p t.size
80
+ # => 0
81
+
82
+
68
83
  === TT remote db
69
84
 
70
85
  http://tokyocabinet.sourceforge.net/tyrantdoc/
71
86
 
87
+ to start a ttserver (backed by a hash), on the command line
88
+
89
+ ttserver -port 45001 data.tch
90
+
91
+
92
+ then, in Ruby :
93
+
72
94
  require 'rubygems'
73
- require 'rufus/tokyo'
95
+ require 'rufus/tokyo/tyrant'
74
96
 
75
- db = Rufus::Tokyo::Tyrant.new('tyrant.example.com', 45001)
97
+ db = Rufus::Tokyo::Tyrant.new('localhost', 45001)
76
98
 
77
99
  db['nada'] = 'surf'
78
100
 
@@ -82,31 +104,76 @@ http://tokyocabinet.sourceforge.net/tyrantdoc/
82
104
  db.close
83
105
 
84
106
 
107
+ Rufus::Tokyo::Tyrant instances have a #stat method :
108
+
109
+ puts db.stat.inject('') { |s, (k, v)| s << "#{k} => #{v}\n" }
110
+ # =>
111
+ # pid => 7566
112
+ # loadavg => 0.398438
113
+ # size => 528736
114
+ # rnum => 0
115
+ # time => 1234764065.305923
116
+ # sid => 898521513
117
+ # type => hash
118
+ # bigend => 0
119
+ # ru_sys => 3.398698
120
+ # version => 1.1.15
121
+ # ru_user => 2.155215
122
+ # ru_real => 3218.451152
123
+ # fd => 7
124
+
125
+
85
126
  === TT remote table
86
127
 
87
- like a local table :
128
+ to start a ttserver (backed by a table), on the command line :
129
+
130
+ ttserver -port 45002 data.tct
131
+
132
+
133
+ then, in Ruby, much like a local table :
88
134
 
89
135
  require 'rubygems'
90
- require 'rufus/tokyo'
91
-
92
- t = Rufus::Tokyo::TyrantTable.new('localhost', 45006)
93
-
136
+ require 'rufus/tokyo/tyrant'
137
+
138
+ t = Rufus::Tokyo::TyrantTable.new('localhost', 45002)
139
+
94
140
  t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
95
141
  t['pk1'] = { 'name' => 'bob', 'age' => '18' }
96
142
  t['pk2'] = { 'name' => 'charly', 'age' => '45' }
97
143
  t['pk3'] = { 'name' => 'doug', 'age' => '77' }
98
144
  t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }
99
-
145
+
100
146
  p t.query { |q|
101
147
  q.add_condition 'age', :numge, '32'
102
148
  q.order_by 'age'
103
149
  }
104
150
  # => [ {"name"=>"ephrem", :pk=>"pk4", "age"=>"32"},
105
151
  # {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]
106
-
152
+
107
153
  t.close
108
154
 
109
155
 
156
+ Rufus::Tokyo::TyrantTable instances have a #stat method :
157
+
158
+ puts t.stat.inject('') { |s, (k, v)| s << "#{k} => #{v}\n" }
159
+ # =>
160
+ # pid => 7569
161
+ # loadavg => 0.295410
162
+ # size => 935792
163
+ # rnum => 0
164
+ # time => 1234764228.942014
165
+ # sid => 1027604232
166
+ # type => table
167
+ # bigend => 0
168
+ # ru_sys => 5.966750
169
+ # version => 1.1.15
170
+ # ru_user => 2.601947
171
+ # ru_real => 3382.084479
172
+ # fd => 10
173
+
174
+
175
+ == rdoc
176
+
110
177
  more in the rdoc
111
178
 
112
179
  http://rufus.rubyforge.org/rufus-tokyo/
@@ -115,6 +182,8 @@ more in the rdoc
115
182
  http://rufus.rubyforge.org/rufus-tokyo/classes/Rufus/Tokyo/Tyrant.html
116
183
  http://rufus.rubyforge.org/rufus-tokyo/classes/Rufus/Tokyo/TyrantTable.html
117
184
 
185
+ don't hesitate to "man ttserver" on the command line.
186
+
118
187
  or directly in the source
119
188
 
120
189
  http://github.com/jmettraux/rufus-tokyo/blob/master/lib/rufus/tokyo/cabinet/abstract.rb
@@ -123,62 +192,28 @@ or directly in the source
123
192
  http://github.com/jmettraux/rufus-tokyo/blob/master/lib/rufus/tokyo/tyrant/table.rb
124
193
 
125
194
 
126
- == Tokyo Cabinet install
127
-
128
- On a Mac, you would do
129
-
130
- sudo port install tokyocabinet
131
-
132
-
133
- If you don't have Tokyo Cabinet on your system, you can get it and compile it :
134
-
135
- git clone git://github.com/etrepum/tokyo-cabinet.git
136
- cd tokyo-cabinet
137
- #git checkout 1.4.4
138
- ./configure
139
- make
140
- sudo make install
141
-
142
- or get the souce at
143
-
144
- http://sourceforge.net/project/showfiles.php?group_id=200242&package_id=237686
145
-
146
- (note : I tend to run rufus-tokyo against the latest version of Tokyo Cabinet)
147
-
148
-
149
- == Tokyo Tyrant install
150
-
151
- (Tokyo Tyrant requires Tokyo Cabinet)
152
-
153
- If you don't have Tokyo Tyrant on your system, you can get it and compile it :
154
-
155
- git clone git://github.com/etrepum/tokyo-tyrant.git
156
- cd tokyo-cabinet
157
- #git checkout 1.1.14
158
- ./configure
159
- make
160
- sudo make install
195
+ == Tokyo Cabinet / Tyrant install
161
196
 
162
- or get the souce at
197
+ a compilation of notes is available at :
163
198
 
164
- http://sourceforge.net/project/showfiles.php?group_id=200242&package_id=237686
199
+ http://openwferu.rubyforge.org/tokyo.html
165
200
 
166
201
 
167
202
  == dependencies
168
203
 
169
- the ruby gem ffi
204
+ the ruby gem 'ffi'
170
205
 
171
206
 
172
207
  == mailing list
173
208
 
174
- On the rufus-ruby list[http://groups.google.com/group/rufus-ruby] :
209
+ On the rufus-ruby list :
175
210
 
176
211
  http://groups.google.com/group/rufus-ruby
177
212
 
178
213
 
179
214
  == issue tracker
180
215
 
181
- http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
216
+ http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
182
217
 
183
218
 
184
219
  == irc
data/lib/rufus/tokyo.rb CHANGED
@@ -28,7 +28,7 @@ require 'ffi' # sudo gem install ffi
28
28
  module Rufus
29
29
  module Tokyo
30
30
 
31
- VERSION = '0.1.5'
31
+ VERSION = '0.1.6'
32
32
 
33
33
  #
34
34
  # A common error class
@@ -38,8 +38,9 @@ module Rufus
38
38
  end
39
39
  end
40
40
 
41
- require File.dirname(__FILE__) + '/tokyo/hmethods'
42
- require File.dirname(__FILE__) + '/tokyo/cabinet'
43
- require File.dirname(__FILE__) + '/tokyo/tyrant'
44
- require File.dirname(__FILE__) + '/tokyo/dystopia'
41
+ require 'rufus/tokyo/cabinet'
42
+
43
+ # TODO : do not include me
44
+ #require 'rufus/tokyo/tyrant'
45
+ #require 'rufus/tokyo/dystopia'
45
46
 
@@ -1,6 +1,6 @@
1
1
 
2
- require File.dirname(__FILE__) + '/cabinet/lib'
3
- require File.dirname(__FILE__) + '/cabinet/util'
4
- require File.dirname(__FILE__) + '/cabinet/table'
5
- require File.dirname(__FILE__) + '/cabinet/abstract'
2
+ require 'rufus/tokyo/cabinet/lib'
3
+ require 'rufus/tokyo/cabinet/util'
4
+ require 'rufus/tokyo/cabinet/table'
5
+ require 'rufus/tokyo/cabinet/abstract'
6
6
 
@@ -35,23 +35,23 @@ module Rufus
35
35
  # The libtokyocabinet.so methods get bound to this module
36
36
  #
37
37
  module CabinetLib #:nodoc#
38
- extend ::FFI::Library
38
+ extend FFI::Library
39
39
 
40
40
  #
41
41
  # find Tokyo Cabinet lib
42
42
 
43
43
  paths = Array(ENV['TOKYO_CABINET_LIB'] || %w{
44
- /opt/local/lib/libtokyocabinet.dylib
45
- /usr/local/lib/libtokyocabinet.dylib
46
- /usr/local/lib/libtokyocabinet.so
47
- })
44
+ /opt/local/lib/libtokyocabinet.dylib
45
+ /usr/local/lib/libtokyocabinet.dylib
46
+ /usr/local/lib/libtokyocabinet.so
47
+ })
48
48
 
49
49
  path = paths.find { |path| File.exist?(path) }
50
50
 
51
51
  raise(
52
- "didn't find Tokyo Cabinet libs on your system. " +
53
- "Please install Tokyo Cabinet (http://tokyocabinet.sf.net)"
54
- ) unless path
52
+ "didn't find Tokyo Cabinet libs on your system. " +
53
+ "Please install Tokyo Cabinet (http://tokyocabinet.sf.net)"
54
+ ) unless path
55
55
 
56
56
  ffi_lib(path)
57
57
 
@@ -116,7 +116,9 @@ module Rufus
116
116
  attfunc :tab_iternext2, :tctdbiternext2, [ :pointer ], :string
117
117
 
118
118
  attfunc :tab_put, :tctdbput, [ :pointer, :string, :int, :pointer ], :int
119
- attfunc :tctdbput3, [ :pointer, :string, :string ], :int
119
+
120
+ #attfunc :tctdbput3, [ :pointer, :string, :string ], :int
121
+ # not using it anymore, Ruby can turn an array into a hash so easily
120
122
 
121
123
  attfunc :tab_out, :tctdbout, [ :pointer, :string, :int ], :int
122
124
 
@@ -131,6 +133,10 @@ module Rufus
131
133
 
132
134
  attfunc :tab_setindex, :tctdbsetindex, [ :pointer, :string, :int ], :int
133
135
 
136
+ attfunc :tctdbtranbegin, [ :pointer ], :int
137
+ attfunc :tctdbtrancommit, [ :pointer ], :int
138
+ attfunc :tctdbtranabort, [ :pointer ], :int
139
+
134
140
  #
135
141
  # tctdbqry functions
136
142
  #
@@ -52,7 +52,7 @@ module Rufus
52
52
  def params_to_h (params)
53
53
 
54
54
  params.is_a?(Hash) ?
55
- params :
55
+ params :
56
56
  Array(params).inject({}) { |h, e| h[e] = true; h }
57
57
  end
58
58
 
@@ -146,7 +146,7 @@ module Rufus
146
146
 
147
147
  @db = lib.tctdbnew
148
148
 
149
- (lib.tctdbopen(@db, path, mode) == 1 ) || raise_error
149
+ libcall(:tctdbopen, path, mode)
150
150
  end
151
151
 
152
152
  #
@@ -201,46 +201,21 @@ module Rufus
201
201
  (lib.tab_setindex(@db, column_name, i) == 1)
202
202
  end
203
203
 
204
- #
205
- # Accepts a variable number of arguments, at least two. First one
206
- # is the primary key of the record, the others are the columns.
207
- #
208
- # One can also directly write
209
- #
210
- # table['one'] = [ 'name', 'toto', 'age', '33' ]
211
- # table['two'] = [ 'name', 'fred', 'age', '45' ]
212
- #
213
- # instead of
214
- #
215
- # table.tabbed_put('one', 'name', 'toto', 'age', '33')
216
- # table.tabbed_put('two', 'name', 'fred', 'age', '45')
217
- #
218
- # beware : inserting an array uses a tab separator...
219
- #
220
- def tabbed_put (pk, *args)
221
-
222
- cols = args.collect { |e| e.to_s }.join("\t")
223
-
224
- (CabinetLib.tctdbput3(@db, pk, cols) == 1) || raise_error
225
-
226
- args
227
- end
228
-
229
204
  #
230
205
  # Inserts a record in the table db
231
206
  #
232
207
  # table['pk0'] = [ 'name', 'fred', 'age', '45' ]
233
208
  # table['pk1'] = { 'name' => 'jeff', 'age' => '46' }
234
209
  #
210
+ # Accepts both a hash or an array (expects the array to be of the
211
+ # form [ key, value, key, value, ... ] else it will raise
212
+ # an ArgumentError)
213
+ #
235
214
  def []= (pk, h_or_a)
236
215
 
237
- return tabbed_put(pk, *h_or_a) if h_or_a.is_a?(Array)
238
-
239
- pklen = CabinetLib.strlen(pk)
240
-
241
- m = Map.from_h(h_or_a)
216
+ m = Rufus::Tokyo::Map[h_or_a]
242
217
 
243
- r = lib.tab_put(@db, pk, pklen, m.pointer)
218
+ r = lib.tab_put(@db, pk, CabinetLib.strlen(pk), m.pointer)
244
219
 
245
220
  m.free
246
221
 
@@ -258,7 +233,7 @@ module Rufus
258
233
  def delete (k)
259
234
  v = self[k]
260
235
  return nil unless v
261
- (lib.tab_out(@db, k, CabinetLib.strlen(k)) == 1) || raise_error
236
+ libcall(:tab_out, k, CabinetLib.strlen(k))
262
237
  v
263
238
  end
264
239
 
@@ -266,7 +241,7 @@ module Rufus
266
241
  # Removes all records in this table database
267
242
  #
268
243
  def clear
269
- (lib.tab_vanish(@db) == 1) || raise_error
244
+ libcall(:tab_vanish)
270
245
  end
271
246
 
272
247
  #
@@ -329,6 +304,70 @@ module Rufus
329
304
  a
330
305
  end
331
306
 
307
+ #
308
+ # Transaction in a block.
309
+ #
310
+ # table.transaction do
311
+ # table['pk0'] => { 'name' => 'Fred', 'age' => '40' }
312
+ # table['pk1'] => { 'name' => 'Brooke', 'age' => '76' }
313
+ # table.abort if weather.bad?
314
+ # end
315
+ #
316
+ # If an error or an abort is trigger withing the transaction, it's rolled
317
+ # back. If the block executes successfully, it gets commited.
318
+ #
319
+ def transaction
320
+
321
+ return unless block_given?
322
+
323
+ begin
324
+ tranbegin
325
+ yield
326
+ trancommit
327
+ rescue Exception => e
328
+ tranabort
329
+ end
330
+ end
331
+
332
+ #
333
+ # Aborts the enclosing transaction
334
+ #
335
+ # See #transaction
336
+ #
337
+ def abort
338
+ raise "abort transaction !"
339
+ end
340
+
341
+ #
342
+ # Warning : this method is low-level, you probably only need
343
+ # to use #transaction and a block.
344
+ #
345
+ # Direct call for 'transaction begin'.
346
+ #
347
+ def tranbegin
348
+ libcall(:tctdbtranbegin)
349
+ end
350
+
351
+ #
352
+ # Warning : this method is low-level, you probably only need
353
+ # to use #transaction and a block.
354
+ #
355
+ # Direct call for 'transaction commit'.
356
+ #
357
+ def trancommit
358
+ libcall(:tctdbtrancommit)
359
+ end
360
+
361
+ #
362
+ # Warning : this method is low-level, you probably only need
363
+ # to use #transaction and a block.
364
+ #
365
+ # Direct call for 'transaction abort'.
366
+ #
367
+ def tranabort
368
+ libcall(:tctdbtranabort)
369
+ end
370
+
332
371
  #
333
372
  # Returns the actual pointer to the Tokyo Cabinet table
334
373
  #
@@ -338,6 +377,15 @@ module Rufus
338
377
 
339
378
  protected
340
379
 
380
+ def libcall (lib_method, *args)
381
+
382
+ #(lib.send(lib_method, @db, *args) == 1) or raise_error
383
+ # stack level too deep with JRuby 1.1.6 :(
384
+
385
+ (eval(%{ lib.#{lib_method}(@db, *args) }) == 1) or raise_error
386
+ # works with JRuby 1.1.6
387
+ end
388
+
341
389
  #
342
390
  # Obviously something got wrong, let's ask the db about it and raise
343
391
  # a TokyoError
@@ -28,6 +28,9 @@
28
28
  # jmettraux@gmail.com
29
29
  #
30
30
 
31
+ require 'rufus/tokyo/hmethods'
32
+
33
+
31
34
  module Rufus
32
35
  module Tokyo
33
36
 
@@ -142,10 +145,24 @@ module Rufus
142
145
 
143
146
  #
144
147
  # Turns a Ruby hash into a Tokyo Cabinet Map and returns it
148
+ # (don't forget to free the map when you're done with it !)
145
149
  #
146
150
  def self.from_h (h)
147
151
  h.inject(Map.new) { |m, (k, v)| m[k] = v; m }
148
152
  end
153
+
154
+ #
155
+ # Behaves much like Hash#[] but outputs a Rufus::Tokyo::Map
156
+ # (don't forget to free the map when you're done with it !)
157
+ #
158
+ def self.[] (*h_or_a)
159
+
160
+ if h_or_a.is_a?(Array) && h_or_a.size == 1 && h_or_a.first.is_a?(Array)
161
+ h_or_a = h_or_a.first
162
+ end
163
+
164
+ from_h(::Hash[*h_or_a])
165
+ end
149
166
  end
150
167
 
151
168
  #
@@ -173,8 +190,11 @@ module Rufus
173
190
  CabinetLib
174
191
  end
175
192
 
193
+ #
194
+ # Inserts an element in the list (note that the lib will raise an
195
+ # ArgumentError if s is not a String)
196
+ #
176
197
  def << (s)
177
- #raise 'cannot insert nils into Tokyo Cabinet lists' unless s
178
198
  clib.tclistpush2(@list, s)
179
199
  self
180
200
  end
@@ -184,6 +204,7 @@ module Rufus
184
204
  #
185
205
  def push (*args)
186
206
  args.each { |a| self << a }
207
+ self
187
208
  end
188
209
 
189
210
  #
@@ -37,6 +37,6 @@ module Rufus
37
37
  end
38
38
  end
39
39
 
40
- require File.dirname(__FILE__) + '/dystopia/lib'
41
- require File.dirname(__FILE__) + '/dystopia/words'
40
+ require 'rufus/tokyo/dystopia/lib'
41
+ require 'rufus/tokyo/dystopia/words'
42
42
 
@@ -36,41 +36,36 @@ module Rufus
36
36
  #
37
37
  module DystopiaLib #:nodoc#
38
38
 
39
+ extend FFI::Library
40
+
39
41
  #
40
42
  # find Tokyo Dystopia lib
41
43
 
42
44
  paths = Array(ENV['TOKYO_DYSTOPIA_LIB'] || %w{
43
- /opt/local/lib/libtokyodystopia.dylib
44
- /usr/local/lib/libtokyodystopia.dylib
45
- /usr/local/lib/libtokyodystopia.so
46
- })
45
+ /opt/local/lib/libtokyodystopia.dylib
46
+ /usr/local/lib/libtokyodystopia.dylib
47
+ /usr/local/lib/libtokyodystopia.so
48
+ })
47
49
 
48
50
  if path = paths.find { |path| File.exist?(path) }
49
51
 
50
- extend ::FFI::Library
51
-
52
- ffi_lib(path)
52
+ raise "did not find Tokyo Dystopia libs on your system" unless path
53
53
 
54
- #
55
- # tcwdb functions
56
- #
57
- # http://tokyocabinet.sourceforge.net/dystopiadoc/#tcwdbapi
54
+ ffi_lib(path)
58
55
 
59
- attach_function :tcwdbnew, [], :pointer
56
+ #
57
+ # tcwdb functions
58
+ #
59
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/#tcwdbapi
60
60
 
61
- attach_function :tcwdbopen, [ :pointer, :string, :int ], :int
62
- attach_function :tcwdbclose, [ :pointer ], :int
61
+ attach_function :tcwdbnew, [], :pointer
63
62
 
64
- attach_function :tcwdbecode, [ :pointer ], :int
63
+ attach_function :tcwdbopen, [ :pointer, :string, :int ], :int
64
+ attach_function :tcwdbclose, [ :pointer ], :int
65
65
 
66
- attach_function :tcwdbput2, [ :pointer, :int64, :string, :string ], :pointer
67
- else
66
+ attach_function :tcwdbecode, [ :pointer ], :int
68
67
 
69
- def method_missing (m, *args)
70
- raise "no libtokyodystopia.dylib found on your system"
71
- end
72
- end
68
+ attach_function :tcwdbput2, [ :pointer, :int64, :string, :string ], :pointer
73
69
  end
74
-
75
70
  end
76
71
  end
@@ -1,5 +1,58 @@
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
+ #
1
24
 
2
- require File.dirname(__FILE__) + '/tyrant/lib'
3
- require File.dirname(__FILE__) + '/tyrant/abstract'
4
- require File.dirname(__FILE__) + '/tyrant/table'
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ require 'rufus/tokyo'
32
+
33
+ module Rufus::Tokyo
34
+
35
+ #
36
+ # Gathering some methods common to the Tokyo Tyrant abstract and table APIs.
37
+ #
38
+ module TyrantMethods
39
+
40
+ #
41
+ # Returns a hash of information about the Tokyo Tyrant database (or table)
42
+ # at the other end of the connection.
43
+ #
44
+ def stat
45
+
46
+ lib.tcrdbstat(@db).split("\n").inject({}) { |r, l|
47
+ kv = l.split("\t")
48
+ r[kv.first] = kv.last
49
+ r
50
+ }
51
+ end
52
+ end
53
+ end
54
+
55
+ require 'rufus/tokyo/tyrant/lib'
56
+ require 'rufus/tokyo/tyrant/abstract'
57
+ require 'rufus/tokyo/tyrant/table'
5
58
 
@@ -40,6 +40,7 @@ module Rufus
40
40
  # t['toto'] # => 'blah blah'
41
41
  #
42
42
  class Tyrant < Cabinet
43
+ include TyrantMethods
43
44
 
44
45
  attr_reader :host, :port
45
46
 
@@ -55,6 +56,15 @@ module Rufus
55
56
 
56
57
  (lib.tcrdbopen(@db, host, port) == 1) ||
57
58
  raise("couldn't connect to tyrant at #{host}:#{port}")
59
+
60
+ if self.stat['type'] == 'table'
61
+
62
+ self.close
63
+
64
+ raise ArgumentError.new(
65
+ "tyrant at #{host}:#{port} is a table, " +
66
+ "use Rufus::Tokyo::TyrantTable instead to access it.")
67
+ end
58
68
  end
59
69
 
60
70
  #
@@ -64,6 +74,5 @@ module Rufus
64
74
  TyrantLib
65
75
  end
66
76
  end
67
-
68
77
  end
69
78
  end
@@ -36,97 +36,92 @@ module Rufus
36
36
  #
37
37
  module TyrantLib #:nodoc#
38
38
 
39
+ extend FFI::Library
40
+
39
41
  #
40
42
  # find Tokyo Tyrant lib
41
43
 
42
44
  paths = Array(ENV['TOKYO_TYRANT_LIB'] || %w{
43
- /opt/local/lib/libtokyotyrant.dylib
44
- /usr/local/lib/libtokyotyrant.dylib
45
- /usr/local/lib/libtokyotyrant.so
46
- })
47
-
48
- if path = paths.find { |path| File.exist?(path) }
49
-
50
- extend ::FFI::Library
45
+ /opt/local/lib/libtokyotyrant.dylib
46
+ /usr/local/lib/libtokyotyrant.dylib
47
+ /usr/local/lib/libtokyotyrant.so
48
+ })
51
49
 
52
- ffi_lib(path)
50
+ path = paths.find { |path| File.exist?(path) }
53
51
 
54
- class << self
55
- alias :attfunc :attach_function
56
- end
52
+ raise "Did not find Tokyo Tyrant libraries on your system" unless path
57
53
 
58
- #
59
- # tcrdb functions
54
+ ffi_lib(path)
60
55
 
61
- attfunc :tcrdbnew, [], :pointer
56
+ class << self
57
+ alias :attfunc :attach_function
58
+ end
62
59
 
63
- attfunc :tcrdbopen, [ :pointer, :string, :int ], :int
64
- attfunc :abs_close, :tcrdbclose, [ :pointer ], :int
60
+ #
61
+ # tcrdb functions
65
62
 
66
- attfunc :abs_del, :tcrdbdel, [ :pointer ], :void
63
+ attfunc :tcrdbnew, [], :pointer
67
64
 
68
- attfunc :abs_rnum, :tcrdbrnum, [ :pointer ], :uint64
69
- attfunc :abs_size, :tcrdbsize, [ :pointer ], :uint64
65
+ attfunc :tcrdbstat, [ :pointer ], :string
70
66
 
71
- attfunc :abs_put2, :tcrdbput2, [ :pointer, :string, :string ], :int
72
- attfunc :abs_get2, :tcrdbget2, [ :pointer, :string ], :string
73
- attfunc :abs_out2, :tcrdbout2, [ :pointer, :string ], :int
67
+ attfunc :tcrdbopen, [ :pointer, :string, :int ], :int
68
+ attfunc :abs_close, :tcrdbclose, [ :pointer ], :int
74
69
 
75
- attfunc :abs_iterinit, :tcrdbiterinit, [ :pointer ], :int
76
- attfunc :abs_iternext2, :tcrdbiternext2, [ :pointer ], :string
70
+ attfunc :abs_del, :tcrdbdel, [ :pointer ], :void
77
71
 
78
- attfunc :abs_vanish, :tcrdbvanish, [ :pointer ], :int
72
+ attfunc :abs_rnum, :tcrdbrnum, [ :pointer ], :uint64
73
+ attfunc :abs_size, :tcrdbsize, [ :pointer ], :uint64
79
74
 
80
- attfunc :abs_sync, :tcrdbsync, [ :pointer ], :int
81
- attfunc :abs_copy, :tcrdbcopy, [ :pointer, :string ], :int
75
+ attfunc :abs_put2, :tcrdbput2, [ :pointer, :string, :string ], :int
76
+ attfunc :abs_get2, :tcrdbget2, [ :pointer, :string ], :string
77
+ attfunc :abs_out2, :tcrdbout2, [ :pointer, :string ], :int
82
78
 
83
- #
84
- # table functions
79
+ attfunc :abs_iterinit, :tcrdbiterinit, [ :pointer ], :int
80
+ attfunc :abs_iternext2, :tcrdbiternext2, [ :pointer ], :string
85
81
 
86
- attfunc :tab_close, :tcrdbclose, [ :pointer ], :int
82
+ attfunc :abs_vanish, :tcrdbvanish, [ :pointer ], :int
87
83
 
88
- attfunc :tab_genuid, :tcrdbtblgenuid, [ :pointer ], :int64
84
+ attfunc :abs_sync, :tcrdbsync, [ :pointer ], :int
85
+ attfunc :abs_copy, :tcrdbcopy, [ :pointer, :string ], :int
89
86
 
90
- attfunc :tab_get, :tcrdbtblget, [ :pointer, :string, :int ], :pointer
87
+ #
88
+ # table functions
91
89
 
92
- attfunc :tab_iterinit, :tcrdbiterinit, [ :pointer ], :int
93
- attfunc :tab_iternext2, :tcrdbiternext2, [ :pointer ], :string
90
+ attfunc :tab_close, :tcrdbclose, [ :pointer ], :int
94
91
 
95
- attfunc :tab_put, :tcrdbtblput, [ :pointer, :string, :int, :pointer ], :int
92
+ attfunc :tab_genuid, :tcrdbtblgenuid, [ :pointer ], :int64
96
93
 
97
- attfunc :tab_out, :tcrdbtblout, [ :pointer, :string, :int ], :int
94
+ attfunc :tab_get, :tcrdbtblget, [ :pointer, :string, :int ], :pointer
98
95
 
99
- attfunc :tab_ecode, :tcrdbecode, [ :pointer ], :int
100
- attfunc :tab_errmsg, :tcrdberrmsg, [ :int ], :string
96
+ attfunc :tab_iterinit, :tcrdbiterinit, [ :pointer ], :int
97
+ attfunc :tab_iternext2, :tcrdbiternext2, [ :pointer ], :string
101
98
 
102
- attfunc :tab_del, :tcrdbdel, [ :pointer ], :void
99
+ attfunc :tab_put, :tcrdbtblput, [ :pointer, :string, :int, :pointer ], :int
103
100
 
104
- attfunc :tab_rnum, :tcrdbrnum, [ :pointer ], :uint64
101
+ attfunc :tab_out, :tcrdbtblout, [ :pointer, :string, :int ], :int
105
102
 
106
- attfunc :tab_vanish, :tcrdbvanish, [ :pointer ], :int
103
+ attfunc :tab_ecode, :tcrdbecode, [ :pointer ], :int
104
+ attfunc :tab_errmsg, :tcrdberrmsg, [ :int ], :string
107
105
 
108
- attfunc :tab_setindex, :tcrdbtblsetindex, [ :pointer, :string, :int ], :int
106
+ attfunc :tab_del, :tcrdbdel, [ :pointer ], :void
109
107
 
110
- #
111
- # qry functions
108
+ attfunc :tab_rnum, :tcrdbrnum, [ :pointer ], :uint64
112
109
 
113
- attfunc :qry_new, :tcrdbqrynew, [ :pointer ], :pointer
114
- attfunc :qry_del, :tcrdbqrydel, [ :pointer ], :void
110
+ attfunc :tab_vanish, :tcrdbvanish, [ :pointer ], :int
115
111
 
116
- attfunc :qry_addcond, :tcrdbqryaddcond, [ :pointer, :string, :int, :string ], :void
117
- attfunc :qry_setorder, :tcrdbqrysetorder, [ :pointer, :string, :int ], :void
118
- attfunc :qry_setmax, :tcrdbqrysetmax, [ :pointer, :int ], :void
112
+ attfunc :tab_setindex, :tcrdbtblsetindex, [ :pointer, :string, :int ], :int
119
113
 
120
- attfunc :qry_search, :tcrdbqrysearch, [ :pointer ], :pointer
114
+ #
115
+ # qry functions
121
116
 
122
- else
117
+ attfunc :qry_new, :tcrdbqrynew, [ :pointer ], :pointer
118
+ attfunc :qry_del, :tcrdbqrydel, [ :pointer ], :void
123
119
 
124
- def method_missing (m, *args)
125
- raise "no libtokyotyrant.dylib found on your system"
126
- end
127
- end
120
+ attfunc :qry_addcond, :tcrdbqryaddcond, [ :pointer, :string, :int, :string ], :void
121
+ attfunc :qry_setorder, :tcrdbqrysetorder, [ :pointer, :string, :int ], :void
122
+ attfunc :qry_setmax, :tcrdbqrysetmax, [ :pointer, :int ], :void
128
123
 
124
+ attfunc :qry_search, :tcrdbqrysearch, [ :pointer ], :pointer
129
125
  end
130
-
131
126
  end
132
127
  end
@@ -41,6 +41,7 @@ module Rufus
41
41
  # # => { 'name' => 'toto the first', 'age' => '34' }
42
42
  #
43
43
  class TyrantTable < Table
44
+ include TyrantMethods
44
45
 
45
46
  attr_reader :host, :port
46
47
 
@@ -53,6 +54,15 @@ module Rufus
53
54
 
54
55
  (lib.tcrdbopen(@db, host, port) == 1) ||
55
56
  raise("couldn't connect to tyrant at #{host}:#{port}")
57
+
58
+ if self.stat['type'] != 'table'
59
+
60
+ self.close
61
+
62
+ raise ArgumentError.new(
63
+ "tyrant at #{host}:#{port} is a not table, " +
64
+ "use Rufus::Tokyo::Tyrant instead to access it.")
65
+ end
56
66
  end
57
67
 
58
68
  #
@@ -62,24 +72,27 @@ module Rufus
62
72
  TyrantLib
63
73
  end
64
74
 
65
- #
66
- # Inserts a record in the table db
67
- #
68
- # table['pk1'] = { 'name' => 'jeff', 'age' => '46' }
69
- #
70
- def []= (pk, h)
71
-
72
- pklen = CabinetLib.strlen(pk)
73
-
74
- m = Map.from_h(h)
75
-
76
- r = lib.tab_put(@db, pk, pklen, m.pointer)
77
-
78
- m.free
75
+ def transaction #:nodoc#
76
+ raise_transaction_nme('transaction')
77
+ end
78
+ def abort #:nodoc#
79
+ raise_transaction_nme('abort')
80
+ end
81
+ def tranbegin #:nodoc#
82
+ raise_transaction_nme('tranbegin')
83
+ end
84
+ def trancommit #:nodoc#
85
+ raise_transaction_nme('trancommit')
86
+ end
87
+ def tranabort #:nodoc#
88
+ raise_transaction_nme('tranabort')
89
+ end
79
90
 
80
- (r == 1) || raise_error
91
+ protected
81
92
 
82
- h
93
+ def raise_transaction_nme (method_name)
94
+ raise NoMethodError.new(
95
+ "Tyrant tables don't support transactions", method_name)
83
96
  end
84
97
  end
85
98
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-tokyo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-13 00:00:00 +09:00
13
+ date: 2009-02-16 00:00:00 +09:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency