tokyomessenger 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/COPYING +504 -0
  2. data/README.rdoc +224 -0
  3. data/Rakefile +72 -0
  4. data/benchmarks/balancer.rb +101 -0
  5. data/benchmarks/bulk_db.rb +92 -0
  6. data/benchmarks/bulk_table.rb +104 -0
  7. data/benchmarks/db.rb +131 -0
  8. data/benchmarks/table.rb +186 -0
  9. data/ext/a.h +496 -0
  10. data/ext/extconf.rb +27 -0
  11. data/ext/md5.c +381 -0
  12. data/ext/md5.h +101 -0
  13. data/ext/tc_myconf.c +493 -0
  14. data/ext/tc_myconf.h +543 -0
  15. data/ext/tcadb.c +4339 -0
  16. data/ext/tcadb.h +533 -0
  17. data/ext/tcbdb.c +4180 -0
  18. data/ext/tcbdb.h +1086 -0
  19. data/ext/tcfdb.c +2746 -0
  20. data/ext/tcfdb.h +842 -0
  21. data/ext/tchdb.c +5153 -0
  22. data/ext/tchdb.h +856 -0
  23. data/ext/tcrdb.c +2637 -0
  24. data/ext/tcrdb.h +785 -0
  25. data/ext/tctdb.c +6199 -0
  26. data/ext/tctdb.h +1070 -0
  27. data/ext/tcutil.c +10528 -0
  28. data/ext/tcutil.h +4166 -0
  29. data/ext/tokyo_messenger.c +147 -0
  30. data/ext/tokyo_messenger.h +49 -0
  31. data/ext/tokyo_messenger_db.c +227 -0
  32. data/ext/tokyo_messenger_db.h +8 -0
  33. data/ext/tokyo_messenger_module.c +453 -0
  34. data/ext/tokyo_messenger_module.h +10 -0
  35. data/ext/tokyo_messenger_query.c +226 -0
  36. data/ext/tokyo_messenger_query.h +9 -0
  37. data/ext/tokyo_messenger_table.c +319 -0
  38. data/ext/tokyo_messenger_table.h +8 -0
  39. data/ext/tt_myconf.c +169 -0
  40. data/ext/tt_myconf.h +408 -0
  41. data/ext/ttutil.c +1509 -0
  42. data/ext/ttutil.h +480 -0
  43. data/lib/tokyo_messenger/balancer.rb +188 -0
  44. data/spec/ext.lua +4 -0
  45. data/spec/plu_db.rb +538 -0
  46. data/spec/spec.rb +1 -0
  47. data/spec/spec_base.rb +17 -0
  48. data/spec/start_tyrants.sh +36 -0
  49. data/spec/stop_tyrants.sh +9 -0
  50. data/spec/tokyo_tyrant_balancer_db_spec.rb +160 -0
  51. data/spec/tokyo_tyrant_balancer_table_spec.rb +177 -0
  52. data/spec/tokyo_tyrant_query_spec.rb +159 -0
  53. data/spec/tokyo_tyrant_spec.rb +254 -0
  54. data/spec/tokyo_tyrant_table_spec.rb +301 -0
  55. metadata +117 -0
@@ -0,0 +1,147 @@
1
+ #include "tokyo_messenger.h"
2
+
3
+ extern VALUE StringRaw(const char *buf, int bsiz){
4
+ VALUE vval;
5
+ int i;
6
+ vval = rb_str_buf_new2("");
7
+ char s[5];
8
+
9
+ for(i=0;i<bsiz;i++){
10
+ char c = *buf++;
11
+ s[0] = c;
12
+ rb_str_buf_cat(vval, s, 1);
13
+ }
14
+ // buf -= bsiz;
15
+ // rb_str_buf_cat2(vval, "");
16
+ return vval;
17
+ }
18
+
19
+ extern VALUE StringValueEx(VALUE vobj){
20
+ if (rb_respond_to(vobj, rb_intern("to_tokyo_tyrant"))) {
21
+ return rb_convert_type(vobj, T_STRING, "String", "to_tokyo_tyrant");
22
+ } else if (rb_respond_to(vobj, rb_intern("to_s"))) {
23
+ return rb_convert_type(vobj, T_STRING, "String", "to_s");
24
+ } else {
25
+ rb_raise(rb_eArgError, "can't stringify object");
26
+ }
27
+ return StringValue(vobj);
28
+ }
29
+
30
+ extern TCLIST *varytolist(VALUE vary){
31
+ VALUE vval;
32
+ TCLIST *list;
33
+ int i, num;
34
+ num = RARRAY_LEN(vary);
35
+ list = tclistnew2(num);
36
+ for(i = 0; i < num; i++){
37
+ vval = rb_ary_entry(vary, i);
38
+ vval = StringValueEx(vval);
39
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
40
+ }
41
+ return list;
42
+ }
43
+
44
+ extern VALUE listtovary(TCLIST *list){
45
+ VALUE vary;
46
+ const char *vbuf;
47
+ int i, num, vsiz;
48
+ num = tclistnum(list);
49
+ vary = rb_ary_new2(num);
50
+ for(i = 0; i < num; i++){
51
+ vbuf = tclistval(list, i, &vsiz);
52
+ rb_ary_push(vary, rb_str_new(vbuf, vsiz));
53
+ }
54
+ return vary;
55
+ }
56
+
57
+ extern TCMAP *vhashtomap(VALUE vhash){
58
+ VALUE vkeys, vkey, vval;
59
+ TCMAP *map;
60
+ int i, num;
61
+ map = tcmapnew2(31);
62
+ vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
63
+ num = RARRAY_LEN(vkeys);
64
+ for(i = 0; i < num; i++){
65
+ vkey = rb_ary_entry(vkeys, i);
66
+ vval = rb_hash_aref(vhash, vkey);
67
+ vkey = StringValueEx(vkey);
68
+ vval = StringValueEx(vval);
69
+ tcmapput(map, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vval), RSTRING_LEN(vval));
70
+ }
71
+ return map;
72
+ }
73
+
74
+ extern VALUE maptovhash(TCMAP *map){
75
+ const char *kbuf;
76
+ int ksiz, vsiz;
77
+ VALUE vhash;
78
+ vhash = rb_hash_new();
79
+ tcmapiterinit(map);
80
+ while((kbuf = tcmapiternext(map, &ksiz)) != NULL){
81
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
82
+ rb_hash_aset(vhash, rb_str_new(kbuf, ksiz), StringRaw(vbuf, vsiz));
83
+ }
84
+ return vhash;
85
+ }
86
+
87
+ extern TCMAP *varytomap(VALUE vary){
88
+ int i;
89
+ TCLIST *keys;
90
+ TCMAP *recs = tcmapnew();
91
+ keys = varytolist(vary);
92
+ for(i = 0; i < tclistnum(keys); i++){
93
+ int ksiz;
94
+ const char *kbuf = tclistval(keys, i, &ksiz);
95
+ tcmapput(recs, kbuf, ksiz, "", 0);
96
+ }
97
+ tclistdel(keys);
98
+ return recs;
99
+ }
100
+
101
+ extern TCLIST *vhashtolist(VALUE vhash){
102
+ /*
103
+ Seems like something like this might work just as well
104
+ vary = rb_hash_to_a(vhash);
105
+ vary = rb_ary_flatten(vary);
106
+ args = varytolist(vary);
107
+ */
108
+
109
+ VALUE vkeys, vkey, vval;
110
+ TCLIST *list;
111
+ int i, num;
112
+ vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
113
+ num = RARRAY_LEN(vkeys);
114
+ list = tclistnew2(num);
115
+ for(i = 0; i < num; i++){
116
+ vkey = rb_ary_entry(vkeys, i);
117
+ vval = rb_hash_aref(vhash, vkey);
118
+ vkey = StringValueEx(vkey);
119
+ vval = StringValueEx(vval);
120
+ tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
121
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
122
+ }
123
+ return list;
124
+ }
125
+
126
+ VALUE mTokyoMessenger;
127
+ VALUE eTokyoMessengerError;
128
+ VALUE cDB;
129
+ VALUE cTable;
130
+ VALUE cQuery;
131
+
132
+ void Init_tokyo_messenger(){
133
+ mTokyoMessenger = rb_define_module("TokyoMessenger");
134
+ eTokyoMessengerError = rb_define_class("TokyoMessengerError", rb_eStandardError);
135
+ init_mod();
136
+
137
+ cDB = rb_define_class_under(mTokyoMessenger, "DB", rb_cObject);
138
+ rb_include_module(cDB, mTokyoMessenger);
139
+ init_db();
140
+
141
+ cTable = rb_define_class_under(mTokyoMessenger, "Table", rb_cObject);
142
+ rb_include_module(cTable, mTokyoMessenger);
143
+ init_table();
144
+
145
+ cQuery = rb_define_class_under(mTokyoMessenger, "Query", rb_cObject);
146
+ init_query();
147
+ }
@@ -0,0 +1,49 @@
1
+ #ifndef RUBY_TOKYOMESSENGER
2
+ #define RUBY_TOKYOMESSENGER
3
+
4
+ #include <ruby.h>
5
+ #include <string.h>
6
+ #include <math.h>
7
+ #include <time.h>
8
+ #include <locale.h>
9
+
10
+ #include "tcrdb.h"
11
+ #include "tokyo_messenger_module.h"
12
+ #include "tokyo_messenger_db.h"
13
+ #include "tokyo_messenger_table.h"
14
+ #include "tokyo_messenger_query.h"
15
+
16
+ #define RDBVNDATA "@rdb"
17
+ #define RDBQRYVNDATA "@rdbquery"
18
+ #define NUMBUFSIZ 32
19
+ #define TTPUT 0
20
+ #define TTPUTKEEP 1
21
+ #define TTPUTCAT 2
22
+ #define TTPUTNR 3
23
+
24
+ #if !defined(RSTRING_PTR)
25
+ #define RSTRING_PTR(TC_s) (RSTRING(TC_s)->ptr)
26
+ #endif
27
+ #if !defined(RSTRING_LEN)
28
+ #define RSTRING_LEN(TC_s) (RSTRING(TC_s)->len)
29
+ #endif
30
+ #if !defined(RARRAY_LEN)
31
+ #define RARRAY_LEN(TC_a) (RARRAY(TC_a)->len)
32
+ #endif
33
+
34
+ extern VALUE mTokyoMessenger;
35
+ extern VALUE eTokyoMessengerError;
36
+ extern VALUE cDB;
37
+ extern VALUE cTable;
38
+ extern VALUE cQuery;
39
+
40
+ extern VALUE StringRaw(const char *buf, int bsiz);
41
+ extern VALUE StringValueEx(VALUE vobj);
42
+ extern TCLIST *varytolist(VALUE vary);
43
+ extern VALUE listtovary(TCLIST *list);
44
+ extern TCMAP *vhashtomap(VALUE vhash);
45
+ extern VALUE maptovhash(TCMAP *map);
46
+ extern TCMAP *varytomap(VALUE vhash);
47
+ extern TCLIST *vhashtolist(VALUE vhash);
48
+
49
+ #endif
@@ -0,0 +1,227 @@
1
+ #include "tokyo_messenger_db.h"
2
+
3
+ static VALUE cDB_put_method(VALUE vself, VALUE vkey, VALUE vstr, int method){
4
+ bool res;
5
+ TCRDB *db = mTokyoMessenger_getdb(vself);
6
+
7
+ vkey = StringValueEx(vkey);
8
+ vstr = StringValueEx(vstr);
9
+
10
+ switch(method){
11
+ case TTPUT:
12
+ res = tcrdbput(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
13
+ break;
14
+ case TTPUTKEEP:
15
+ res = tcrdbputkeep(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
16
+ break;
17
+ case TTPUTCAT:
18
+ res = tcrdbputcat(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
19
+ break;
20
+ case TTPUTNR:
21
+ res = tcrdbputnr(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
22
+ break;
23
+ default:
24
+ res = false;
25
+ break;
26
+ }
27
+
28
+ if(!res) mTokyoMessenger_exception(vself);
29
+
30
+ return Qtrue;
31
+ }
32
+
33
+ static VALUE cDB_put(VALUE vself, VALUE vkey, VALUE vstr){
34
+ return cDB_put_method(vself, vkey, vstr, TTPUT);
35
+ }
36
+
37
+ static VALUE cDB_mput(VALUE vself, VALUE vhash){
38
+ VALUE vary;
39
+ TCLIST *list, *args;
40
+ TCRDB *db = mTokyoMessenger_getdb(vself);
41
+
42
+ args = vhashtolist(vhash);
43
+ list = tcrdbmisc(db, "putlist", 0, args);
44
+ vary = listtovary(list);
45
+ tclistdel(args);
46
+ tclistdel(list);
47
+ return vary;
48
+ }
49
+
50
+ static VALUE cDB_putkeep(VALUE vself, VALUE vkey, VALUE vstr){
51
+ return cDB_put_method(vself, vkey, vstr, TTPUTKEEP);
52
+ }
53
+
54
+ static VALUE cDB_putcat(VALUE vself, VALUE vkey, VALUE vstr){
55
+ return cDB_put_method(vself, vkey, vstr, TTPUTCAT);
56
+ }
57
+
58
+ static VALUE cDB_putnr(VALUE vself, VALUE vkey, VALUE vstr){
59
+ return cDB_put_method(vself, vkey, vstr, TTPUTNR);
60
+ }
61
+
62
+ static VALUE cDB_putshl(VALUE vself, VALUE vkey, VALUE vstr, VALUE vwidth){
63
+ bool res;
64
+ TCRDB *db = mTokyoMessenger_getdb(vself);
65
+
66
+ vkey = StringValueEx(vkey);
67
+ vstr = StringValueEx(vstr);
68
+
69
+ res = tcrdbputshl(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr), FIXNUM_P(vwidth));
70
+
71
+ if(!res) mTokyoMessenger_exception(vself);
72
+
73
+ return Qtrue;
74
+ }
75
+
76
+ static VALUE cDB_get(VALUE vself, VALUE vkey){
77
+ VALUE vval;
78
+ char *buf;
79
+ int bsiz, ecode;
80
+ TCRDB *db = mTokyoMessenger_getdb(vself);
81
+
82
+ // this is ugly
83
+ vkey = StringValueEx(vkey);
84
+ if(!(buf = tcrdbget(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), &bsiz))){
85
+ if ((ecode = tcrdbecode(db))) {
86
+ if (ecode != TTENOREC) mTokyoMessenger_exception(vself);
87
+ }
88
+ return Qnil;
89
+ } else {
90
+ vval = StringRaw(buf, bsiz);
91
+ }
92
+
93
+ tcfree(buf);
94
+ return vval;
95
+ }
96
+
97
+ static VALUE cDB_mget(int argc, VALUE *argv, VALUE vself){
98
+ VALUE vkeys, vhash, vvalue;
99
+ TCMAP *recs;
100
+ TCRDB *db = mTokyoMessenger_getdb(vself);
101
+ rb_scan_args(argc, argv, "*", &vkeys);
102
+
103
+ // I really hope there is a better way to do this
104
+ if (RARRAY_LEN(vkeys) == 1) {
105
+ vvalue = rb_ary_entry(vkeys, 0);
106
+ switch (TYPE(vvalue)){
107
+ case T_STRING:
108
+ case T_FIXNUM:
109
+ break;
110
+ case T_ARRAY:
111
+ vkeys = vvalue;
112
+ break;
113
+ case T_STRUCT: // range is not a T_STRUCT instead of a T_OBJECT in ruby1.9?
114
+ case T_OBJECT:
115
+ vkeys = rb_convert_type(vvalue, T_ARRAY, "Array", "to_a");
116
+ break;
117
+ }
118
+ }
119
+
120
+ Check_Type(vkeys, T_ARRAY);
121
+
122
+ recs = varytomap(vkeys);
123
+ if(!tcrdbget3(db, recs)) return Qnil;
124
+ vhash = maptovhash(recs);
125
+ tcmapdel(recs);
126
+ return vhash;
127
+ }
128
+
129
+ static VALUE cDB_vsiz(VALUE vself, VALUE vkey){
130
+ TCRDB *db = mTokyoMessenger_getdb(vself);
131
+
132
+ vkey = StringValueEx(vkey);
133
+ return INT2NUM(tcrdbvsiz(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)));
134
+ }
135
+
136
+ static VALUE cDB_fetch(int argc, VALUE *argv, VALUE vself){
137
+ VALUE vkey, vrv, vforce;
138
+ rb_scan_args(argc, argv, "11", &vkey, &vforce);
139
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
140
+ if(vforce == Qnil) vforce = Qfalse;
141
+
142
+ if(vforce != Qfalse || (vrv = cDB_get(vself, vkey)) == Qnil){
143
+ vrv = rb_yield(vkey);
144
+ cDB_put(vself, vkey, vrv);
145
+ }
146
+ return vrv;
147
+ }
148
+
149
+ static VALUE cDB_each(VALUE vself){
150
+ VALUE vrv;
151
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
152
+ TCRDB *db = mTokyoMessenger_getdb(vself);
153
+ vrv = Qnil;
154
+ tcrdbiterinit(db);
155
+ int ksiz;
156
+ char *kbuf;
157
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
158
+ int vsiz;
159
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
160
+ vrv = rb_yield_values(2, rb_str_new2(kbuf), StringRaw(vbuf, vsiz));
161
+ tcfree(vbuf);
162
+ tcfree(kbuf);
163
+ }
164
+ return vrv;
165
+ }
166
+
167
+ static VALUE cDB_each_value(VALUE vself){
168
+ VALUE vrv;
169
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
170
+ TCRDB *db = mTokyoMessenger_getdb(vself);
171
+ vrv = Qnil;
172
+ tcrdbiterinit(db);
173
+ int ksiz;
174
+ char *kbuf;
175
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
176
+ int vsiz;
177
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
178
+ vrv = rb_yield_values(1, StringRaw(vbuf, vsiz));
179
+ tcfree(vbuf);
180
+ tcfree(kbuf);
181
+ }
182
+ return vrv;
183
+ }
184
+
185
+ static VALUE cDB_values(VALUE vself){
186
+ VALUE vary;
187
+ TCRDB *db = mTokyoMessenger_getdb(vself);
188
+ vary = rb_ary_new2(tcrdbrnum(db));
189
+ tcrdbiterinit(db);
190
+ int ksiz;
191
+ char *kbuf;
192
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
193
+ int vsiz;
194
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
195
+ rb_ary_push(vary, StringRaw(vbuf, vsiz));
196
+ tcfree(vbuf);
197
+ tcfree(kbuf);
198
+ }
199
+ return vary;
200
+ }
201
+
202
+ void init_db(){
203
+ rb_define_method(cDB, "mput", cDB_mput, 1);
204
+ rb_define_alias(cDB, "lput", "mput"); // Rufus Compat
205
+ rb_define_method(cDB, "put", cDB_put, 2);
206
+ rb_define_alias(cDB, "[]=", "put");
207
+ rb_define_method(cDB, "putkeep", cDB_putkeep, 2);
208
+ rb_define_method(cDB, "putcat", cDB_putcat, 2);
209
+ rb_define_method(cDB, "putshl", cDB_putshl, 3);
210
+ rb_define_method(cDB, "putnr", cDB_putnr, 2);
211
+ rb_define_method(cDB, "get", cDB_get, 1);
212
+ rb_define_alias(cDB, "[]", "get");
213
+ rb_define_method(cDB, "mget", cDB_mget, -1);
214
+ rb_define_alias(cDB, "lget", "mget"); // Rufus Compat
215
+ rb_define_method(cDB, "vsiz", cDB_vsiz, 1);
216
+ /*
217
+ rb_define_method(cDB, "check_value", cDB_check_value, 1);
218
+ rb_define_alias(cDB, "has_value?", "check_value");
219
+ rb_define_alias(cDB, "value?", "check_value");
220
+ */
221
+
222
+ rb_define_method(cDB, "fetch", cDB_fetch, -1);
223
+ rb_define_method(cDB, "each", cDB_each, 0);
224
+ rb_define_alias(cDB, "each_pair", "each");
225
+ rb_define_method(cDB, "each_value", cDB_each_value, 0);
226
+ rb_define_method(cDB, "values", cDB_values, 0);
227
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef RUBY_TOKYOMESSENGER_DB
2
+ #define RUBY_TOKYOMESSENGER_DB
3
+
4
+ #include "tokyo_messenger.h"
5
+
6
+ void init_db();
7
+
8
+ #endif
@@ -0,0 +1,453 @@
1
+ #include "tokyo_messenger_db.h"
2
+
3
+ extern TCRDB *mTokyoMessenger_getdb(VALUE vself){
4
+ TCRDB *db;
5
+ Data_Get_Struct(rb_iv_get(vself, RDBVNDATA), TCRDB, db);
6
+ return db;
7
+ }
8
+
9
+ extern void mTokyoMessenger_exception(VALUE vself){
10
+ int ecode;
11
+ TCRDB *db = mTokyoMessenger_getdb(vself);
12
+
13
+ ecode = tcrdbecode(db);
14
+ rb_raise(eTokyoMessengerError, tcrdberrmsg(ecode));
15
+ }
16
+
17
+ static void mTokyoMessenger_free(TCRDB *db){
18
+ tcrdbdel(db);
19
+ }
20
+
21
+ static VALUE mTokyoMessenger_server(VALUE vself){
22
+ return rb_iv_get(vself, "@server");
23
+ }
24
+
25
+ static VALUE mTokyoMessenger_close(VALUE vself){
26
+ int ecode;
27
+ TCRDB *db = mTokyoMessenger_getdb(vself);
28
+
29
+ if(!tcrdbclose(db)){
30
+ ecode = tcrdbecode(db);
31
+ rb_raise(eTokyoMessengerError, "close error: %s", tcrdberrmsg(ecode));
32
+ }
33
+ return Qtrue;
34
+ }
35
+
36
+ static VALUE mTokyoMessenger_connect(VALUE vself){
37
+ VALUE host, port, timeout, retry, server;
38
+ int ecode;
39
+ TCRDB *db = mTokyoMessenger_getdb(vself);
40
+
41
+ host = rb_iv_get(vself, "@host");
42
+ port = rb_iv_get(vself, "@port");
43
+ timeout = rb_iv_get(vself, "@timeout");
44
+ retry = rb_iv_get(vself, "@retry");
45
+
46
+ if((!tcrdbtune(db, NUM2DBL(timeout), retry == Qtrue ? RDBTRECON : 0)) ||
47
+ (!tcrdbopen(db, RSTRING_PTR(host), FIX2INT(port)))){
48
+ ecode = tcrdbecode(db);
49
+ rb_raise(eTokyoMessengerError, "open error: %s", tcrdberrmsg(ecode));
50
+ }
51
+
52
+ server = rb_str_new2(tcrdbexpr(db));
53
+ rb_iv_set(vself, "@server", server);
54
+
55
+ return Qtrue;
56
+ }
57
+
58
+ static VALUE mTokyoMessenger_reconnect(VALUE vself){
59
+ TCRDB *db = mTokyoMessenger_getdb(vself);
60
+ if(db->fd != -1) mTokyoMessenger_close(vself);
61
+ db = tcrdbnew();
62
+ rb_iv_set(vself, RDBVNDATA, Data_Wrap_Struct(rb_cObject, 0, mTokyoMessenger_free, db));
63
+
64
+ return mTokyoMessenger_connect(vself);
65
+ }
66
+
67
+ static VALUE mTokyoMessenger_initialize(int argc, VALUE *argv, VALUE vself){
68
+ VALUE host, port, timeout, retry;
69
+ TCRDB *db;
70
+
71
+ rb_scan_args(argc, argv, "04", &host, &port, &timeout, &retry);
72
+ if(NIL_P(host)) host = rb_str_new2("127.0.0.1");
73
+ if(NIL_P(port)) port = INT2FIX(1978);
74
+ if(NIL_P(timeout)) timeout = rb_float_new(0.0);
75
+ if(NIL_P(retry)) retry = Qfalse;
76
+
77
+ rb_iv_set(vself, "@host", host);
78
+ rb_iv_set(vself, "@port", port);
79
+ rb_iv_set(vself, "@timeout", timeout);
80
+ rb_iv_set(vself, "@retry", retry);
81
+
82
+ db = tcrdbnew();
83
+ rb_iv_set(vself, RDBVNDATA, Data_Wrap_Struct(rb_cObject, 0, mTokyoMessenger_free, db));
84
+
85
+ return mTokyoMessenger_connect(vself);
86
+ }
87
+
88
+ static VALUE mTokyoMessenger_errmsg(int argc, VALUE *argv, VALUE vself){
89
+ VALUE vecode;
90
+ const char *msg;
91
+ int ecode;
92
+ TCRDB *db = mTokyoMessenger_getdb(vself);
93
+ rb_scan_args(argc, argv, "01", &vecode);
94
+
95
+ ecode = (vecode == Qnil) ? tcrdbecode(db) : NUM2INT(vecode);
96
+ msg = tcrdberrmsg(ecode);
97
+ return rb_str_new2(msg);
98
+ }
99
+
100
+ static VALUE mTokyoMessenger_ecode(VALUE vself){
101
+ TCRDB *db = mTokyoMessenger_getdb(vself);
102
+
103
+ return INT2NUM(tcrdbecode(db));
104
+ }
105
+
106
+ static VALUE mTokyoMessenger_out(VALUE vself, VALUE vkey){
107
+ TCRDB *db = mTokyoMessenger_getdb(vself);
108
+
109
+ vkey = StringValueEx(vkey);
110
+ return tcrdbout(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)) ? Qtrue : Qfalse;
111
+ }
112
+
113
+ // TODO: merge out and mout?
114
+ static VALUE mTokyoMessenger_outlist(int argc, VALUE *argv, VALUE vself){
115
+ VALUE vkeys, vary, vvalue;
116
+ TCLIST *list, *result;
117
+ TCRDB *db = mTokyoMessenger_getdb(vself);
118
+ rb_scan_args(argc, argv, "*", &vkeys);
119
+
120
+ // I really hope there is a better way to do this
121
+ if (RARRAY_LEN(vkeys) == 1) {
122
+ vvalue = rb_ary_entry(vkeys, 0);
123
+ switch (TYPE(vvalue)){
124
+ case T_STRING:
125
+ case T_FIXNUM:
126
+ break;
127
+ case T_ARRAY:
128
+ vkeys = vvalue;
129
+ break;
130
+ case T_OBJECT:
131
+ vkeys = rb_convert_type(vvalue, T_ARRAY, "Array", "to_a");
132
+ break;
133
+ }
134
+ }
135
+ Check_Type(vkeys, T_ARRAY);
136
+
137
+ list = varytolist(vkeys);
138
+ result = tcrdbmisc(db, "outlist", 0, list);
139
+ tclistdel(list);
140
+ vary = listtovary(result);
141
+ tclistdel(result);
142
+ return vary;
143
+ }
144
+
145
+ static VALUE mTokyoMessenger_check(VALUE vself, VALUE vkey){
146
+ TCRDB *db = mTokyoMessenger_getdb(vself);
147
+
148
+ vkey = StringValueEx(vkey);
149
+ return tcrdbvsiz(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)) >= 0 ? Qtrue : Qfalse;
150
+ }
151
+
152
+ static VALUE mTokyoMessenger_iterinit(VALUE vself){
153
+ TCRDB *db = mTokyoMessenger_getdb(vself);
154
+
155
+ return tcrdbiterinit(db) ? Qtrue : Qfalse;
156
+ }
157
+
158
+ static VALUE mTokyoMessenger_iternext(VALUE vself){
159
+ VALUE vval;
160
+ char *vbuf;
161
+ TCRDB *db = mTokyoMessenger_getdb(vself);
162
+
163
+ if(!(vbuf = tcrdbiternext2(db))) return Qnil;
164
+ vval = rb_str_new2(vbuf);
165
+ tcfree(vbuf);
166
+
167
+ return vval;
168
+ }
169
+
170
+ static VALUE mTokyoMessenger_fwmkeys(int argc, VALUE *argv, VALUE vself){
171
+ VALUE vprefix, vmax, vary;
172
+ TCLIST *keys;
173
+ int max;
174
+ TCRDB *db = mTokyoMessenger_getdb(vself);
175
+ rb_scan_args(argc, argv, "11", &vprefix, &vmax);
176
+
177
+ vprefix = StringValueEx(vprefix);
178
+ max = (vmax == Qnil) ? -1 : NUM2INT(vmax);
179
+ keys = tcrdbfwmkeys(db, RSTRING_PTR(vprefix), RSTRING_LEN(vprefix), max);
180
+ vary = listtovary(keys);
181
+ tclistdel(keys);
182
+ return vary;
183
+ }
184
+
185
+ static VALUE mTokyoMessenger_delete_keys_with_prefix(int argc, VALUE *argv, VALUE vself){
186
+ VALUE vprefix, vmax;
187
+ TCLIST *keys;
188
+ int max;
189
+ TCRDB *db = mTokyoMessenger_getdb(vself);
190
+ rb_scan_args(argc, argv, "11", &vprefix, &vmax);
191
+
192
+ vprefix = StringValueEx(vprefix);
193
+ max = (vmax == Qnil) ? -1 : NUM2INT(vmax);
194
+ keys = tcrdbfwmkeys(db, RSTRING_PTR(vprefix), RSTRING_LEN(vprefix), max);
195
+ tcrdbmisc(db, "outlist", 0, keys);
196
+ tclistdel(keys);
197
+ return Qnil;
198
+ }
199
+
200
+ static VALUE mTokyoMessenger_keys(VALUE vself){
201
+ /*
202
+ VALUE vary;
203
+ char *kxstr;
204
+ TCRDB *db = mTokyoMessenger_getdb(vself);
205
+ vary = rb_ary_new2(tcrdbrnum(db));
206
+ tcrdbiterinit(db);
207
+ while((kxstr = tcrdbiternext2(db)) != NULL){
208
+ rb_ary_push(vary, rb_str_new2(kxstr));
209
+ }
210
+ return vary;
211
+ */
212
+
213
+ // Using forward matching keys with an empty string is 100x faster than iternext+get
214
+ VALUE vary;
215
+ TCLIST *keys;
216
+ char *prefix;
217
+ TCRDB *db = mTokyoMessenger_getdb(vself);
218
+ prefix = "";
219
+ keys = tcrdbfwmkeys2(db, prefix, -1);
220
+ vary = listtovary(keys);
221
+ tclistdel(keys);
222
+ return vary;
223
+ }
224
+
225
+ static VALUE mTokyoMessenger_addint(VALUE vself, VALUE vkey, int inum){
226
+ TCRDB *db = mTokyoMessenger_getdb(vself);
227
+ vkey = StringValueEx(vkey);
228
+
229
+ inum = tcrdbaddint(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), inum);
230
+ return inum == INT_MIN ? Qnil : INT2NUM(inum);
231
+ }
232
+
233
+ static VALUE mTokyoMessenger_add_int(int argc, VALUE *argv, VALUE vself){
234
+ VALUE vkey, vnum;
235
+ int inum = 1;
236
+
237
+ rb_scan_args(argc, argv, "11", &vkey, &vnum);
238
+ vkey = StringValueEx(vkey);
239
+ if(NIL_P(vnum)) vnum = INT2NUM(inum);
240
+
241
+ return mTokyoMessenger_addint(vself, vkey, NUM2INT(vnum));
242
+ }
243
+
244
+ static VALUE mTokyoMessenger_get_int(VALUE vself, VALUE vkey){
245
+ return mTokyoMessenger_addint(vself, vkey, 0);
246
+ }
247
+
248
+ static VALUE mTokyoMessenger_adddouble(VALUE vself, VALUE vkey, double dnum){
249
+ TCRDB *db = mTokyoMessenger_getdb(vself);
250
+
251
+ vkey = StringValueEx(vkey);
252
+ dnum = tcrdbadddouble(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), dnum);
253
+ return isnan(dnum) ? Qnil : rb_float_new(dnum);
254
+ }
255
+
256
+ static VALUE mTokyoMessenger_add_double(int argc, VALUE *argv, VALUE vself){
257
+ VALUE vkey, vnum;
258
+ double dnum = 1.0;
259
+
260
+ rb_scan_args(argc, argv, "11", &vkey, &vnum);
261
+ vkey = StringValueEx(vkey);
262
+ if(NIL_P(vnum)) vnum = rb_float_new(dnum);
263
+
264
+ return mTokyoMessenger_adddouble(vself, vkey, NUM2DBL(vnum));
265
+ }
266
+
267
+ static VALUE mTokyoMessenger_get_double(VALUE vself, VALUE vkey){
268
+ return mTokyoMessenger_adddouble(vself, vkey, 0.0);
269
+ }
270
+
271
+ static VALUE mTokyoMessenger_sync(VALUE vself){
272
+ TCRDB *db = mTokyoMessenger_getdb(vself);
273
+
274
+ return tcrdbsync(db) ? Qtrue : Qfalse;
275
+ }
276
+
277
+ static VALUE mTokyoMessenger_optimize(int argc, VALUE *argv, VALUE vself){
278
+ VALUE vparams;
279
+ const char *params = NULL;
280
+ TCRDB *db = mTokyoMessenger_getdb(vself);
281
+ rb_scan_args(argc, argv, "01", &vparams);
282
+ if(NIL_P(vparams)) vparams = Qnil;
283
+ if(vparams != Qnil) params = RSTRING_PTR(vparams);
284
+
285
+ return tcrdboptimize(db, params) ? Qtrue : Qfalse;
286
+ }
287
+
288
+ static VALUE mTokyoMessenger_vanish(VALUE vself){
289
+ TCRDB *db = mTokyoMessenger_getdb(vself);
290
+
291
+ return tcrdbvanish(db) ? Qtrue : Qfalse;
292
+ }
293
+
294
+ static VALUE mTokyoMessenger_copy(VALUE vself, VALUE path){
295
+ TCRDB *db = mTokyoMessenger_getdb(vself);
296
+
297
+ Check_Type(path, T_STRING);
298
+ return tcrdbcopy(db, RSTRING_PTR(path)) ? Qtrue : Qfalse;
299
+ }
300
+
301
+ static VALUE mTokyoMessenger_restore(VALUE vself, VALUE vpath, VALUE vts, VALUE vopts){
302
+ uint64_t ts;
303
+ int opts;
304
+ TCRDB *db = mTokyoMessenger_getdb(vself);
305
+
306
+ Check_Type(vpath, T_STRING);
307
+ ts = (uint64_t) FIX2INT(vts);
308
+ opts = FIX2INT(vopts);
309
+ return tcrdbrestore(db, RSTRING_PTR(vpath), ts, opts) ? Qtrue : Qfalse;
310
+ }
311
+
312
+ static VALUE mTokyoMessenger_setmst(VALUE vself, VALUE vhost, VALUE vport, VALUE vts, VALUE vopts){
313
+ uint64_t ts;
314
+ int opts;
315
+ TCRDB *db = mTokyoMessenger_getdb(vself);
316
+
317
+ ts = (uint64_t) FIX2INT(vts);
318
+ opts = FIX2INT(vopts);
319
+ return tcrdbsetmst(db, RSTRING_PTR(vhost), FIX2INT(vport), ts, opts) ? Qtrue : Qfalse;
320
+ }
321
+
322
+ static VALUE mTokyoMessenger_rnum(VALUE vself){
323
+ TCRDB *db = mTokyoMessenger_getdb(vself);
324
+
325
+ return LL2NUM(tcrdbrnum(db));
326
+ }
327
+
328
+ static VALUE mTokyoMessenger_empty(VALUE vself){
329
+ TCRDB *db = mTokyoMessenger_getdb(vself);
330
+
331
+ return tcrdbrnum(db) < 1 ? Qtrue : Qfalse;
332
+ }
333
+
334
+ static VALUE mTokyoMessenger_size(VALUE vself){
335
+ TCRDB *db = mTokyoMessenger_getdb(vself);
336
+
337
+ return LL2NUM(tcrdbsize(db));
338
+ }
339
+
340
+ static VALUE mTokyoMessenger_stat(VALUE vself){
341
+ TCRDB *db = mTokyoMessenger_getdb(vself);
342
+
343
+ return rb_str_new2(tcrdbstat(db));
344
+ }
345
+
346
+ static VALUE mTokyoMessenger_misc(int argc, VALUE *argv, VALUE vself){
347
+ VALUE vname, vopts, vargs, vary;
348
+ TCLIST *list, *args;
349
+ TCRDB *db = mTokyoMessenger_getdb(vself);
350
+ rb_scan_args(argc, argv, "13", &vname, &vopts, &vargs);
351
+
352
+ args = varytolist(vargs);
353
+ vname = StringValueEx(vname);
354
+
355
+ list = tcrdbmisc(db, RSTRING_PTR(vname), NUM2INT(vopts), args);
356
+ vary = listtovary(list);
357
+ tclistdel(list);
358
+ return vary;
359
+ }
360
+
361
+ static VALUE mTokyoMessenger_ext(VALUE vself, VALUE vext, VALUE vkey, VALUE vvalue){
362
+ int vsiz;
363
+ char *vbuf;
364
+ TCRDB *db = mTokyoMessenger_getdb(vself);
365
+ vext = StringValueEx(vext);
366
+ vkey = StringValueEx(vkey);
367
+ vvalue = StringValueEx(vvalue);
368
+
369
+ if(!(vbuf = tcrdbext(db, RSTRING_PTR(vext), 0, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vvalue), RSTRING_LEN(vvalue), &vsiz))){
370
+ return Qnil;
371
+ } else {
372
+ return rb_str_new(vbuf, vsiz);
373
+ }
374
+ }
375
+
376
+ static VALUE mTokyoMessenger_each_key(VALUE vself){
377
+ VALUE vrv;
378
+ char *kxstr;
379
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
380
+ TCRDB *db = mTokyoMessenger_getdb(vself);
381
+ vrv = Qnil;
382
+ tcrdbiterinit(db);
383
+ while((kxstr = tcrdbiternext2(db)) != NULL){
384
+ vrv = rb_yield_values(1, rb_str_new2(kxstr));
385
+ }
386
+ return vrv;
387
+ }
388
+
389
+ void init_mod(){
390
+ rb_define_const(mTokyoMessenger, "ESUCCESS", INT2NUM(TTESUCCESS));
391
+ rb_define_const(mTokyoMessenger, "EINVALID", INT2NUM(TTEINVALID));
392
+ rb_define_const(mTokyoMessenger, "ENOHOST", INT2NUM(TTENOHOST));
393
+ rb_define_const(mTokyoMessenger, "EREFUSED", INT2NUM(TTEREFUSED));
394
+ rb_define_const(mTokyoMessenger, "ESEND", INT2NUM(TTESEND));
395
+ rb_define_const(mTokyoMessenger, "ERECV", INT2NUM(TTERECV));
396
+ rb_define_const(mTokyoMessenger, "EKEEP", INT2NUM(TTEKEEP));
397
+ rb_define_const(mTokyoMessenger, "ENOREC", INT2NUM(TTENOREC));
398
+ rb_define_const(mTokyoMessenger, "EMISC", INT2NUM(TTEMISC));
399
+
400
+ rb_define_const(mTokyoMessenger, "ITLEXICAL", INT2NUM(RDBITLEXICAL));
401
+ rb_define_const(mTokyoMessenger, "ITDECIMAL", INT2NUM(RDBITDECIMAL));
402
+ rb_define_const(mTokyoMessenger, "ITVOID", INT2NUM(RDBITVOID));
403
+ rb_define_const(mTokyoMessenger, "ITKEEP", INT2NUM(RDBITKEEP));
404
+
405
+ rb_define_private_method(mTokyoMessenger, "initialize", mTokyoMessenger_initialize, -1);
406
+ rb_define_private_method(mTokyoMessenger, "connect", mTokyoMessenger_connect, 0);
407
+ rb_define_method(mTokyoMessenger, "reconnect", mTokyoMessenger_reconnect, 0);
408
+ rb_define_method(mTokyoMessenger, "server", mTokyoMessenger_server, 0);
409
+ rb_define_method(mTokyoMessenger, "close", mTokyoMessenger_close, 0);
410
+ rb_define_method(mTokyoMessenger, "errmsg", mTokyoMessenger_errmsg, -1);
411
+ rb_define_method(mTokyoMessenger, "ecode", mTokyoMessenger_ecode, 0);
412
+ rb_define_method(mTokyoMessenger, "out", mTokyoMessenger_out, 1);
413
+ rb_define_alias(mTokyoMessenger, "delete", "out"); // Rufus Compat
414
+ rb_define_method(mTokyoMessenger, "outlist", mTokyoMessenger_outlist, -1);
415
+ rb_define_alias(mTokyoMessenger, "mdelete", "outlist");
416
+ rb_define_alias(mTokyoMessenger, "ldelete", "outlist"); // Rufus Compat
417
+ rb_define_method(mTokyoMessenger, "check", mTokyoMessenger_check, 1);
418
+ rb_define_alias(mTokyoMessenger, "has_key?", "check");
419
+ rb_define_alias(mTokyoMessenger, "key?", "check");
420
+ rb_define_alias(mTokyoMessenger, "include?", "check");
421
+ rb_define_alias(mTokyoMessenger, "member?", "check");
422
+ rb_define_method(mTokyoMessenger, "iterinit", mTokyoMessenger_iterinit, 0);
423
+ rb_define_method(mTokyoMessenger, "iternext", mTokyoMessenger_iternext, 0);
424
+ rb_define_method(mTokyoMessenger, "fwmkeys", mTokyoMessenger_fwmkeys, -1);
425
+ rb_define_method(mTokyoMessenger, "delete_keys_with_prefix", mTokyoMessenger_delete_keys_with_prefix, -1);// Rufus Compat
426
+ rb_define_alias(mTokyoMessenger, "dfwmkeys", "delete_keys_with_prefix");
427
+ rb_define_method(mTokyoMessenger, "keys", mTokyoMessenger_keys, 0);
428
+ rb_define_method(mTokyoMessenger, "add_int", mTokyoMessenger_add_int, -1);
429
+ rb_define_alias(mTokyoMessenger, "addint", "add_int");
430
+ rb_define_alias(mTokyoMessenger, "increment", "add_int");
431
+ rb_define_method(mTokyoMessenger, "get_int", mTokyoMessenger_get_int, 1);
432
+ rb_define_method(mTokyoMessenger, "add_double", mTokyoMessenger_add_double, -1);
433
+ rb_define_alias(mTokyoMessenger, "adddouble", "add_double");
434
+ rb_define_method(mTokyoMessenger, "get_double", mTokyoMessenger_get_double, 1);
435
+ rb_define_method(mTokyoMessenger, "sync", mTokyoMessenger_sync, 0);
436
+ rb_define_method(mTokyoMessenger, "optimize", mTokyoMessenger_optimize, -1);
437
+ rb_define_method(mTokyoMessenger, "vanish", mTokyoMessenger_vanish, 0);
438
+ rb_define_alias(mTokyoMessenger, "clear", "vanish");
439
+ rb_define_method(mTokyoMessenger, "copy", mTokyoMessenger_copy, 1);
440
+ rb_define_method(mTokyoMessenger, "restore", mTokyoMessenger_restore, 2);
441
+ rb_define_method(mTokyoMessenger, "setmst", mTokyoMessenger_setmst, 4);
442
+ rb_define_method(mTokyoMessenger, "rnum", mTokyoMessenger_rnum, 0);
443
+ rb_define_alias(mTokyoMessenger, "count", "rnum");
444
+ rb_define_method(mTokyoMessenger, "empty?", mTokyoMessenger_empty, 0);
445
+ rb_define_alias(mTokyoMessenger, "size", "rnum"); // Rufus Compat
446
+ rb_define_method(mTokyoMessenger, "db_size", mTokyoMessenger_size, 0); // Rufus Compat
447
+ rb_define_alias(mTokyoMessenger, "length", "size");
448
+ rb_define_method(mTokyoMessenger, "stat", mTokyoMessenger_stat, 0);
449
+ rb_define_method(mTokyoMessenger, "misc", mTokyoMessenger_misc, -1);
450
+ rb_define_method(mTokyoMessenger, "ext", mTokyoMessenger_ext, 3);
451
+ rb_define_alias(mTokyoMessenger, "run", "ext");
452
+ rb_define_method(mTokyoMessenger, "each_key", mTokyoMessenger_each_key, 0);
453
+ }