actsasflinn-ruby-tokyotyrant 0.1.2 → 0.1.3
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/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
|
+
}
|