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.
Files changed (52) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/README.rdoc +4 -0
  3. data/Rakefile +1 -1
  4. data/TODO.rdoc +2 -3
  5. data/lib/oklahoma_mixer.rb +7 -20
  6. data/lib/oklahoma_mixer/array_list.rb +21 -7
  7. data/lib/oklahoma_mixer/array_list/c.rb +9 -1
  8. data/lib/oklahoma_mixer/b_tree_database.rb +25 -9
  9. data/lib/oklahoma_mixer/b_tree_database/c.rb +5 -0
  10. data/lib/oklahoma_mixer/cursor.rb +3 -0
  11. data/lib/oklahoma_mixer/cursor/c.rb +2 -0
  12. data/lib/oklahoma_mixer/error.rb +2 -0
  13. data/lib/oklahoma_mixer/extensible_string.rb +4 -2
  14. data/lib/oklahoma_mixer/extensible_string/c.rb +2 -0
  15. data/lib/oklahoma_mixer/fixed_length_database.rb +11 -3
  16. data/lib/oklahoma_mixer/fixed_length_database/c.rb +2 -0
  17. data/lib/oklahoma_mixer/hash_database.rb +24 -7
  18. data/lib/oklahoma_mixer/hash_database/c.rb +2 -0
  19. data/lib/oklahoma_mixer/hash_map.rb +42 -0
  20. data/lib/oklahoma_mixer/hash_map/c.rb +27 -0
  21. data/lib/oklahoma_mixer/query.rb +73 -0
  22. data/lib/oklahoma_mixer/query/c.rb +51 -0
  23. data/lib/oklahoma_mixer/table_database.rb +402 -0
  24. data/lib/oklahoma_mixer/table_database/c.rb +104 -0
  25. data/lib/oklahoma_mixer/utilities.rb +26 -1
  26. data/test/{b_tree_binary_data_test.rb → b_tree_database/b_tree_binary_data_test.rb} +2 -2
  27. data/test/{b_tree_tuning_test.rb → b_tree_database/b_tree_tuning_test.rb} +2 -2
  28. data/test/{cursor_based_iteration_test.rb → b_tree_database/cursor_based_iteration_test.rb} +2 -2
  29. data/test/{duplicate_storage_test.rb → b_tree_database/duplicate_storage_test.rb} +18 -12
  30. data/test/{binary_data_test.rb → core_database/binary_data_test.rb} +2 -2
  31. data/test/{file_system_test.rb → core_database/file_system_test.rb} +0 -0
  32. data/test/{getting_and_setting_keys_test.rb → core_database/getting_and_setting_keys_test.rb} +31 -60
  33. data/test/{iteration_test.rb → core_database/iteration_test.rb} +2 -2
  34. data/test/{transactions_test.rb → core_database/transactions_test.rb} +0 -0
  35. data/test/core_database/tuning_test.rb +31 -0
  36. data/test/{fixed_length_tuning_test.rb → fixed_length_database/fixed_length_tuning_test.rb} +0 -0
  37. data/test/{getting_and_setting_by_id_test.rb → fixed_length_database/getting_and_setting_by_id_test.rb} +8 -0
  38. data/test/{shared_binary_data.rb → shared/binary_data_tests.rb} +1 -1
  39. data/test/{tuning_test.rb → shared/hash_tuning_tests.rb} +18 -42
  40. data/test/{shared_iteration.rb → shared/iteration_tests.rb} +8 -7
  41. data/test/{key_range_test.rb → shared/key_range_test.rb} +0 -0
  42. data/test/{order_test.rb → shared/order_test.rb} +0 -0
  43. data/test/shared/storage_tests.rb +65 -0
  44. data/test/{top_level_interface_test.rb → shared/top_level_interface_test.rb} +39 -2
  45. data/test/{shared_tuning.rb → shared/tuning_tests.rb} +1 -1
  46. data/test/table_database/document_iteration_test.rb +22 -0
  47. data/test/table_database/document_storage_test.rb +225 -0
  48. data/test/table_database/index_test.rb +57 -0
  49. data/test/table_database/query_test.rb +866 -0
  50. data/test/table_database/table_tuning_test.rb +56 -0
  51. data/test/test_helper.rb +27 -0
  52. 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
@@ -8,7 +8,7 @@ task :default => :test
8
8
 
9
9
  Rake::TestTask.new do |test|
10
10
  test.libs << "test"
11
- test.pattern = "test/*_test.rb"
11
+ test.pattern = "test/**/*_test.rb"
12
12
  test.warning = true
13
13
  test.verbose = true
14
14
  end
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 Table Databases
6
+ 1. Add support for Tokyo Tyrant
7
7
  2. Ensure Ruby 1.9 compatibility
8
8
  3. Write API documentation
9
- 4. Add support for Tokyo Tyrant
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
@@ -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.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(pointer = C.new)
4
- @pointer = 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
- include Enumerable
12
-
13
- def each
19
+ def map
20
+ values = [ ]
14
21
  while value = shift
15
- yield value
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
- def_new_and_del_funcs
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
- to_enum_int(options.fetch(:opts, 0xFF), :opt) )
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
- try(:putdup, cast_key_in(key), cast_value_in(value))
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.to_a
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.to_a
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
- break unless iterator.send(yield(*key_and_value) ? :delete : :next)
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
@@ -1,3 +1,6 @@
1
+ require "oklahoma_mixer/extensible_string"
2
+ require "oklahoma_mixer/cursor/c"
3
+
1
4
  module OklahomaMixer
2
5
  class Cursor # :nodoc:
3
6
  def initialize(b_tree_pointer, start = nil, reverse = false)
@@ -1,3 +1,5 @@
1
+ require "oklahoma_mixer/utilities"
2
+
1
3
  module OklahomaMixer
2
4
  class Cursor
3
5
  module C # :nodoc:
@@ -2,5 +2,7 @@ module OklahomaMixer
2
2
  module Error
3
3
  class TransactionError < RuntimeError; end
4
4
  class CabinetError < RuntimeError; end
5
+ class QueryError < RuntimeError; end
6
+ class IndexError < RuntimeError; end
5
7
  end
6
8
  end
@@ -1,7 +1,9 @@
1
+ require "oklahoma_mixer/extensible_string/c"
2
+
1
3
  module OklahomaMixer
2
4
  class ExtensibleString # :nodoc:
3
- def initialize(pointer = C.new)
4
- @pointer = pointer
5
+ def initialize
6
+ @pointer = C.new
5
7
  end
6
8
 
7
9
  attr_reader :pointer
@@ -1,3 +1,5 @@
1
+ require "oklahoma_mixer/utilities"
2
+
1
3
  module OklahomaMixer
2
4
  class ExtensibleString
3
5
  module C # :nodoc:
@@ -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
- C::IDS["FDBID#{key.to_s.upcase}".to_sym]
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,5 @@
1
+ require "oklahoma_mixer/utilities"
2
+
1
3
  module OklahomaMixer
2
4
  class FixedLengthDatabase < HashDatabase
3
5
  module C # :nodoc:
@@ -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, path, to_enum_int(options.fetch(:mode, mode || "wc"), :mode))
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
- to_enum_int(options.fetch(:opts, 0xFF), :opt) )
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.to_a
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 to_enum_int(str_or_int, name)
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