couchbase 1.1.5-x86-mingw32 → 1.2.0.beta-x86-mingw32
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/.gitignore +2 -1
- data/.travis.yml +12 -1
- data/HISTORY.markdown +112 -1
- data/README.markdown +149 -6
- data/couchbase.gemspec +5 -1
- data/ext/couchbase_ext/.gitignore +4 -0
- data/ext/couchbase_ext/arguments.c +973 -0
- data/ext/couchbase_ext/arithmetic.c +322 -0
- data/ext/couchbase_ext/bucket.c +1092 -0
- data/ext/couchbase_ext/couchbase_ext.c +618 -3247
- data/ext/couchbase_ext/couchbase_ext.h +519 -0
- data/ext/couchbase_ext/delete.c +167 -0
- data/ext/couchbase_ext/extconf.rb +24 -5
- data/ext/couchbase_ext/get.c +301 -0
- data/ext/couchbase_ext/gethrtime.c +124 -0
- data/ext/couchbase_ext/http.c +402 -0
- data/ext/couchbase_ext/observe.c +174 -0
- data/ext/couchbase_ext/result.c +126 -0
- data/ext/couchbase_ext/stats.c +169 -0
- data/ext/couchbase_ext/store.c +522 -0
- data/ext/couchbase_ext/timer.c +192 -0
- data/ext/couchbase_ext/touch.c +190 -0
- data/ext/couchbase_ext/unlock.c +180 -0
- data/ext/couchbase_ext/utils.c +471 -0
- data/ext/couchbase_ext/version.c +147 -0
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
- data/lib/active_support/cache/couchbase_store.rb +356 -0
- data/lib/couchbase.rb +24 -3
- data/lib/couchbase/bucket.rb +372 -9
- data/lib/couchbase/result.rb +26 -0
- data/lib/couchbase/utils.rb +59 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +305 -0
- data/lib/couchbase/view_row.rb +230 -0
- data/lib/ext/multi_json_fix.rb +47 -0
- data/lib/rack/session/couchbase.rb +104 -0
- data/tasks/compile.rake +5 -14
- data/test/setup.rb +6 -2
- data/test/test_arithmetic.rb +32 -2
- data/test/test_async.rb +18 -4
- data/test/test_bucket.rb +11 -1
- data/test/test_cas.rb +13 -3
- data/test/test_couchbase_rails_cache_store.rb +294 -0
- data/test/test_delete.rb +60 -3
- data/test/test_format.rb +28 -17
- data/test/test_get.rb +91 -14
- data/test/test_store.rb +31 -1
- data/test/{test_flush.rb → test_timer.rb} +11 -18
- data/test/test_touch.rb +33 -5
- data/test/test_unlock.rb +120 -0
- data/test/test_utils.rb +26 -0
- metadata +102 -12
@@ -0,0 +1,174 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
void
|
21
|
+
observe_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_observe_resp_t *resp)
|
22
|
+
{
|
23
|
+
struct context_st *ctx = (struct context_st *)cookie;
|
24
|
+
struct bucket_st *bucket = ctx->bucket;
|
25
|
+
VALUE key, res, *rv = ctx->rv;
|
26
|
+
|
27
|
+
if (resp->v.v0.key) {
|
28
|
+
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
29
|
+
ctx->exception = cb_check_error(error, "failed to execute observe request", key);
|
30
|
+
if (ctx->exception) {
|
31
|
+
cb_gc_protect(bucket, ctx->exception);
|
32
|
+
}
|
33
|
+
res = rb_class_new_instance(0, NULL, cResult);
|
34
|
+
rb_ivar_set(res, id_iv_completed, Qfalse);
|
35
|
+
rb_ivar_set(res, id_iv_error, ctx->exception);
|
36
|
+
rb_ivar_set(res, id_iv_operation, sym_observe);
|
37
|
+
rb_ivar_set(res, id_iv_key, key);
|
38
|
+
rb_ivar_set(res, id_iv_cas, ULL2NUM(resp->v.v0.cas));
|
39
|
+
rb_ivar_set(res, id_iv_from_master, resp->v.v0.from_master ? Qtrue : Qfalse);
|
40
|
+
rb_ivar_set(res, id_iv_time_to_persist, ULONG2NUM(resp->v.v0.ttp));
|
41
|
+
rb_ivar_set(res, id_iv_time_to_replicate, ULONG2NUM(resp->v.v0.ttr));
|
42
|
+
switch (resp->v.v0.status) {
|
43
|
+
case LCB_OBSERVE_FOUND:
|
44
|
+
rb_ivar_set(res, id_iv_status, sym_found);
|
45
|
+
break;
|
46
|
+
case LCB_OBSERVE_PERSISTED:
|
47
|
+
rb_ivar_set(res, id_iv_status, sym_persisted);
|
48
|
+
break;
|
49
|
+
case LCB_OBSERVE_NOT_FOUND:
|
50
|
+
rb_ivar_set(res, id_iv_status, sym_not_found);
|
51
|
+
break;
|
52
|
+
default:
|
53
|
+
rb_ivar_set(res, id_iv_status, Qnil);
|
54
|
+
}
|
55
|
+
if (bucket->async) { /* asynchronous */
|
56
|
+
if (ctx->proc != Qnil) {
|
57
|
+
cb_proc_call(ctx->proc, 1, res);
|
58
|
+
}
|
59
|
+
} else { /* synchronous */
|
60
|
+
if (NIL_P(ctx->exception)) {
|
61
|
+
VALUE stats = rb_hash_aref(*rv, key);
|
62
|
+
if (NIL_P(stats)) {
|
63
|
+
stats = rb_ary_new();
|
64
|
+
rb_hash_aset(*rv, key, stats);
|
65
|
+
}
|
66
|
+
rb_ary_push(stats, res);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
} else {
|
70
|
+
if (bucket->async && ctx->proc != Qnil) {
|
71
|
+
res = rb_class_new_instance(0, NULL, cResult);
|
72
|
+
rb_ivar_set(res, id_iv_completed, Qtrue);
|
73
|
+
cb_proc_call(ctx->proc, 1, res);
|
74
|
+
}
|
75
|
+
ctx->nqueries--;
|
76
|
+
cb_gc_unprotect(bucket, ctx->proc);
|
77
|
+
}
|
78
|
+
(void)handle;
|
79
|
+
}
|
80
|
+
|
81
|
+
/*
|
82
|
+
* Observe key state
|
83
|
+
*
|
84
|
+
* @since 1.2.0.dp6
|
85
|
+
*
|
86
|
+
* @overload observe(*keys, options = {})
|
87
|
+
* @param keys [String, Symbol, Array] One or several keys to fetch
|
88
|
+
* @param options [Hash] Options for operation.
|
89
|
+
*
|
90
|
+
* @yieldparam ret [Result] the result of operation in asynchronous mode
|
91
|
+
* (valid attributes: +error+, +status+, +operation+, +key+, +cas+,
|
92
|
+
* +from_master+, +time_to_persist+, +time_to_replicate+).
|
93
|
+
*
|
94
|
+
* @return [Hash<String, Array<Result>>, Array<Result>] the state of the
|
95
|
+
* keys on all nodes. If the +keys+ argument was String or Symbol, this
|
96
|
+
* method will return just array of results (result per each node),
|
97
|
+
* otherwise it will return hash map.
|
98
|
+
*
|
99
|
+
* @example Observe single key
|
100
|
+
* c.observe("foo")
|
101
|
+
* #=> [#<Couchbase::Result:0x00000001650df0 ...>, ...]
|
102
|
+
*
|
103
|
+
* @example Observe multiple keys
|
104
|
+
* keys = ["foo", "bar"]
|
105
|
+
* stats = c.observe(keys)
|
106
|
+
* stats.size #=> 2
|
107
|
+
* stats["foo"] #=> [#<Couchbase::Result:0x00000001650df0 ...>, ...]
|
108
|
+
*/
|
109
|
+
|
110
|
+
VALUE
|
111
|
+
cb_bucket_observe(int argc, VALUE *argv, VALUE self)
|
112
|
+
{
|
113
|
+
struct bucket_st *bucket = DATA_PTR(self);
|
114
|
+
struct context_st *ctx;
|
115
|
+
VALUE args, rv, proc, exc;
|
116
|
+
lcb_error_t err;
|
117
|
+
struct params_st params;
|
118
|
+
|
119
|
+
if (bucket->handle == NULL) {
|
120
|
+
rb_raise(eConnectError, "closed connection");
|
121
|
+
}
|
122
|
+
rb_scan_args(argc, argv, "0*&", &args, &proc);
|
123
|
+
if (!bucket->async && proc != Qnil) {
|
124
|
+
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
125
|
+
}
|
126
|
+
memset(¶ms, 0, sizeof(struct params_st));
|
127
|
+
params.type = cmd_observe;
|
128
|
+
params.bucket = bucket;
|
129
|
+
cb_params_build(¶ms, RARRAY_LEN(args), args);
|
130
|
+
ctx = xcalloc(1, sizeof(struct context_st));
|
131
|
+
if (ctx == NULL) {
|
132
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for context");
|
133
|
+
}
|
134
|
+
ctx->proc = cb_gc_protect(bucket, proc);
|
135
|
+
ctx->bucket = bucket;
|
136
|
+
rv = rb_hash_new();
|
137
|
+
ctx->rv = &rv;
|
138
|
+
ctx->exception = Qnil;
|
139
|
+
ctx->nqueries = params.cmd.observe.num;
|
140
|
+
err = lcb_observe(bucket->handle, (const void *)ctx,
|
141
|
+
params.cmd.observe.num, params.cmd.observe.ptr);
|
142
|
+
cb_params_destroy(¶ms);
|
143
|
+
exc = cb_check_error(err, "failed to schedule observe request", Qnil);
|
144
|
+
if (exc != Qnil) {
|
145
|
+
xfree(ctx);
|
146
|
+
rb_exc_raise(exc);
|
147
|
+
}
|
148
|
+
bucket->nbytes += params.npayload;
|
149
|
+
if (bucket->async) {
|
150
|
+
maybe_do_loop(bucket);
|
151
|
+
return Qnil;
|
152
|
+
} else {
|
153
|
+
if (ctx->nqueries > 0) {
|
154
|
+
/* we have some operations pending */
|
155
|
+
lcb_wait(bucket->handle);
|
156
|
+
}
|
157
|
+
exc = ctx->exception;
|
158
|
+
xfree(ctx);
|
159
|
+
if (exc != Qnil) {
|
160
|
+
cb_gc_unprotect(bucket, exc);
|
161
|
+
rb_exc_raise(exc);
|
162
|
+
}
|
163
|
+
if (bucket->exception != Qnil) {
|
164
|
+
rb_exc_raise(bucket->exception);
|
165
|
+
}
|
166
|
+
if (params.cmd.observe.num > 1 || params.cmd.observe.array) {
|
167
|
+
return rv; /* return as a hash {key => {}, ...} */
|
168
|
+
} else {
|
169
|
+
VALUE vv = Qnil;
|
170
|
+
rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv);
|
171
|
+
return vv; /* return first value */
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
/*
|
21
|
+
* Check if result of operation was successful.
|
22
|
+
*
|
23
|
+
* @since 1.0.0
|
24
|
+
*
|
25
|
+
* @return [true, false] +false+ if there is an +error+ object attached,
|
26
|
+
* +false+ otherwise.
|
27
|
+
*/
|
28
|
+
VALUE
|
29
|
+
cb_result_success_p(VALUE self)
|
30
|
+
{
|
31
|
+
return RTEST(rb_ivar_get(self, id_iv_error)) ? Qfalse : Qtrue;
|
32
|
+
}
|
33
|
+
|
34
|
+
/*
|
35
|
+
* Returns a string containing a human-readable representation of the Result.
|
36
|
+
*
|
37
|
+
* @since 1.0.0
|
38
|
+
*
|
39
|
+
* @return [String]
|
40
|
+
*/
|
41
|
+
VALUE
|
42
|
+
cb_result_inspect(VALUE self)
|
43
|
+
{
|
44
|
+
VALUE str, attr, error;
|
45
|
+
char buf[100];
|
46
|
+
|
47
|
+
str = rb_str_buf_new2("#<");
|
48
|
+
rb_str_buf_cat2(str, rb_obj_classname(self));
|
49
|
+
snprintf(buf, 100, ":%p", (void *)self);
|
50
|
+
rb_str_buf_cat2(str, buf);
|
51
|
+
|
52
|
+
attr = rb_ivar_get(self, id_iv_error);
|
53
|
+
if (RTEST(attr)) {
|
54
|
+
error = rb_ivar_get(attr, id_iv_error);
|
55
|
+
} else {
|
56
|
+
error = INT2FIX(0);
|
57
|
+
}
|
58
|
+
rb_str_buf_cat2(str, " error=0x");
|
59
|
+
rb_str_append(str, rb_funcall(error, id_to_s, 1, INT2FIX(16)));
|
60
|
+
|
61
|
+
attr = rb_ivar_get(self, id_iv_operation);
|
62
|
+
if (RTEST(attr)) {
|
63
|
+
rb_str_buf_cat2(str, " operation=");
|
64
|
+
rb_str_append(str, rb_inspect(attr));
|
65
|
+
}
|
66
|
+
|
67
|
+
attr = rb_ivar_get(self, id_iv_key);
|
68
|
+
if (RTEST(attr)) {
|
69
|
+
rb_str_buf_cat2(str, " key=");
|
70
|
+
rb_str_append(str, rb_inspect(attr));
|
71
|
+
}
|
72
|
+
|
73
|
+
attr = rb_ivar_get(self, id_iv_status);
|
74
|
+
if (RTEST(attr)) {
|
75
|
+
rb_str_buf_cat2(str, " status=");
|
76
|
+
rb_str_append(str, rb_inspect(attr));
|
77
|
+
}
|
78
|
+
|
79
|
+
attr = rb_ivar_get(self, id_iv_cas);
|
80
|
+
if (RTEST(attr)) {
|
81
|
+
rb_str_buf_cat2(str, " cas=");
|
82
|
+
rb_str_append(str, rb_inspect(attr));
|
83
|
+
}
|
84
|
+
|
85
|
+
attr = rb_ivar_get(self, id_iv_flags);
|
86
|
+
if (RTEST(attr)) {
|
87
|
+
rb_str_buf_cat2(str, " flags=0x");
|
88
|
+
rb_str_append(str, rb_funcall(attr, id_to_s, 1, INT2FIX(16)));
|
89
|
+
}
|
90
|
+
|
91
|
+
attr = rb_ivar_get(self, id_iv_node);
|
92
|
+
if (RTEST(attr)) {
|
93
|
+
rb_str_buf_cat2(str, " node=");
|
94
|
+
rb_str_append(str, rb_inspect(attr));
|
95
|
+
}
|
96
|
+
|
97
|
+
attr = rb_ivar_get(self, id_iv_from_master);
|
98
|
+
if (attr != Qnil) {
|
99
|
+
rb_str_buf_cat2(str, " from_master=");
|
100
|
+
rb_str_append(str, rb_inspect(attr));
|
101
|
+
}
|
102
|
+
|
103
|
+
attr = rb_ivar_get(self, id_iv_time_to_persist);
|
104
|
+
if (RTEST(attr)) {
|
105
|
+
rb_str_buf_cat2(str, " time_to_persist=");
|
106
|
+
rb_str_append(str, rb_inspect(attr));
|
107
|
+
}
|
108
|
+
|
109
|
+
attr = rb_ivar_get(self, id_iv_time_to_replicate);
|
110
|
+
if (RTEST(attr)) {
|
111
|
+
rb_str_buf_cat2(str, " time_to_replicate=");
|
112
|
+
rb_str_append(str, rb_inspect(attr));
|
113
|
+
}
|
114
|
+
|
115
|
+
attr = rb_ivar_get(self, id_iv_headers);
|
116
|
+
if (RTEST(attr)) {
|
117
|
+
rb_str_buf_cat2(str, " headers=");
|
118
|
+
rb_str_append(str, rb_inspect(attr));
|
119
|
+
}
|
120
|
+
|
121
|
+
rb_str_buf_cat2(str, ">");
|
122
|
+
|
123
|
+
return str;
|
124
|
+
}
|
125
|
+
|
126
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
void
|
21
|
+
stat_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_server_stat_resp_t *resp)
|
22
|
+
{
|
23
|
+
struct context_st *ctx = (struct context_st *)cookie;
|
24
|
+
struct bucket_st *bucket = ctx->bucket;
|
25
|
+
VALUE stats, node, key, val, *rv = ctx->rv, exc = Qnil, res;
|
26
|
+
|
27
|
+
node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil;
|
28
|
+
exc = cb_check_error(error, "failed to fetch stats", node);
|
29
|
+
if (exc != Qnil) {
|
30
|
+
rb_ivar_set(exc, id_iv_operation, sym_stats);
|
31
|
+
if (NIL_P(ctx->exception)) {
|
32
|
+
ctx->exception = cb_gc_protect(bucket, exc);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
if (node != Qnil) {
|
36
|
+
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
37
|
+
val = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
|
38
|
+
if (bucket->async) { /* asynchronous */
|
39
|
+
if (ctx->proc != Qnil) {
|
40
|
+
res = rb_class_new_instance(0, NULL, cResult);
|
41
|
+
rb_ivar_set(res, id_iv_error, exc);
|
42
|
+
rb_ivar_set(res, id_iv_operation, sym_stats);
|
43
|
+
rb_ivar_set(res, id_iv_node, node);
|
44
|
+
rb_ivar_set(res, id_iv_key, key);
|
45
|
+
rb_ivar_set(res, id_iv_value, val);
|
46
|
+
cb_proc_call(ctx->proc, 1, res);
|
47
|
+
}
|
48
|
+
} else { /* synchronous */
|
49
|
+
if (NIL_P(exc)) {
|
50
|
+
stats = rb_hash_aref(*rv, key);
|
51
|
+
if (NIL_P(stats)) {
|
52
|
+
stats = rb_hash_new();
|
53
|
+
rb_hash_aset(*rv, key, stats);
|
54
|
+
}
|
55
|
+
rb_hash_aset(stats, node, val);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
} else {
|
59
|
+
ctx->nqueries--;
|
60
|
+
cb_gc_unprotect(bucket, ctx->proc);
|
61
|
+
}
|
62
|
+
(void)handle;
|
63
|
+
}
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Request server statistics.
|
67
|
+
*
|
68
|
+
* @since 1.0.0
|
69
|
+
*
|
70
|
+
* Fetches stats from each node in cluster. Without a key specified the
|
71
|
+
* server will respond with a "default" set of statistical information. In
|
72
|
+
* asynchronous mode each statistic is returned in separate call where the
|
73
|
+
* Result object yielded (+#key+ contains the name of the statistical item
|
74
|
+
* and the +#value+ contains the value, the +#node+ will indicate the server
|
75
|
+
* address). In synchronous mode it returns the hash of stats keys and
|
76
|
+
* node-value pairs as a value.
|
77
|
+
*
|
78
|
+
* @overload stats(arg = nil)
|
79
|
+
* @param [String] arg argument to STATS query
|
80
|
+
* @yieldparam [Result] ret the object with +node+, +key+ and +value+
|
81
|
+
* attributes.
|
82
|
+
*
|
83
|
+
* @example Found how many items in the bucket
|
84
|
+
* total = 0
|
85
|
+
* c.stats["total_items"].each do |key, value|
|
86
|
+
* total += value.to_i
|
87
|
+
* end
|
88
|
+
*
|
89
|
+
* @example Found total items number asynchronously
|
90
|
+
* total = 0
|
91
|
+
* c.run do
|
92
|
+
* c.stats do |ret|
|
93
|
+
* if ret.key == "total_items"
|
94
|
+
* total += ret.value.to_i
|
95
|
+
* end
|
96
|
+
* end
|
97
|
+
* end
|
98
|
+
*
|
99
|
+
* @example Get memory stats (works on couchbase buckets)
|
100
|
+
* c.stats(:memory) #=> {"mem_used"=>{...}, ...}
|
101
|
+
*
|
102
|
+
* @return [Hash] where keys are stat keys, values are host-value pairs
|
103
|
+
*
|
104
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
105
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
106
|
+
*/
|
107
|
+
VALUE
|
108
|
+
cb_bucket_stats(int argc, VALUE *argv, VALUE self)
|
109
|
+
{
|
110
|
+
struct bucket_st *bucket = DATA_PTR(self);
|
111
|
+
struct context_st *ctx;
|
112
|
+
VALUE rv, exc, args, proc;
|
113
|
+
lcb_error_t err;
|
114
|
+
struct params_st params;
|
115
|
+
|
116
|
+
if (bucket->handle == NULL) {
|
117
|
+
rb_raise(eConnectError, "closed connection");
|
118
|
+
}
|
119
|
+
rb_scan_args(argc, argv, "0*&", &args, &proc);
|
120
|
+
if (!bucket->async && proc != Qnil) {
|
121
|
+
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
122
|
+
}
|
123
|
+
memset(¶ms, 0, sizeof(struct params_st));
|
124
|
+
params.type = cmd_stats;
|
125
|
+
params.bucket = bucket;
|
126
|
+
cb_params_build(¶ms, RARRAY_LEN(args), args);
|
127
|
+
ctx = xcalloc(1, sizeof(struct context_st));
|
128
|
+
if (ctx == NULL) {
|
129
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for context");
|
130
|
+
}
|
131
|
+
rv = rb_hash_new();
|
132
|
+
ctx->rv = &rv;
|
133
|
+
ctx->bucket = bucket;
|
134
|
+
ctx->proc = cb_gc_protect(bucket, proc);
|
135
|
+
ctx->exception = Qnil;
|
136
|
+
ctx->nqueries = params.cmd.stats.num;
|
137
|
+
err = lcb_server_stats(bucket->handle, (const void *)ctx,
|
138
|
+
params.cmd.stats.num, params.cmd.stats.ptr);
|
139
|
+
exc = cb_check_error(err, "failed to schedule stat request", Qnil);
|
140
|
+
cb_params_destroy(¶ms);
|
141
|
+
if (exc != Qnil) {
|
142
|
+
xfree(ctx);
|
143
|
+
rb_exc_raise(exc);
|
144
|
+
}
|
145
|
+
bucket->nbytes += params.npayload;
|
146
|
+
if (bucket->async) {
|
147
|
+
maybe_do_loop(bucket);
|
148
|
+
return Qnil;
|
149
|
+
} else {
|
150
|
+
if (ctx->nqueries > 0) {
|
151
|
+
/* we have some operations pending */
|
152
|
+
lcb_wait(bucket->handle);
|
153
|
+
}
|
154
|
+
exc = ctx->exception;
|
155
|
+
xfree(ctx);
|
156
|
+
if (exc != Qnil) {
|
157
|
+
cb_gc_unprotect(bucket, exc);
|
158
|
+
rb_exc_raise(exc);
|
159
|
+
}
|
160
|
+
if (bucket->exception != Qnil) {
|
161
|
+
rb_exc_raise(bucket->exception);
|
162
|
+
}
|
163
|
+
return rv;
|
164
|
+
}
|
165
|
+
|
166
|
+
return Qnil;
|
167
|
+
}
|
168
|
+
|
169
|
+
|