oklahoma_mixer 0.1.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/AUTHORS.rdoc +1 -0
- data/CHANGELOG.rdoc +7 -0
- data/INSTALL.rdoc +22 -0
- data/MIT-LICENSE +19 -0
- data/README.rdoc +48 -0
- data/Rakefile +61 -0
- data/TODO.rdoc +11 -0
- data/lib/oklahoma_mixer/array_list/c.rb +15 -0
- data/lib/oklahoma_mixer/array_list.rb +23 -0
- data/lib/oklahoma_mixer/error.rb +6 -0
- data/lib/oklahoma_mixer/extensible_string/c.rb +18 -0
- data/lib/oklahoma_mixer/extensible_string.rb +27 -0
- data/lib/oklahoma_mixer/hash_database/c.rb +128 -0
- data/lib/oklahoma_mixer/hash_database.rb +335 -0
- data/lib/oklahoma_mixer/utilities.rb +88 -0
- data/lib/oklahoma_mixer.rb +33 -0
- data/test/binary_data_test.rb +41 -0
- data/test/file_system_test.rb +74 -0
- data/test/getting_and_setting_keys_test.rb +218 -0
- data/test/iteration_test.rb +94 -0
- data/test/test_helper.rb +51 -0
- data/test/top_level_interface_test.rb +47 -0
- data/test/transactions_test.rb +66 -0
- data/test/tuning_test.rb +173 -0
- metadata +115 -0
data/AUTHORS.rdoc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<b>James Edward Gray II</b>:: {james@graysoftinc.com}[mailto:james@graysoftinc.com]
|
data/CHANGELOG.rdoc
ADDED
data/INSTALL.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= Installing Oklahoma Mixer
|
2
|
+
|
3
|
+
RubyGems is the preferred install method for Oklahoma Mixer.
|
4
|
+
|
5
|
+
== Installing the Gem
|
6
|
+
|
7
|
+
Oklahoma Mixer is intended to be installed via the
|
8
|
+
RubyGems[http://rubyforge.org/projects/rubygems/] system. To get the latest
|
9
|
+
version, simply enter the following into your command prompt:
|
10
|
+
|
11
|
+
$ sudo gem install oklahoma_mixer
|
12
|
+
|
13
|
+
You must have RubyGems[http://rubyforge.org/projects/rubygems/] installed for
|
14
|
+
the above to work.
|
15
|
+
|
16
|
+
== Running the Tests
|
17
|
+
|
18
|
+
If you would like to run Oklahoma Mixer's test suite on your system and you have
|
19
|
+
Rake installed, just issue the following command from the root of the project
|
20
|
+
directory:
|
21
|
+
|
22
|
+
$ rake
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 James Edward Gray II
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= What is Oklahoma Mixer?
|
2
|
+
|
3
|
+
Oklahoma Mixer is a Ruby FFI interface to the C library for Tokyo Cabinet. It allows you to use the key-value store from Ruby.
|
4
|
+
|
5
|
+
== Why not just use rufus-tokyo?
|
6
|
+
|
7
|
+
There is already a Ruby FFI interface to Tokyo Cabinet and more called {rufus-tokyo}[http://github.com/jmettraux/rufus-tokyo]. I am a huge fan of rufus-tokyo and have contributed to that project. I have learned a ton from working with rufus-tokyo and that code was my inspiration for this library.
|
8
|
+
|
9
|
+
That said, I did want to change some things that would require big changes in rufus-tokyo. Here are the things I plan to do differently with Oklahoma Mixer:
|
10
|
+
|
11
|
+
* Tokyo Cabinet's B+Tree Database has some neat features, like custom ordering
|
12
|
+
functions, that are hard to expose through rufus-tokyo due to the way it is
|
13
|
+
designed. I would have had to rewrite pretty much that entire section of the
|
14
|
+
library anyway to add these features.
|
15
|
+
* There are some places where rufus-tokyo uses more memory than it absolutely
|
16
|
+
must or slows itself down a bit with extra iterations of the data. Again,
|
17
|
+
this is a result of how it is designed. It allows more code reuse at the cost
|
18
|
+
of some efficiency. I wanted to improve performance in those areas.
|
19
|
+
* I'm working on some higher level abstractions for Tokyo Cabinet that I
|
20
|
+
eventually plan to include in this library. These extra tools are the reason
|
21
|
+
I needed to make these changes and additions.
|
22
|
+
* Finally, rufus-tokyo paved the way to a Ruby-like interface for Tokyo Cabinet.
|
23
|
+
Previous choices were scary in comparison. I wanted to push that movement
|
24
|
+
even further though and get an even more Hash- and File-like interface, where
|
25
|
+
possible.
|
26
|
+
|
27
|
+
It's important to note though that rufus-tokyo does do some things better and it always will. Its advantages are:
|
28
|
+
|
29
|
+
* It offers a nice Ruby interface over a raw C extension which is faster than
|
30
|
+
using FFI. I have no intention of duplicating that interface, so rufus-tokyo
|
31
|
+
will remain the right choice for raw speed when using MRI.
|
32
|
+
* For now, rufus-tokyo is more full featured. It provides interfaces for Tokyo
|
33
|
+
Tyrant and Tokyo Dystopia. I would like to add these eventually, but I'm
|
34
|
+
starting with just Tokyo Cabinet.
|
35
|
+
* It offers a pure Ruby interface for communicating with Tokyo Tyrant without
|
36
|
+
needing the C libraries installed. I won't be copying that either, so it will
|
37
|
+
remain the right choice for a no dependency install.
|
38
|
+
* For now, it's more mature. A lot of developers have used it and contributed
|
39
|
+
to it. It's probably the safer library to trust for production applications
|
40
|
+
at this time.
|
41
|
+
|
42
|
+
== Why did you call it Oklahoma Mixer?
|
43
|
+
|
44
|
+
When I was in Japan, people would ask where I was from. When I would tell them, "Oklahoma, U.S.A.," they often replied with, "Ah, I know the Oklahoma Mixer." Some would even dance a little when they said it.
|
45
|
+
|
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
|
+
|
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.
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require "rubygems"
|
4
|
+
require "rake/gempackagetask"
|
5
|
+
|
6
|
+
desc "Default task: run all tests"
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
Rake::TestTask.new do |test|
|
10
|
+
test.libs << "test"
|
11
|
+
test.pattern = "test/*_test.rb"
|
12
|
+
test.warning = true
|
13
|
+
test.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
Rake::RDocTask.new do |rdoc|
|
17
|
+
rdoc.main = "README.rdoc"
|
18
|
+
rdoc.rdoc_dir = "doc/html"
|
19
|
+
rdoc.title = "Oklahoma Mixer Documentation"
|
20
|
+
rdoc.rdoc_files.include *%w[ README.rdoc INSTALL.rdoc
|
21
|
+
TODO.rdoc CHANGELOG.rdoc
|
22
|
+
AUTHORS.rdoc MIT-LICENSE
|
23
|
+
lib/ ]
|
24
|
+
end
|
25
|
+
|
26
|
+
spec = Gem::Specification.new do |spec|
|
27
|
+
spec.name = "oklahoma_mixer"
|
28
|
+
spec.version = File.read(
|
29
|
+
File.join(File.dirname(__FILE__), *%w[lib oklahoma_mixer.rb])
|
30
|
+
)[/^\s*VERSION\s*=\s*(['"])(\d\.\d\.\d)\1/, 2]
|
31
|
+
|
32
|
+
spec.platform = Gem::Platform::RUBY
|
33
|
+
spec.summary = "An full featured and robust FFI interface to Tokyo Cabinet."
|
34
|
+
|
35
|
+
spec.test_files = Dir.glob("test/*_test.rb")
|
36
|
+
spec.files = Dir.glob("{lib,test}/**/*.rb") +
|
37
|
+
Dir.glob("*.rdoc") +
|
38
|
+
%w[MIT-LICENSE Rakefile]
|
39
|
+
|
40
|
+
spec.has_rdoc = true
|
41
|
+
spec.extra_rdoc_files = %w[ README.rdoc INSTALL.rdoc
|
42
|
+
TODO.rdoc CHANGELOG.rdoc
|
43
|
+
AUTHORS.rdoc MIT-LICENSE ]
|
44
|
+
spec.rdoc_options << "--title" << "Oklahoma Mixer Documentation" <<
|
45
|
+
"--main" << "README.rdoc"
|
46
|
+
|
47
|
+
spec.add_dependency("ffi", ">= 0.5.4")
|
48
|
+
spec.add_development_dependency("rake")
|
49
|
+
|
50
|
+
spec.author = "James Edward Gray II"
|
51
|
+
spec.email = "james@graysoftinc.com"
|
52
|
+
spec.homepage = "http://github.com/JEG2/oklahoma_mixer"
|
53
|
+
spec.description = <<END_DESC
|
54
|
+
Oklahoma Mixer is a intended to be an all inclusive wrapper for Tokyo Cabinet.
|
55
|
+
It provides Rubyish interfaces for all database types and supports the full
|
56
|
+
range of features provided.
|
57
|
+
END_DESC
|
58
|
+
end
|
59
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
60
|
+
# do nothing: the spec is all we need
|
61
|
+
end
|
data/TODO.rdoc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
= To Do List
|
2
|
+
|
3
|
+
The following is a list of planned expansions for Oklahoma Mixer in the order I
|
4
|
+
intend to address them.
|
5
|
+
|
6
|
+
1. Add support for B+Tree and Fixed-length Databases
|
7
|
+
2. Add support for Table Databases
|
8
|
+
3. Ensure Ruby 1.9 compatibility
|
9
|
+
4. Add support for Tokyo Tyrant
|
10
|
+
5. Add support for Tokyo Dystopia
|
11
|
+
6. Include some higher level abstractions like mixed tables, queues, and shards
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OklahomaMixer
|
2
|
+
class ArrayList
|
3
|
+
module C # :nodoc:
|
4
|
+
extend OklahomaMixer::Utilities::FFIDSL
|
5
|
+
|
6
|
+
prefix :tclist
|
7
|
+
|
8
|
+
def_new_and_del_funcs
|
9
|
+
|
10
|
+
func :name => :shift,
|
11
|
+
:args => [:pointer, :pointer],
|
12
|
+
:returns => :pointer
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OklahomaMixer
|
2
|
+
class ArrayList # :nodoc:
|
3
|
+
def initialize(pointer = C.new)
|
4
|
+
@pointer = pointer
|
5
|
+
end
|
6
|
+
|
7
|
+
def shift
|
8
|
+
C.read_from_func(:shift, @pointer)
|
9
|
+
end
|
10
|
+
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
def each
|
14
|
+
while value = shift
|
15
|
+
yield value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def free
|
20
|
+
C.del(@pointer)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module OklahomaMixer
|
2
|
+
class ExtensibleString
|
3
|
+
module C # :nodoc:
|
4
|
+
extend OklahomaMixer::Utilities::FFIDSL
|
5
|
+
|
6
|
+
prefix :tcxstr
|
7
|
+
|
8
|
+
def_new_and_del_funcs
|
9
|
+
|
10
|
+
func :name => :ptr,
|
11
|
+
:args => :pointer,
|
12
|
+
:returns => :pointer
|
13
|
+
func :name => :size,
|
14
|
+
:args => :pointer,
|
15
|
+
:returns => :int
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module OklahomaMixer
|
2
|
+
class ExtensibleString # :nodoc:
|
3
|
+
def initialize(pointer = C.new)
|
4
|
+
@pointer = pointer
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :pointer
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
data_pointer.get_bytes(0, data_size)
|
11
|
+
end
|
12
|
+
|
13
|
+
def free
|
14
|
+
C.del(@pointer)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def data_pointer
|
20
|
+
C.ptr(@pointer)
|
21
|
+
end
|
22
|
+
|
23
|
+
def data_size
|
24
|
+
C.size(@pointer)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module OklahomaMixer
|
2
|
+
class HashDatabase
|
3
|
+
module C # :nodoc:
|
4
|
+
extend OklahomaMixer::Utilities::FFIDSL
|
5
|
+
|
6
|
+
MODES = enum :HDBOREADER, 1 << 0,
|
7
|
+
:HDBOWRITER, 1 << 1,
|
8
|
+
:HDBOCREAT, 1 << 2,
|
9
|
+
:HDBOTRUNC, 1 << 3,
|
10
|
+
:HDBONOLCK, 1 << 4,
|
11
|
+
:HDBOLCKNB, 1 << 5,
|
12
|
+
:HDBOTSYNC, 1 << 6
|
13
|
+
OPTS = enum :HDBTLARGE, 1 << 0,
|
14
|
+
:HDBTDEFLATE, 1 << 1,
|
15
|
+
:HDBTBZIP, 1 << 2,
|
16
|
+
:HDBTTCBS, 1 << 3
|
17
|
+
|
18
|
+
prefix :tchdb
|
19
|
+
|
20
|
+
def_new_and_del_funcs
|
21
|
+
func :name => :open,
|
22
|
+
:args => [:pointer, :string, MODES],
|
23
|
+
:returns => :bool
|
24
|
+
func :name => :sync,
|
25
|
+
:args => :pointer,
|
26
|
+
:returns => :bool
|
27
|
+
func :name => :fsiz,
|
28
|
+
:args => :pointer,
|
29
|
+
:returns => :uint64
|
30
|
+
func :name => :copy,
|
31
|
+
:args => [:pointer, :string],
|
32
|
+
:returns => :bool
|
33
|
+
func :name => :defrag,
|
34
|
+
:args => [:pointer, :int64],
|
35
|
+
:returns => :bool
|
36
|
+
|
37
|
+
func :name => :ecode,
|
38
|
+
:args => :pointer,
|
39
|
+
:returns => :int
|
40
|
+
func :name => :errmsg,
|
41
|
+
:args => :int,
|
42
|
+
:returns => :string
|
43
|
+
|
44
|
+
func :name => :setmutex,
|
45
|
+
:args => :pointer,
|
46
|
+
:returns => :bool
|
47
|
+
func :name => :tune,
|
48
|
+
:args => [:pointer, :int64, :int8, :int8, OPTS],
|
49
|
+
:returns => :bool
|
50
|
+
func :name => :setcache,
|
51
|
+
:args => [:pointer, :int32],
|
52
|
+
:returns => :bool
|
53
|
+
func :name => :setxmsiz,
|
54
|
+
:args => [:pointer, :int64],
|
55
|
+
:returns => :bool
|
56
|
+
func :name => :setdfunit,
|
57
|
+
:args => [:pointer, :int32],
|
58
|
+
:returns => :bool
|
59
|
+
func :name => :optimize,
|
60
|
+
:args => [:pointer, :int64, :int8, :int8, OPTS],
|
61
|
+
:returns => :bool
|
62
|
+
|
63
|
+
func :name => :put,
|
64
|
+
:args => [:pointer, :pointer, :int, :pointer, :int],
|
65
|
+
:returns => :bool
|
66
|
+
func :name => :putkeep,
|
67
|
+
:args => [:pointer, :pointer, :int, :pointer, :int],
|
68
|
+
:returns => :bool
|
69
|
+
func :name => :putcat,
|
70
|
+
:args => [:pointer, :pointer, :int, :pointer, :int],
|
71
|
+
:returns => :bool
|
72
|
+
func :name => :putasync,
|
73
|
+
:args => [:pointer, :pointer, :int, :pointer, :int],
|
74
|
+
:returns => :bool
|
75
|
+
call :name => :TCPDPROC,
|
76
|
+
:args => [:pointer, :int, :pointer, :pointer],
|
77
|
+
:returns => :pointer
|
78
|
+
func :name => :putproc,
|
79
|
+
:args => [:pointer, :pointer, :int, :pointer, :int, :TCPDPROC,
|
80
|
+
:pointer],
|
81
|
+
:returns => :bool
|
82
|
+
func :name => :addint,
|
83
|
+
:args => [:pointer, :pointer, :int, :int],
|
84
|
+
:returns => :int
|
85
|
+
func :name => :adddouble,
|
86
|
+
:args => [:pointer, :pointer, :int, :double],
|
87
|
+
:returns => :double
|
88
|
+
func :name => :out,
|
89
|
+
:args => [:pointer, :pointer, :int],
|
90
|
+
:returns => :bool
|
91
|
+
func :name => :get,
|
92
|
+
:args => [:pointer, :pointer, :int, :pointer],
|
93
|
+
:returns => :pointer
|
94
|
+
func :name => :vanish,
|
95
|
+
:args => :pointer,
|
96
|
+
:returns => :bool
|
97
|
+
func :name => :vanish,
|
98
|
+
:args => :pointer,
|
99
|
+
:returns => :bool
|
100
|
+
func :name => :fwmkeys,
|
101
|
+
:args => [:pointer, :pointer, :int, :int],
|
102
|
+
:returns => :pointer
|
103
|
+
func :name => :rnum,
|
104
|
+
:args => :pointer,
|
105
|
+
:returns => :uint64
|
106
|
+
|
107
|
+
func :name => :iterinit,
|
108
|
+
:args => [:pointer],
|
109
|
+
:returns => :bool
|
110
|
+
func :name => :iternext,
|
111
|
+
:args => [:pointer, :pointer],
|
112
|
+
:returns => :pointer
|
113
|
+
func :name => :iternext3,
|
114
|
+
:args => [:pointer, :pointer, :pointer],
|
115
|
+
:returns => :bool
|
116
|
+
|
117
|
+
func :name => :tranbegin,
|
118
|
+
:args => :pointer,
|
119
|
+
:returns => :bool
|
120
|
+
func :name => :trancommit,
|
121
|
+
:args => :pointer,
|
122
|
+
:returns => :bool
|
123
|
+
func :name => :tranabort,
|
124
|
+
:args => :pointer,
|
125
|
+
:returns => :bool
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|