ruby-tokyotyrant 0.3.1 → 0.4

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 CHANGED
@@ -4,10 +4,11 @@ This is a c extension for Ruby to access TokyoTyrant databases. It currently su
4
4
 
5
5
  == Install
6
6
 
7
- # install tokyocabinet (1.4.30) and tokyotyrant (requires 1.1.33)
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
- gem sources -a http://gems.github.com
10
- sudo gem install actsasflinn-ruby-tokyotyrant
9
+ sudo gem install gemcutter
10
+ sudo gem tumble
11
+ sudo gem install ruby-tokyotyrant
11
12
 
12
13
  == Performance
13
14
 
@@ -196,6 +197,32 @@ This is not in production but the initial benchmarks are very interesting. Resul
196
197
  t.run(:echo, 'hello', 'world')
197
198
  # => "hello\tworld"
198
199
 
200
+ === Balanced Nodes with Consistent Hashing
201
+
202
+ # usage is similar to single node
203
+ require 'tokyo_tyrant/balancer'
204
+
205
+ servers = ['127.0.0.1:1978',
206
+ '127.0.0.1:1979',
207
+ '127.0.0.1:1980',
208
+ '127.0.0.1:1981']
209
+
210
+ tb = TokyoTyrant::Balancer::Table.new(servers)
211
+
212
+ # store server is determined by key which is consistent
213
+ tb[:foo] = { 'foo' => 'bar' }
214
+ tb[:bar] = { 'bar' => 'baz' }
215
+
216
+ # retrieval server is determined by key which is consistent
217
+ tb[:foo]
218
+ # => { 'foo' => 'bar' }
219
+
220
+ # aggregate from all nodes
221
+ tb.size
222
+
223
+ # parallel_search based querying across all nodes
224
+ tb.find{ |q| q.condition(:foo, :streq, 'bar') }
225
+
199
226
  == Contributors
200
227
 
201
228
  * Flinn Mueller (actsasflinn) author/maintainer
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.3.1'
23
+ s.version = '0.4'
24
24
  s.authors = [ 'Flinn' ]
25
25
  s.email = 'flinn@actsasflinn.com'
26
26
  s.homepage = 'http://github.com/actsasflinn/ruby-tokyotyrant/'
@@ -35,9 +35,12 @@ gemspec = Gem::Specification.new do |s|
35
35
  'Rakefile',
36
36
  'README.rdoc'] +
37
37
  Dir['ext/**/*.[rb|c|h]'] +
38
+ Dir['lib/**/*.rb'] +
38
39
  Dir['spec/**/*'] +
39
40
  Dir['benchmarks/**/*']
40
41
  s.extensions << "ext/extconf.rb"
42
+
43
+ s.add_runtime_dependency('fast_hash_ring', '>= 0.1.1')
41
44
  end
42
45
 
43
46
  task :gemspec do
@@ -50,13 +53,14 @@ Rake::GemPackageTask.new(gemspec) do |pkg|
50
53
  pkg.need_tar = true
51
54
  end
52
55
 
53
- Rake::PackageTask.new('ruby-tokyotyrant', '0.1') do |pkg|
56
+ Rake::PackageTask.new('ruby-tokyotyrant', '0.4') do |pkg|
54
57
  pkg.need_zip = true
55
58
  pkg.package_files = FileList[
56
59
  'COPYING',
57
60
  'Rakefile',
58
61
  'README.rdoc',
59
62
  'ext/**/*',
63
+ 'lib/**/*.[rb]',
60
64
  'spec/**/*',
61
65
  'benchmarks/**/*'
62
66
  ].to_a
@@ -0,0 +1,101 @@
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 'tokyo_tyrant'
64
+
65
+ t = TokyoTyrant::Table.new('127.0.0.1', 45001)
66
+ t.clear
67
+
68
+ 2.times { puts }
69
+ puts 'TokyoTyrant Single'
70
+
71
+ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
72
+ b.report('inserting data') do
73
+ data1.each_with_index { |e, i| t[i.to_s] = e }
74
+ end
75
+
76
+ b.report('reading data') do
77
+ data1.each_with_index { |e, i| nothing = t[i.to_s] }
78
+ end
79
+ end
80
+
81
+ require 'lib/tokyo_tyrant/balancer'
82
+
83
+ servers = ['127.0.0.1:45001',
84
+ '127.0.0.1:45002',
85
+ '127.0.0.1:45003']
86
+
87
+ tb = TokyoTyrant::Balancer::Table.new(servers)
88
+ tb.clear
89
+
90
+ 2.times { puts }
91
+ puts 'TokyoTyrant Balancer'
92
+
93
+ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
94
+ b.report('inserting data') do
95
+ data1.each_with_index { |e, i| tb[i.to_s] = e }
96
+ end
97
+
98
+ b.report('reading data') do
99
+ data1.each_with_index { |e, i| nothing = tb[i.to_s] }
100
+ end
101
+ end
data/benchmarks/db.rb CHANGED
@@ -4,10 +4,11 @@ require 'faker'
4
4
 
5
5
  data = []
6
6
 
7
- 10_000.times do |i|
7
+ 100_000.times do |i|
8
8
  data << Faker::Name.name
9
9
  end
10
10
 
11
+ =begin
11
12
  require 'rufus/tokyo/tyrant'
12
13
 
13
14
  r = Rufus::Tokyo::Tyrant.new('127.0.0.1', 45000)
@@ -44,9 +45,10 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
44
45
  data.each_with_index { |e, i| nothing = rdb.get(i.to_s) }
45
46
  end
46
47
  end
48
+ =end
47
49
 
48
50
  require 'tokyo_tyrant'
49
- t = TokyoTyrant::DB.new('127.0.0.1', 45000)
51
+ t = TokyoTyrant::DB.new('127.0.0.1', 1978)
50
52
  t.clear
51
53
 
52
54
  2.times { puts }
@@ -62,6 +64,23 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
62
64
  end
63
65
  end
64
66
 
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
65
84
  require 'memcached'
66
85
  m = Memcached.new('127.0.0.1:45000')
67
86
  m.flush
@@ -112,3 +131,4 @@ Benchmark.benchmark(' ' * 20 + Benchmark::Tms::CAPTION, 20) do |b|
112
131
  data.each_with_index { |e, i| nothing = mc.get(i.to_s) }
113
132
  end
114
133
  end
134
+ =end
data/ext/tokyo_tyrant.c CHANGED
@@ -128,6 +128,7 @@ VALUE eTokyoTyrantError;
128
128
  VALUE cDB;
129
129
  VALUE cTable;
130
130
  VALUE cQuery;
131
+ VALUE cMDB;
131
132
 
132
133
  void Init_tokyo_tyrant(){
133
134
  mTokyoTyrant = rb_define_module("TokyoTyrant");
@@ -144,4 +145,7 @@ void Init_tokyo_tyrant(){
144
145
 
145
146
  cQuery = rb_define_class_under(mTokyoTyrant, "Query", rb_cObject);
146
147
  init_query();
148
+
149
+ cMDB = rb_define_class_under(mTokyoTyrant, "MDB", rb_cObject);
150
+ init_utils();
147
151
  }
data/ext/tokyo_tyrant.h CHANGED
@@ -11,6 +11,7 @@
11
11
  #include <tokyo_tyrant_db.h>
12
12
  #include <tokyo_tyrant_table.h>
13
13
  #include <tokyo_tyrant_query.h>
14
+ #include <tokyo_utils.h>
14
15
 
15
16
  #define RDBVNDATA "@rdb"
16
17
  #define RDBQRYVNDATA "@rdbquery"
@@ -19,6 +20,7 @@
19
20
  #define TTPUTKEEP 1
20
21
  #define TTPUTCAT 2
21
22
  #define TTPUTNR 3
23
+ #define MDBVNDATA "@mdb"
22
24
 
23
25
  #if !defined(RSTRING_PTR)
24
26
  #define RSTRING_PTR(TC_s) (RSTRING(TC_s)->ptr)
@@ -35,6 +37,7 @@ extern VALUE eTokyoTyrantError;
35
37
  extern VALUE cDB;
36
38
  extern VALUE cTable;
37
39
  extern VALUE cQuery;
40
+ extern VALUE cMDB;
38
41
 
39
42
  extern VALUE StringRaw(const char *buf, int bsiz);
40
43
  extern VALUE StringValueEx(VALUE vobj);
@@ -1,4 +1,4 @@
1
- #include <tokyo_tyrant_db.h>
1
+ #include <tokyo_tyrant_module.h>
2
2
 
3
3
  extern TCRDB *mTokyoTyrant_getdb(VALUE vself){
4
4
  TCRDB *db;
@@ -438,7 +438,7 @@ void init_mod(){
438
438
  rb_define_alias(mTokyoTyrant, "clear", "vanish");
439
439
  rb_define_method(mTokyoTyrant, "copy", mTokyoTyrant_copy, 1);
440
440
  rb_define_method(mTokyoTyrant, "restore", mTokyoTyrant_restore, 2);
441
- rb_define_method(mTokyoTyrant, "setmst", mTokyoTyrant_setmst, 2);
441
+ rb_define_method(mTokyoTyrant, "setmst", mTokyoTyrant_setmst, 4);
442
442
  rb_define_method(mTokyoTyrant, "rnum", mTokyoTyrant_rnum, 0);
443
443
  rb_define_alias(mTokyoTyrant, "count", "rnum");
444
444
  rb_define_method(mTokyoTyrant, "empty?", mTokyoTyrant_empty, 0);
data/ext/tokyo_utils.c ADDED
@@ -0,0 +1,362 @@
1
+ #include <tokyo_utils.h>
2
+
3
+ extern TCMDB *cMDB_getdb(VALUE vself){
4
+ TCMDB *db;
5
+ Data_Get_Struct(rb_iv_get(vself, MDBVNDATA), TCMDB, db);
6
+ return db;
7
+ }
8
+
9
+ static void cMDB_free(TCMDB *db){
10
+ tcmdbdel(db);
11
+ }
12
+
13
+ static VALUE cMDB_bnum(VALUE vself){
14
+ return rb_iv_get(vself, "@bnum");
15
+ }
16
+
17
+ static VALUE cMDB_initialize(int argc, VALUE *argv, VALUE vself){
18
+ VALUE bnum;
19
+ TCMDB *db;
20
+
21
+ rb_scan_args(argc, argv, "0", &bnum);
22
+ if(NIL_P(bnum)){
23
+ db = tcmdbnew();
24
+ } else {
25
+ db = tcmdbnew2(bnum);
26
+ }
27
+
28
+ rb_iv_set(vself, "@bnum", bnum);
29
+
30
+ rb_iv_set(vself, MDBVNDATA, Data_Wrap_Struct(rb_cObject, 0, cMDB_free, db));
31
+
32
+ return Qtrue;
33
+ }
34
+
35
+ static VALUE cMDB_put_method(VALUE vself, VALUE vkey, VALUE vstr, int method){
36
+ bool res;
37
+ TCMDB *db = cMDB_getdb(vself);
38
+
39
+ vkey = StringValueEx(vkey);
40
+ vstr = StringValueEx(vstr);
41
+
42
+ res = true;
43
+ switch(method){
44
+ case TTPUT:
45
+ tcmdbput(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
46
+ break;
47
+ case TTPUTKEEP:
48
+ res = tcmdbputkeep(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
49
+ break;
50
+ case TTPUTCAT:
51
+ tcmdbputcat(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
52
+ break;
53
+ default:
54
+ res = false;
55
+ break;
56
+ }
57
+
58
+ return res ? Qtrue : Qfalse;
59
+ }
60
+
61
+ static VALUE cMDB_put(VALUE vself, VALUE vkey, VALUE vstr){
62
+ return cMDB_put_method(vself, vkey, vstr, TTPUT);
63
+ }
64
+
65
+ static VALUE cMDB_putkeep(VALUE vself, VALUE vkey, VALUE vstr){
66
+ return cMDB_put_method(vself, vkey, vstr, TTPUTKEEP);
67
+ }
68
+
69
+ static VALUE cMDB_putcat(VALUE vself, VALUE vkey, VALUE vstr){
70
+ return cMDB_put_method(vself, vkey, vstr, TTPUTCAT);
71
+ }
72
+
73
+ static VALUE cMDB_get(VALUE vself, VALUE vkey){
74
+ VALUE vval;
75
+ char *buf;
76
+ int bsiz;
77
+ TCMDB *db = cMDB_getdb(vself);
78
+
79
+ // this is ugly
80
+ vkey = StringValueEx(vkey);
81
+ if(!(buf = tcmdbget(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), &bsiz))){
82
+ return Qnil;
83
+ } else {
84
+ vval = StringRaw(buf, bsiz);
85
+ }
86
+
87
+ tcfree(buf);
88
+ return vval;
89
+ }
90
+
91
+ static VALUE cMDB_vsiz(VALUE vself, VALUE vkey){
92
+ TCMDB *db = cMDB_getdb(vself);
93
+
94
+ vkey = StringValueEx(vkey);
95
+ return INT2NUM(tcmdbvsiz(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)));
96
+ }
97
+
98
+ static VALUE cMDB_fetch(int argc, VALUE *argv, VALUE vself){
99
+ VALUE vkey, vrv, vforce;
100
+ rb_scan_args(argc, argv, "11", &vkey, &vforce);
101
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
102
+ if(vforce == Qnil) vforce = Qfalse;
103
+
104
+ if(vforce != Qfalse || (vrv = cMDB_get(vself, vkey)) == Qnil){
105
+ vrv = rb_yield(vkey);
106
+ cMDB_put(vself, vkey, vrv);
107
+ }
108
+ return vrv;
109
+ }
110
+
111
+ static VALUE cMDB_each(VALUE vself){
112
+ VALUE vrv;
113
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
114
+ TCMDB *db = cMDB_getdb(vself);
115
+ vrv = Qnil;
116
+ tcmdbiterinit(db);
117
+ int ksiz;
118
+ char *kbuf;
119
+ while((kbuf = tcmdbiternext(db, &ksiz)) != NULL){
120
+ int vsiz;
121
+ char *vbuf = tcmdbget(db, kbuf, ksiz, &vsiz);
122
+ vrv = rb_yield_values(2, rb_str_new2(kbuf), StringRaw(vbuf, vsiz));
123
+ tcfree(vbuf);
124
+ tcfree(kbuf);
125
+ }
126
+ return vrv;
127
+ }
128
+
129
+ static VALUE cMDB_each_value(VALUE vself){
130
+ VALUE vrv;
131
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
132
+ TCMDB *db = cMDB_getdb(vself);
133
+ vrv = Qnil;
134
+ tcmdbiterinit(db);
135
+ int ksiz;
136
+ char *kbuf;
137
+ while((kbuf = tcmdbiternext(db, &ksiz)) != NULL){
138
+ int vsiz;
139
+ char *vbuf = tcmdbget(db, kbuf, ksiz, &vsiz);
140
+ vrv = rb_yield_values(1, StringRaw(vbuf, vsiz));
141
+ tcfree(vbuf);
142
+ tcfree(kbuf);
143
+ }
144
+ return vrv;
145
+ }
146
+
147
+ static VALUE cMDB_values(VALUE vself){
148
+ VALUE vary;
149
+ TCMDB *db = cMDB_getdb(vself);
150
+ vary = rb_ary_new2(tcmdbrnum(db));
151
+ tcmdbiterinit(db);
152
+ int ksiz;
153
+ char *kbuf;
154
+ while((kbuf = tcmdbiternext(db, &ksiz)) != NULL){
155
+ int vsiz;
156
+ char *vbuf = tcmdbget(db, kbuf, ksiz, &vsiz);
157
+ rb_ary_push(vary, StringRaw(vbuf, vsiz));
158
+ tcfree(vbuf);
159
+ tcfree(kbuf);
160
+ }
161
+ return vary;
162
+ }
163
+
164
+ static VALUE cMDB_out(VALUE vself, VALUE vkey){
165
+ TCMDB *db = cMDB_getdb(vself);
166
+
167
+ vkey = StringValueEx(vkey);
168
+ return tcmdbout(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)) ? Qtrue : Qfalse;
169
+ }
170
+
171
+ static VALUE cMDB_check(VALUE vself, VALUE vkey){
172
+ TCMDB *db = cMDB_getdb(vself);
173
+
174
+ vkey = StringValueEx(vkey);
175
+ return tcmdbvsiz(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)) >= 0 ? Qtrue : Qfalse;
176
+ }
177
+
178
+ static VALUE cMDB_iterinit(VALUE vself){
179
+ TCMDB *db = cMDB_getdb(vself);
180
+
181
+ tcmdbiterinit(db);
182
+ return Qtrue;
183
+ }
184
+
185
+ static VALUE cMDB_iternext(VALUE vself){
186
+ VALUE vval;
187
+ char *vbuf;
188
+ TCMDB *db = cMDB_getdb(vself);
189
+
190
+ if(!(vbuf = tcmdbiternext2(db))) return Qnil;
191
+ vval = rb_str_new2(vbuf);
192
+ tcfree(vbuf);
193
+
194
+ return vval;
195
+ }
196
+
197
+ static VALUE cMDB_fwmkeys(int argc, VALUE *argv, VALUE vself){
198
+ VALUE vprefix, vmax, vary;
199
+ TCLIST *keys;
200
+ int max;
201
+ TCMDB *db = cMDB_getdb(vself);
202
+ rb_scan_args(argc, argv, "11", &vprefix, &vmax);
203
+
204
+ vprefix = StringValueEx(vprefix);
205
+ max = (vmax == Qnil) ? -1 : NUM2INT(vmax);
206
+ keys = tcmdbfwmkeys(db, RSTRING_PTR(vprefix), RSTRING_LEN(vprefix), max);
207
+ vary = listtovary(keys);
208
+ tclistdel(keys);
209
+ return vary;
210
+ }
211
+
212
+ static VALUE cMDB_keys(VALUE vself){
213
+ /*
214
+ VALUE vary;
215
+ char *kxstr;
216
+ TCMDB *db = cMDB_getdb(vself);
217
+ vary = rb_ary_new2(tcmdbrnum(db));
218
+ tcmdbiterinit(db);
219
+ while((kxstr = tcmdbiternext2(db)) != NULL){
220
+ rb_ary_push(vary, rb_str_new2(kxstr));
221
+ }
222
+ return vary;
223
+ */
224
+
225
+ // Using forward matching keys with an empty string is 100x faster than iternext+get
226
+ VALUE vary;
227
+ TCLIST *keys;
228
+ char *prefix;
229
+ TCMDB *db = cMDB_getdb(vself);
230
+ prefix = "";
231
+ keys = tcmdbfwmkeys2(db, prefix, -1);
232
+ vary = listtovary(keys);
233
+ tclistdel(keys);
234
+ return vary;
235
+ }
236
+
237
+ static VALUE cMDB_addint(VALUE vself, VALUE vkey, int inum){
238
+ TCMDB *db = cMDB_getdb(vself);
239
+ vkey = StringValueEx(vkey);
240
+
241
+ inum = tcmdbaddint(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), inum);
242
+ return inum == INT_MIN ? Qnil : INT2NUM(inum);
243
+ }
244
+
245
+ static VALUE cMDB_add_int(int argc, VALUE *argv, VALUE vself){
246
+ VALUE vkey, vnum;
247
+ int inum = 1;
248
+
249
+ rb_scan_args(argc, argv, "11", &vkey, &vnum);
250
+ vkey = StringValueEx(vkey);
251
+ if(NIL_P(vnum)) vnum = INT2NUM(inum);
252
+
253
+ return cMDB_addint(vself, vkey, NUM2INT(vnum));
254
+ }
255
+
256
+ static VALUE cMDB_get_int(VALUE vself, VALUE vkey){
257
+ return cMDB_addint(vself, vkey, 0);
258
+ }
259
+
260
+ static VALUE cMDB_adddouble(VALUE vself, VALUE vkey, double dnum){
261
+ TCMDB *db = cMDB_getdb(vself);
262
+
263
+ vkey = StringValueEx(vkey);
264
+ dnum = tcmdbadddouble(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), dnum);
265
+ return isnan(dnum) ? Qnil : rb_float_new(dnum);
266
+ }
267
+
268
+ static VALUE cMDB_add_double(int argc, VALUE *argv, VALUE vself){
269
+ VALUE vkey, vnum;
270
+ double dnum = 1.0;
271
+
272
+ rb_scan_args(argc, argv, "11", &vkey, &vnum);
273
+ vkey = StringValueEx(vkey);
274
+ if(NIL_P(vnum)) vnum = rb_float_new(dnum);
275
+
276
+ return cMDB_adddouble(vself, vkey, NUM2DBL(vnum));
277
+ }
278
+
279
+ static VALUE cMDB_get_double(VALUE vself, VALUE vkey){
280
+ return cMDB_adddouble(vself, vkey, 0.0);
281
+ }
282
+
283
+ static VALUE cMDB_vanish(VALUE vself){
284
+ TCMDB *db = cMDB_getdb(vself);
285
+
286
+ tcmdbvanish(db);
287
+ return Qtrue;
288
+ }
289
+
290
+ static VALUE cMDB_rnum(VALUE vself){
291
+ TCMDB *db = cMDB_getdb(vself);
292
+
293
+ return LL2NUM(tcmdbrnum(db));
294
+ }
295
+
296
+ static VALUE cMDB_empty(VALUE vself){
297
+ TCMDB *db = cMDB_getdb(vself);
298
+
299
+ return tcmdbrnum(db) < 1 ? Qtrue : Qfalse;
300
+ }
301
+
302
+ static VALUE cMDB_size(VALUE vself){
303
+ TCMDB *db = cMDB_getdb(vself);
304
+
305
+ return LL2NUM(tcmdbmsiz(db));
306
+ }
307
+
308
+ static VALUE cMDB_each_key(VALUE vself){
309
+ VALUE vrv;
310
+ char *kxstr;
311
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
312
+ TCMDB *db = cMDB_getdb(vself);
313
+ vrv = Qnil;
314
+ tcmdbiterinit(db);
315
+ while((kxstr = tcmdbiternext2(db)) != NULL){
316
+ vrv = rb_yield_values(1, rb_str_new2(kxstr));
317
+ }
318
+ return vrv;
319
+ }
320
+
321
+ void init_utils(){
322
+ rb_define_private_method(cMDB, "initialize", cMDB_initialize, -1);
323
+ rb_define_method(cMDB, "bnum", cMDB_bnum, 0);
324
+ rb_define_method(cMDB, "put", cMDB_put, 2);
325
+ rb_define_alias(cMDB, "[]=", "put");
326
+ rb_define_method(cMDB, "putkeep", cMDB_putkeep, 2);
327
+ rb_define_method(cMDB, "putcat", cMDB_putcat, 2);
328
+ rb_define_method(cMDB, "get", cMDB_get, 1);
329
+ rb_define_alias(cMDB, "[]", "get");
330
+ rb_define_method(cMDB, "vsiz", cMDB_vsiz, 1);
331
+ rb_define_method(cMDB, "out", cMDB_out, 1);
332
+ rb_define_method(cMDB, "check", cMDB_check, 1);
333
+ rb_define_alias(cMDB, "has_key?", "check");
334
+ rb_define_alias(cMDB, "key?", "check");
335
+ rb_define_alias(cMDB, "include?", "check");
336
+ rb_define_alias(cMDB, "member?", "check");
337
+ rb_define_method(cMDB, "iterinit", cMDB_iterinit, 0);
338
+ rb_define_method(cMDB, "iternext", cMDB_iternext, 0);
339
+ rb_define_method(cMDB, "fwmkeys", cMDB_fwmkeys, -1);
340
+ rb_define_method(cMDB, "keys", cMDB_keys, 0);
341
+ rb_define_method(cMDB, "add_int", cMDB_add_int, -1);
342
+ rb_define_alias(cMDB, "addint", "add_int");
343
+ rb_define_alias(cMDB, "increment", "add_int");
344
+ rb_define_method(cMDB, "get_int", cMDB_get_int, 1);
345
+ rb_define_method(cMDB, "add_double", cMDB_add_double, -1);
346
+ rb_define_alias(cMDB, "adddouble", "add_double");
347
+ rb_define_method(cMDB, "get_double", cMDB_get_double, 1);
348
+ rb_define_method(cMDB, "vanish", cMDB_vanish, 0);
349
+ rb_define_alias(cMDB, "clear", "vanish");
350
+ rb_define_method(cMDB, "rnum", cMDB_rnum, 0);
351
+ rb_define_alias(cMDB, "count", "rnum");
352
+ rb_define_alias(cMDB, "length", "rnum");
353
+ rb_define_method(cMDB, "size", cMDB_size, 0);
354
+ rb_define_method(cMDB, "empty?", cMDB_empty, 0);
355
+ rb_define_method(cMDB, "each_key", cMDB_each_key, 0);
356
+
357
+ rb_define_method(cMDB, "fetch", cMDB_fetch, -1);
358
+ rb_define_method(cMDB, "each", cMDB_each, 0);
359
+ rb_define_alias(cMDB, "each_pair", "each");
360
+ rb_define_method(cMDB, "each_value", cMDB_each_value, 0);
361
+ rb_define_method(cMDB, "values", cMDB_values, 0);
362
+ }
data/ext/tokyo_utils.h ADDED
@@ -0,0 +1,8 @@
1
+ #ifndef RUBY_TOKYO_UTILS
2
+ #define RUBY_TOKYO_UTILS
3
+
4
+ #include <tokyo_tyrant.h>
5
+
6
+ void init_utils();
7
+
8
+ #endif
@@ -0,0 +1,189 @@
1
+ require 'tokyo_tyrant'
2
+ # require 'hash_ring'
3
+ require 'fast_hash_ring'
4
+
5
+ module TokyoTyrant
6
+ module Balancer
7
+ class Base
8
+ def initialize(servers = [], weights = {})
9
+ servers.collect! do |server|
10
+ host, port = server.split(':')
11
+ klass.new(host, port.to_i)
12
+ end
13
+ @servers = servers
14
+ # @ring = HashRing.new(servers, weights)
15
+ @ring = FastHashRing.new(servers, weights)
16
+ end
17
+
18
+ def ring
19
+ @ring
20
+ end
21
+
22
+ def servers
23
+ @servers
24
+ end
25
+
26
+ def db_for_key(key)
27
+ ring.get_node(key)
28
+ end
29
+
30
+ # Delegate Methods
31
+ def get(key)
32
+ db = db_for_key(key)
33
+ db.get(key)
34
+ end
35
+ alias :[] :get
36
+
37
+ def add_int(key, i = 1)
38
+ db = db_for_key(key)
39
+ db.add_int(key, i)
40
+ end
41
+ alias :addint :add_int
42
+ alias :increment :add_int
43
+
44
+ def get_int(key)
45
+ db = db_for_key(key)
46
+ db.get_int(key)
47
+ end
48
+
49
+ def add_double(key, i = 1.0)
50
+ db = db_for_key(key)
51
+ db.add_double(key, i)
52
+ end
53
+ alias :adddouble :add_double
54
+
55
+ def get_double(key)
56
+ db = db_for_key(key)
57
+ db.get_double(key)
58
+ end
59
+
60
+ def put(key, value)
61
+ db = db_for_key(key)
62
+ db.put(key, value)
63
+ end
64
+ alias :[]= :put
65
+
66
+ def putkeep(key, value)
67
+ db = db_for_key(key)
68
+ db.putkeep(key, value)
69
+ end
70
+
71
+ def putcat(key, value)
72
+ db = db_for_key(key)
73
+ db.putcat(key, value)
74
+ end
75
+
76
+ def putshl(key, value, width)
77
+ db = db_for_key(key)
78
+ db.putshl(key, value, width)
79
+ end
80
+
81
+ def putnr(key, value)
82
+ db = db_for_key(key)
83
+ db.putnr(key, value)
84
+ end
85
+
86
+ def vsiz(key)
87
+ db = db_for_key(key)
88
+ db.vsiz(key)
89
+ end
90
+
91
+ def fetch(key, &block)
92
+ db = db_for_key(key)
93
+ db.fetch(key, &block)
94
+ end
95
+
96
+ def out(key)
97
+ db = db_for_key(key)
98
+ db.out(key)
99
+ end
100
+ alias :delete :out
101
+
102
+ # Aggregate Methods
103
+ def close
104
+ @servers.all?{ |server| server.close }
105
+ end
106
+
107
+ def rnum
108
+ @servers.collect{ |server| server.rnum }.inject(nil){ |sum,x| sum ? sum+x : x }
109
+ end
110
+ alias :count :rnum
111
+ alias :size :rnum
112
+ alias :length :rnum
113
+
114
+ def empty?
115
+ @servers.all?{ |server| server.empty? }
116
+ end
117
+
118
+ def vanish
119
+ @servers.all?{ |server| server.vanish }
120
+ end
121
+ alias :clear :vanish
122
+
123
+ def sync
124
+ @servers.each{ |server| server.sync }
125
+ end
126
+
127
+ def optimize(*args)
128
+ @servers.all?{ |server| server.optimize(*args) }
129
+ end
130
+
131
+ def check(key)
132
+ @servers.any?{ |server| server.check(key) }
133
+ end
134
+ alias :has_key? :check
135
+ alias :key? :check
136
+ alias :include? :check
137
+ alias :member? :check
138
+
139
+ def set_index(name, type)
140
+ @servers.all?{ |server| server.set_index(name, type) }
141
+ end
142
+
143
+ def fwmkeys(prefix, max = -1)
144
+ @servers.collect{ |server| server.fwmkeys(prefix, max) }.flatten
145
+ end
146
+
147
+ def delete_keys_with_prefix(prefix, max = -1)
148
+ @servers.each{ |server| server.delete_keys_with_prefix(prefix, max) }
149
+ nil
150
+ end
151
+ alias :dfwmkeys :delete_keys_with_prefix
152
+
153
+ def keys
154
+ @servers.collect{ |server| server.keys }.flatten.uniq
155
+ end
156
+
157
+ def values
158
+ @servers.collect{ |server| server.values }.flatten.uniq
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ module TokyoTyrant
165
+ module Balancer
166
+ class DB < Base
167
+ def klass
168
+ TokyoTyrant::DB
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ module TokyoTyrant
175
+ module Balancer
176
+ class Table < Base
177
+ def klass
178
+ TokyoTyrant::Table
179
+ end
180
+
181
+ def find(&block)
182
+ queries = @servers.collect{ |server|
183
+ server.prepare_query(&block)
184
+ }
185
+ TokyoTyrant::Query.parallel_search(*queries)
186
+ end
187
+ end
188
+ end
189
+ end
data/spec/spec_base.rb CHANGED
@@ -9,6 +9,7 @@ require 'rubygems'
9
9
  require 'fileutils'
10
10
  require 'bacon'
11
11
  require 'tokyo_tyrant'
12
+ require 'lib/tokyo_tyrant/balancer'
12
13
 
13
14
  $root.class.glob('spec/*_spec.rb').each {|l| load l}
14
15
 
@@ -0,0 +1,160 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.join('spec_base') unless $root
3
+
4
+ describe TokyoTyrant::Balancer::DB, "with an open database" do
5
+
6
+ before do
7
+ @db = TokyoTyrant::Balancer::DB.new(['127.0.0.1:45000'])
8
+ @db.clear
9
+ end
10
+
11
+ it "should not be nil" do
12
+ @db.should.not.be.nil
13
+ end
14
+
15
+ it "should close" do
16
+ @db.close.should.be.true
17
+ begin
18
+ @db.close
19
+ rescue => e
20
+ e.message.should == 'close error: invalid operation'
21
+ end
22
+ end
23
+
24
+ it "should optimize" do
25
+ @db.optimize.should.be.true
26
+ end
27
+
28
+ it "should save a value" do
29
+ @db['salad'] = 'bacon bits'
30
+ @db['salad'].should == 'bacon bits'
31
+ end
32
+
33
+ it "should return a value" do
34
+ @db['salad'] = 'bacon bits'
35
+ @db['salad'].should == 'bacon bits'
36
+ end
37
+
38
+ it "should accept binary data" do
39
+ s = "mango#{0.chr}salsa"
40
+ @db.put(s, s).should.be.true
41
+ @db[s].should.equal(s)
42
+ end
43
+
44
+ it "should out a value" do
45
+ k = 'tomato'
46
+ @db[k] = 'green'
47
+ @db.out(k).should.be.true
48
+ @db[k].should.be.nil
49
+ @db.out(k).should.be.false
50
+ end
51
+
52
+ it "should get a value size" do
53
+ k = 'cereal'
54
+ v = 'granola'
55
+ @db[k] = v
56
+ @db.vsiz(k).should == v.size
57
+ end
58
+
59
+ it "should check a key" do
60
+ k = 'fruit'
61
+ @db[k] = 'banana'
62
+ @db.check(k).should.be.true
63
+ @db.out(k)
64
+ @db.check(k).should.be.false
65
+ end
66
+
67
+ it "should get forward matching keys" do
68
+ @db['apples/royalgala'] = '4173'
69
+ @db['apples/grannysmith'] = '4139'
70
+ @db['bananas/yellow'] = '4011'
71
+ @db['oranges/shamouti'] = '3027'
72
+ @db['grapefruit/deepred'] = '4288'
73
+ @db.fwmkeys('apples').sort.should == ["apples/grannysmith", "apples/royalgala"]
74
+ end
75
+
76
+ it "should delete forward matching keys" do
77
+ @db['apples/royalgala'] = '4173'
78
+ @db['apples/grannysmith'] = '4139'
79
+ @db['bananas/yellow'] = '4011'
80
+ @db['oranges/shamouti'] = '3027'
81
+ @db['grapefruit/deepred'] = '4288'
82
+ @db.delete_keys_with_prefix('apples').should == nil
83
+ @db.fwmkeys('apples').should.be.empty
84
+ @db.keys.sort.should == ['bananas/yellow', 'grapefruit/deepred', 'oranges/shamouti']
85
+ end
86
+
87
+ it "should get all keys" do
88
+ keys = %w[appetizers entree dessert]
89
+ values = %w[chips chicken\ caeser\ salad ice\ cream]
90
+ keys.each_with_index do |k,i|
91
+ @db[k] = values[i]
92
+ end
93
+ @db.keys.should == keys
94
+ end
95
+
96
+ it "should get all values" do
97
+ keys = %w[appetizers entree dessert]
98
+ values = %w[chips chicken\ caeser\ salad ice\ cream]
99
+ keys.each_with_index do |k,i|
100
+ @db[k] = values[i]
101
+ end
102
+ @db.values.should == values
103
+ end
104
+
105
+ it "should vanish all records" do
106
+ @db['chocolate'] = 'dark'
107
+ @db['tea'] = 'earl grey'
108
+ @db.empty?.should.be.false
109
+ @db.vanish.should.be.true
110
+ @db.empty?.should.be.true
111
+ end
112
+
113
+ it "should count records" do
114
+ @db['hummus'] = 'chickpeas'
115
+ @db['falafel'] = 'chickpeas'
116
+ @db.rnum.should == 2
117
+ end
118
+
119
+ it "should fetch a record" do
120
+ @db.out('beer')
121
+ @db.fetch('beer'){ 'heineken' }.should == 'heineken'
122
+ @db['beer'].should == 'heineken'
123
+ @db.fetch('beer'){ 'becks' }.should == 'heineken'
124
+ end
125
+
126
+ it "should add serialized integer values" do
127
+ key = 'counter'
128
+ @db.out(key)
129
+ @db.add_int(key, 1).should == 1
130
+ @db.add_int(key, 1).should == 2
131
+ @db.get_int(key).should == 2
132
+ end
133
+
134
+ it "should increment integer values" do
135
+ key = 'counter'
136
+ @db.out(key)
137
+ @db.increment(key).should == 1
138
+ @db.increment(key, 2).should == 3
139
+ @db.get_int(key).should == 3
140
+ end
141
+
142
+ it "should add serialized double values" do
143
+ key = 'counter'
144
+ @db.out(key)
145
+ @db.add_double(key, 1.0).should.be.close?(1.0, 0.005)
146
+ @db.add_double(key, 1.0).should.be.close?(2.0, 0.005)
147
+ @db.get_double(key).should.be.close?(2.0, 0.005)
148
+ end
149
+
150
+ it "should serialize objects that respond to to_tokyo_tyrant" do
151
+ class Thing
152
+ def to_tokyo_tyrant
153
+ "success"
154
+ end
155
+ end
156
+
157
+ @db["to_tokyo_tyrant"] = Thing.new
158
+ @db["to_tokyo_tyrant"].should == "success"
159
+ end
160
+ end
@@ -0,0 +1,177 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.join('spec_base') unless $root
3
+
4
+ describe TokyoTyrant::Balancer::Table, "with an open database" do
5
+
6
+ before do
7
+ @db = TokyoTyrant::Balancer::Table.new(['127.0.0.1:45001'])
8
+ @db.clear
9
+ end
10
+
11
+ it "should not be nil" do
12
+ @db.should.not.be.nil
13
+ end
14
+
15
+ it "should close" do
16
+ @db.close.should.be.true
17
+ begin
18
+ @db.close
19
+ rescue => e
20
+ e.message.should == 'close error: invalid operation'
21
+ end
22
+ end
23
+
24
+ it "should optimize" do
25
+ @db.optimize.should.be.true
26
+ end
27
+
28
+ it "should save a value" do
29
+ value = { 'lettuce' => 'Red Leaf', 'dressing' => 'ranch', 'extra' => 'bacon bits' }
30
+ @db['salad'] = value
31
+ @db['salad'].should == value
32
+ end
33
+
34
+ it "should return a value" do
35
+ value = { 'lettuce' => 'Red Leaf', 'dressing' => 'ranch', 'extra' => 'bacon bits' }
36
+ @db['salad'] = value
37
+ @db['salad'].should == value
38
+ end
39
+
40
+ it "should accept binary data" do
41
+ s = "mango#{0.chr}salsa"
42
+ h = { s => s }
43
+ @db.put(s, h).should.be.true
44
+ @db[s].should.equal(h)
45
+ end
46
+
47
+ it "should out a value" do
48
+ k = 'tomato'
49
+ @db[k] = { 'color' => 'red', 'variety' => 'beefy' }
50
+ @db.out(k).should.be.true
51
+ @db[k].should.be.nil
52
+ @db.out(k).should.be.false
53
+ end
54
+
55
+ it "should check a key" do
56
+ k = 'fruit'
57
+ @db[k] = { 'name' => 'banana', 'code' => '4011' }
58
+ @db.check(k).should.be.true
59
+ @db.out(k)
60
+ @db.check(k).should.be.false
61
+ end
62
+
63
+ it "should get forward matching keys" do
64
+ @db['apples/royalgala'] = { 'code' => '4173', 'color' => 'red-yellow' }
65
+ @db['apples/grannysmith'] = { 'code' => '4139', 'color' => 'green' }
66
+ @db['bananas/yellow'] = { 'code' => '4011', 'color' => 'yellow' }
67
+ @db['oranges/shamouti'] = { 'code' => '3027', 'color' => 'orange' }
68
+ @db['grapefruit/deepred'] = { 'code' => '4288', 'color' => 'yellow/pink' }
69
+ @db.fwmkeys('apples').sort.should == ["apples/grannysmith", "apples/royalgala"]
70
+ end
71
+
72
+ it "should delete forward matching keys" do
73
+ @db['apples/royalgala'] = { 'code' => '4173', 'color' => 'red-yellow' }
74
+ @db['apples/grannysmith'] = { 'code' => '4139', 'color' => 'green' }
75
+ @db['bananas/yellow'] = { 'code' => '4011', 'color' => 'yellow' }
76
+ @db['oranges/shamouti'] = { 'code' => '3027', 'color' => 'orange' }
77
+ @db['grapefruit/deepred'] = { 'code' => '4288', 'color' => 'yellow/pink' }
78
+ @db.delete_keys_with_prefix('apples').should == nil
79
+ @db.fwmkeys('apples').should.be.empty
80
+ @db.keys.sort.should == ['bananas/yellow', 'grapefruit/deepred', 'oranges/shamouti']
81
+ end
82
+
83
+ it "should get all keys" do
84
+ keys = %w[appetizers entree dessert]
85
+ values = [{ 'cheap' => 'chips', 'expensive' => 'sample everything platter' },
86
+ { 'cheap' => 'hoagie', 'expensive' => 'steak' },
87
+ { 'cheap' => 'water ice', 'expensive' => 'cheesecake' }]
88
+
89
+ keys.each_with_index do |k,i|
90
+ @db[k] = values[i]
91
+ end
92
+ @db.keys.should == keys
93
+ end
94
+
95
+ it "should get all values" do
96
+ keys = %w[appetizers entree dessert]
97
+ values = [{ 'cheap' => 'chips', 'expensive' => 'sample everything platter' },
98
+ { 'cheap' => 'hoagie', 'expensive' => 'steak' },
99
+ { 'cheap' => 'water ice', 'expensive' => 'cheesecake' }]
100
+
101
+ keys.each_with_index do |k,i|
102
+ @db[k] = values[i]
103
+ end
104
+ @db.values.should == values
105
+ end
106
+
107
+ it "should vanish all records" do
108
+ @db['chocolate'] = { 'type' => 'dark' }
109
+ @db['tea'] = { 'type' => 'earl grey' }
110
+ @db.empty?.should.be.false
111
+ @db.vanish.should.be.true
112
+ @db.empty?.should.be.true
113
+ end
114
+
115
+ it "should count records" do
116
+ @db['hummus'] = { 'ingredients' => 'chickpeas,garlic' }
117
+ @db['falafel'] = { 'ingredients' => 'chickpeas,herbs' }
118
+ @db.rnum.should == 2
119
+ end
120
+
121
+ it "should fetch a record" do
122
+ @db.out('beer')
123
+ @db.fetch('beer'){{ 'import' => 'heineken' }}.should == { 'import' => 'heineken' }
124
+ @db['beer'].should == { 'import' => 'heineken' }
125
+ @db.fetch('beer'){{ 'import' => 'becks' }}.should == { 'import' => 'heineken' }
126
+ end
127
+
128
+ it "should add serialized integer values" do
129
+ key = 'counter'
130
+ @db.out(key)
131
+ @db[key] = { 'title' => 'Bean Counter' }
132
+ @db.add_int(key, 1).should == 1
133
+ @db.add_int(key, 1).should == 2
134
+ @db.get_int(key).should == 2
135
+ @db[key].should == { 'title' => 'Bean Counter', '_num' => "2" }
136
+ end
137
+
138
+ it "should increment integer values" do
139
+ key = 'counter'
140
+ @db.out(key)
141
+ @db[key] = { 'title' => 'Bean Counter' }
142
+ @db.increment(key).should == 1
143
+ @db.increment(key, 2).should == 3
144
+ @db.get_int(key).should == 3
145
+ @db[key].should == { 'title' => 'Bean Counter', '_num' => "3" }
146
+ end
147
+
148
+ it "should add serialized double values" do
149
+ key = 'counter'
150
+ @db.out(key)
151
+ @db[key] = { 'title' => 'Bean Counter' }
152
+ @db.add_double(key, 1.0).should.be.close?(1.0, 0.005)
153
+ @db.add_double(key, 1.0).should.be.close?(2.0, 0.005)
154
+ @db.get_double(key).should.be.close?(2.0, 0.005)
155
+ @db[key].should == { 'title' => 'Bean Counter', '_num' => "2" }
156
+ end
157
+
158
+ it "should set an index" do
159
+ key = 'counter'
160
+ 50.times do |i|
161
+ @db["key#{i}"] = { 'title' => %w{rice beans corn}.sort_by{rand}.first,
162
+ 'description' => 'a whole protein' }
163
+ end
164
+ @db.set_index('title', :lexical).should.be.true
165
+ end
166
+
167
+ it "should serialize objects that respond to to_tokyo_tyrant" do
168
+ class Thing
169
+ def to_tokyo_tyrant
170
+ "success"
171
+ end
172
+ end
173
+
174
+ @db["to_tokyo_tyrant"] = { "thing" => Thing.new }
175
+ @db["to_tokyo_tyrant"].should == { "thing" => "success" }
176
+ end
177
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-tokyotyrant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: "0.4"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flinn
@@ -9,10 +9,19 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-17 00:00:00 -04:00
12
+ date: 2009-11-29 00:00:00 -05:00
13
13
  default_executable:
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fast_hash_ring
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.1
24
+ version:
16
25
  description:
17
26
  email: flinn@actsasflinn.com
18
27
  executables: []
@@ -35,15 +44,21 @@ files:
35
44
  - ext/tokyo_tyrant_query.h
36
45
  - ext/tokyo_tyrant_table.c
37
46
  - ext/tokyo_tyrant_table.h
47
+ - ext/tokyo_utils.c
48
+ - ext/tokyo_utils.h
49
+ - lib/tokyo_tyrant/balancer.rb
38
50
  - spec/ext.lua
39
51
  - spec/plu_db.rb
40
52
  - spec/spec.rb
41
53
  - spec/spec_base.rb
42
54
  - spec/start_tyrants.sh
43
55
  - spec/stop_tyrants.sh
56
+ - spec/tokyo_tyrant_balancer_db_spec.rb
57
+ - spec/tokyo_tyrant_balancer_table_spec.rb
44
58
  - spec/tokyo_tyrant_query_spec.rb
45
59
  - spec/tokyo_tyrant_spec.rb
46
60
  - spec/tokyo_tyrant_table_spec.rb
61
+ - benchmarks/balancer.rb
47
62
  - benchmarks/bulk_db.rb
48
63
  - benchmarks/bulk_table.rb
49
64
  - benchmarks/db.rb