oklahoma_mixer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|