ruby-tokyotyrant 0.4 → 0.5
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/README.rdoc +23 -3
- data/Rakefile +3 -5
- data/benchmarks/bulk_db.rb +23 -0
- data/benchmarks/bulk_table.rb +51 -3
- data/benchmarks/db.rb +61 -22
- data/benchmarks/table.rb +62 -20
- data/ext/tokyo_tyrant.c +75 -3
- data/ext/tokyo_tyrant.h +18 -3
- data/{lib → ext}/tokyo_tyrant/balancer.rb +3 -6
- data/ext/tokyo_tyrant/rails/tokyo_tyrant_store.rb +106 -0
- data/ext/tokyo_tyrant_bdb.c +138 -0
- data/ext/tokyo_tyrant_bdb.h +8 -0
- data/ext/tokyo_tyrant_consistent_hash.c +34 -0
- data/ext/tokyo_tyrant_consistent_hash.h +8 -0
- data/ext/tokyo_tyrant_db.c +3 -3
- data/ext/tokyo_tyrant_module.c +75 -24
- data/ext/tokyo_tyrant_module.h +1 -1
- data/ext/tokyo_tyrant_table.c +2 -2
- data/spec/spec_base.rb +1 -1
- data/spec/start_tyrants.sh +7 -0
- data/spec/stop_tyrants.sh +2 -1
- data/spec/tokyo_tyrant_bdb_spec.rb +34 -0
- data/spec/tokyo_tyrant_spec.rb +10 -0
- metadata +20 -19
- data/ext/tokyo_utils.c +0 -362
- data/ext/tokyo_utils.h +0 -8
data/README.rdoc
CHANGED
@@ -6,9 +6,7 @@ This is a c extension for Ruby to access TokyoTyrant databases. It currently su
|
|
6
6
|
|
7
7
|
# install tokyocabinet (1.4.34) and tokyotyrant (requires 1.1.35)
|
8
8
|
# after installing tc and tt on linux I had to /sbin/ldconfig (as root)
|
9
|
-
sudo gem install gemcutter
|
10
|
-
sudo gem tumble
|
11
|
-
sudo gem install ruby-tokyotyrant
|
9
|
+
sudo gem install ruby-tokyotyrant --source=http://gemcutter.org
|
12
10
|
|
13
11
|
== Performance
|
14
12
|
|
@@ -39,6 +37,28 @@ This is not in production but the initial benchmarks are very interesting. Resul
|
|
39
37
|
db.mput("1"=>"number_1", "2"=>"number_2", "3"=>"number_3", "4"=>"number_4", "5"=>"number_5")
|
40
38
|
db.mget(1..3) # => {"1"=>"number_1", "2"=>"number_2", "3"=>"number_3"}
|
41
39
|
|
40
|
+
=== B+ Tree DB
|
41
|
+
|
42
|
+
# start tyrant like so:
|
43
|
+
# ttserver example.tcb
|
44
|
+
|
45
|
+
require 'tokyo_tyrant'
|
46
|
+
bdb = TokyoTyrant::BDB.new('127.0.0.1', 1978)
|
47
|
+
|
48
|
+
bdb.putdup('foo', 'bar')
|
49
|
+
# => true
|
50
|
+
|
51
|
+
bdb.putlist({ 'foo' => ['baz', 'bat']})
|
52
|
+
# => []
|
53
|
+
|
54
|
+
bdb.getlist('foo')
|
55
|
+
# => {"foo"=>["bar", "baz", "bat"]}
|
56
|
+
|
57
|
+
bdb.each{ |k,v| puts [k, v].inspect }
|
58
|
+
# ["foo", "bar"]
|
59
|
+
# ["foo", "baz"]
|
60
|
+
# ["foo", "bat"]
|
61
|
+
|
42
62
|
=== Table DB
|
43
63
|
|
44
64
|
# start tyrant like so:
|
data/Rakefile
CHANGED
@@ -20,7 +20,7 @@ CLEAN.include('pkg', 'tmp')
|
|
20
20
|
|
21
21
|
gemspec = Gem::Specification.new do |s|
|
22
22
|
s.name = 'ruby-tokyotyrant'
|
23
|
-
s.version = '0.
|
23
|
+
s.version = '0.5'
|
24
24
|
s.authors = [ 'Flinn' ]
|
25
25
|
s.email = 'flinn@actsasflinn.com'
|
26
26
|
s.homepage = 'http://github.com/actsasflinn/ruby-tokyotyrant/'
|
@@ -35,12 +35,10 @@ gemspec = Gem::Specification.new do |s|
|
|
35
35
|
'Rakefile',
|
36
36
|
'README.rdoc'] +
|
37
37
|
Dir['ext/**/*.[rb|c|h]'] +
|
38
|
-
Dir['
|
38
|
+
Dir['ext/tokyo_tyrant/**/*.rb'] +
|
39
39
|
Dir['spec/**/*'] +
|
40
40
|
Dir['benchmarks/**/*']
|
41
41
|
s.extensions << "ext/extconf.rb"
|
42
|
-
|
43
|
-
s.add_runtime_dependency('fast_hash_ring', '>= 0.1.1')
|
44
42
|
end
|
45
43
|
|
46
44
|
task :gemspec do
|
@@ -53,7 +51,7 @@ Rake::GemPackageTask.new(gemspec) do |pkg|
|
|
53
51
|
pkg.need_tar = true
|
54
52
|
end
|
55
53
|
|
56
|
-
Rake::PackageTask.new('ruby-tokyotyrant', '0.
|
54
|
+
Rake::PackageTask.new('ruby-tokyotyrant', '0.5') do |pkg|
|
57
55
|
pkg.need_zip = true
|
58
56
|
pkg.package_files = FileList[
|
59
57
|
'COPYING',
|
data/benchmarks/bulk_db.rb
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
=begin
|
2
|
+
Tokyo Tyrant Bulk Operations Benchmark
|
3
|
+
|
4
|
+
|
5
|
+
TokyoTyrant::RDB (Ruby) mget
|
6
|
+
user system total real
|
7
|
+
inserting data 7.770000 1.870000 9.640000 ( 12.598373)
|
8
|
+
reading data 1.540000 0.250000 1.790000 ( 2.290628)
|
9
|
+
|
10
|
+
|
11
|
+
TokyoTyrant (c) mput/mget
|
12
|
+
user system total real
|
13
|
+
inserting data 0.020000 0.000000 0.020000 ( 0.037996)
|
14
|
+
reading data 0.060000 0.010000 0.070000 ( 0.120651)
|
15
|
+
|
16
|
+
|
17
|
+
Memcached (C) set/get_multi
|
18
|
+
user system total real
|
19
|
+
inserting data* 0.160000 0.140000 0.300000 ( 0.884097)
|
20
|
+
reading data 0.090000 0.000000 0.090000 ( 0.140217)
|
21
|
+
* bulk operation not supported
|
22
|
+
=end
|
23
|
+
|
1
24
|
require 'benchmark'
|
2
25
|
require 'rubygems'
|
3
26
|
require 'faker'
|
data/benchmarks/bulk_table.rb
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
=begin
|
2
|
+
Tokyo Tyrant Bulk Table Operations Benchmark
|
3
|
+
|
4
|
+
|
5
|
+
TokyoTyrant (C)
|
6
|
+
user system total real
|
7
|
+
bulk writing data 0.180000 0.000000 0.180000 ( 0.292081)
|
8
|
+
bulk reading data 0.120000 0.020000 0.140000 ( 0.216074)
|
9
|
+
|
10
|
+
|
11
|
+
TokyoTyrant::RDB (Ruby)
|
12
|
+
user system total real
|
13
|
+
bulk inserting data* 42.410000 4.130000 46.540000 ( 63.657929)
|
14
|
+
bulk reading data 2.360000 0.280000 2.640000 ( 3.709915)
|
15
|
+
|
16
|
+
|
17
|
+
Mongo
|
18
|
+
user system total real
|
19
|
+
bulk writing data 27.860000 0.470000 28.330000 ( 37.619586)
|
20
|
+
bulk reading data 0.650000 0.100000 0.750000 ( 1.371567)
|
21
|
+
|
22
|
+
Notes:
|
23
|
+
* To supply a hash for bulk operations TokyoTyrant::RDB creates an array and join hash columns.
|
24
|
+
* This operation is included in the benchmark because the same code exists within the c-ext.
|
25
|
+
Rufus::Tokyo::TyrantTable does not support the misc method, therefor cannot handle a putlist/getlist
|
26
|
+
Memcached does not support bulk writing
|
27
|
+
=end
|
28
|
+
|
1
29
|
require 'benchmark'
|
2
30
|
require 'rubygems'
|
3
31
|
require 'faker'
|
@@ -10,7 +38,7 @@ $month = (1..12).to_a
|
|
10
38
|
$day = (1..28).to_a # not bothering with month diffs
|
11
39
|
|
12
40
|
def rbdate
|
13
|
-
|
41
|
+
Date.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
|
14
42
|
end
|
15
43
|
|
16
44
|
def rdiv
|
@@ -30,9 +58,12 @@ end
|
|
30
58
|
|
31
59
|
data = {}
|
32
60
|
10_000.times do |i|
|
33
|
-
data[i] = { :name => Faker::Name.name, :sex => rgen, :birthday => rbdate.to_s, :divisions => rdiv }
|
61
|
+
data[i.to_s] = { :_id => i.to_s, :name => Faker::Name.name, :sex => rgen, :birthday => rbdate.to_s, :divisions => rdiv }
|
34
62
|
end
|
35
63
|
|
64
|
+
data_keys = data.keys
|
65
|
+
data_values = data.values
|
66
|
+
|
36
67
|
require 'tokyo_tyrant'
|
37
68
|
t = TokyoTyrant::Table.new('127.0.0.1', 45001)
|
38
69
|
t.clear
|
@@ -46,7 +77,7 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
46
77
|
end
|
47
78
|
|
48
79
|
b.report('bulk reading data') do
|
49
|
-
nothing = t.mget(
|
80
|
+
nothing = t.mget(data_keys)
|
50
81
|
end
|
51
82
|
end
|
52
83
|
|
@@ -80,6 +111,23 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
80
111
|
end
|
81
112
|
end
|
82
113
|
|
114
|
+
require 'mongo'
|
115
|
+
db = Mongo::Connection.new.db("benchmark")
|
116
|
+
2.times { puts }
|
117
|
+
puts 'Mongo'
|
118
|
+
mdb = db["data"]
|
119
|
+
mdb.remove
|
120
|
+
|
121
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
122
|
+
b.report('bulk writing data') do
|
123
|
+
nothing = mdb.insert(data_values)
|
124
|
+
end
|
125
|
+
|
126
|
+
b.report('bulk reading data') do
|
127
|
+
nothing = mdb.find(:_id => {'$in' => data_keys}).to_a
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
83
131
|
puts "\nNotes:"
|
84
132
|
puts "* To supply a hash for bulk operations TokyoTyrant::RDB creates an array and join hash columns."
|
85
133
|
puts "* This operation is included in the benchmark because the same code exists within the c-ext."
|
data/benchmarks/db.rb
CHANGED
@@ -1,14 +1,56 @@
|
|
1
|
+
=begin
|
2
|
+
Tokyo::Tyrant (Ruby FFI)
|
3
|
+
user system total real
|
4
|
+
inserting data 0.140000 0.180000 0.320000 ( 1.208150)
|
5
|
+
reading data 0.240000 0.170000 0.410000 ( 1.467640)
|
6
|
+
|
7
|
+
|
8
|
+
TokyoTyrant::RDB (Ruby)
|
9
|
+
user system total real
|
10
|
+
inserting data 0.300000 0.170000 0.470000 ( 1.481900)
|
11
|
+
reading data 0.410000 0.210000 0.620000 ( 1.705723)
|
12
|
+
|
13
|
+
|
14
|
+
TokyoTyrant (C)
|
15
|
+
user system total real
|
16
|
+
inserting data 0.130000 0.170000 0.300000 ( 1.251842)
|
17
|
+
reading data 0.120000 0.160000 0.280000 ( 1.539256)
|
18
|
+
|
19
|
+
|
20
|
+
Memcached (C) to Tyrant
|
21
|
+
user system total real
|
22
|
+
inserting data 0.200000 0.150000 0.350000 ( 1.814691)
|
23
|
+
reading data 0.180000 0.160000 0.340000 ( 1.358712)
|
24
|
+
|
25
|
+
|
26
|
+
Memcached (C) to Memcached
|
27
|
+
user system total real
|
28
|
+
inserting data 0.190000 0.140000 0.330000 ( 1.022183)
|
29
|
+
reading data 0.160000 0.140000 0.300000 ( 0.908084)
|
30
|
+
|
31
|
+
|
32
|
+
MemCache (Ruby)
|
33
|
+
user system total real
|
34
|
+
inserting data 1.200000 0.210000 1.410000 ( 2.329328)
|
35
|
+
reading data 1.510000 0.220000 1.730000 ( 2.721509)
|
36
|
+
|
37
|
+
|
38
|
+
Voldemort (Ruby)
|
39
|
+
user system total real
|
40
|
+
inserting data 18.290000 1.050000 19.340000 ( 37.562370)
|
41
|
+
reading data 9.040000 0.530000 9.570000 ( 15.145843)
|
42
|
+
=end
|
43
|
+
|
1
44
|
require 'benchmark'
|
2
45
|
require 'rubygems'
|
3
46
|
require 'faker'
|
4
47
|
|
5
48
|
data = []
|
6
49
|
|
7
|
-
|
50
|
+
10_000.times do |i|
|
8
51
|
data << Faker::Name.name
|
9
52
|
end
|
10
53
|
|
11
|
-
=begin
|
12
54
|
require 'rufus/tokyo/tyrant'
|
13
55
|
|
14
56
|
r = Rufus::Tokyo::Tyrant.new('127.0.0.1', 45000)
|
@@ -45,10 +87,9 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
45
87
|
data.each_with_index { |e, i| nothing = rdb.get(i.to_s) }
|
46
88
|
end
|
47
89
|
end
|
48
|
-
=end
|
49
90
|
|
50
91
|
require 'tokyo_tyrant'
|
51
|
-
t = TokyoTyrant::DB.new('127.0.0.1',
|
92
|
+
t = TokyoTyrant::DB.new('127.0.0.1', 45000)
|
52
93
|
t.clear
|
53
94
|
|
54
95
|
2.times { puts }
|
@@ -64,23 +105,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
64
105
|
end
|
65
106
|
end
|
66
107
|
|
67
|
-
m = TokyoTyrant::MDB.new
|
68
|
-
m.clear
|
69
|
-
|
70
|
-
2.times { puts }
|
71
|
-
puts 'MDB'
|
72
|
-
|
73
|
-
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
74
|
-
b.report('inserting data') do
|
75
|
-
data.each_with_index { |e, i| m[i] = e }
|
76
|
-
end
|
77
|
-
|
78
|
-
b.report('reading data') do
|
79
|
-
data.each_with_index { |e, i| nothing = m[i] }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
=begin
|
84
108
|
require 'memcached'
|
85
109
|
m = Memcached.new('127.0.0.1:45000')
|
86
110
|
m.flush
|
@@ -131,4 +155,19 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
131
155
|
data.each_with_index { |e, i| nothing = mc.get(i.to_s) }
|
132
156
|
end
|
133
157
|
end
|
134
|
-
|
158
|
+
|
159
|
+
require 'voldemort-rb'
|
160
|
+
vdb = VoldemortClient.new("test", "localhost:6666")
|
161
|
+
2.times { puts }
|
162
|
+
puts 'Voldemort (Ruby)'
|
163
|
+
|
164
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
165
|
+
b.report('inserting data') do
|
166
|
+
data.each_with_index { |e, i| vdb.put(i.to_s, e) }
|
167
|
+
end
|
168
|
+
|
169
|
+
b.report('reading data') do
|
170
|
+
data.each_with_index { |e, i| nothing = vdb.get(i.to_s) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
data/benchmarks/table.rb
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
=begin
|
2
|
+
Tokyo::TyrantTable (Ruby FFI)
|
3
|
+
user system total real
|
4
|
+
inserting data 0.840000 0.190000 1.030000 ( 3.214565)
|
5
|
+
reading data 1.310000 0.210000 1.520000 ( 3.024142)
|
6
|
+
|
7
|
+
|
8
|
+
TokyoTyrant::RDB (Ruby)
|
9
|
+
user system total real
|
10
|
+
inserting data 1.170000 0.240000 1.410000 ( 2.859321)
|
11
|
+
reading data 2.250000 0.660000 2.910000 ( 4.752291)
|
12
|
+
|
13
|
+
|
14
|
+
TokyoTyrant (C)
|
15
|
+
user system total real
|
16
|
+
inserting data 0.260000 0.180000 0.440000 ( 1.637843)
|
17
|
+
reading data 0.300000 0.170000 0.470000 ( 1.631104)
|
18
|
+
|
19
|
+
|
20
|
+
Memcached (C)
|
21
|
+
user system total real
|
22
|
+
inserting data 0.300000 0.160000 0.460000 ( 1.230830)
|
23
|
+
reading data 0.310000 0.140000 0.450000 ( 1.171531)
|
24
|
+
|
25
|
+
|
26
|
+
MemCache (Ruby)
|
27
|
+
user system total real
|
28
|
+
inserting data 2.080000 0.220000 2.300000 ( 3.379047)
|
29
|
+
reading data 2.220000 0.200000 2.420000 ( 4.018160)
|
30
|
+
|
31
|
+
|
32
|
+
Mongo
|
33
|
+
user system total real
|
34
|
+
inserting data 1.590000 0.130000 1.720000 ( 2.310027)
|
35
|
+
reading data 4.220000 0.380000 4.600000 ( 7.178335)
|
36
|
+
=end
|
37
|
+
|
1
38
|
require 'benchmark'
|
2
39
|
require 'rubygems'
|
3
40
|
require 'faker'
|
@@ -7,14 +44,14 @@ require 'date'
|
|
7
44
|
# the data
|
8
45
|
#
|
9
46
|
|
10
|
-
colnames = %w{ name sex birthday divisions }
|
47
|
+
colnames = %w{ _id name sex birthday divisions }
|
11
48
|
|
12
49
|
$year = (1909 .. 2009).to_a
|
13
50
|
$month = (1..12).to_a
|
14
51
|
$day = (1..28).to_a # not bothering with month diffs
|
15
52
|
|
16
53
|
def rbdate
|
17
|
-
|
54
|
+
Date.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
|
18
55
|
end
|
19
56
|
|
20
57
|
def rdiv
|
@@ -31,16 +68,16 @@ end
|
|
31
68
|
def rgen
|
32
69
|
(rand(2) == 1 ? 'male' : 'female')
|
33
70
|
end
|
34
|
-
|
71
|
+
|
35
72
|
data = [
|
36
|
-
[ 'Alphonse Armalite', 'male',
|
37
|
-
[ 'Brutus Beromunster', 'male',
|
38
|
-
[ 'Crystel Chucknorris', 'female',
|
39
|
-
[ 'Desree Dylan', 'female',
|
73
|
+
['alphonse-armalite', 'Alphonse Armalite', 'male', Date.new(1972, 10, 14).to_s, 'brd,dev'],
|
74
|
+
['brutus-beromunster', 'Brutus Beromunster', 'male', Date.new(1964, 07, 14).to_s, 'dev'],
|
75
|
+
['crystel-chucknorris', 'Crystel Chucknorris', 'female', Date.new(1980, 07, 12).to_s, 'brd'],
|
76
|
+
['desree-dylan', 'Desree Dylan', 'female', Date.new(1954, 07, 13).to_s, 'brd,dev']
|
40
77
|
]
|
41
78
|
|
42
79
|
10_000.times do |i|
|
43
|
-
data << [ Faker::Name.name, rgen, rbdate, rdiv]
|
80
|
+
data << [i.to_s, Faker::Name.name, rgen, rbdate.to_s, rdiv]
|
44
81
|
end
|
45
82
|
|
46
83
|
$find_name_list = []
|
@@ -112,14 +149,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
112
149
|
b.report('reading data') do
|
113
150
|
data1.each_with_index { |e, i| nothing = t[i] }
|
114
151
|
end
|
115
|
-
|
116
|
-
b.report('bulk writing data') do
|
117
|
-
nothing = t.mput(data_h)
|
118
|
-
end
|
119
|
-
|
120
|
-
b.report('bulk reading data') do
|
121
|
-
nothing = t.mget(0..9999)
|
122
|
-
end
|
123
152
|
end
|
124
153
|
|
125
154
|
require 'memcached'
|
@@ -137,10 +166,6 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
137
166
|
b.report('reading data') do
|
138
167
|
data1.each_with_index { |e, i| nothing = m.get(i.to_s) }
|
139
168
|
end
|
140
|
-
|
141
|
-
b.report('bulk reading data') do
|
142
|
-
nothing = m.get((0..9999).to_a.collect{|i| i.to_s})
|
143
|
-
end
|
144
169
|
end
|
145
170
|
|
146
171
|
require 'memcache'
|
@@ -159,3 +184,20 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
|
159
184
|
data1.each_with_index { |e, i| nothing = mc.get(i.to_s) }
|
160
185
|
end
|
161
186
|
end
|
187
|
+
|
188
|
+
require 'mongo'
|
189
|
+
db = Mongo::Connection.new.db("benchmark")
|
190
|
+
2.times { puts }
|
191
|
+
puts 'Mongo'
|
192
|
+
mdb = db["data"]
|
193
|
+
mdb.remove
|
194
|
+
|
195
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
196
|
+
b.report('inserting data') do
|
197
|
+
data1.each_with_index { |e, i| mdb.insert(e) }
|
198
|
+
end
|
199
|
+
|
200
|
+
b.report('reading data') do
|
201
|
+
data1.each_with_index { |e, i| nothing = mdb.find_one({ "_id" => i.to_s }) }
|
202
|
+
end
|
203
|
+
end
|
data/ext/tokyo_tyrant.c
CHANGED
@@ -123,22 +123,94 @@ extern TCLIST *vhashtolist(VALUE vhash){
|
|
123
123
|
return list;
|
124
124
|
}
|
125
125
|
|
126
|
+
extern TCLIST *vhashtoputlist(VALUE vhash){
|
127
|
+
VALUE vkey, vval, vkeys, vvals;
|
128
|
+
TCLIST *list;
|
129
|
+
int i, j;
|
130
|
+
vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
|
131
|
+
list = tclistnew();
|
132
|
+
for(i = 0; i < RARRAY_LEN(vkeys); i++){
|
133
|
+
vkey = rb_ary_entry(vkeys, i);
|
134
|
+
vkey = StringValueEx(vkey);
|
135
|
+
|
136
|
+
vvals = rb_hash_aref(vhash, vkey);
|
137
|
+
if (TYPE(vvals) == T_ARRAY){
|
138
|
+
for(j = 0; j < RARRAY_LEN(vvals); j++){
|
139
|
+
vval = rb_ary_entry(vvals, j);
|
140
|
+
vval = StringValueEx(vval);
|
141
|
+
tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
|
142
|
+
tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
|
143
|
+
}
|
144
|
+
} else {
|
145
|
+
vval = StringValueEx(vvals);
|
146
|
+
tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
|
147
|
+
tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
|
148
|
+
}
|
149
|
+
}
|
150
|
+
return list;
|
151
|
+
}
|
152
|
+
|
153
|
+
extern VALUE listtovhash(TCLIST *list){
|
154
|
+
VALUE vhash, vkey, vval, vvals;
|
155
|
+
const char *key, *val;
|
156
|
+
int i, num, ksiz, vsiz;
|
157
|
+
vhash = rb_hash_new();
|
158
|
+
|
159
|
+
num = tclistnum(list);
|
160
|
+
for(i = 0; i < num; i += 2){
|
161
|
+
key = tclistval(list, i, &ksiz);
|
162
|
+
val = tclistval(list, i + 1, &vsiz);
|
163
|
+
vkey = rb_str_new(key, ksiz);
|
164
|
+
vval = rb_str_new(val, vsiz);
|
165
|
+
|
166
|
+
vvals = rb_hash_aref(vhash, vkey);
|
167
|
+
if (TYPE(vvals) != T_ARRAY) vvals = rb_ary_new();
|
168
|
+
vvals = rb_ary_push(vvals, vval);
|
169
|
+
rb_hash_aset(vhash, vkey, vvals);
|
170
|
+
}
|
171
|
+
return vhash;
|
172
|
+
}
|
173
|
+
|
126
174
|
VALUE mTokyoTyrant;
|
175
|
+
|
127
176
|
VALUE eTokyoTyrantError;
|
177
|
+
VALUE eTokyoTyrantErrorInvalid;
|
178
|
+
VALUE eTokyoTyrantErrorNoHost;
|
179
|
+
VALUE eTokyoTyrantErrorRefused;
|
180
|
+
VALUE eTokyoTyrantErrorSend;
|
181
|
+
VALUE eTokyoTyrantErrorReceive;
|
182
|
+
VALUE eTokyoTyrantErrorKeep;
|
183
|
+
VALUE eTokyoTyrantErrorNoRecord;
|
184
|
+
VALUE eTokyoTyrantErrorMisc;
|
185
|
+
|
128
186
|
VALUE cDB;
|
187
|
+
VALUE cBDB;
|
129
188
|
VALUE cTable;
|
130
189
|
VALUE cQuery;
|
131
|
-
VALUE
|
190
|
+
VALUE cConstistentHash;
|
132
191
|
|
133
192
|
void Init_tokyo_tyrant(){
|
134
193
|
mTokyoTyrant = rb_define_module("TokyoTyrant");
|
194
|
+
|
135
195
|
eTokyoTyrantError = rb_define_class("TokyoTyrantError", rb_eStandardError);
|
196
|
+
eTokyoTyrantErrorInvalid = rb_define_class("TokyoTyrantErrorInvalid", eTokyoTyrantError);
|
197
|
+
eTokyoTyrantErrorNoHost = rb_define_class("TokyoTyrantErrorNoHost", eTokyoTyrantError);
|
198
|
+
eTokyoTyrantErrorRefused = rb_define_class("TokyoTyrantErrorRefused", eTokyoTyrantError);
|
199
|
+
eTokyoTyrantErrorSend = rb_define_class("TokyoTyrantErrorSend", eTokyoTyrantError);
|
200
|
+
eTokyoTyrantErrorReceive = rb_define_class("TokyoTyrantErrorReceive", eTokyoTyrantError);
|
201
|
+
eTokyoTyrantErrorKeep = rb_define_class("TokyoTyrantErrorKeep", eTokyoTyrantError);
|
202
|
+
eTokyoTyrantErrorNoRecord = rb_define_class("TokyoTyrantErrorNoRecord", eTokyoTyrantError);
|
203
|
+
eTokyoTyrantErrorMisc = rb_define_class("TokyoTyrantErrorMisc", eTokyoTyrantError);
|
204
|
+
|
136
205
|
init_mod();
|
137
206
|
|
138
207
|
cDB = rb_define_class_under(mTokyoTyrant, "DB", rb_cObject);
|
139
208
|
rb_include_module(cDB, mTokyoTyrant);
|
140
209
|
init_db();
|
141
210
|
|
211
|
+
cBDB = rb_define_class_under(mTokyoTyrant, "BDB", cDB);
|
212
|
+
init_bdb();
|
213
|
+
|
142
214
|
cTable = rb_define_class_under(mTokyoTyrant, "Table", rb_cObject);
|
143
215
|
rb_include_module(cTable, mTokyoTyrant);
|
144
216
|
init_table();
|
@@ -146,6 +218,6 @@ void Init_tokyo_tyrant(){
|
|
146
218
|
cQuery = rb_define_class_under(mTokyoTyrant, "Query", rb_cObject);
|
147
219
|
init_query();
|
148
220
|
|
149
|
-
|
150
|
-
|
221
|
+
cConstistentHash = rb_define_class_under(mTokyoTyrant, "ConstistentHash", rb_cObject);
|
222
|
+
init_consistent_hash();
|
151
223
|
}
|