oklahoma_mixer 0.2.0 → 0.3.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.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
|