oklahoma_mixer 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +7 -0
- data/README.rdoc +4 -0
- data/Rakefile +1 -1
- data/TODO.rdoc +2 -3
- data/lib/oklahoma_mixer.rb +7 -20
- data/lib/oklahoma_mixer/array_list.rb +21 -7
- data/lib/oklahoma_mixer/array_list/c.rb +9 -1
- data/lib/oklahoma_mixer/b_tree_database.rb +25 -9
- data/lib/oklahoma_mixer/b_tree_database/c.rb +5 -0
- data/lib/oklahoma_mixer/cursor.rb +3 -0
- data/lib/oklahoma_mixer/cursor/c.rb +2 -0
- data/lib/oklahoma_mixer/error.rb +2 -0
- data/lib/oklahoma_mixer/extensible_string.rb +4 -2
- data/lib/oklahoma_mixer/extensible_string/c.rb +2 -0
- data/lib/oklahoma_mixer/fixed_length_database.rb +11 -3
- data/lib/oklahoma_mixer/fixed_length_database/c.rb +2 -0
- data/lib/oklahoma_mixer/hash_database.rb +24 -7
- data/lib/oklahoma_mixer/hash_database/c.rb +2 -0
- data/lib/oklahoma_mixer/hash_map.rb +42 -0
- data/lib/oklahoma_mixer/hash_map/c.rb +27 -0
- data/lib/oklahoma_mixer/query.rb +73 -0
- data/lib/oklahoma_mixer/query/c.rb +51 -0
- data/lib/oklahoma_mixer/table_database.rb +402 -0
- data/lib/oklahoma_mixer/table_database/c.rb +104 -0
- data/lib/oklahoma_mixer/utilities.rb +26 -1
- data/test/{b_tree_binary_data_test.rb → b_tree_database/b_tree_binary_data_test.rb} +2 -2
- data/test/{b_tree_tuning_test.rb → b_tree_database/b_tree_tuning_test.rb} +2 -2
- data/test/{cursor_based_iteration_test.rb → b_tree_database/cursor_based_iteration_test.rb} +2 -2
- data/test/{duplicate_storage_test.rb → b_tree_database/duplicate_storage_test.rb} +18 -12
- data/test/{binary_data_test.rb → core_database/binary_data_test.rb} +2 -2
- data/test/{file_system_test.rb → core_database/file_system_test.rb} +0 -0
- data/test/{getting_and_setting_keys_test.rb → core_database/getting_and_setting_keys_test.rb} +31 -60
- data/test/{iteration_test.rb → core_database/iteration_test.rb} +2 -2
- data/test/{transactions_test.rb → core_database/transactions_test.rb} +0 -0
- data/test/core_database/tuning_test.rb +31 -0
- data/test/{fixed_length_tuning_test.rb → fixed_length_database/fixed_length_tuning_test.rb} +0 -0
- data/test/{getting_and_setting_by_id_test.rb → fixed_length_database/getting_and_setting_by_id_test.rb} +8 -0
- data/test/{shared_binary_data.rb → shared/binary_data_tests.rb} +1 -1
- data/test/{tuning_test.rb → shared/hash_tuning_tests.rb} +18 -42
- data/test/{shared_iteration.rb → shared/iteration_tests.rb} +8 -7
- data/test/{key_range_test.rb → shared/key_range_test.rb} +0 -0
- data/test/{order_test.rb → shared/order_test.rb} +0 -0
- data/test/shared/storage_tests.rb +65 -0
- data/test/{top_level_interface_test.rb → shared/top_level_interface_test.rb} +39 -2
- data/test/{shared_tuning.rb → shared/tuning_tests.rb} +1 -1
- data/test/table_database/document_iteration_test.rb +22 -0
- data/test/table_database/document_storage_test.rb +225 -0
- data/test/table_database/index_test.rb +57 -0
- data/test/table_database/query_test.rb +866 -0
- data/test/table_database/table_tuning_test.rb +56 -0
- data/test/test_helper.rb +27 -0
- metadata +35 -36
data/CHANGELOG.rdoc
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
Below is a complete listing of changes for each revision of Oklahoma Mixer.
|
4
4
|
|
5
|
+
== 0.3.0
|
6
|
+
|
7
|
+
* Added the empty?() method
|
8
|
+
* Added the ability to set an Array of duplicates at once for B+Tree Databases
|
9
|
+
* Added Table Database support (document storage, queries/searches, and indexes)
|
10
|
+
* Switched to autoloading database interfaces as they are used
|
11
|
+
|
5
12
|
== 0.2.0
|
6
13
|
|
7
14
|
* Added a to_hash() iterator that can preserve defaults
|
data/README.rdoc
CHANGED
@@ -46,3 +46,7 @@ When I was in Japan, people would ask where I was from. When I would tell them,
|
|
46
46
|
It turns out Oklahoma Mixer is a song in Japan. I had to track it down in a music store. It's kind of a camp song medley, including things like the Hokey Pokey. I'm not too sure what that has to do with Oklahoma, but at least they had heard of where I'm from.
|
47
47
|
|
48
48
|
On a more practical side, this interface to Tokyo Cabinet is from Oklahoma. I intend it to _mix_ together all of the great features of that library in some exciting new ways. Thus, Oklahoma Mixer it is.
|
49
|
+
|
50
|
+
== Is there any documentation yet?
|
51
|
+
|
52
|
+
I'll write some proper API documentation down the road a bit, but users playing with the preview releases can read about how to use this library in {the Tokyo Cabinet series on my blog}[http://blog.grayproductions.net/articles/using_keyvalue_stores_from_ruby].
|
data/Rakefile
CHANGED
data/TODO.rdoc
CHANGED
@@ -3,9 +3,8 @@
|
|
3
3
|
The following is a list of planned expansions for Oklahoma Mixer in the order I
|
4
4
|
intend to address them.
|
5
5
|
|
6
|
-
1. Add support for
|
6
|
+
1. Add support for Tokyo Tyrant
|
7
7
|
2. Ensure Ruby 1.9 compatibility
|
8
8
|
3. Write API documentation
|
9
|
-
4.
|
9
|
+
4. Include some higher level abstractions like mixed tables, queues, and shards
|
10
10
|
5. Add support for Tokyo Dystopia
|
11
|
-
6. Include some higher level abstractions like mixed tables, queues, and shards
|
data/lib/oklahoma_mixer.rb
CHANGED
@@ -1,30 +1,17 @@
|
|
1
|
-
require "ffi"
|
2
|
-
|
3
|
-
require "oklahoma_mixer/error"
|
4
|
-
require "oklahoma_mixer/utilities"
|
5
|
-
|
6
|
-
require "oklahoma_mixer/extensible_string/c"
|
7
|
-
require "oklahoma_mixer/extensible_string"
|
8
|
-
require "oklahoma_mixer/array_list/c"
|
9
|
-
require "oklahoma_mixer/array_list"
|
10
|
-
require "oklahoma_mixer/cursor/c"
|
11
|
-
require "oklahoma_mixer/cursor"
|
12
|
-
|
13
|
-
require "oklahoma_mixer/hash_database/c"
|
14
|
-
require "oklahoma_mixer/hash_database"
|
15
|
-
require "oklahoma_mixer/b_tree_database/c"
|
16
|
-
require "oklahoma_mixer/b_tree_database"
|
17
|
-
require "oklahoma_mixer/fixed_length_database/c"
|
18
|
-
require "oklahoma_mixer/fixed_length_database"
|
19
|
-
|
20
1
|
module OklahomaMixer
|
21
|
-
VERSION = "0.
|
2
|
+
VERSION = "0.3.0"
|
3
|
+
|
4
|
+
autoload :HashDatabase, "oklahoma_mixer/hash_database"
|
5
|
+
autoload :BTreeDatabase, "oklahoma_mixer/b_tree_database"
|
6
|
+
autoload :FixedLengthDatabase, "oklahoma_mixer/fixed_length_database"
|
7
|
+
autoload :TableDatabase, "oklahoma_mixer/table_database"
|
22
8
|
|
23
9
|
def self.open(path, *args)
|
24
10
|
db_class = case File.extname(path).downcase
|
25
11
|
when ".tch" then HashDatabase
|
26
12
|
when ".tcb" then BTreeDatabase
|
27
13
|
when ".tcf" then FixedLengthDatabase
|
14
|
+
when ".tct" then TableDatabase
|
28
15
|
else fail ArgumentError, "unsupported database type"
|
29
16
|
end
|
30
17
|
db = db_class.new(path, *args)
|
@@ -1,18 +1,32 @@
|
|
1
|
+
require "oklahoma_mixer/array_list/c"
|
2
|
+
|
1
3
|
module OklahomaMixer
|
2
4
|
class ArrayList # :nodoc:
|
3
|
-
def initialize(
|
4
|
-
@pointer =
|
5
|
+
def initialize(pointer_or_size)
|
6
|
+
@pointer = case pointer_or_size
|
7
|
+
when FFI::Pointer then pointer_or_size
|
8
|
+
else C.new2(pointer_or_size.to_i)
|
9
|
+
end
|
5
10
|
end
|
6
11
|
|
12
|
+
attr_reader :pointer
|
13
|
+
|
7
14
|
def shift
|
8
|
-
C.read_from_func(:shift, @pointer)
|
15
|
+
value = C.read_from_func(:shift, @pointer)
|
16
|
+
block_given? ? yield(value) : value
|
9
17
|
end
|
10
18
|
|
11
|
-
|
12
|
-
|
13
|
-
def each
|
19
|
+
def map
|
20
|
+
values = [ ]
|
14
21
|
while value = shift
|
15
|
-
yield
|
22
|
+
values << yield(value)
|
23
|
+
end
|
24
|
+
values
|
25
|
+
end
|
26
|
+
|
27
|
+
def push(*values)
|
28
|
+
values.each do |value|
|
29
|
+
C.push(@pointer, *yield(value))
|
16
30
|
end
|
17
31
|
end
|
18
32
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "oklahoma_mixer/utilities"
|
2
|
+
|
1
3
|
module OklahomaMixer
|
2
4
|
class ArrayList
|
3
5
|
module C # :nodoc:
|
@@ -5,11 +7,17 @@ module OklahomaMixer
|
|
5
7
|
|
6
8
|
prefix :tclist
|
7
9
|
|
8
|
-
|
10
|
+
func :name => :new2,
|
11
|
+
:args => :int,
|
12
|
+
:returns => :pointer
|
13
|
+
func :name => :del,
|
14
|
+
:args => :pointer
|
9
15
|
|
10
16
|
func :name => :shift,
|
11
17
|
:args => [:pointer, :pointer],
|
12
18
|
:returns => :pointer
|
19
|
+
func :name => :push,
|
20
|
+
:args => [:pointer, :pointer, :int]
|
13
21
|
end
|
14
22
|
end
|
15
23
|
end
|
@@ -1,3 +1,8 @@
|
|
1
|
+
require "oklahoma_mixer/array_list"
|
2
|
+
require "oklahoma_mixer/cursor"
|
3
|
+
require "oklahoma_mixer/hash_database"
|
4
|
+
require "oklahoma_mixer/b_tree_database/c"
|
5
|
+
|
1
6
|
module OklahomaMixer
|
2
7
|
class BTreeDatabase < HashDatabase
|
3
8
|
###################
|
@@ -11,7 +16,7 @@ module OklahomaMixer
|
|
11
16
|
options.fetch(:bnum, 0).to_i,
|
12
17
|
options.fetch(:apow, -1).to_i,
|
13
18
|
options.fetch(:fpow, -1).to_i,
|
14
|
-
|
19
|
+
cast_to_enum_int(options.fetch(:opts, 0xFF), :opt) )
|
15
20
|
end
|
16
21
|
|
17
22
|
################################
|
@@ -20,7 +25,14 @@ module OklahomaMixer
|
|
20
25
|
|
21
26
|
def store(key, value, mode = nil)
|
22
27
|
if mode == :dup
|
23
|
-
|
28
|
+
if value.is_a? Array
|
29
|
+
Utilities.temp_list(value.size) do |list|
|
30
|
+
list.push(*value) { |string| cast_value_in(string) }
|
31
|
+
try(:putdup3, cast_key_in(key), list.pointer)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
try(:putdup, cast_key_in(key), cast_value_in(value))
|
35
|
+
end
|
24
36
|
value
|
25
37
|
else
|
26
38
|
super
|
@@ -42,7 +54,7 @@ module OklahomaMixer
|
|
42
54
|
*[ start, include_start,
|
43
55
|
finish, include_finish,
|
44
56
|
limit ].flatten ) )
|
45
|
-
list.
|
57
|
+
list.map { |key| cast_key_out(key) }
|
46
58
|
ensure
|
47
59
|
list.free if list
|
48
60
|
end
|
@@ -63,7 +75,7 @@ module OklahomaMixer
|
|
63
75
|
[ ]
|
64
76
|
else
|
65
77
|
list = ArrayList.new(pointer)
|
66
|
-
list.
|
78
|
+
list.map { |value| cast_value_out(value) }
|
67
79
|
end
|
68
80
|
ensure
|
69
81
|
list.free if list
|
@@ -100,14 +112,15 @@ module OklahomaMixer
|
|
100
112
|
def each_key(start = nil)
|
101
113
|
cursor_in_loop(start) do |iterator|
|
102
114
|
throw(:finish_iteration) unless key = iterator.key
|
103
|
-
yield key
|
115
|
+
yield cast_key_out(key)
|
104
116
|
end
|
105
117
|
end
|
106
118
|
|
107
119
|
def each(start = nil)
|
108
120
|
cursor_in_loop(start) do |iterator|
|
109
121
|
throw(:finish_iteration) unless key_and_value = iterator.key_and_value
|
110
|
-
yield key_and_value
|
122
|
+
yield [ cast_key_out(key_and_value.first),
|
123
|
+
cast_value_out(key_and_value.last) ]
|
111
124
|
end
|
112
125
|
end
|
113
126
|
alias_method :each_pair, :each
|
@@ -115,14 +128,15 @@ module OklahomaMixer
|
|
115
128
|
def reverse_each(start = nil)
|
116
129
|
cursor_in_loop(start, :reverse) do |iterator|
|
117
130
|
throw(:finish_iteration) unless key_and_value = iterator.key_and_value
|
118
|
-
yield key_and_value
|
131
|
+
yield [ cast_key_out(key_and_value.first),
|
132
|
+
cast_value_out(key_and_value.last) ]
|
119
133
|
end
|
120
134
|
end
|
121
135
|
|
122
136
|
def each_value(start = nil)
|
123
137
|
cursor_in_loop(start) do |iterator|
|
124
138
|
throw(:finish_iteration) unless value = iterator.value
|
125
|
-
yield value
|
139
|
+
yield cast_value_out(value)
|
126
140
|
end
|
127
141
|
end
|
128
142
|
|
@@ -130,7 +144,9 @@ module OklahomaMixer
|
|
130
144
|
cursor(start) do |iterator|
|
131
145
|
loop do
|
132
146
|
break unless key_and_value = iterator.key_and_value
|
133
|
-
|
147
|
+
test = yield( cast_key_out(key_and_value.first),
|
148
|
+
cast_value_out(key_and_value.last) )
|
149
|
+
break unless iterator.send(test ? :delete : :next)
|
134
150
|
end
|
135
151
|
end
|
136
152
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "oklahoma_mixer/utilities"
|
2
|
+
|
1
3
|
module OklahomaMixer
|
2
4
|
class BTreeDatabase < HashDatabase
|
3
5
|
module C # :nodoc:
|
@@ -26,6 +28,9 @@ module OklahomaMixer
|
|
26
28
|
func :name => :putdup,
|
27
29
|
:args => [:pointer, :pointer, :int, :pointer, :int],
|
28
30
|
:returns => :bool
|
31
|
+
func :name => :putdup3,
|
32
|
+
:args => [:pointer, :pointer, :int, :pointer],
|
33
|
+
:returns => :bool
|
29
34
|
func :name => :out3,
|
30
35
|
:args => [:pointer, :pointer, :int],
|
31
36
|
:returns => :bool
|
data/lib/oklahoma_mixer/error.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "oklahoma_mixer/hash_database"
|
2
|
+
require "oklahoma_mixer/fixed_length_database/c"
|
3
|
+
|
1
4
|
module OklahomaMixer
|
2
5
|
class FixedLengthDatabase < HashDatabase
|
3
6
|
###################
|
@@ -45,7 +48,7 @@ module OklahomaMixer
|
|
45
48
|
array = list.get_array_of_uint64(0, count.get_int(0))
|
46
49
|
array.shift if array.first == start and not include_start
|
47
50
|
array.pop if array.last == finish and not include_finish
|
48
|
-
array
|
51
|
+
array # cast not needed: already Integer
|
49
52
|
ensure
|
50
53
|
Utilities.free(list) if list
|
51
54
|
end
|
@@ -62,7 +65,7 @@ module OklahomaMixer
|
|
62
65
|
return self unless key = try( :iternext,
|
63
66
|
:failure => 0,
|
64
67
|
:no_error => {22 => nil} )
|
65
|
-
yield key
|
68
|
+
yield key # cast not needed: already Integer
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
@@ -86,10 +89,15 @@ module OklahomaMixer
|
|
86
89
|
def cast_key_in(key)
|
87
90
|
case key
|
88
91
|
when :min, :max, :prev, :next, "min", "max", "prev", "next"
|
89
|
-
|
92
|
+
lib::IDS["FDBID#{key.to_s.upcase}".to_sym]
|
90
93
|
else
|
91
94
|
key.to_i
|
92
95
|
end
|
93
96
|
end
|
97
|
+
|
98
|
+
# Override to prevent String manipulations on ID.
|
99
|
+
def cast_key_out(integer)
|
100
|
+
integer
|
101
|
+
end
|
94
102
|
end
|
95
103
|
end
|
@@ -1,3 +1,8 @@
|
|
1
|
+
require "oklahoma_mixer/error"
|
2
|
+
require "oklahoma_mixer/extensible_string"
|
3
|
+
require "oklahoma_mixer/array_list"
|
4
|
+
require "oklahoma_mixer/hash_database/c"
|
5
|
+
|
1
6
|
module OklahomaMixer
|
2
7
|
class HashDatabase
|
3
8
|
#################
|
@@ -34,7 +39,9 @@ module OklahomaMixer
|
|
34
39
|
tune(options)
|
35
40
|
|
36
41
|
warn "mode option supersedes mode argument" if mode and options[:mode]
|
37
|
-
try(:open,
|
42
|
+
try( :open,
|
43
|
+
path,
|
44
|
+
cast_to_enum_int(options.fetch(:mode, mode || "wc"), :mode) )
|
38
45
|
rescue Exception
|
39
46
|
close if defined?(@db) and @db
|
40
47
|
raise
|
@@ -45,7 +52,7 @@ module OklahomaMixer
|
|
45
52
|
options.fetch(:bnum, 0).to_i,
|
46
53
|
options.fetch(:apow, -1).to_i,
|
47
54
|
options.fetch(:fpow, -1).to_i,
|
48
|
-
|
55
|
+
cast_to_enum_int(options.fetch(:opts, 0xFF), :opt) )
|
49
56
|
end
|
50
57
|
|
51
58
|
attr_reader :path
|
@@ -130,7 +137,7 @@ module OklahomaMixer
|
|
130
137
|
def fetch(key, *default)
|
131
138
|
if value = try( :read_from_func, :get, cast_key_in(key),
|
132
139
|
:failure => nil, :no_error => {22 => nil} )
|
133
|
-
value
|
140
|
+
cast_value_out(value)
|
134
141
|
else
|
135
142
|
if block_given?
|
136
143
|
warn "block supersedes default value argument" unless default.empty?
|
@@ -164,7 +171,7 @@ module OklahomaMixer
|
|
164
171
|
prefix = options.fetch(:prefix, "").to_s
|
165
172
|
limit = options.fetch(:limit, -1)
|
166
173
|
list = ArrayList.new(lib.fwmkeys(@db, prefix, prefix.size, limit))
|
167
|
-
list.
|
174
|
+
list.map { |key| cast_key_out(key) }
|
168
175
|
ensure
|
169
176
|
list.free if list
|
170
177
|
end
|
@@ -205,6 +212,10 @@ module OklahomaMixer
|
|
205
212
|
end
|
206
213
|
alias_method :length, :size
|
207
214
|
|
215
|
+
def empty?
|
216
|
+
size.zero?
|
217
|
+
end
|
218
|
+
|
208
219
|
#################
|
209
220
|
### Iteration ###
|
210
221
|
#################
|
@@ -217,7 +228,7 @@ module OklahomaMixer
|
|
217
228
|
return self unless key = try( :read_from_func, :iternext,
|
218
229
|
:failure => nil,
|
219
230
|
:no_error => {22 => nil} )
|
220
|
-
yield key
|
231
|
+
yield cast_key_out(key)
|
221
232
|
end
|
222
233
|
end
|
223
234
|
|
@@ -228,7 +239,7 @@ module OklahomaMixer
|
|
228
239
|
Utilities.temp_xstr do |value|
|
229
240
|
return self unless try( :iternext3, key.pointer, value.pointer,
|
230
241
|
:no_error => {22 => false} )
|
231
|
-
yield [key.to_s, value.to_s]
|
242
|
+
yield [cast_key_out(key.to_s), cast_value_out(value.to_s)]
|
232
243
|
end
|
233
244
|
end
|
234
245
|
end
|
@@ -327,7 +338,7 @@ module OklahomaMixer
|
|
327
338
|
end
|
328
339
|
end
|
329
340
|
|
330
|
-
def
|
341
|
+
def cast_to_enum_int(str_or_int, name)
|
331
342
|
return str_or_int if str_or_int.is_a? Integer
|
332
343
|
const = "#{name.to_s.upcase}S"
|
333
344
|
names = self.class.const_get(const)
|
@@ -361,5 +372,11 @@ module OklahomaMixer
|
|
361
372
|
end
|
362
373
|
alias_method :cast_key_in, :cast_to_bytes_and_length
|
363
374
|
alias_method :cast_value_in, :cast_to_bytes_and_length
|
375
|
+
|
376
|
+
def cast_to_encoded_string(string)
|
377
|
+
string
|
378
|
+
end
|
379
|
+
alias_method :cast_key_out, :cast_to_encoded_string
|
380
|
+
alias_method :cast_value_out, :cast_to_encoded_string
|
364
381
|
end
|
365
382
|
end
|