ruby-tokyotyrant 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|