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