ruby-tokyotyrant 0.4 → 0.5
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 +23 -3
- data/Rakefile +3 -5
- data/benchmarks/bulk_db.rb +23 -0
- data/benchmarks/bulk_table.rb +51 -3
- data/benchmarks/db.rb +61 -22
- data/benchmarks/table.rb +62 -20
- data/ext/tokyo_tyrant.c +75 -3
- data/ext/tokyo_tyrant.h +18 -3
- data/{lib → ext}/tokyo_tyrant/balancer.rb +3 -6
- data/ext/tokyo_tyrant/rails/tokyo_tyrant_store.rb +106 -0
- data/ext/tokyo_tyrant_bdb.c +138 -0
- data/ext/tokyo_tyrant_bdb.h +8 -0
- data/ext/tokyo_tyrant_consistent_hash.c +34 -0
- data/ext/tokyo_tyrant_consistent_hash.h +8 -0
- data/ext/tokyo_tyrant_db.c +3 -3
- data/ext/tokyo_tyrant_module.c +75 -24
- data/ext/tokyo_tyrant_module.h +1 -1
- data/ext/tokyo_tyrant_table.c +2 -2
- data/spec/spec_base.rb +1 -1
- data/spec/start_tyrants.sh +7 -0
- data/spec/stop_tyrants.sh +2 -1
- data/spec/tokyo_tyrant_bdb_spec.rb +34 -0
- data/spec/tokyo_tyrant_spec.rb +10 -0
- metadata +20 -19
- data/ext/tokyo_utils.c +0 -362
- data/ext/tokyo_utils.h +0 -8
data/ext/tokyo_tyrant.h
CHANGED
@@ -6,12 +6,15 @@
|
|
6
6
|
#include <math.h>
|
7
7
|
#include <time.h>
|
8
8
|
#include <locale.h>
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <unistd.h>
|
9
11
|
#include <tcrdb.h>
|
10
12
|
#include <tokyo_tyrant_module.h>
|
11
13
|
#include <tokyo_tyrant_db.h>
|
14
|
+
#include <tokyo_tyrant_bdb.h>
|
12
15
|
#include <tokyo_tyrant_table.h>
|
13
16
|
#include <tokyo_tyrant_query.h>
|
14
|
-
#include <
|
17
|
+
#include <tokyo_tyrant_consistent_hash.h>
|
15
18
|
|
16
19
|
#define RDBVNDATA "@rdb"
|
17
20
|
#define RDBQRYVNDATA "@rdbquery"
|
@@ -20,7 +23,6 @@
|
|
20
23
|
#define TTPUTKEEP 1
|
21
24
|
#define TTPUTCAT 2
|
22
25
|
#define TTPUTNR 3
|
23
|
-
#define MDBVNDATA "@mdb"
|
24
26
|
|
25
27
|
#if !defined(RSTRING_PTR)
|
26
28
|
#define RSTRING_PTR(TC_s) (RSTRING(TC_s)->ptr)
|
@@ -33,11 +35,22 @@
|
|
33
35
|
#endif
|
34
36
|
|
35
37
|
extern VALUE mTokyoTyrant;
|
38
|
+
|
36
39
|
extern VALUE eTokyoTyrantError;
|
40
|
+
extern VALUE eTokyoTyrantErrorInvalid;
|
41
|
+
extern VALUE eTokyoTyrantErrorNoHost;
|
42
|
+
extern VALUE eTokyoTyrantErrorRefused;
|
43
|
+
extern VALUE eTokyoTyrantErrorSend;
|
44
|
+
extern VALUE eTokyoTyrantErrorReceive;
|
45
|
+
extern VALUE eTokyoTyrantErrorKeep;
|
46
|
+
extern VALUE eTokyoTyrantErrorNoRecord;
|
47
|
+
extern VALUE eTokyoTyrantErrorMisc;
|
48
|
+
|
37
49
|
extern VALUE cDB;
|
50
|
+
extern VALUE cBDB;
|
38
51
|
extern VALUE cTable;
|
39
52
|
extern VALUE cQuery;
|
40
|
-
extern VALUE
|
53
|
+
extern VALUE cConstistentHash;
|
41
54
|
|
42
55
|
extern VALUE StringRaw(const char *buf, int bsiz);
|
43
56
|
extern VALUE StringValueEx(VALUE vobj);
|
@@ -47,5 +60,7 @@ extern TCMAP *vhashtomap(VALUE vhash);
|
|
47
60
|
extern VALUE maptovhash(TCMAP *map);
|
48
61
|
extern TCMAP *varytomap(VALUE vhash);
|
49
62
|
extern TCLIST *vhashtolist(VALUE vhash);
|
63
|
+
extern TCLIST *vhashtoputlist(VALUE vhash);
|
64
|
+
extern VALUE listtovhash(TCLIST *list);
|
50
65
|
|
51
66
|
#endif
|
@@ -1,18 +1,15 @@
|
|
1
1
|
require 'tokyo_tyrant'
|
2
|
-
# require 'hash_ring'
|
3
|
-
require 'fast_hash_ring'
|
4
2
|
|
5
3
|
module TokyoTyrant
|
6
4
|
module Balancer
|
7
5
|
class Base
|
8
|
-
def initialize(servers = []
|
6
|
+
def initialize(servers = [])
|
9
7
|
servers.collect! do |server|
|
10
8
|
host, port = server.split(':')
|
11
9
|
klass.new(host, port.to_i)
|
12
10
|
end
|
13
11
|
@servers = servers
|
14
|
-
|
15
|
-
@ring = FastHashRing.new(servers, weights)
|
12
|
+
@ring = TokyoTyrant::ConstistentHash.new(servers)
|
16
13
|
end
|
17
14
|
|
18
15
|
def ring
|
@@ -24,7 +21,7 @@ module TokyoTyrant
|
|
24
21
|
end
|
25
22
|
|
26
23
|
def db_for_key(key)
|
27
|
-
ring.
|
24
|
+
ring.db_for_key(key)
|
28
25
|
end
|
29
26
|
|
30
27
|
# Delegate Methods
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'tokyo_tyrant/balancer'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Cache
|
5
|
+
# A cache store implementation which stores data in Tokyo Tyrant:
|
6
|
+
# http://1978th.net/tokyotyrant/
|
7
|
+
#
|
8
|
+
# Special features:
|
9
|
+
# - Clustering and load balancing. One can specify multiple servers,
|
10
|
+
# and TokyoTyrantStore will load balance between all available servers.
|
11
|
+
# - Per-request in memory cache for all communication with the Tokyo Tyrant server(s).
|
12
|
+
class TokyoTyrantStore < Store
|
13
|
+
def self.build_servers(*addresses)
|
14
|
+
addresses = addresses.flatten
|
15
|
+
options = addresses.extract_options!
|
16
|
+
addresses = ["127.0.0.1:1978"] if addresses.empty?
|
17
|
+
TokyoTyrant::Balancer::DB.new(addresses, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates a new TokyoTyrantStore object, with the given server
|
21
|
+
# addresses. Each address is either a host name, or a host-with-port string
|
22
|
+
# in the form of "host_name:port". For example:
|
23
|
+
#
|
24
|
+
# ActiveSupport::Cache::TokyoTyrantStore.new("localhost", "server-downstairs.localnetwork:8229")
|
25
|
+
#
|
26
|
+
# If no addresses are specified, then TokyoTyrantStore will connect to
|
27
|
+
# localhost port 1978 (the default tokyo tyrant port).
|
28
|
+
def initialize(*addresses)
|
29
|
+
if addresses.first.respond_to?(:get)
|
30
|
+
@data = addresses.first
|
31
|
+
else
|
32
|
+
@data = self.class.build_servers(*addresses)
|
33
|
+
end
|
34
|
+
|
35
|
+
extend Strategy::LocalCache
|
36
|
+
end
|
37
|
+
|
38
|
+
def read(key, options = nil) # :nodoc:
|
39
|
+
super
|
40
|
+
@data.get(key)
|
41
|
+
rescue TokyoTyrantError => e
|
42
|
+
logger.error("TokyoTyrantError (#{e}): #{e.message}")
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Writes a value to the cache.
|
47
|
+
#
|
48
|
+
# Possible options:
|
49
|
+
# - +:unless_exist+ - set to true if you don't want to update the cache
|
50
|
+
# if the key is already set.
|
51
|
+
# the cache. See ActiveSupport::Cache::Store#write for an example.
|
52
|
+
def write(key, value, options = nil)
|
53
|
+
super
|
54
|
+
method = options && options[:unless_exist] ? :putkeep : :put
|
55
|
+
@data.send(method, key, value)
|
56
|
+
rescue TokyoTyrantError => e
|
57
|
+
logger.error("TokyoTyrantError (#{e}): #{e.message}")
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete(key, options = nil) # :nodoc:
|
62
|
+
super
|
63
|
+
@data.delete(key)
|
64
|
+
rescue TokyoTyrantError => e
|
65
|
+
logger.error("TokyoTyrantError (#{e}): #{e.message}")
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
def exist?(key, options = nil) # :nodoc:
|
70
|
+
@data.has_key?(key)
|
71
|
+
end
|
72
|
+
|
73
|
+
def increment(key, amount = 1) # :nodoc:
|
74
|
+
log("incrementing", key, amount)
|
75
|
+
@data.add_int(key, amount)
|
76
|
+
rescue TokyoTyrantError
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def decrement(key, amount = 1) # :nodoc:
|
81
|
+
log("decrement", key, amount)
|
82
|
+
@data.add_int(key, amount * -1)
|
83
|
+
rescue TokyoTyrantError
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def integer(key) # :nodoc:
|
88
|
+
log("integer", key)
|
89
|
+
@data.get_int(integer)
|
90
|
+
rescue TokyoTyrantError
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def delete_matched(matcher, options = nil) # :nodoc:
|
95
|
+
super
|
96
|
+
@data.delete_keys_with_prefix(matcher)
|
97
|
+
rescue TokyoTyrantError
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def clear
|
102
|
+
@data.clear
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#include <tokyo_tyrant_bdb.h>
|
2
|
+
|
3
|
+
static VALUE cBDB_put_method(VALUE vself, VALUE vkey, VALUE vval, char *command, bool bang){
|
4
|
+
VALUE vres;
|
5
|
+
TCLIST *list, *result;
|
6
|
+
TCRDB *db = mTokyoTyrant_getdb(vself);
|
7
|
+
|
8
|
+
vkey = StringValueEx(vkey);
|
9
|
+
vval = StringValueEx(vval);
|
10
|
+
|
11
|
+
list = tclistnew2(2);
|
12
|
+
tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
|
13
|
+
tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
|
14
|
+
if ((result = tcrdbmisc(db, command, 0, list)) != NULL){
|
15
|
+
if (tclistnum(result) == 0){
|
16
|
+
vres = Qtrue;
|
17
|
+
} else {
|
18
|
+
vres = listtovary(result);
|
19
|
+
}
|
20
|
+
} else {
|
21
|
+
if (bang) mTokyoTyrant_exception(vself, NULL);
|
22
|
+
vres = Qfalse;
|
23
|
+
}
|
24
|
+
tclistdel(list);
|
25
|
+
return vres;
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE cBDB_putlist(VALUE vself, VALUE vhash){
|
29
|
+
VALUE vary;
|
30
|
+
TCLIST *list, *result;
|
31
|
+
TCRDB *db = mTokyoTyrant_getdb(vself);
|
32
|
+
Check_Type(vhash, T_HASH);
|
33
|
+
|
34
|
+
list = vhashtoputlist(vhash);
|
35
|
+
if ((result = tcrdbmisc(db, "putlist", 0, list)) != NULL){
|
36
|
+
vary = listtovary(result);
|
37
|
+
tclistdel(result);
|
38
|
+
} else {
|
39
|
+
vary = rb_ary_new();
|
40
|
+
}
|
41
|
+
tclistdel(list);
|
42
|
+
|
43
|
+
return vary;
|
44
|
+
}
|
45
|
+
|
46
|
+
static VALUE cBDB_getlist(int argc, VALUE *argv, VALUE vself){
|
47
|
+
VALUE vkeys, vvalue, vhash;
|
48
|
+
TCLIST *list, *result;
|
49
|
+
TCRDB *db = mTokyoTyrant_getdb(vself);
|
50
|
+
rb_scan_args(argc, argv, "*", &vkeys);
|
51
|
+
|
52
|
+
// I really hope there is a better way to do this
|
53
|
+
if (RARRAY_LEN(vkeys) == 1) {
|
54
|
+
vvalue = rb_ary_entry(vkeys, 0);
|
55
|
+
switch (TYPE(vvalue)){
|
56
|
+
case T_STRING:
|
57
|
+
case T_FIXNUM:
|
58
|
+
break;
|
59
|
+
case T_ARRAY:
|
60
|
+
vkeys = vvalue;
|
61
|
+
break;
|
62
|
+
case T_OBJECT:
|
63
|
+
vkeys = rb_convert_type(vvalue, T_ARRAY, "Array", "to_a");
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
Check_Type(vkeys, T_ARRAY);
|
68
|
+
|
69
|
+
list = varytolist(vkeys);
|
70
|
+
result = tcrdbmisc(db, "getlist", RDBMONOULOG, list);
|
71
|
+
tclistdel(list);
|
72
|
+
vhash = listtovhash(result);
|
73
|
+
tclistdel(result);
|
74
|
+
return vhash;
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE cBDB_each(VALUE vself){
|
78
|
+
VALUE vrv;
|
79
|
+
const char *kbuf, *vbuf;
|
80
|
+
int ksiz, vsiz;
|
81
|
+
TCLIST *result;
|
82
|
+
TCRDB *db = mTokyoTyrant_getdb(vself);
|
83
|
+
vrv = Qnil;
|
84
|
+
|
85
|
+
if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
|
86
|
+
|
87
|
+
tcrdbiterinit(db);
|
88
|
+
tcrdbmisc(db, "iterinit", RDBMONOULOG, tclistnew());
|
89
|
+
while((result = tcrdbmisc(db, "iternext", RDBMONOULOG, tclistnew())) != NULL){
|
90
|
+
if (tclistnum(result) == 2) {
|
91
|
+
kbuf = tclistval(result, 0, &ksiz);
|
92
|
+
vbuf = tclistval(result, 1, &vsiz);
|
93
|
+
vrv = rb_yield_values(2, rb_str_new(kbuf, ksiz), rb_str_new(vbuf, vsiz));
|
94
|
+
}
|
95
|
+
tclistdel(result);
|
96
|
+
}
|
97
|
+
return vrv;
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE cBDB_values(VALUE vself){
|
101
|
+
VALUE vary;
|
102
|
+
const char *vbuf;
|
103
|
+
int vsiz;
|
104
|
+
TCLIST *result;
|
105
|
+
TCRDB *db = mTokyoTyrant_getdb(vself);
|
106
|
+
|
107
|
+
vary = rb_ary_new();
|
108
|
+
tcrdbiterinit(db);
|
109
|
+
tcrdbmisc(db, "iterinit", RDBMONOULOG, tclistnew());
|
110
|
+
while((result = tcrdbmisc(db, "iternext", RDBMONOULOG, tclistnew())) != NULL){
|
111
|
+
if (tclistnum(result) == 2){
|
112
|
+
vbuf = tclistval(result, 1, &vsiz);
|
113
|
+
vary = rb_ary_push(vary, rb_str_new(vbuf, vsiz));
|
114
|
+
}
|
115
|
+
tclistdel(result);
|
116
|
+
}
|
117
|
+
|
118
|
+
return vary;
|
119
|
+
}
|
120
|
+
|
121
|
+
static VALUE cBDB_putdup(VALUE vself, VALUE vkey, VALUE vval){
|
122
|
+
return cBDB_put_method(vself, vkey, vval, "putdup", false);
|
123
|
+
}
|
124
|
+
|
125
|
+
static VALUE cBDB_putdup_bang(VALUE vself, VALUE vkey, VALUE vval){
|
126
|
+
return cBDB_put_method(vself, vkey, vval, "putdup", true);
|
127
|
+
}
|
128
|
+
|
129
|
+
void init_bdb(){
|
130
|
+
rb_define_method(cBDB, "putlist", cBDB_putlist, 1);
|
131
|
+
rb_define_alias(cBDB, "mput", "putlist");
|
132
|
+
rb_define_method(cBDB, "getlist", cBDB_getlist, -1);
|
133
|
+
rb_define_alias(cBDB, "mget", "putlist");
|
134
|
+
rb_define_method(cBDB, "each", cBDB_each, 0);
|
135
|
+
rb_define_method(cBDB, "values", cBDB_values, 0);
|
136
|
+
rb_define_method(cBDB, "putdup", cBDB_putdup, 2);
|
137
|
+
rb_define_method(cBDB, "putdup!", cBDB_putdup_bang, 2);
|
138
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#include <tokyo_tyrant_consistent_hash.h>
|
2
|
+
|
3
|
+
static void cConstistentHash_free(TCCHIDX *idx){
|
4
|
+
tcchidxdel(idx);
|
5
|
+
}
|
6
|
+
|
7
|
+
static VALUE cConstistentHash_initialize(VALUE self, VALUE dbs){
|
8
|
+
TCCHIDX *idx;
|
9
|
+
|
10
|
+
Check_Type(dbs, T_ARRAY);
|
11
|
+
idx = tcchidxnew(RARRAY_LEN(dbs));
|
12
|
+
|
13
|
+
rb_iv_set(self, "@dbs", dbs);
|
14
|
+
rb_iv_set(self, "@idx", Data_Wrap_Struct(rb_cObject, 0, cConstistentHash_free, idx));
|
15
|
+
|
16
|
+
return Qtrue;
|
17
|
+
}
|
18
|
+
|
19
|
+
static VALUE cConstistentHash_db_for_key(VALUE self, VALUE key){
|
20
|
+
VALUE dbs;
|
21
|
+
TCCHIDX *idx;
|
22
|
+
int hash;
|
23
|
+
|
24
|
+
Data_Get_Struct(rb_iv_get(self, "@idx"), TCCHIDX, idx);
|
25
|
+
hash = tcchidxhash(idx, RSTRING_PTR(key), RSTRING_LEN(key));
|
26
|
+
dbs = rb_iv_get(self, "@dbs");
|
27
|
+
|
28
|
+
return rb_ary_entry(dbs, hash);
|
29
|
+
}
|
30
|
+
|
31
|
+
void init_consistent_hash(){
|
32
|
+
rb_define_private_method(cConstistentHash, "initialize", cConstistentHash_initialize, 1);
|
33
|
+
rb_define_method(cConstistentHash, "db_for_key", cConstistentHash_db_for_key, 1);
|
34
|
+
}
|
data/ext/tokyo_tyrant_db.c
CHANGED
@@ -25,7 +25,7 @@ static VALUE cDB_put_method(VALUE vself, VALUE vkey, VALUE vstr, int method){
|
|
25
25
|
break;
|
26
26
|
}
|
27
27
|
|
28
|
-
if(!res) mTokyoTyrant_exception(vself);
|
28
|
+
if(!res) mTokyoTyrant_exception(vself, NULL);
|
29
29
|
|
30
30
|
return Qtrue;
|
31
31
|
}
|
@@ -68,7 +68,7 @@ static VALUE cDB_putshl(VALUE vself, VALUE vkey, VALUE vstr, VALUE vwidth){
|
|
68
68
|
|
69
69
|
res = tcrdbputshl(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr), FIXNUM_P(vwidth));
|
70
70
|
|
71
|
-
if(!res) mTokyoTyrant_exception(vself);
|
71
|
+
if(!res) mTokyoTyrant_exception(vself, NULL);
|
72
72
|
|
73
73
|
return Qtrue;
|
74
74
|
}
|
@@ -83,7 +83,7 @@ static VALUE cDB_get(VALUE vself, VALUE vkey){
|
|
83
83
|
vkey = StringValueEx(vkey);
|
84
84
|
if(!(buf = tcrdbget(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), &bsiz))){
|
85
85
|
if ((ecode = tcrdbecode(db))) {
|
86
|
-
if (ecode != TTENOREC) mTokyoTyrant_exception(vself);
|
86
|
+
if (ecode != TTENOREC) mTokyoTyrant_exception(vself, NULL);
|
87
87
|
}
|
88
88
|
return Qnil;
|
89
89
|
} else {
|
data/ext/tokyo_tyrant_module.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#include <
|
1
|
+
#include <tokyo_tyrant_db.h>
|
2
2
|
|
3
3
|
extern TCRDB *mTokyoTyrant_getdb(VALUE vself){
|
4
4
|
TCRDB *db;
|
@@ -6,12 +6,44 @@ extern TCRDB *mTokyoTyrant_getdb(VALUE vself){
|
|
6
6
|
return db;
|
7
7
|
}
|
8
8
|
|
9
|
-
extern void mTokyoTyrant_exception(VALUE vself){
|
9
|
+
extern void mTokyoTyrant_exception(VALUE vself, void *message){
|
10
|
+
VALUE exception;
|
10
11
|
int ecode;
|
11
12
|
TCRDB *db = mTokyoTyrant_getdb(vself);
|
13
|
+
if (message == NULL) message = "%s";
|
12
14
|
|
13
15
|
ecode = tcrdbecode(db);
|
14
|
-
|
16
|
+
// Is there a better way to do this?
|
17
|
+
switch(ecode){
|
18
|
+
case TTEINVALID:
|
19
|
+
exception = eTokyoTyrantErrorInvalid;
|
20
|
+
break;
|
21
|
+
case TTENOHOST:
|
22
|
+
exception = eTokyoTyrantErrorNoHost;
|
23
|
+
break;
|
24
|
+
case TTEREFUSED:
|
25
|
+
exception = eTokyoTyrantErrorRefused;
|
26
|
+
break;
|
27
|
+
case TTESEND:
|
28
|
+
exception = eTokyoTyrantErrorSend;
|
29
|
+
break;
|
30
|
+
case TTERECV:
|
31
|
+
exception = eTokyoTyrantErrorReceive;
|
32
|
+
break;
|
33
|
+
case TTEKEEP:
|
34
|
+
exception = eTokyoTyrantErrorKeep;
|
35
|
+
break;
|
36
|
+
case TTENOREC:
|
37
|
+
exception = eTokyoTyrantErrorNoRecord;
|
38
|
+
break;
|
39
|
+
case TTEMISC:
|
40
|
+
exception = eTokyoTyrantErrorMisc;
|
41
|
+
break;
|
42
|
+
default:
|
43
|
+
exception = eTokyoTyrantError;
|
44
|
+
break;
|
45
|
+
}
|
46
|
+
rb_raise(exception, message, tcrdberrmsg(ecode));
|
15
47
|
}
|
16
48
|
|
17
49
|
static void mTokyoTyrant_free(TCRDB *db){
|
@@ -23,34 +55,36 @@ static VALUE mTokyoTyrant_server(VALUE vself){
|
|
23
55
|
}
|
24
56
|
|
25
57
|
static VALUE mTokyoTyrant_close(VALUE vself){
|
26
|
-
int ecode;
|
27
58
|
TCRDB *db = mTokyoTyrant_getdb(vself);
|
28
59
|
|
29
|
-
if(!tcrdbclose(db))
|
30
|
-
ecode = tcrdbecode(db);
|
31
|
-
rb_raise(eTokyoTyrantError, "close error: %s", tcrdberrmsg(ecode));
|
32
|
-
}
|
60
|
+
if(!tcrdbclose(db)) mTokyoTyrant_exception(vself, "close error: %s");
|
33
61
|
return Qtrue;
|
34
62
|
}
|
35
63
|
|
36
64
|
static VALUE mTokyoTyrant_connect(VALUE vself){
|
37
|
-
VALUE
|
38
|
-
int
|
65
|
+
VALUE vhost, vport, vtimeout, vretry, vserver;
|
66
|
+
int port;
|
67
|
+
char *host;
|
39
68
|
TCRDB *db = mTokyoTyrant_getdb(vself);
|
40
69
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
70
|
+
vhost = rb_iv_get(vself, "@host");
|
71
|
+
vport = rb_iv_get(vself, "@port");
|
72
|
+
vtimeout = rb_iv_get(vself, "@timeout");
|
73
|
+
vretry = rb_iv_get(vself, "@retry");
|
74
|
+
host = RSTRING_PTR(vhost);
|
75
|
+
port = FIX2INT(vport);
|
76
|
+
|
77
|
+
if(port == 0 && access(host, R_OK) < 0 && access(host, W_OK) < 0){
|
78
|
+
rb_raise(rb_eArgError, "Can't open unix socket: %s", host);
|
79
|
+
}
|
45
80
|
|
46
|
-
if((!tcrdbtune(db, NUM2DBL(
|
47
|
-
(!tcrdbopen(db,
|
48
|
-
|
49
|
-
rb_raise(eTokyoTyrantError, "open error: %s", tcrdberrmsg(ecode));
|
81
|
+
if((!tcrdbtune(db, NUM2DBL(vtimeout), vretry == Qtrue ? RDBTRECON : 0)) ||
|
82
|
+
(!tcrdbopen(db, host, port))){
|
83
|
+
mTokyoTyrant_exception(vself, "open error: %s");
|
50
84
|
}
|
51
85
|
|
52
|
-
|
53
|
-
rb_iv_set(vself, "@server",
|
86
|
+
vserver = rb_str_new2(tcrdbexpr(db));
|
87
|
+
rb_iv_set(vself, "@server", vserver);
|
54
88
|
|
55
89
|
return Qtrue;
|
56
90
|
}
|
@@ -338,9 +372,18 @@ static VALUE mTokyoTyrant_size(VALUE vself){
|
|
338
372
|
}
|
339
373
|
|
340
374
|
static VALUE mTokyoTyrant_stat(VALUE vself){
|
375
|
+
VALUE vhash;
|
376
|
+
char *stats;
|
377
|
+
TCMAP *map;
|
341
378
|
TCRDB *db = mTokyoTyrant_getdb(vself);
|
379
|
+
vhash = rb_hash_new();
|
342
380
|
|
343
|
-
|
381
|
+
if ((stats = tcrdbstat(db)) != NULL){
|
382
|
+
map = tcstrsplit3(stats, "\t\n");
|
383
|
+
vhash = maptovhash(map);
|
384
|
+
tcmapdel(map);
|
385
|
+
}
|
386
|
+
return vhash;
|
344
387
|
}
|
345
388
|
|
346
389
|
static VALUE mTokyoTyrant_misc(int argc, VALUE *argv, VALUE vself){
|
@@ -348,13 +391,21 @@ static VALUE mTokyoTyrant_misc(int argc, VALUE *argv, VALUE vself){
|
|
348
391
|
TCLIST *list, *args;
|
349
392
|
TCRDB *db = mTokyoTyrant_getdb(vself);
|
350
393
|
rb_scan_args(argc, argv, "13", &vname, &vopts, &vargs);
|
394
|
+
if (vopts == Qnil) vopts = INT2NUM(0);
|
395
|
+
if (vargs == Qnil) vargs = rb_ary_new();
|
351
396
|
|
397
|
+
Check_Type(vargs, T_ARRAY);
|
352
398
|
args = varytolist(vargs);
|
353
399
|
vname = StringValueEx(vname);
|
354
400
|
|
355
|
-
list = tcrdbmisc(db, RSTRING_PTR(vname), NUM2INT(vopts), args)
|
356
|
-
|
357
|
-
|
401
|
+
if ((list = tcrdbmisc(db, RSTRING_PTR(vname), NUM2INT(vopts), args)) != NULL){
|
402
|
+
vary = listtovary(list);
|
403
|
+
tclistdel(list);
|
404
|
+
} else {
|
405
|
+
vary = rb_ary_new();
|
406
|
+
}
|
407
|
+
tclistdel(args);
|
408
|
+
|
358
409
|
return vary;
|
359
410
|
}
|
360
411
|
|