actsasflinn-ruby-tokyotyrant 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/benchmarks/bulk_db.rb +74 -0
- data/benchmarks/bulk_table.rb +85 -0
- data/benchmarks/db.rb +114 -0
- data/benchmarks/table.rb +161 -0
- data/ext/tokyo_tyrant.c +162 -0
- data/ext/tokyo_tyrant.h +48 -0
- data/ext/tokyo_tyrant_db.c +242 -0
- data/ext/tokyo_tyrant_db.h +8 -0
- data/ext/tokyo_tyrant_module.c +298 -0
- data/ext/tokyo_tyrant_module.h +8 -0
- data/ext/tokyo_tyrant_query.c +149 -0
- data/ext/tokyo_tyrant_query.h +9 -0
- data/ext/tokyo_tyrant_table.c +259 -0
- data/ext/tokyo_tyrant_table.h +8 -0
- data/spec/plu_db.rb +538 -0
- data/spec/spec_base.rb +16 -0
- data/spec/tokyo_tyrant_query_spec.rb +71 -0
- data/spec/tokyo_tyrant_spec.rb +180 -0
- data/spec/tokyo_tyrant_table_spec.rb +190 -0
- metadata +24 -1
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
puts "Tokyo Tyrant Bulk Operations Benchmark"
|
6
|
+
|
7
|
+
data = {}
|
8
|
+
data_e = {}
|
9
|
+
data_a = []
|
10
|
+
|
11
|
+
10_000.times do |i|
|
12
|
+
data[i.to_s] = Faker::Name.name
|
13
|
+
data_e[i.to_s] = nil
|
14
|
+
data_a << i.to_s
|
15
|
+
data_a << data[i.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'tokyotyrant'
|
19
|
+
|
20
|
+
rdb = TokyoTyrant::RDB::new
|
21
|
+
rdb.open("127.0.0.1", 1978)
|
22
|
+
rdb.clear
|
23
|
+
nothing = nil
|
24
|
+
|
25
|
+
2.times { puts }
|
26
|
+
puts 'TokyoTyrant::RDB (Ruby) mget'
|
27
|
+
|
28
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
29
|
+
b.report('inserting data') do
|
30
|
+
rdb.misc('putlist', data_a)
|
31
|
+
end
|
32
|
+
|
33
|
+
b.report('reading data') do
|
34
|
+
rdb.mget(data_e)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'tokyo_tyrant'
|
39
|
+
t = TokyoTyrant::DB.new('127.0.0.1', 1978)
|
40
|
+
t.clear
|
41
|
+
nothing = nil
|
42
|
+
|
43
|
+
2.times { puts }
|
44
|
+
puts 'TokyoTyrant (c) mput/mget'
|
45
|
+
|
46
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
47
|
+
b.report('inserting data ') do
|
48
|
+
t.mput(data)
|
49
|
+
end
|
50
|
+
|
51
|
+
b.report('reading data') do
|
52
|
+
nothing = t.mget(0..9999)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
require 'memcached'
|
57
|
+
m = Memcached.new('127.0.0.1:11211')
|
58
|
+
m.flush
|
59
|
+
nothing = nil
|
60
|
+
|
61
|
+
2.times { puts }
|
62
|
+
puts 'Memcached (C) set/get_multi'
|
63
|
+
|
64
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
65
|
+
b.report('inserting data*') do
|
66
|
+
data.each_pair { |k, v| m.set(k, v) }
|
67
|
+
end
|
68
|
+
|
69
|
+
b.report('reading data') do
|
70
|
+
nothing = m.get(data.keys)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
puts "* bulk operation not supported"
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'faker'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
$year = (1909 .. 2009).to_a
|
7
|
+
$month = (1..12).to_a
|
8
|
+
$day = (1..28).to_a # not bothering with month diffs
|
9
|
+
|
10
|
+
def rbdate
|
11
|
+
DateTime.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
|
12
|
+
end
|
13
|
+
|
14
|
+
def rdiv
|
15
|
+
case rand(3)
|
16
|
+
when 0
|
17
|
+
'dev'
|
18
|
+
when 1
|
19
|
+
'brd'
|
20
|
+
else
|
21
|
+
'brd,dev'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def rgen
|
26
|
+
(rand(2) == 1 ? 'male' : 'female')
|
27
|
+
end
|
28
|
+
|
29
|
+
data = {}
|
30
|
+
10_000.times do |i|
|
31
|
+
data[i] = { :name => Faker::Name.name, :sex => rgen, :birthday => rbdate.to_s, :divisions => rdiv }
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'tokyo_tyrant'
|
35
|
+
t = TokyoTyrant::Table.new('127.0.0.1', 1978)
|
36
|
+
t.clear
|
37
|
+
|
38
|
+
2.times { puts }
|
39
|
+
puts 'TokyoTyrant (C)'
|
40
|
+
|
41
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
42
|
+
b.report('bulk writing data') do
|
43
|
+
nothing = t.mput(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
b.report('bulk reading data') do
|
47
|
+
nothing = t.mget(0..9999)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require 'tokyotyrant'
|
52
|
+
|
53
|
+
rdb = TokyoTyrant::RDB::new
|
54
|
+
rdb.open("127.0.0.1", 1978)
|
55
|
+
rdb.clear
|
56
|
+
|
57
|
+
2.times { puts }
|
58
|
+
puts 'TokyoTyrant::RDB (Ruby)'
|
59
|
+
|
60
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
61
|
+
b.report('bulk inserting data*') do
|
62
|
+
# is this fair to put in the benchmark? yes because it happens within the c-ext
|
63
|
+
data_a = []
|
64
|
+
data.each_pair{ |i,v|
|
65
|
+
data_a << i.to_s
|
66
|
+
data_a << v.collect{ |k,v| [k.to_s,v] }.join("\0")
|
67
|
+
}
|
68
|
+
rdb.misc('putlist', data_a)
|
69
|
+
end
|
70
|
+
|
71
|
+
b.report('bulk reading data ') do
|
72
|
+
l = rdb.misc('getlist', data.keys)
|
73
|
+
h = Hash[*l]
|
74
|
+
h.each_pair do |k,v|
|
75
|
+
a = v.split("\0")
|
76
|
+
h[k] = Hash[*a]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
puts "\nNotes:"
|
82
|
+
puts "* To supply a hash for bulk operations TokyoTyrant::RDB creates an array and join hash columns."
|
83
|
+
puts "* This operation is included in the benchmark because the same code exists within the c-ext."
|
84
|
+
puts "Rufus::Tokyo::TyrantTable does not support the misc method, therefor cannot handle a putlist/getlist"
|
85
|
+
puts "Memcached does not support bulk writing"
|
data/benchmarks/db.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
data = []
|
6
|
+
|
7
|
+
10_000.times do |i|
|
8
|
+
data << Faker::Name.name
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rufus/tokyo/tyrant'
|
12
|
+
|
13
|
+
r = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)
|
14
|
+
r.clear
|
15
|
+
|
16
|
+
2.times { puts }
|
17
|
+
puts 'Tokyo::Tyrant (Ruby FFI)'
|
18
|
+
|
19
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
20
|
+
b.report('inserting data') do
|
21
|
+
data.each_with_index { |e, i| r[i.to_s] = e }
|
22
|
+
end
|
23
|
+
|
24
|
+
b.report('reading data') do
|
25
|
+
data.each_with_index { |e, i| nothing = r[i.to_s] }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'tokyotyrant'
|
30
|
+
|
31
|
+
rdb = TokyoTyrant::RDB::new
|
32
|
+
rdb.open("127.0.0.1", 1978)
|
33
|
+
rdb.clear
|
34
|
+
|
35
|
+
2.times { puts }
|
36
|
+
puts 'TokyoTyrant::RDB (Ruby)'
|
37
|
+
|
38
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
39
|
+
b.report('inserting data') do
|
40
|
+
data.each_with_index { |e, i| rdb.put(i.to_s, e) }
|
41
|
+
end
|
42
|
+
|
43
|
+
b.report('reading data') do
|
44
|
+
data.each_with_index { |e, i| nothing = rdb.get(i.to_s) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
require 'tokyo_tyrant'
|
49
|
+
t = TokyoTyrant::DB.new('127.0.0.1', 1978)
|
50
|
+
t.clear
|
51
|
+
|
52
|
+
2.times { puts }
|
53
|
+
puts 'TokyoTyrant (C)'
|
54
|
+
|
55
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
56
|
+
b.report('inserting data') do
|
57
|
+
data.each_with_index { |e, i| t[i] = e }
|
58
|
+
end
|
59
|
+
|
60
|
+
b.report('reading data') do
|
61
|
+
data.each_with_index { |e, i| nothing = t[i] }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
require 'memcached'
|
66
|
+
m = Memcached.new('127.0.0.1:1978')
|
67
|
+
m.flush
|
68
|
+
|
69
|
+
2.times { puts }
|
70
|
+
puts 'Memcached (C) to Tyrant'
|
71
|
+
|
72
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
73
|
+
b.report('inserting data') do
|
74
|
+
data.each_with_index { |e, i| m.set(i.to_s, e) }
|
75
|
+
end
|
76
|
+
|
77
|
+
b.report('reading data') do
|
78
|
+
data.each_with_index { |e, i| nothing = m.get(i.to_s) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
require 'memcached'
|
83
|
+
m = Memcached.new('127.0.0.1:11211')
|
84
|
+
m.flush
|
85
|
+
|
86
|
+
2.times { puts }
|
87
|
+
puts 'Memcached (C) to Memcached'
|
88
|
+
|
89
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
90
|
+
b.report('inserting data') do
|
91
|
+
data.each_with_index { |e, i| m.set(i.to_s, e) }
|
92
|
+
end
|
93
|
+
|
94
|
+
b.report('reading data') do
|
95
|
+
data.each_with_index { |e, i| nothing = m.get(i.to_s) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
require 'memcache'
|
100
|
+
mc = MemCache.new('127.0.0.1:11211')
|
101
|
+
mc.flush_all
|
102
|
+
|
103
|
+
2.times { puts }
|
104
|
+
puts 'MemCache (Ruby)'
|
105
|
+
|
106
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
107
|
+
b.report('inserting data') do
|
108
|
+
data.each_with_index { |e, i| mc.set(i.to_s, e) }
|
109
|
+
end
|
110
|
+
|
111
|
+
b.report('reading data') do
|
112
|
+
data.each_with_index { |e, i| nothing = mc.get(i.to_s) }
|
113
|
+
end
|
114
|
+
end
|
data/benchmarks/table.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'faker'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
#
|
7
|
+
# the data
|
8
|
+
#
|
9
|
+
|
10
|
+
colnames = %w{ name sex birthday divisions }
|
11
|
+
|
12
|
+
$year = (1909 .. 2009).to_a
|
13
|
+
$month = (1..12).to_a
|
14
|
+
$day = (1..28).to_a # not bothering with month diffs
|
15
|
+
|
16
|
+
def rbdate
|
17
|
+
DateTime.new($year[rand($year.size)], $month[rand($month.size)], $day[rand($day.size)])
|
18
|
+
end
|
19
|
+
|
20
|
+
def rdiv
|
21
|
+
case rand(3)
|
22
|
+
when 0
|
23
|
+
'dev'
|
24
|
+
when 1
|
25
|
+
'brd'
|
26
|
+
else
|
27
|
+
'brd,dev'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def rgen
|
32
|
+
(rand(2) == 1 ? 'male' : 'female')
|
33
|
+
end
|
34
|
+
|
35
|
+
data = [
|
36
|
+
[ 'Alphonse Armalite', 'male', DateTime.new(1972, 10, 14), 'brd,dev' ],
|
37
|
+
[ 'Brutus Beromunster', 'male', DateTime.new(1964, 07, 14), 'dev' ],
|
38
|
+
[ 'Crystel Chucknorris', 'female', DateTime.new(1980, 07, 12), 'brd' ],
|
39
|
+
[ 'Desree Dylan', 'female', DateTime.new(1954, 07, 13), 'brd,dev' ]
|
40
|
+
]
|
41
|
+
|
42
|
+
10_000.times do |i|
|
43
|
+
data << [ Faker::Name.name, rgen, rbdate, rdiv]
|
44
|
+
end
|
45
|
+
|
46
|
+
$find_name_list = []
|
47
|
+
100.times { $find_name_list << data[rand(data.size)][0] }
|
48
|
+
|
49
|
+
data.collect! { |e|
|
50
|
+
(0..colnames.length - 1).inject({}) { |h, i| h[colnames[i]] = e[i]; h }
|
51
|
+
}
|
52
|
+
|
53
|
+
data_h = {}
|
54
|
+
i = 0
|
55
|
+
data1 = data.collect { |e|
|
56
|
+
i = i + 1
|
57
|
+
h = e.dup
|
58
|
+
h['birthday'] = h['birthday'].to_s
|
59
|
+
data_h[i.to_s] = h
|
60
|
+
h
|
61
|
+
}
|
62
|
+
|
63
|
+
require 'rufus/tokyo/tyrant'
|
64
|
+
|
65
|
+
r = Rufus::Tokyo::TyrantTable.new('127.0.0.1', 1978)
|
66
|
+
r.clear
|
67
|
+
|
68
|
+
2.times { puts }
|
69
|
+
puts 'Tokyo::TyrantTable (Ruby FFI)'
|
70
|
+
|
71
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
72
|
+
b.report('inserting data') do
|
73
|
+
data1.each_with_index { |e, i| r[i.to_s] = e }
|
74
|
+
end
|
75
|
+
|
76
|
+
b.report('reading data') do
|
77
|
+
data1.each_with_index { |e, i| nothing = r[i.to_s] }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
require 'tokyotyrant'
|
82
|
+
|
83
|
+
rdb = TokyoTyrant::RDBTBL::new
|
84
|
+
rdb.open("127.0.0.1", 1978)
|
85
|
+
rdb.clear
|
86
|
+
|
87
|
+
2.times { puts }
|
88
|
+
puts 'TokyoTyrant::RDB (Ruby)'
|
89
|
+
|
90
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
91
|
+
b.report('inserting data') do
|
92
|
+
data1.each_with_index { |e, i| rdb.put(i.to_s, e) }
|
93
|
+
end
|
94
|
+
|
95
|
+
b.report('reading data') do
|
96
|
+
data1.each_with_index { |e, i| nothing = rdb.get(i.to_s) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
require 'tokyo_tyrant'
|
101
|
+
t = TokyoTyrant::Table.new('127.0.0.1', 1978)
|
102
|
+
t.clear
|
103
|
+
|
104
|
+
2.times { puts }
|
105
|
+
puts 'TokyoTyrant (C)'
|
106
|
+
|
107
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
108
|
+
b.report('inserting data') do
|
109
|
+
data1.each_with_index { |e, i| t[i] = e }
|
110
|
+
end
|
111
|
+
|
112
|
+
b.report('reading data') do
|
113
|
+
data1.each_with_index { |e, i| nothing = t[i] }
|
114
|
+
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
|
+
end
|
124
|
+
|
125
|
+
require 'memcached'
|
126
|
+
m = Memcached.new('127.0.0.1:11211')
|
127
|
+
m.flush
|
128
|
+
|
129
|
+
2.times { puts }
|
130
|
+
puts 'Memcached (C)'
|
131
|
+
|
132
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
133
|
+
b.report('inserting data') do
|
134
|
+
data1.each_with_index { |e, i| m.set(i.to_s, e) }
|
135
|
+
end
|
136
|
+
|
137
|
+
b.report('reading data') do
|
138
|
+
data1.each_with_index { |e, i| nothing = m.get(i.to_s) }
|
139
|
+
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
|
+
end
|
145
|
+
|
146
|
+
require 'memcache'
|
147
|
+
mc = MemCache.new('127.0.0.1:11211')
|
148
|
+
mc.flush_all
|
149
|
+
|
150
|
+
2.times { puts }
|
151
|
+
puts 'MemCache (Ruby)'
|
152
|
+
|
153
|
+
Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
|
154
|
+
b.report('inserting data') do
|
155
|
+
data1.each_with_index { |e, i| mc.set(i.to_s, e) }
|
156
|
+
end
|
157
|
+
|
158
|
+
b.report('reading data') do
|
159
|
+
data1.each_with_index { |e, i| nothing = mc.get(i.to_s) }
|
160
|
+
end
|
161
|
+
end
|
data/ext/tokyo_tyrant.c
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
#include <tokyo_tyrant.h>
|
2
|
+
|
3
|
+
extern VALUE StringValueEx(VALUE vobj){
|
4
|
+
char kbuf[NUMBUFSIZ];
|
5
|
+
int ksiz;
|
6
|
+
switch(TYPE(vobj)){
|
7
|
+
case T_FIXNUM:
|
8
|
+
ksiz = sprintf(kbuf, "%d", (int)FIX2INT(vobj));
|
9
|
+
return rb_str_new(kbuf, ksiz);
|
10
|
+
case T_BIGNUM:
|
11
|
+
ksiz = sprintf(kbuf, "%lld", (long long)NUM2LL(vobj));
|
12
|
+
return rb_str_new(kbuf, ksiz);
|
13
|
+
case T_SYMBOL:
|
14
|
+
return rb_str_new2(rb_id2name(SYM2ID(vobj)));
|
15
|
+
case T_TRUE:
|
16
|
+
ksiz = sprintf(kbuf, "true");
|
17
|
+
return rb_str_new(kbuf, ksiz);
|
18
|
+
case T_FALSE:
|
19
|
+
ksiz = sprintf(kbuf, "false");
|
20
|
+
return rb_str_new(kbuf, ksiz);
|
21
|
+
// I don't like this, I'd rather an empty string
|
22
|
+
// case T_NIL:
|
23
|
+
// ksiz = sprintf(kbuf, "nil");
|
24
|
+
// return rb_str_new(kbuf, ksiz);
|
25
|
+
default:
|
26
|
+
if (rb_respond_to(vobj, rb_intern("to_s"))) {
|
27
|
+
return rb_convert_type(vobj, T_STRING, "String", "to_s");
|
28
|
+
}
|
29
|
+
}
|
30
|
+
return StringValue(vobj);
|
31
|
+
}
|
32
|
+
|
33
|
+
extern TCLIST *varytolist(VALUE vary){
|
34
|
+
VALUE vval;
|
35
|
+
TCLIST *list;
|
36
|
+
int i, num;
|
37
|
+
num = RARRAY_LEN(vary);
|
38
|
+
list = tclistnew2(num);
|
39
|
+
for(i = 0; i < num; i++){
|
40
|
+
vval = rb_ary_entry(vary, i);
|
41
|
+
vval = StringValueEx(vval);
|
42
|
+
tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
|
43
|
+
}
|
44
|
+
return list;
|
45
|
+
}
|
46
|
+
|
47
|
+
extern VALUE listtovary(TCLIST *list){
|
48
|
+
VALUE vary;
|
49
|
+
const char *vbuf;
|
50
|
+
int i, num, vsiz;
|
51
|
+
num = tclistnum(list);
|
52
|
+
vary = rb_ary_new2(num);
|
53
|
+
for(i = 0; i < num; i++){
|
54
|
+
vbuf = tclistval(list, i, &vsiz);
|
55
|
+
rb_ary_push(vary, rb_str_new(vbuf, vsiz));
|
56
|
+
}
|
57
|
+
return vary;
|
58
|
+
}
|
59
|
+
|
60
|
+
extern TCMAP *vhashtomap(VALUE vhash){
|
61
|
+
VALUE vkeys, vkey, vval;
|
62
|
+
TCMAP *map;
|
63
|
+
int i, num;
|
64
|
+
map = tcmapnew2(31);
|
65
|
+
vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
|
66
|
+
num = RARRAY_LEN(vkeys);
|
67
|
+
for(i = 0; i < num; i++){
|
68
|
+
vkey = rb_ary_entry(vkeys, i);
|
69
|
+
vval = rb_hash_aref(vhash, vkey);
|
70
|
+
vkey = StringValueEx(vkey);
|
71
|
+
vval = StringValueEx(vval);
|
72
|
+
tcmapput(map, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vval), RSTRING_LEN(vval));
|
73
|
+
}
|
74
|
+
return map;
|
75
|
+
}
|
76
|
+
|
77
|
+
extern VALUE maptovhash(TCMAP *map){
|
78
|
+
const char *kbuf, *vbuf;
|
79
|
+
int ksiz, vsiz;
|
80
|
+
VALUE vhash;
|
81
|
+
vhash = rb_hash_new();
|
82
|
+
tcmapiterinit(map);
|
83
|
+
while((kbuf = tcmapiternext(map, &ksiz)) != NULL){
|
84
|
+
vbuf = tcmapiterval(kbuf, &vsiz);
|
85
|
+
rb_hash_aset(vhash, rb_str_new(kbuf, ksiz), rb_str_new(vbuf, vsiz));
|
86
|
+
}
|
87
|
+
return vhash;
|
88
|
+
}
|
89
|
+
|
90
|
+
extern VALUE maptovhashsym(TCMAP *map){
|
91
|
+
const char *kbuf, *vbuf;
|
92
|
+
int ksiz, vsiz;
|
93
|
+
VALUE vhash;
|
94
|
+
vhash = rb_hash_new();
|
95
|
+
tcmapiterinit(map);
|
96
|
+
while((kbuf = tcmapiternext(map, &ksiz)) != NULL){
|
97
|
+
vbuf = tcmapiterval(kbuf, &vsiz);
|
98
|
+
rb_hash_aset(vhash, ID2SYM(rb_intern(kbuf)), rb_str_new(vbuf, vsiz));
|
99
|
+
}
|
100
|
+
return vhash;
|
101
|
+
}
|
102
|
+
|
103
|
+
extern TCMAP *varytomap(VALUE vary){
|
104
|
+
int i;
|
105
|
+
TCLIST *keys;
|
106
|
+
TCMAP *recs = tcmapnew();
|
107
|
+
keys = varytolist(vary);
|
108
|
+
for(i = 0; i < tclistnum(keys); i++){
|
109
|
+
int ksiz;
|
110
|
+
const char *kbuf = tclistval(keys, i, &ksiz);
|
111
|
+
tcmapput(recs, kbuf, ksiz, "", 0);
|
112
|
+
}
|
113
|
+
return recs;
|
114
|
+
}
|
115
|
+
|
116
|
+
extern TCLIST *vhashtolist(VALUE vhash){
|
117
|
+
/*
|
118
|
+
Seems like something like this might work just as well
|
119
|
+
vary = rb_hash_to_a(vhash);
|
120
|
+
vary = rb_ary_flatten(vary);
|
121
|
+
args = varytolist(vary);
|
122
|
+
*/
|
123
|
+
|
124
|
+
VALUE vkeys, vkey, vval;
|
125
|
+
TCLIST *list;
|
126
|
+
int i, num;
|
127
|
+
vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
|
128
|
+
num = RARRAY_LEN(vkeys);
|
129
|
+
list = tclistnew2(num);
|
130
|
+
for(i = 0; i < num; i++){
|
131
|
+
vkey = rb_ary_entry(vkeys, i);
|
132
|
+
vval = rb_hash_aref(vhash, vkey);
|
133
|
+
vkey = StringValueEx(vkey);
|
134
|
+
vval = StringValueEx(vval);
|
135
|
+
tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
|
136
|
+
tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
|
137
|
+
}
|
138
|
+
return list;
|
139
|
+
}
|
140
|
+
|
141
|
+
VALUE mTokyoTyrant;
|
142
|
+
VALUE eTokyoTyrantError;
|
143
|
+
VALUE cDB;
|
144
|
+
VALUE cTable;
|
145
|
+
VALUE cQuery;
|
146
|
+
|
147
|
+
void Init_tokyo_tyrant(){
|
148
|
+
mTokyoTyrant = rb_define_module("TokyoTyrant");
|
149
|
+
eTokyoTyrantError = rb_define_class("TokyoTyrantError", rb_eStandardError);
|
150
|
+
init_mod();
|
151
|
+
|
152
|
+
cDB = rb_define_class_under(mTokyoTyrant, "DB", rb_cObject);
|
153
|
+
rb_include_module(cDB, mTokyoTyrant);
|
154
|
+
init_db();
|
155
|
+
|
156
|
+
cTable = rb_define_class_under(mTokyoTyrant, "Table", rb_cObject);
|
157
|
+
rb_include_module(cTable, mTokyoTyrant);
|
158
|
+
init_table();
|
159
|
+
|
160
|
+
cQuery = rb_define_class_under(mTokyoTyrant, "Query", rb_cObject);
|
161
|
+
init_query();
|
162
|
+
}
|