rufus-tokyo 0.1.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,17 +27,20 @@ require 'rufus/tokyo'
27
27
 
28
28
 
29
29
  module Rufus::Tokyo
30
-
31
- #
32
- # An error for Dystopia
33
- #
34
- class DystopianError < RuntimeError
35
- def new (error_code)
36
- super("tokyo dystopia error #{error_code}")
30
+ module Dystopia
31
+ #
32
+ # An error for Dystopia
33
+ #
34
+ class Error < RuntimeError
35
+ def new (error_code)
36
+ super("tokyo dystopia error #{error_code}")
37
+ end
37
38
  end
38
39
  end
39
40
  end
40
41
 
41
42
  require 'rufus/tokyo/dystopia/lib'
43
+
44
+ require 'rufus/tokyo/dystopia/core'
42
45
  require 'rufus/tokyo/dystopia/words'
43
46
 
@@ -0,0 +1,198 @@
1
+ #--
2
+ # Copyright (c) 2009, Jeremy Hinegardner, jeremy@copiousfreetime.org
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Developed with and sponsored by Seven Scale <http://sevenscale.com/>,
23
+ # creators of Open Syslog.
24
+ #
25
+ #++
26
+
27
+ module Rufus::Tokyo::Dystopia
28
+ #
29
+ # Tokyo Dystopia Indexed Database
30
+ #
31
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/#dystopiaapi
32
+ #
33
+ class Core
34
+ class Error < Rufus::Tokyo::Dystopia::Error; end
35
+
36
+ def self.lib
37
+ ::Rufus::Tokyo::DystopiaLib
38
+ end
39
+
40
+ def self.mode_to_bits( mode )
41
+ @modes_to_bits ||= {
42
+ "r" => lib::READER,
43
+ "r+" => lib::READER | lib::WRITER,
44
+ "w" => lib::WRITER | lib::CREAT | lib::TRUNC,
45
+ "w+" => lib::READER | lib::WRITER | lib::CREAT | lib::TRUNC,
46
+ "a" => lib::WRITER | lib::CREAT,
47
+ "a+" => lib::READER | lib::WRITER | lib::CREAT ,
48
+ }
49
+
50
+ return @modes_to_bits[mode]
51
+ end
52
+
53
+ def self.locking_to_bits( locking )
54
+ @locking_to_bits ||= {
55
+ true => 0,
56
+ false => lib::NOLCK,
57
+ :nonblocking => lib::LCKNB
58
+ }
59
+ return @locking_to_bits[locking]
60
+ end
61
+
62
+ def lib
63
+ Core.lib
64
+ end
65
+
66
+ #
67
+ # Opens/creates a new Tokyo dystopia database
68
+ #
69
+ # The modes are equivelent to those when opening a file:
70
+ #
71
+ # 'r' : readonly
72
+ # 'r+' : read/write does not create or truncate
73
+ # 'w' : write only, create and truncate
74
+ # 'w+' : read/write, create and truncate
75
+ # 'a' : write only, create if db does not exist
76
+ # 'a+' : read/write, create if db does not exist
77
+ #
78
+ # The third parameter 'locking' can be one of 'true', 'false' or
79
+ # :nonblocking
80
+ #
81
+ def initialize( path, mode = "a+", locking = true )
82
+ mode_bits = Core.mode_to_bits( mode )
83
+ raise Error.new( "Invalid mode '#{mode}'" ) unless mode_bits
84
+ lock_bits = Core.locking_to_bits( locking )
85
+ raise Error.new( "Invalid Locking mode #{locking}" ) unless lock_bits
86
+
87
+ @db = lib.tcidbnew()
88
+
89
+ rc = lib.tcidbopen( @db, path, mode_bits | lock_bits )
90
+ raise_error unless rc == 1
91
+ end
92
+
93
+ #
94
+ # Close and detach from the database. This instance can not be used anymore
95
+ #
96
+ def close
97
+ rc = lib.tcidbclose( @db )
98
+ raise_error unless rc == 1
99
+
100
+ lib.tcidbdel( @db )
101
+ raise_error unless rc == 1
102
+
103
+ @db = nil
104
+ end
105
+
106
+ #
107
+ # Add a new document to the database
108
+ #
109
+ def store( id, text )
110
+ rc = lib.tcidbput( @db, id, text )
111
+ raise_error unless rc == 1
112
+ end
113
+
114
+ #
115
+ # Remove the given document from the index
116
+ #
117
+ def delete( id )
118
+ rc = lib.tcidbout( @db, id )
119
+ raise_error unless rc == 1
120
+ end
121
+
122
+ #
123
+ # Return the document at the specified index
124
+ #
125
+ def fetch( id )
126
+ r = nil
127
+ begin
128
+ r = lib.tcidbget( @db, id )
129
+ rescue => e
130
+ # if we have 'no record found' then return nil
131
+ if lib.tcidbecode( @db ) == 22 then
132
+ return nil
133
+ else
134
+ raise_error
135
+ end
136
+ end
137
+ return r
138
+ end
139
+
140
+ #
141
+ # Return the document ids of the documents that matche the search expression
142
+ #
143
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/#dystopiaapi and scroll
144
+ # down to 'Compound Expression of Search'
145
+ #
146
+ def search( expression )
147
+ out_count = ::FFI::MemoryPointer.new :pointer
148
+ out_list = ::FFI::MemoryPointer.new :pointer
149
+ out_list = lib.tcidbsearch2( @db, expression, out_count )
150
+
151
+ count = out_count.read_int
152
+ results = out_list.get_array_of_uint64(0, count )
153
+ return results
154
+ end
155
+
156
+ #
157
+ # Remove all records from the db
158
+ #
159
+ def clear
160
+ lib.tcidbvanish( @db )
161
+ end
162
+
163
+ #
164
+ # Report the path of the database
165
+ #
166
+ def path
167
+ s = lib.tcidbpath( @db )
168
+ return File.expand_path( s ) if s
169
+ end
170
+
171
+ #
172
+ # Return the number of records in the database
173
+ #
174
+ def count
175
+ lib.tcidbrnum( @db )
176
+ end
177
+ alias :rnum :count
178
+
179
+ #
180
+ # return the disk space used by the index
181
+ #
182
+ def fsize
183
+ lib.tcidbfsiz( @db )
184
+ end
185
+
186
+ protected
187
+
188
+ #
189
+ # Raises a dystopian error (asks the db which one)
190
+ #
191
+ def raise_error
192
+ code = lib.tcidbecode( @db )
193
+ msg = lib.tcidberrmsg( code )
194
+ raise Error.new("[ERROR #{code}] : #{msg}")
195
+ end
196
+
197
+ end
198
+ end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2009, Jeremy Hinegardner, John Mettraux
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -36,19 +36,81 @@ module Rufus::Tokyo
36
36
  # find Tokyo Dystopia lib
37
37
 
38
38
  paths = Array(ENV['TOKYO_DYSTOPIA_LIB'] || %w{
39
+ /usr/lib/libtokyodystopia.so
40
+ /usr/lib64/libtokyodystopia.so
39
41
  /opt/local/lib/libtokyodystopia.dylib
42
+ /opt/local/lib/libtokyodystopia.so
40
43
  /usr/local/lib/libtokyodystopia.dylib
41
44
  /usr/local/lib/libtokyodystopia.so
42
45
  })
43
46
 
44
- if path = paths.find { |path| File.exist?(path) }
47
+ path = paths.find { |path| File.exist?(path) }
45
48
 
46
49
  raise "did not find Tokyo Dystopia libs on your system" unless path
47
50
 
48
51
  ffi_lib(path)
49
52
 
50
53
  #
51
- # tcwdb functions
54
+ # tcidb functions - The Core API
55
+ #
56
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/#dystopiaapi
57
+
58
+ # tuning options <dystopia.h>
59
+ LARGE = 1 << 0
60
+ DEFLATE = 1 << 1
61
+ BZIP = 1 << 2
62
+ TCBS = 1 << 3
63
+
64
+ # open modes <dystopia.h>
65
+ READER = 1 << 0
66
+ WRITER = 1 << 1
67
+ CREAT = 1 << 2
68
+ TRUNC = 1 << 3
69
+ NOLCK = 1 << 4
70
+ LCKNB = 1 << 5
71
+
72
+ # for get modes
73
+ SUBSTR = 0
74
+ PREFIX = 1
75
+ SUFFIX = 2
76
+ FULL = 3
77
+ TOKEN = 4
78
+ TOKPRE = 5
79
+ TOKSUF = 6
80
+
81
+
82
+ attach_function :tcidberrmsg, [ :int ], :string
83
+ attach_function :tcidbecode, [ :pointer ], :int
84
+
85
+ attach_function :tcidbnew, [], :pointer
86
+ attach_function :tcidbopen, [ :pointer, :pointer, :int ], :int
87
+ attach_function :tcidbclose, [ :pointer ], :int
88
+ attach_function :tcidbdel, [ :pointer ], :void
89
+ attach_function :tcidbvanish, [ :pointer ], :int
90
+
91
+ # TODO
92
+ #attach_function :tcidbtune, [ :pointer, :int64, :int64, :int64, :int8 ], :int
93
+ #attach_function :tcidbsetcache, [ :pointer, :int64, :int32 ], :int
94
+ #attach_function :tcidbsetfwmmax, [ :pointer, :uint32 ], :int
95
+ #attach_function :tcidbsync, [ :pointer ], :int
96
+ #attach_function :tcidboptimize, [ :pointer ], :int
97
+ #attach_function :tcidbcopy, [ :pointer, :pointer ], :int
98
+
99
+ attach_function :tcidbpath, [ :pointer ], :string
100
+ attach_function :tcidbrnum, [ :pointer ], :uint64
101
+ attach_function :tcidbfsiz, [ :pointer ], :uint64
102
+
103
+ attach_function :tcidbput, [ :pointer, :int64, :string ], :int
104
+ attach_function :tcidbout, [ :pointer, :int64 ], :int
105
+ attach_function :tcidbget, [ :pointer, :int64 ], :string
106
+ #attach_function :tcidbsearch, [ :pointer, :pointer, :int, :pointer ], :pointer
107
+ attach_function :tcidbsearch2, [ :pointer, :string, :pointer], :pointer
108
+ #attach_function :tcidbiterinit, [ :pointer ], :int
109
+ #attach_function :tcidbiternext, [ :pointer ], :uint64
110
+
111
+
112
+ #
113
+ # tcwdb functions - The Word Database API
52
114
  #
53
115
  # http://tokyocabinet.sourceforge.net/dystopiadoc/#tcwdbapi
54
116
 
@@ -23,7 +23,7 @@
23
23
  #++
24
24
 
25
25
 
26
- module Rufus::Tokyo
26
+ module Rufus::Tokyo::Dystopia
27
27
 
28
28
  #
29
29
  # Tokyo Dystopia words database.
@@ -0,0 +1,46 @@
1
+ #--
2
+ # Copyright (c) 2009, Adam Keys, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ module Rufus::Tokyo
26
+ module Outlen
27
+
28
+ # A wrapper for library returning a string (binary data potentially)
29
+ #
30
+ def outlen_op (method, *args)
31
+
32
+ args.unshift(@db)
33
+
34
+ outlen = FFI::MemoryPointer.new(:int)
35
+ args << outlen
36
+
37
+ out = lib.send(method, *args)
38
+
39
+ return nil if out.address == 0
40
+ return out.get_bytes(0, outlen.get_int(0))
41
+ ensure
42
+ outlen.free
43
+ end
44
+ end
45
+ end
46
+
@@ -81,7 +81,15 @@ module Tokyo
81
81
  :bt => 13,
82
82
  :between => 13,
83
83
 
84
- :numoreq => 14 # number which is equal to at least one token
84
+ :numoreq => 14, # number which is equal to at least one token
85
+
86
+ # full-text search
87
+ :ftsph => 15,
88
+ :ftsphrase => 15,
89
+ :phrase => 15,
90
+ :ftsand => 16,
91
+ :ftsor => 17,
92
+ :ftsex => 18
85
93
  }
86
94
 
87
95
  TDBQCNEGATE = 1 << 24
@@ -22,9 +22,8 @@
22
22
  # Made in Japan.
23
23
  #++
24
24
 
25
-
26
25
  require 'rufus/tokyo/ttcommons'
27
-
26
+ require 'rufus/tokyo/tyrant/ext'
28
27
 
29
28
  module Rufus::Tokyo
30
29
 
@@ -39,6 +38,7 @@ module Rufus::Tokyo
39
38
  class Tyrant < Cabinet
40
39
 
41
40
  include TyrantCommons
41
+ include Ext
42
42
 
43
43
  attr_reader :host, :port
44
44
 
@@ -70,8 +70,8 @@ module Rufus::Tokyo
70
70
  @host = host
71
71
  @port = port
72
72
 
73
- (lib.tcrdbopen(@db, host, port) == 1) ||
74
- raise("couldn't connect to tyrant at #{host}:#{port}")
73
+ (lib.tcrdbopen(@db, host, port) == 1) || raise(
74
+ TokyoError.new("couldn't connect to tyrant at #{host}:#{port}"))
75
75
 
76
76
  if self.stat['type'] == 'table'
77
77
 
@@ -100,28 +100,6 @@ module Rufus::Tokyo
100
100
  raise 'not allowed to create files on the server'
101
101
  end
102
102
 
103
- # Calls a lua embedded function
104
- # (http://tokyocabinet.sourceforge.net/tyrantdoc/#luaext)
105
- #
106
- # Options are :global_locking and :record_locking
107
- #
108
- # Returns the return value of the called function.
109
- #
110
- # Nil is returned in case of failure.
111
- #
112
- def ext (func_name, key, value, opts={})
113
-
114
- k = key.to_s
115
- v = value.to_s
116
-
117
- outlen_op(
118
- :tcrdbext,
119
- func_name.to_s,
120
- compute_ext_opts(opts),
121
- k, Rufus::Tokyo.blen(k),
122
- v, Rufus::Tokyo.blen(v))
123
- end
124
-
125
103
  # Tyrant databases DO NOT support the 'defrag' call. Calling this method
126
104
  # will raise an exception.
127
105
  #