couchbase 1.2.0.beta-x86-mingw32 → 1.2.0-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/.travis.yml +1 -1
- data/Makefile +3 -0
- data/README.markdown +15 -4
- data/RELEASE_NOTES.markdown +513 -0
- data/couchbase.gemspec +0 -1
- data/ext/couchbase_ext/arguments.c +161 -244
- data/ext/couchbase_ext/arithmetic.c +29 -37
- data/ext/couchbase_ext/bucket.c +252 -219
- data/ext/couchbase_ext/couchbase_ext.c +540 -417
- data/ext/couchbase_ext/couchbase_ext.h +218 -191
- data/ext/couchbase_ext/delete.c +30 -27
- data/ext/couchbase_ext/extconf.rb +15 -3
- data/ext/couchbase_ext/get.c +45 -37
- data/ext/couchbase_ext/http.c +95 -74
- data/ext/couchbase_ext/multithread_plugin.c +1201 -0
- data/ext/couchbase_ext/observe.c +42 -37
- data/ext/couchbase_ext/result.c +17 -20
- data/ext/couchbase_ext/stats.c +30 -28
- data/ext/couchbase_ext/store.c +46 -39
- data/ext/couchbase_ext/timer.c +11 -11
- data/ext/couchbase_ext/touch.c +30 -27
- data/ext/couchbase_ext/unlock.c +30 -27
- data/ext/couchbase_ext/utils.c +166 -89
- data/ext/couchbase_ext/version.c +29 -26
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +2 -2
- data/lib/active_support/cache/couchbase_store.rb +6 -6
- data/lib/couchbase.rb +1 -0
- data/lib/couchbase/bucket.rb +6 -11
- data/lib/couchbase/cluster.rb +105 -0
- data/lib/couchbase/utils.rb +8 -5
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +51 -5
- data/lib/couchbase/view_row.rb +1 -1
- data/lib/ext/multi_json_fix.rb +13 -9
- data/lib/rack/session/couchbase.rb +11 -7
- data/tasks/compile.rake +1 -1
- data/tasks/test.rake +40 -34
- data/tasks/util.rake +1 -1
- data/test/setup.rb +9 -2
- data/test/test_arithmetic.rb +37 -0
- data/test/test_async.rb +22 -18
- data/test/test_unlock.rb +0 -1
- data/test/test_utils.rb +32 -0
- metadata +13 -23
- data/HISTORY.markdown +0 -215
data/ext/couchbase_ext/timer.c
CHANGED
@@ -26,7 +26,7 @@ cb_timer_free(void *ptr)
|
|
26
26
|
void
|
27
27
|
cb_timer_mark(void *ptr)
|
28
28
|
{
|
29
|
-
struct
|
29
|
+
struct cb_timer_st *timer = ptr;
|
30
30
|
if (timer) {
|
31
31
|
rb_gc_mark(timer->callback);
|
32
32
|
}
|
@@ -36,10 +36,10 @@ cb_timer_mark(void *ptr)
|
|
36
36
|
cb_timer_alloc(VALUE klass)
|
37
37
|
{
|
38
38
|
VALUE obj;
|
39
|
-
struct
|
39
|
+
struct cb_timer_st *timer;
|
40
40
|
|
41
41
|
/* allocate new bucket struct and set it to zero */
|
42
|
-
obj = Data_Make_Struct(klass, struct
|
42
|
+
obj = Data_Make_Struct(klass, struct cb_timer_st, cb_timer_mark,
|
43
43
|
cb_timer_free, timer);
|
44
44
|
return obj;
|
45
45
|
}
|
@@ -56,7 +56,7 @@ cb_timer_alloc(VALUE klass)
|
|
56
56
|
cb_timer_inspect(VALUE self)
|
57
57
|
{
|
58
58
|
VALUE str;
|
59
|
-
struct
|
59
|
+
struct cb_timer_st *tm = DATA_PTR(self);
|
60
60
|
char buf[200];
|
61
61
|
|
62
62
|
str = rb_str_buf_new2("#<");
|
@@ -97,7 +97,7 @@ cb_timer_inspect(VALUE self)
|
|
97
97
|
VALUE
|
98
98
|
cb_timer_cancel(VALUE self)
|
99
99
|
{
|
100
|
-
struct
|
100
|
+
struct cb_timer_st *tm = DATA_PTR(self);
|
101
101
|
lcb_timer_destroy(tm->bucket->handle, tm->timer);
|
102
102
|
return self;
|
103
103
|
}
|
@@ -105,15 +105,15 @@ cb_timer_cancel(VALUE self)
|
|
105
105
|
static VALUE
|
106
106
|
trigger_timer(VALUE timer)
|
107
107
|
{
|
108
|
-
struct
|
109
|
-
return cb_proc_call(tm->callback, 1, timer);
|
108
|
+
struct cb_timer_st *tm = DATA_PTR(timer);
|
109
|
+
return cb_proc_call(tm->bucket, tm->callback, 1, timer);
|
110
110
|
}
|
111
111
|
|
112
112
|
static void
|
113
113
|
timer_callback(lcb_timer_t timer, lcb_t instance,
|
114
114
|
const void *cookie)
|
115
115
|
{
|
116
|
-
struct
|
116
|
+
struct cb_timer_st *tm = (struct cb_timer_st *)cookie;
|
117
117
|
int error = 0;
|
118
118
|
|
119
119
|
rb_protect(trigger_timer, tm->self, &error);
|
@@ -162,14 +162,14 @@ timer_callback(lcb_timer_t timer, lcb_t instance,
|
|
162
162
|
VALUE
|
163
163
|
cb_timer_init(int argc, VALUE *argv, VALUE self)
|
164
164
|
{
|
165
|
-
struct
|
165
|
+
struct cb_timer_st *tm = DATA_PTR(self);
|
166
166
|
VALUE bucket, opts, timeout, exc, cb;
|
167
167
|
lcb_error_t err;
|
168
168
|
|
169
169
|
rb_need_block();
|
170
170
|
rb_scan_args(argc, argv, "21&", &bucket, &timeout, &opts, &cb);
|
171
171
|
|
172
|
-
if (CLASS_OF(bucket) !=
|
172
|
+
if (CLASS_OF(bucket) != cb_cBucket) {
|
173
173
|
rb_raise(rb_eTypeError, "wrong argument type (expected Couchbase::Bucket)");
|
174
174
|
}
|
175
175
|
tm->self = self;
|
@@ -178,7 +178,7 @@ cb_timer_init(int argc, VALUE *argv, VALUE self)
|
|
178
178
|
tm->bucket = DATA_PTR(bucket);
|
179
179
|
if (opts != Qnil) {
|
180
180
|
Check_Type(opts, T_HASH);
|
181
|
-
tm->periodic = RTEST(rb_hash_aref(opts,
|
181
|
+
tm->periodic = RTEST(rb_hash_aref(opts, cb_sym_periodic));
|
182
182
|
}
|
183
183
|
tm->timer = lcb_timer_create(tm->bucket->handle, tm, tm->usec,
|
184
184
|
tm->periodic, timer_callback, &err);
|
data/ext/couchbase_ext/touch.c
CHANGED
@@ -18,39 +18,40 @@
|
|
18
18
|
#include "couchbase_ext.h"
|
19
19
|
|
20
20
|
void
|
21
|
-
|
21
|
+
cb_touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_touch_resp_t *resp)
|
22
22
|
{
|
23
|
-
struct
|
24
|
-
struct
|
23
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
25
25
|
VALUE key, *rv = ctx->rv, exc = Qnil, res;
|
26
26
|
|
27
27
|
ctx->nqueries--;
|
28
28
|
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
29
|
-
|
29
|
+
cb_strip_key_prefix(bucket, key);
|
30
30
|
|
31
31
|
if (error != LCB_KEY_ENOENT || !ctx->quiet) {
|
32
32
|
exc = cb_check_error(error, "failed to touch value", key);
|
33
33
|
if (exc != Qnil) {
|
34
|
-
rb_ivar_set(exc,
|
35
|
-
|
36
|
-
ctx->exception = cb_gc_protect(bucket, exc);
|
37
|
-
}
|
34
|
+
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_touch);
|
35
|
+
ctx->exception = cb_gc_protect(bucket, exc);
|
38
36
|
}
|
39
37
|
}
|
40
38
|
|
41
39
|
if (bucket->async) { /* asynchronous */
|
42
40
|
if (ctx->proc != Qnil) {
|
43
|
-
res = rb_class_new_instance(0, NULL,
|
44
|
-
rb_ivar_set(res,
|
45
|
-
rb_ivar_set(res,
|
46
|
-
rb_ivar_set(res,
|
47
|
-
cb_proc_call(ctx->proc, 1, res);
|
41
|
+
res = rb_class_new_instance(0, NULL, cb_cResult);
|
42
|
+
rb_ivar_set(res, cb_id_iv_error, exc);
|
43
|
+
rb_ivar_set(res, cb_id_iv_operation, cb_sym_touch);
|
44
|
+
rb_ivar_set(res, cb_id_iv_key, key);
|
45
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
48
46
|
}
|
49
47
|
} else { /* synchronous */
|
50
48
|
rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
|
51
49
|
}
|
52
50
|
if (ctx->nqueries == 0) {
|
53
51
|
cb_gc_unprotect(bucket, ctx->proc);
|
52
|
+
if (bucket->async) {
|
53
|
+
free(ctx);
|
54
|
+
}
|
54
55
|
}
|
55
56
|
(void)handle;
|
56
57
|
}
|
@@ -123,27 +124,27 @@ touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_to
|
|
123
124
|
VALUE
|
124
125
|
cb_bucket_touch(int argc, VALUE *argv, VALUE self)
|
125
126
|
{
|
126
|
-
struct
|
127
|
-
struct
|
127
|
+
struct cb_bucket_st *bucket = DATA_PTR(self);
|
128
|
+
struct cb_context_st *ctx;
|
128
129
|
VALUE args, rv, proc, exc;
|
129
130
|
lcb_error_t err;
|
130
|
-
struct
|
131
|
+
struct cb_params_st params;
|
131
132
|
|
132
133
|
if (bucket->handle == NULL) {
|
133
|
-
rb_raise(
|
134
|
+
rb_raise(cb_eConnectError, "closed connection");
|
134
135
|
}
|
135
136
|
rb_scan_args(argc, argv, "0*&", &args, &proc);
|
136
137
|
if (!bucket->async && proc != Qnil) {
|
137
138
|
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
138
139
|
}
|
139
|
-
rb_funcall(args,
|
140
|
-
memset(¶ms, 0, sizeof(struct
|
141
|
-
params.type =
|
140
|
+
rb_funcall(args, cb_id_flatten_bang, 0);
|
141
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
142
|
+
params.type = cb_cmd_touch;
|
142
143
|
params.bucket = bucket;
|
143
144
|
cb_params_build(¶ms, RARRAY_LEN(args), args);
|
144
|
-
ctx =
|
145
|
+
ctx = calloc(1, sizeof(struct cb_context_st));
|
145
146
|
if (ctx == NULL) {
|
146
|
-
rb_raise(
|
147
|
+
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
|
147
148
|
}
|
148
149
|
ctx->proc = cb_gc_protect(bucket, proc);
|
149
150
|
ctx->bucket = bucket;
|
@@ -157,12 +158,12 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
|
|
157
158
|
cb_params_destroy(¶ms);
|
158
159
|
exc = cb_check_error(err, "failed to schedule touch request", Qnil);
|
159
160
|
if (exc != Qnil) {
|
160
|
-
|
161
|
+
free(ctx);
|
161
162
|
rb_exc_raise(exc);
|
162
163
|
}
|
163
164
|
bucket->nbytes += params.npayload;
|
164
165
|
if (bucket->async) {
|
165
|
-
|
166
|
+
cb_maybe_do_loop(bucket);
|
166
167
|
return Qnil;
|
167
168
|
} else {
|
168
169
|
if (ctx->nqueries > 0) {
|
@@ -170,12 +171,14 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
|
|
170
171
|
lcb_wait(bucket->handle);
|
171
172
|
}
|
172
173
|
exc = ctx->exception;
|
173
|
-
|
174
|
+
free(ctx);
|
174
175
|
if (exc != Qnil) {
|
175
176
|
rb_exc_raise(cb_gc_unprotect(bucket, exc));
|
176
177
|
}
|
177
|
-
|
178
|
-
|
178
|
+
exc = bucket->exception;
|
179
|
+
if (exc != Qnil) {
|
180
|
+
bucket->exception = Qnil;
|
181
|
+
rb_exc_raise(exc);
|
179
182
|
}
|
180
183
|
if (params.cmd.touch.num > 1) {
|
181
184
|
return rv; /* return as a hash {key => true, ...} */
|
data/ext/couchbase_ext/unlock.c
CHANGED
@@ -18,39 +18,40 @@
|
|
18
18
|
#include "couchbase_ext.h"
|
19
19
|
|
20
20
|
void
|
21
|
-
|
21
|
+
cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_unlock_resp_t *resp)
|
22
22
|
{
|
23
|
-
struct
|
24
|
-
struct
|
23
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
25
25
|
VALUE key, *rv = ctx->rv, exc = Qnil, res;
|
26
26
|
|
27
27
|
ctx->nqueries--;
|
28
28
|
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
29
|
-
|
29
|
+
cb_strip_key_prefix(bucket, key);
|
30
30
|
|
31
31
|
if (error != LCB_KEY_ENOENT || !ctx->quiet) {
|
32
32
|
exc = cb_check_error(error, "failed to unlock value", key);
|
33
33
|
if (exc != Qnil) {
|
34
|
-
rb_ivar_set(exc,
|
35
|
-
|
36
|
-
ctx->exception = cb_gc_protect(bucket, exc);
|
37
|
-
}
|
34
|
+
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_unlock);
|
35
|
+
ctx->exception = cb_gc_protect(bucket, exc);
|
38
36
|
}
|
39
37
|
}
|
40
38
|
|
41
39
|
if (bucket->async) { /* asynchronous */
|
42
40
|
if (ctx->proc != Qnil) {
|
43
|
-
res = rb_class_new_instance(0, NULL,
|
44
|
-
rb_ivar_set(res,
|
45
|
-
rb_ivar_set(res,
|
46
|
-
rb_ivar_set(res,
|
47
|
-
cb_proc_call(ctx->proc, 1, res);
|
41
|
+
res = rb_class_new_instance(0, NULL, cb_cResult);
|
42
|
+
rb_ivar_set(res, cb_id_iv_error, exc);
|
43
|
+
rb_ivar_set(res, cb_id_iv_operation, cb_sym_unlock);
|
44
|
+
rb_ivar_set(res, cb_id_iv_key, key);
|
45
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
48
46
|
}
|
49
47
|
} else { /* synchronous */
|
50
48
|
rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
|
51
49
|
}
|
52
50
|
if (ctx->nqueries == 0) {
|
53
51
|
cb_gc_unprotect(bucket, ctx->proc);
|
52
|
+
if (bucket->async) {
|
53
|
+
free(ctx);
|
54
|
+
}
|
54
55
|
}
|
55
56
|
(void)handle;
|
56
57
|
}
|
@@ -113,27 +114,27 @@ unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_u
|
|
113
114
|
VALUE
|
114
115
|
cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
|
115
116
|
{
|
116
|
-
struct
|
117
|
-
struct
|
117
|
+
struct cb_bucket_st *bucket = DATA_PTR(self);
|
118
|
+
struct cb_context_st *ctx;
|
118
119
|
VALUE args, rv, proc, exc;
|
119
120
|
lcb_error_t err;
|
120
|
-
struct
|
121
|
+
struct cb_params_st params;
|
121
122
|
|
122
123
|
if (bucket->handle == NULL) {
|
123
|
-
rb_raise(
|
124
|
+
rb_raise(cb_eConnectError, "closed connection");
|
124
125
|
}
|
125
126
|
rb_scan_args(argc, argv, "0*&", &args, &proc);
|
126
127
|
if (!bucket->async && proc != Qnil) {
|
127
128
|
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
128
129
|
}
|
129
|
-
rb_funcall(args,
|
130
|
-
memset(¶ms, 0, sizeof(struct
|
131
|
-
params.type =
|
130
|
+
rb_funcall(args, cb_id_flatten_bang, 0);
|
131
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
132
|
+
params.type = cb_cmd_unlock;
|
132
133
|
params.bucket = bucket;
|
133
134
|
cb_params_build(¶ms, RARRAY_LEN(args), args);
|
134
|
-
ctx =
|
135
|
+
ctx = calloc(1, sizeof(struct cb_context_st));
|
135
136
|
if (ctx == NULL) {
|
136
|
-
rb_raise(
|
137
|
+
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
|
137
138
|
}
|
138
139
|
ctx->proc = cb_gc_protect(bucket, proc);
|
139
140
|
ctx->bucket = bucket;
|
@@ -147,12 +148,12 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
|
|
147
148
|
cb_params_destroy(¶ms);
|
148
149
|
exc = cb_check_error(err, "failed to schedule unlock request", Qnil);
|
149
150
|
if (exc != Qnil) {
|
150
|
-
|
151
|
+
free(ctx);
|
151
152
|
rb_exc_raise(exc);
|
152
153
|
}
|
153
154
|
bucket->nbytes += params.npayload;
|
154
155
|
if (bucket->async) {
|
155
|
-
|
156
|
+
cb_maybe_do_loop(bucket);
|
156
157
|
return Qnil;
|
157
158
|
} else {
|
158
159
|
if (ctx->nqueries > 0) {
|
@@ -160,12 +161,14 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
|
|
160
161
|
lcb_wait(bucket->handle);
|
161
162
|
}
|
162
163
|
exc = ctx->exception;
|
163
|
-
|
164
|
+
free(ctx);
|
164
165
|
if (exc != Qnil) {
|
165
166
|
rb_exc_raise(cb_gc_unprotect(bucket, exc));
|
166
167
|
}
|
167
|
-
|
168
|
-
|
168
|
+
exc = bucket->exception;
|
169
|
+
if (exc != Qnil) {
|
170
|
+
bucket->exception = Qnil;
|
171
|
+
rb_exc_raise(exc);
|
169
172
|
}
|
170
173
|
if (params.cmd.unlock.num > 1) {
|
171
174
|
return rv; /* return as a hash {key => true, ...} */
|
data/ext/couchbase_ext/utils.c
CHANGED
@@ -18,28 +18,80 @@
|
|
18
18
|
#include "couchbase_ext.h"
|
19
19
|
|
20
20
|
VALUE
|
21
|
-
cb_gc_protect(struct
|
21
|
+
cb_gc_protect(struct cb_bucket_st *bucket, VALUE val)
|
22
22
|
{
|
23
23
|
rb_hash_aset(bucket->object_space, val|1, val);
|
24
24
|
return val;
|
25
25
|
}
|
26
26
|
|
27
27
|
VALUE
|
28
|
-
cb_gc_unprotect(struct
|
28
|
+
cb_gc_unprotect(struct cb_bucket_st *bucket, VALUE val)
|
29
29
|
{
|
30
|
-
rb_funcall(bucket->object_space,
|
30
|
+
rb_funcall(bucket->object_space, cb_id_delete, 1, val|1);
|
31
31
|
return val;
|
32
32
|
}
|
33
33
|
|
34
|
+
struct proc_params_st
|
35
|
+
{
|
36
|
+
struct cb_bucket_st *bucket;
|
37
|
+
VALUE recv;
|
38
|
+
ID mid;
|
39
|
+
int argc;
|
40
|
+
VALUE *argv;
|
41
|
+
VALUE exc;
|
42
|
+
};
|
43
|
+
|
44
|
+
static VALUE
|
45
|
+
do_async_error_notify(VALUE ptr)
|
46
|
+
{
|
47
|
+
struct proc_params_st *p = (struct proc_params_st *)ptr;
|
48
|
+
return rb_funcall(p->bucket->on_error_proc, cb_id_call, 1, p->exc);
|
49
|
+
}
|
50
|
+
|
51
|
+
void
|
52
|
+
cb_async_error_notify(struct cb_bucket_st *bucket, VALUE exc)
|
53
|
+
{
|
54
|
+
if (bucket->on_error_proc != Qnil) {
|
55
|
+
struct proc_params_st params;
|
56
|
+
int fail;
|
57
|
+
params.bucket = bucket;
|
58
|
+
params.exc = exc;
|
59
|
+
rb_protect(do_async_error_notify, (VALUE)¶ms, &fail);
|
60
|
+
if (fail) {
|
61
|
+
rb_warning("Couchbase::Bucket#on_error shouldn't raise exceptions");
|
62
|
+
}
|
63
|
+
} else {
|
64
|
+
if (NIL_P(bucket->exception)) {
|
65
|
+
bucket->exception = exc;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE
|
71
|
+
func_call_failed(VALUE ptr, VALUE exc)
|
72
|
+
{
|
73
|
+
struct proc_params_st *p = (struct proc_params_st *)ptr;
|
74
|
+
cb_async_error_notify(p->bucket, exc);
|
75
|
+
return Qnil;
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE
|
79
|
+
do_func_call(VALUE ptr)
|
80
|
+
{
|
81
|
+
struct proc_params_st *p = (struct proc_params_st *)ptr;
|
82
|
+
return rb_funcall2(p->recv, p->mid, p->argc, p->argv);
|
83
|
+
}
|
84
|
+
|
34
85
|
VALUE
|
35
|
-
cb_proc_call(VALUE recv, int argc, ...)
|
86
|
+
cb_proc_call(struct cb_bucket_st *bucket, VALUE recv, int argc, ...)
|
36
87
|
{
|
37
88
|
VALUE *argv;
|
38
89
|
va_list ar;
|
39
90
|
int arity;
|
40
91
|
int ii;
|
92
|
+
struct proc_params_st params;
|
41
93
|
|
42
|
-
arity = FIX2INT(rb_funcall(recv,
|
94
|
+
arity = FIX2INT(rb_funcall(recv, cb_id_arity, 0));
|
43
95
|
if (arity < 0) {
|
44
96
|
arity = argc;
|
45
97
|
}
|
@@ -57,13 +109,20 @@ cb_proc_call(VALUE recv, int argc, ...)
|
|
57
109
|
} else {
|
58
110
|
argv = NULL;
|
59
111
|
}
|
60
|
-
|
112
|
+
params.bucket = bucket;
|
113
|
+
params.recv = recv;
|
114
|
+
params.mid = cb_id_call;
|
115
|
+
params.argc = arity;
|
116
|
+
params.argv = argv;
|
117
|
+
return rb_rescue2(do_func_call, (VALUE)¶ms,
|
118
|
+
func_call_failed, (VALUE)¶ms,
|
119
|
+
rb_eException, (VALUE)0);
|
61
120
|
}
|
62
121
|
|
63
122
|
VALUE
|
64
123
|
cb_hash_delete(VALUE hash, VALUE key)
|
65
124
|
{
|
66
|
-
return rb_funcall(hash,
|
125
|
+
return rb_funcall(hash, cb_id_delete, 1, key);
|
67
126
|
}
|
68
127
|
|
69
128
|
/* Helper to convert return code from libcouchbase to meaningful exception.
|
@@ -77,83 +136,93 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key,
|
|
77
136
|
VALUE klass, exc, str;
|
78
137
|
char buf[300];
|
79
138
|
|
80
|
-
if (rc == LCB_SUCCESS ||
|
139
|
+
if ((rc == LCB_SUCCESS && (status == 0 || status / 100 == 2)) ||
|
140
|
+
rc == LCB_AUTH_CONTINUE) {
|
81
141
|
return Qnil;
|
82
142
|
}
|
83
143
|
switch (rc) {
|
84
144
|
case LCB_AUTH_ERROR:
|
85
|
-
klass =
|
145
|
+
klass = cb_eAuthError;
|
86
146
|
break;
|
87
147
|
case LCB_DELTA_BADVAL:
|
88
|
-
klass =
|
148
|
+
klass = cb_eDeltaBadvalError;
|
89
149
|
break;
|
90
150
|
case LCB_E2BIG:
|
91
|
-
klass =
|
151
|
+
klass = cb_eTooBigError;
|
92
152
|
break;
|
93
153
|
case LCB_EBUSY:
|
94
|
-
klass =
|
154
|
+
klass = cb_eBusyError;
|
95
155
|
break;
|
96
156
|
case LCB_EINTERNAL:
|
97
|
-
klass =
|
157
|
+
klass = cb_eInternalError;
|
98
158
|
break;
|
99
159
|
case LCB_EINVAL:
|
100
|
-
klass =
|
160
|
+
klass = cb_eInvalidError;
|
101
161
|
break;
|
102
162
|
case LCB_ENOMEM:
|
103
|
-
klass =
|
163
|
+
klass = cb_eNoMemoryError;
|
104
164
|
break;
|
105
165
|
case LCB_ERANGE:
|
106
|
-
klass =
|
166
|
+
klass = cb_eRangeError;
|
107
167
|
break;
|
108
168
|
case LCB_ETMPFAIL:
|
109
|
-
klass =
|
169
|
+
klass = cb_eTmpFailError;
|
110
170
|
break;
|
111
171
|
case LCB_KEY_EEXISTS:
|
112
|
-
klass =
|
172
|
+
klass = cb_eKeyExistsError;
|
113
173
|
break;
|
114
174
|
case LCB_KEY_ENOENT:
|
115
|
-
klass =
|
175
|
+
klass = cb_eNotFoundError;
|
116
176
|
break;
|
117
|
-
case
|
118
|
-
klass =
|
177
|
+
case LCB_DLOPEN_FAILED:
|
178
|
+
klass = cb_eDlopenFailedError;
|
179
|
+
break;
|
180
|
+
case LCB_DLSYM_FAILED:
|
181
|
+
klass = cb_eDlsymFailedError;
|
119
182
|
break;
|
120
183
|
case LCB_NETWORK_ERROR:
|
121
|
-
klass =
|
184
|
+
klass = cb_eNetworkError;
|
122
185
|
break;
|
123
186
|
case LCB_NOT_MY_VBUCKET:
|
124
|
-
klass =
|
187
|
+
klass = cb_eNotMyVbucketError;
|
125
188
|
break;
|
126
189
|
case LCB_NOT_STORED:
|
127
|
-
klass =
|
190
|
+
klass = cb_eNotStoredError;
|
128
191
|
break;
|
129
192
|
case LCB_NOT_SUPPORTED:
|
130
|
-
klass =
|
193
|
+
klass = cb_eNotSupportedError;
|
131
194
|
break;
|
132
195
|
case LCB_UNKNOWN_COMMAND:
|
133
|
-
klass =
|
196
|
+
klass = cb_eUnknownCommandError;
|
134
197
|
break;
|
135
198
|
case LCB_UNKNOWN_HOST:
|
136
|
-
klass =
|
199
|
+
klass = cb_eUnknownHostError;
|
137
200
|
break;
|
138
201
|
case LCB_PROTOCOL_ERROR:
|
139
|
-
klass =
|
202
|
+
klass = cb_eProtocolError;
|
140
203
|
break;
|
141
204
|
case LCB_ETIMEDOUT:
|
142
|
-
klass =
|
205
|
+
klass = cb_eTimeoutError;
|
143
206
|
break;
|
144
207
|
case LCB_CONNECT_ERROR:
|
145
|
-
klass =
|
208
|
+
klass = cb_eConnectError;
|
146
209
|
break;
|
147
210
|
case LCB_BUCKET_ENOENT:
|
148
|
-
klass =
|
211
|
+
klass = cb_eBucketNotFoundError;
|
149
212
|
break;
|
150
213
|
case LCB_CLIENT_ENOMEM:
|
151
|
-
klass =
|
214
|
+
klass = cb_eClientNoMemoryError;
|
215
|
+
break;
|
216
|
+
case LCB_CLIENT_ETMPFAIL:
|
217
|
+
klass = cb_eClientTmpFailError;
|
218
|
+
break;
|
219
|
+
case LCB_EBADHANDLE:
|
220
|
+
klass = cb_eBadHandleError;
|
152
221
|
break;
|
153
222
|
case LCB_ERROR:
|
154
223
|
/* fall through */
|
155
224
|
default:
|
156
|
-
klass =
|
225
|
+
klass = cb_eLibcouchbaseError;
|
157
226
|
}
|
158
227
|
|
159
228
|
str = rb_str_buf_new2(msg ? msg : "");
|
@@ -164,6 +233,7 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key,
|
|
164
233
|
}
|
165
234
|
if (status > 0) {
|
166
235
|
const char *reason = NULL;
|
236
|
+
klass = cb_eHTTPError;
|
167
237
|
snprintf(buf, 300, "status=\"%d\"", status);
|
168
238
|
rb_str_buf_cat2(str, buf);
|
169
239
|
switch (status) {
|
@@ -261,11 +331,11 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key,
|
|
261
331
|
snprintf(buf, 300, "error=0x%02x)", rc);
|
262
332
|
rb_str_buf_cat2(str, buf);
|
263
333
|
exc = rb_exc_new3(klass, str);
|
264
|
-
rb_ivar_set(exc,
|
265
|
-
rb_ivar_set(exc,
|
266
|
-
rb_ivar_set(exc,
|
267
|
-
rb_ivar_set(exc,
|
268
|
-
rb_ivar_set(exc,
|
334
|
+
rb_ivar_set(exc, cb_id_iv_error, INT2FIX(rc));
|
335
|
+
rb_ivar_set(exc, cb_id_iv_key, key);
|
336
|
+
rb_ivar_set(exc, cb_id_iv_cas, Qnil);
|
337
|
+
rb_ivar_set(exc, cb_id_iv_operation, Qnil);
|
338
|
+
rb_ivar_set(exc, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
|
269
339
|
return exc;
|
270
340
|
}
|
271
341
|
|
@@ -277,35 +347,35 @@ cb_check_error(lcb_error_t rc, const char *msg, VALUE key)
|
|
277
347
|
|
278
348
|
|
279
349
|
uint32_t
|
280
|
-
|
350
|
+
cb_flags_set_format(uint32_t flags, ID format)
|
281
351
|
{
|
282
|
-
flags &= ~((uint32_t)
|
283
|
-
|
284
|
-
if (format ==
|
285
|
-
return flags |
|
286
|
-
} else if (format ==
|
287
|
-
return flags |
|
288
|
-
} else if (format ==
|
289
|
-
return flags |
|
352
|
+
flags &= ~((uint32_t)CB_FMT_MASK); /* clear format bits */
|
353
|
+
|
354
|
+
if (format == cb_sym_document) {
|
355
|
+
return flags | CB_FMT_DOCUMENT;
|
356
|
+
} else if (format == cb_sym_marshal) {
|
357
|
+
return flags | CB_FMT_MARSHAL;
|
358
|
+
} else if (format == cb_sym_plain) {
|
359
|
+
return flags | CB_FMT_PLAIN;
|
290
360
|
}
|
291
361
|
return flags; /* document is the default */
|
292
362
|
}
|
293
363
|
|
294
364
|
ID
|
295
|
-
|
365
|
+
cb_flags_get_format(uint32_t flags)
|
296
366
|
{
|
297
|
-
flags &=
|
367
|
+
flags &= CB_FMT_MASK; /* select format bits */
|
298
368
|
|
299
369
|
switch (flags) {
|
300
|
-
case
|
301
|
-
return
|
302
|
-
case
|
303
|
-
return
|
304
|
-
case
|
370
|
+
case CB_FMT_DOCUMENT:
|
371
|
+
return cb_sym_document;
|
372
|
+
case CB_FMT_MARSHAL:
|
373
|
+
return cb_sym_marshal;
|
374
|
+
case CB_FMT_PLAIN:
|
305
375
|
/* fall through */
|
306
376
|
default:
|
307
377
|
/* all other formats treated as plain */
|
308
|
-
return
|
378
|
+
return cb_sym_plain;
|
309
379
|
}
|
310
380
|
}
|
311
381
|
|
@@ -314,14 +384,14 @@ flags_get_format(uint32_t flags)
|
|
314
384
|
do_encode(VALUE *args)
|
315
385
|
{
|
316
386
|
VALUE val = args[0];
|
317
|
-
uint32_t flags = ((uint32_t)args[1] &
|
387
|
+
uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
|
318
388
|
|
319
389
|
switch (flags) {
|
320
|
-
case
|
321
|
-
return rb_funcall(
|
322
|
-
case
|
323
|
-
return rb_funcall(
|
324
|
-
case
|
390
|
+
case CB_FMT_DOCUMENT:
|
391
|
+
return rb_funcall(cb_mMultiJson, cb_id_dump, 1, val);
|
392
|
+
case CB_FMT_MARSHAL:
|
393
|
+
return rb_funcall(cb_mMarshal, cb_id_dump, 1, val);
|
394
|
+
case CB_FMT_PLAIN:
|
325
395
|
/* fall through */
|
326
396
|
default:
|
327
397
|
/* all other formats treated as plain */
|
@@ -336,22 +406,22 @@ do_decode(VALUE *args)
|
|
336
406
|
VALUE force_format = args[2];
|
337
407
|
|
338
408
|
if (TYPE(force_format) == T_SYMBOL) {
|
339
|
-
if (force_format ==
|
340
|
-
return rb_funcall(
|
341
|
-
} else if (force_format ==
|
342
|
-
return rb_funcall(
|
343
|
-
} else { /*
|
409
|
+
if (force_format == cb_sym_document) {
|
410
|
+
return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
|
411
|
+
} else if (force_format == cb_sym_marshal) {
|
412
|
+
return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
|
413
|
+
} else { /* cb_sym_plain and any other cb_symbol */
|
344
414
|
return blob;
|
345
415
|
}
|
346
416
|
} else {
|
347
|
-
uint32_t flags = ((uint32_t)args[1] &
|
417
|
+
uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
|
348
418
|
|
349
419
|
switch (flags) {
|
350
|
-
case
|
351
|
-
return rb_funcall(
|
352
|
-
case
|
353
|
-
return rb_funcall(
|
354
|
-
case
|
420
|
+
case CB_FMT_DOCUMENT:
|
421
|
+
return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
|
422
|
+
case CB_FMT_MARSHAL:
|
423
|
+
return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
|
424
|
+
case CB_FMT_PLAIN:
|
355
425
|
/* fall through */
|
356
426
|
default:
|
357
427
|
/* all other formats treated as plain */
|
@@ -361,29 +431,25 @@ do_decode(VALUE *args)
|
|
361
431
|
}
|
362
432
|
|
363
433
|
static VALUE
|
364
|
-
coding_failed(
|
434
|
+
coding_failed(VALUE unused, VALUE exc)
|
365
435
|
{
|
366
|
-
|
436
|
+
(void)unused;
|
437
|
+
return exc;
|
367
438
|
}
|
368
439
|
|
369
440
|
VALUE
|
370
|
-
|
441
|
+
cb_encode_value(VALUE val, uint32_t flags)
|
371
442
|
{
|
372
443
|
VALUE blob, args[2];
|
373
444
|
|
374
445
|
args[0] = val;
|
375
446
|
args[1] = (VALUE)flags;
|
376
|
-
/* FIXME re-raise proper exception */
|
377
447
|
blob = rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
|
378
|
-
|
379
|
-
if (TYPE(blob) != T_STRING) {
|
380
|
-
return Qundef;
|
381
|
-
}
|
382
|
-
return blob;
|
448
|
+
return blob; /* bytestring or exception object */
|
383
449
|
}
|
384
450
|
|
385
451
|
VALUE
|
386
|
-
|
452
|
+
cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format)
|
387
453
|
{
|
388
454
|
VALUE val, args[3];
|
389
455
|
|
@@ -395,23 +461,23 @@ decode_value(VALUE blob, uint32_t flags, VALUE force_format)
|
|
395
461
|
args[1] = (VALUE)flags;
|
396
462
|
args[2] = (VALUE)force_format;
|
397
463
|
val = rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
|
398
|
-
return val;
|
464
|
+
return val; /* the value or exception object */
|
399
465
|
}
|
400
466
|
|
401
467
|
void
|
402
|
-
|
468
|
+
cb_strip_key_prefix(struct cb_bucket_st *bucket, VALUE key)
|
403
469
|
{
|
404
|
-
if (bucket->
|
405
|
-
rb_str_update(key, 0, RSTRING_LEN(bucket->key_prefix_val),
|
470
|
+
if (RTEST(bucket->key_prefix_val)) {
|
471
|
+
rb_str_update(key, 0, RSTRING_LEN(bucket->key_prefix_val), cb_vStrEmpty);
|
406
472
|
}
|
407
473
|
}
|
408
474
|
|
409
475
|
VALUE
|
410
|
-
|
476
|
+
cb_unify_key(struct cb_bucket_st *bucket, VALUE key, int apply_prefix)
|
411
477
|
{
|
412
478
|
VALUE ret = Qnil, tmp;
|
413
479
|
|
414
|
-
if (bucket->
|
480
|
+
if (RTEST(bucket->key_prefix_val) && apply_prefix) {
|
415
481
|
ret = rb_str_dup(bucket->key_prefix_val);
|
416
482
|
}
|
417
483
|
switch (TYPE(key)) {
|
@@ -427,7 +493,7 @@ unify_key(struct bucket_st *bucket, VALUE key, int apply_prefix)
|
|
427
493
|
}
|
428
494
|
|
429
495
|
void
|
430
|
-
cb_build_headers(struct
|
496
|
+
cb_build_headers(struct cb_context_st *ctx, const char * const *headers)
|
431
497
|
{
|
432
498
|
if (!ctx->headers_built) {
|
433
499
|
VALUE key = Qnil, val;
|
@@ -469,3 +535,14 @@ cb_first_value_i(VALUE key, VALUE value, VALUE arg)
|
|
469
535
|
(void)key;
|
470
536
|
return ST_STOP;
|
471
537
|
}
|
538
|
+
|
539
|
+
#ifndef HAVE_RB_HASH_LOOKUP2
|
540
|
+
VALUE
|
541
|
+
rb_hash_lookup2(VALUE hash, VALUE key, VALUE dflt)
|
542
|
+
{
|
543
|
+
if (RTEST(rb_funcall2(hash, cb_id_has_key_p, 1, &key))) {
|
544
|
+
dflt = rb_hash_aref(hash, key);
|
545
|
+
}
|
546
|
+
return dflt;
|
547
|
+
}
|
548
|
+
#endif
|