rufus-tokyo 0.1.14 → 1.0.0
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 +9 -0
- data/CREDITS.txt +10 -1
- data/README.rdoc +9 -11
- data/TODO.txt +17 -5
- data/lib/rufus/edo/cabcore.rb +29 -6
- data/lib/rufus/edo/ntyrant/abstract.rb +1 -1
- data/lib/rufus/edo/ntyrant/table.rb +14 -0
- data/lib/rufus/edo/tabcore.rb +45 -18
- data/lib/rufus/tokyo.rb +1 -1
- data/lib/rufus/tokyo/cabinet/abstract.rb +33 -32
- data/lib/rufus/tokyo/cabinet/lib.rb +12 -17
- data/lib/rufus/tokyo/cabinet/table.rb +53 -20
- data/lib/rufus/tokyo/dystopia.rb +10 -7
- data/lib/rufus/tokyo/dystopia/core.rb +198 -0
- data/lib/rufus/tokyo/dystopia/lib.rb +65 -3
- data/lib/rufus/tokyo/dystopia/words.rb +1 -1
- data/lib/rufus/tokyo/outlen.rb +46 -0
- data/lib/rufus/tokyo/query.rb +9 -1
- data/lib/rufus/tokyo/tyrant/abstract.rb +4 -26
- data/lib/rufus/tokyo/tyrant/ext.rb +52 -0
- data/lib/rufus/tokyo/tyrant/lib.rb +6 -6
- data/lib/rufus/tokyo/tyrant/table.rb +3 -1
- data/lib/rufus/tokyo/utils.rb +44 -0
- data/spec/spec.rb +3 -1
- metadata +6 -2
data/lib/rufus/tokyo/dystopia.rb
CHANGED
@@ -27,17 +27,20 @@ require 'rufus/tokyo'
|
|
27
27
|
|
28
28
|
|
29
29
|
module Rufus::Tokyo
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
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
|
-
|
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
|
-
#
|
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
|
|
@@ -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
|
+
|
data/lib/rufus/tokyo/query.rb
CHANGED
@@ -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
|
-
|
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
|
#
|