ruby-tokyotyrant 0.3.1 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
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