couchbase 1.2.1-x86-mingw32 → 1.2.2-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/README.markdown +50 -5
- data/RELEASE_NOTES.markdown +256 -145
- data/couchbase.gemspec +2 -4
- data/examples/chat-em/Gemfile +7 -0
- data/examples/chat-em/README.markdown +45 -0
- data/examples/chat-em/server.rb +82 -0
- data/ext/couchbase_ext/arguments.c +18 -17
- data/ext/couchbase_ext/arithmetic.c +17 -25
- data/ext/couchbase_ext/bucket.c +227 -32
- data/ext/couchbase_ext/context.c +64 -0
- data/ext/couchbase_ext/couchbase_ext.c +106 -14
- data/ext/couchbase_ext/couchbase_ext.h +81 -12
- data/ext/couchbase_ext/delete.c +18 -25
- data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
- data/ext/couchbase_ext/extconf.rb +2 -0
- data/ext/couchbase_ext/get.c +18 -31
- data/ext/couchbase_ext/http.c +40 -31
- data/ext/couchbase_ext/multithread_plugin.c +38 -201
- data/ext/couchbase_ext/observe.c +17 -25
- data/ext/couchbase_ext/plugin_common.c +171 -0
- data/ext/couchbase_ext/result.c +18 -12
- data/ext/couchbase_ext/stats.c +17 -25
- data/ext/couchbase_ext/store.c +43 -47
- data/ext/couchbase_ext/touch.c +18 -25
- data/ext/couchbase_ext/unlock.c +18 -25
- data/ext/couchbase_ext/utils.c +23 -8
- data/ext/couchbase_ext/version.c +16 -24
- data/lib/couchbase.rb +1 -0
- data/lib/couchbase/bucket.rb +1 -1
- data/lib/couchbase/constants.rb +12 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +210 -60
- data/lib/couchbase/view_row.rb +103 -61
- data/tasks/compile.rake +1 -1
- data/test/test_async.rb +63 -0
- data/test/test_eventmachine.rb +70 -0
- metadata +24 -49
- data/tasks/doc.rake +0 -27
data/ext/couchbase_ext/delete.c
CHANGED
@@ -22,7 +22,7 @@ cb_delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
|
|
22
22
|
{
|
23
23
|
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
24
|
struct cb_bucket_st *bucket = ctx->bucket;
|
25
|
-
VALUE key,
|
25
|
+
VALUE key, exc = Qnil, res;
|
26
26
|
|
27
27
|
ctx->nqueries--;
|
28
28
|
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
@@ -32,7 +32,7 @@ cb_delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
|
|
32
32
|
exc = cb_check_error(error, "failed to remove value", key);
|
33
33
|
if (exc != Qnil) {
|
34
34
|
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_delete);
|
35
|
-
ctx->exception =
|
35
|
+
ctx->exception = exc;
|
36
36
|
}
|
37
37
|
}
|
38
38
|
if (bucket->async) { /* asynchronous */
|
@@ -44,12 +44,12 @@ cb_delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
|
|
44
44
|
cb_proc_call(bucket, ctx->proc, 1, res);
|
45
45
|
}
|
46
46
|
} else { /* synchronous */
|
47
|
-
rb_hash_aset(
|
47
|
+
rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
|
48
48
|
}
|
49
49
|
if (ctx->nqueries == 0) {
|
50
|
-
|
50
|
+
ctx->proc = Qnil;
|
51
51
|
if (bucket->async) {
|
52
|
-
|
52
|
+
cb_context_free(ctx);
|
53
53
|
}
|
54
54
|
}
|
55
55
|
(void)handle;
|
@@ -103,40 +103,32 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
|
|
103
103
|
struct cb_bucket_st *bucket = DATA_PTR(self);
|
104
104
|
struct cb_context_st *ctx;
|
105
105
|
VALUE rv, exc;
|
106
|
-
VALUE
|
106
|
+
VALUE proc;
|
107
107
|
lcb_error_t err;
|
108
108
|
struct cb_params_st params;
|
109
109
|
|
110
|
-
if (bucket
|
111
|
-
|
110
|
+
if (!cb_bucket_connected_bang(bucket, cb_sym_delete)) {
|
111
|
+
return Qnil;
|
112
112
|
}
|
113
|
-
|
113
|
+
|
114
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
115
|
+
rb_scan_args(argc, argv, "0*&", ¶ms.args, &proc);
|
114
116
|
if (!bucket->async && proc != Qnil) {
|
115
117
|
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
116
118
|
}
|
117
|
-
rb_funcall(args, cb_id_flatten_bang, 0);
|
118
|
-
memset(¶ms, 0, sizeof(struct cb_params_st));
|
119
|
+
rb_funcall(params.args, cb_id_flatten_bang, 0);
|
119
120
|
params.type = cb_cmd_remove;
|
120
121
|
params.bucket = bucket;
|
121
|
-
cb_params_build(¶ms
|
122
|
+
cb_params_build(¶ms);
|
122
123
|
|
123
|
-
ctx =
|
124
|
-
if (ctx == NULL) {
|
125
|
-
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
|
126
|
-
}
|
124
|
+
ctx = cb_context_alloc_common(bucket, proc, params.cmd.remove.num);
|
127
125
|
ctx->quiet = params.cmd.remove.quiet;
|
128
|
-
ctx->proc = cb_gc_protect(bucket, proc);
|
129
|
-
rv = rb_hash_new();
|
130
|
-
ctx->rv = &rv;
|
131
|
-
ctx->bucket = bucket;
|
132
|
-
ctx->exception = Qnil;
|
133
|
-
ctx->nqueries = params.cmd.remove.num;
|
134
126
|
err = lcb_remove(bucket->handle, (const void *)ctx,
|
135
127
|
params.cmd.remove.num, params.cmd.remove.ptr);
|
136
128
|
cb_params_destroy(¶ms);
|
137
129
|
exc = cb_check_error(err, "failed to schedule delete request", Qnil);
|
138
130
|
if (exc != Qnil) {
|
139
|
-
|
131
|
+
cb_context_free(ctx);
|
140
132
|
rb_exc_raise(exc);
|
141
133
|
}
|
142
134
|
bucket->nbytes += params.npayload;
|
@@ -149,9 +141,10 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
|
|
149
141
|
lcb_wait(bucket->handle);
|
150
142
|
}
|
151
143
|
exc = ctx->exception;
|
152
|
-
|
144
|
+
rv = ctx->rv;
|
145
|
+
cb_context_free(ctx);
|
153
146
|
if (exc != Qnil) {
|
154
|
-
rb_exc_raise(
|
147
|
+
rb_exc_raise(exc);
|
155
148
|
}
|
156
149
|
exc = bucket->exception;
|
157
150
|
if (exc != Qnil) {
|
@@ -0,0 +1,452 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 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
|
+
#ifndef _WIN32
|
21
|
+
#ifdef BUILD_EVENTMACHINE_PLUGIN
|
22
|
+
|
23
|
+
#include <errno.h>
|
24
|
+
|
25
|
+
VALUE cb_mEm;
|
26
|
+
VALUE cb_cEmSocket;
|
27
|
+
VALUE em_cPeriodicTimer;
|
28
|
+
VALUE cb_cEmEvent;
|
29
|
+
VALUE rb_mObSpace;
|
30
|
+
ID cb_id_add_timer;
|
31
|
+
ID cb_id_cancel_timer;
|
32
|
+
ID cb_id_detach;
|
33
|
+
ID cb_id_define_finalizer;
|
34
|
+
ID cb_id_iv_event;
|
35
|
+
ID cb_id_notify_readable_p;
|
36
|
+
ID cb_id_notify_writable_p;
|
37
|
+
ID cb_id_set_notify_readable;
|
38
|
+
ID cb_id_set_notify_writable;
|
39
|
+
ID cb_id_undefine_finalizer;
|
40
|
+
ID cb_id_watch;
|
41
|
+
VALUE cb_sym_clear_holder;
|
42
|
+
VALUE cb_sym_resume;
|
43
|
+
|
44
|
+
typedef struct rb_em_event rb_em_event;
|
45
|
+
typedef struct rb_em_loop rb_em_loop;
|
46
|
+
struct rb_em_event {
|
47
|
+
lcb_socket_t socket;
|
48
|
+
void *cb_data;
|
49
|
+
void (*handler)(lcb_socket_t sock, short which, void *cb_data);
|
50
|
+
VALUE holder;
|
51
|
+
lcb_uint32_t usec;
|
52
|
+
short canceled;
|
53
|
+
short current_flags;
|
54
|
+
VALUE self;
|
55
|
+
rb_em_loop *loop;
|
56
|
+
};
|
57
|
+
|
58
|
+
struct rb_em_loop {
|
59
|
+
VALUE fiber;
|
60
|
+
struct cb_bucket_st *bucket;
|
61
|
+
};
|
62
|
+
|
63
|
+
static void
|
64
|
+
rb_em_event_mark(void *p)
|
65
|
+
{
|
66
|
+
if (p) {
|
67
|
+
rb_em_event *ev = p;
|
68
|
+
rb_gc_mark(ev->holder);
|
69
|
+
rb_gc_mark(ev->loop->bucket->self);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
static void
|
74
|
+
rb_em_event_free(void *p)
|
75
|
+
{
|
76
|
+
if (p) {
|
77
|
+
rb_em_event *ev = p;
|
78
|
+
ev->self = 0;
|
79
|
+
ev->holder = 0;
|
80
|
+
ev->loop = NULL;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
static void
|
85
|
+
rb_em_event_run_callback(rb_em_event *ev, short flags)
|
86
|
+
{
|
87
|
+
if (ev->loop->fiber) {
|
88
|
+
ev->current_flags = flags;
|
89
|
+
rb_fiber_resume(ev->loop->fiber, 1, &ev->self);
|
90
|
+
} else {
|
91
|
+
ev->handler(ev->socket, flags, ev->cb_data);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE
|
96
|
+
rb_em_event_call(VALUE self)
|
97
|
+
{
|
98
|
+
rb_em_event *ev;
|
99
|
+
Data_Get_Struct(self, rb_em_event, ev);
|
100
|
+
|
101
|
+
ev->holder = 0;
|
102
|
+
rb_em_event_run_callback(ev, 0);
|
103
|
+
|
104
|
+
if (!ev->canceled && !ev->holder) {
|
105
|
+
ev->holder = rb_funcall_2(em_m, cb_id_add_timer, rb_float_new((double)ev->usec / 1.0e6), self);
|
106
|
+
}
|
107
|
+
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE
|
112
|
+
rb_em_event_clear_holder(VALUE self)
|
113
|
+
{
|
114
|
+
rb_em_event *ev;
|
115
|
+
Data_Get_Struct(self, rb_em_event, ev);
|
116
|
+
|
117
|
+
ev->holder = 0;
|
118
|
+
|
119
|
+
return Qnil;
|
120
|
+
}
|
121
|
+
|
122
|
+
static void
|
123
|
+
rb_em_event_setup_finalizer(rb_em_event *ev)
|
124
|
+
{
|
125
|
+
rb_funcall_2(rb_mObSpace, cb_id_define_finalizer, ev->holder,
|
126
|
+
rb_obj_method(ev->self, cb_sym_clear_holder));
|
127
|
+
}
|
128
|
+
|
129
|
+
static void
|
130
|
+
rb_em_event_clear_finalizer(rb_em_event *ev)
|
131
|
+
{
|
132
|
+
rb_funcall_1(rb_mObSpace, cb_id_undefine_finalizer, ev->holder);
|
133
|
+
}
|
134
|
+
|
135
|
+
static VALUE
|
136
|
+
rb_em_socket_notify_readable(VALUE self)
|
137
|
+
{
|
138
|
+
VALUE event = rb_ivar_get(self, cb_id_iv_event);
|
139
|
+
rb_em_event *ev;
|
140
|
+
|
141
|
+
if (RTEST(event)) {
|
142
|
+
Data_Get_Struct(event, rb_em_event, ev);
|
143
|
+
rb_em_event_run_callback(ev, LCB_READ_EVENT);
|
144
|
+
} else {
|
145
|
+
rb_funcall_0(self, cb_id_detach);
|
146
|
+
}
|
147
|
+
|
148
|
+
return Qnil;
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE
|
152
|
+
rb_em_socket_notify_writable(VALUE self)
|
153
|
+
{
|
154
|
+
VALUE event = rb_ivar_get(self, cb_id_iv_event);
|
155
|
+
rb_em_event *ev;
|
156
|
+
|
157
|
+
if (RTEST(event)) {
|
158
|
+
Data_Get_Struct(event, rb_em_event, ev);
|
159
|
+
rb_em_event_run_callback(ev, LCB_WRITE_EVENT);
|
160
|
+
} else {
|
161
|
+
rb_funcall_0(self, cb_id_detach);
|
162
|
+
}
|
163
|
+
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
static void
|
168
|
+
cb_gc_em_loop_mark(void *p, struct cb_bucket_st *bucket)
|
169
|
+
{
|
170
|
+
rb_em_loop *loop = p;
|
171
|
+
rb_gc_mark(loop->fiber);
|
172
|
+
(void)bucket;
|
173
|
+
}
|
174
|
+
|
175
|
+
static rb_em_loop *
|
176
|
+
rb_em_loop_create(struct cb_bucket_st *bucket)
|
177
|
+
{
|
178
|
+
rb_em_loop *loop = calloc(1, sizeof(*loop));
|
179
|
+
loop->bucket = bucket;
|
180
|
+
cb_gc_protect_ptr(bucket, loop, cb_gc_em_loop_mark);
|
181
|
+
return loop;
|
182
|
+
}
|
183
|
+
|
184
|
+
static void
|
185
|
+
rb_em_loop_destroy(rb_em_loop *loop)
|
186
|
+
{
|
187
|
+
cb_gc_unprotect_ptr(loop->bucket, loop);
|
188
|
+
free(loop);
|
189
|
+
}
|
190
|
+
|
191
|
+
static void
|
192
|
+
initialize_event_machine_plugin() {
|
193
|
+
VALUE em_cConnection;
|
194
|
+
|
195
|
+
rb_mObSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
|
196
|
+
|
197
|
+
em_m = rb_const_get(rb_cObject, rb_intern("EM"));
|
198
|
+
em_cConnection = rb_const_get(em_m, rb_intern("Connection"));
|
199
|
+
em_cPeriodicTimer = rb_const_get(em_m, rb_intern("PeriodicTimer"));
|
200
|
+
|
201
|
+
cb_mEm = rb_define_module_under(cb_mCouchbase, "EM");
|
202
|
+
|
203
|
+
cb_cEmEvent = rb_define_class_under(cb_mEm, "Event", rb_cObject);
|
204
|
+
rb_define_method(cb_cEmEvent, "call", rb_em_event_call, 0);
|
205
|
+
rb_define_method(cb_cEmEvent, "clear_holder", rb_em_event_clear_holder, 0);
|
206
|
+
|
207
|
+
cb_cEmSocket = rb_define_class_under(cb_mEm, "Socket", em_cConnection);
|
208
|
+
rb_define_method(cb_cEmSocket, "notify_readable", rb_em_socket_notify_readable, 0);
|
209
|
+
rb_define_method(cb_cEmSocket, "notify_writable", rb_em_socket_notify_writable, 0);
|
210
|
+
|
211
|
+
cb_id_add_timer = rb_intern("add_timer");
|
212
|
+
cb_id_cancel_timer = rb_intern("cancel_timer");
|
213
|
+
cb_id_define_finalizer = rb_intern("define_finalizer");
|
214
|
+
cb_id_detach = rb_intern("detach");
|
215
|
+
cb_id_iv_event = rb_intern("@event");
|
216
|
+
cb_id_notify_readable_p = rb_intern("notify_readable?");
|
217
|
+
cb_id_notify_writable_p = rb_intern("notify_writable?");
|
218
|
+
cb_id_set_notify_readable = rb_intern("notify_readable=");
|
219
|
+
cb_id_set_notify_writable = rb_intern("notify_writable=");
|
220
|
+
cb_id_undefine_finalizer = rb_intern("undefine_finalizer");
|
221
|
+
cb_id_watch = rb_intern("watch");
|
222
|
+
cb_sym_clear_holder = ID2SYM(rb_intern("clear_holder"));
|
223
|
+
cb_sym_resume = ID2SYM(rb_intern("resume"));
|
224
|
+
}
|
225
|
+
|
226
|
+
static void
|
227
|
+
cb_gc_em_event_mark(void *p, struct cb_bucket_st *bucket)
|
228
|
+
{
|
229
|
+
rb_em_event *ev = p;
|
230
|
+
rb_gc_mark(ev->self);
|
231
|
+
(void)bucket;
|
232
|
+
}
|
233
|
+
|
234
|
+
static void *
|
235
|
+
lcb_io_create_event(struct lcb_io_opt_st *iops)
|
236
|
+
{
|
237
|
+
rb_em_loop *loop = iops->v.v0.cookie;
|
238
|
+
rb_em_event *ev = calloc(1, sizeof(rb_em_event));
|
239
|
+
VALUE res = Data_Wrap_Struct(cb_cEmEvent, rb_em_event_mark, rb_em_event_free, ev);
|
240
|
+
cb_gc_protect_ptr(loop->bucket, ev, cb_gc_em_event_mark);
|
241
|
+
ev->self = res;
|
242
|
+
ev->loop = loop;
|
243
|
+
ev->socket = -1;
|
244
|
+
|
245
|
+
return ev;
|
246
|
+
}
|
247
|
+
|
248
|
+
static inline void
|
249
|
+
rb_em_event_dealloc(rb_em_event *ev, rb_em_loop *loop)
|
250
|
+
{
|
251
|
+
if (ev->self) {
|
252
|
+
DATA_PTR(ev->self) = 0;
|
253
|
+
}
|
254
|
+
cb_gc_unprotect_ptr(loop->bucket, ev);
|
255
|
+
free(ev);
|
256
|
+
}
|
257
|
+
|
258
|
+
static int
|
259
|
+
lcb_io_update_event(struct lcb_io_opt_st *iops,
|
260
|
+
lcb_socket_t sock,
|
261
|
+
void *event,
|
262
|
+
short flags,
|
263
|
+
void *cb_data,
|
264
|
+
void (*handler)(lcb_socket_t sock,
|
265
|
+
short which,
|
266
|
+
void *cb_data))
|
267
|
+
{
|
268
|
+
rb_em_event *ev = event;
|
269
|
+
|
270
|
+
if (ev->holder == 0) {
|
271
|
+
ev->holder = rb_funcall_2(em_m, cb_id_watch, INT2FIX(sock), cb_cEmSocket);
|
272
|
+
rb_ivar_set(ev->holder, cb_id_iv_event, ev->self);
|
273
|
+
rb_em_event_setup_finalizer(ev);
|
274
|
+
}
|
275
|
+
|
276
|
+
ev->socket = sock;
|
277
|
+
ev->cb_data = cb_data;
|
278
|
+
ev->handler = handler;
|
279
|
+
|
280
|
+
rb_funcall_1(ev->holder, cb_id_set_notify_readable, (flags & LCB_READ_EVENT) ? Qtrue : Qfalse);
|
281
|
+
rb_funcall_1(ev->holder, cb_id_set_notify_writable, (flags & LCB_WRITE_EVENT) ? Qtrue : Qfalse);
|
282
|
+
|
283
|
+
(void)iops;
|
284
|
+
return 0;
|
285
|
+
}
|
286
|
+
|
287
|
+
static void
|
288
|
+
lcb_io_delete_event(struct lcb_io_opt_st *iops,
|
289
|
+
lcb_socket_t sock,
|
290
|
+
void *event)
|
291
|
+
{
|
292
|
+
rb_em_event *ev = event;
|
293
|
+
if (ev->holder) {
|
294
|
+
rb_funcall_1(ev->holder, cb_id_set_notify_readable, Qfalse);
|
295
|
+
rb_funcall_1(ev->holder, cb_id_set_notify_writable, Qfalse);
|
296
|
+
}
|
297
|
+
(void)sock;
|
298
|
+
(void)iops;
|
299
|
+
}
|
300
|
+
|
301
|
+
static void
|
302
|
+
lcb_io_destroy_event(struct lcb_io_opt_st *iops,
|
303
|
+
void *event)
|
304
|
+
{
|
305
|
+
rb_em_loop *loop = iops->v.v0.cookie;
|
306
|
+
rb_em_event *ev = event;
|
307
|
+
if (ev->holder) {
|
308
|
+
rb_em_event_clear_finalizer(ev);
|
309
|
+
rb_ivar_set(ev->holder, cb_id_iv_event, Qfalse);
|
310
|
+
rb_funcall_0(ev->holder, cb_id_detach);
|
311
|
+
ev->holder = 0;
|
312
|
+
}
|
313
|
+
rb_em_event_dealloc(ev, loop);
|
314
|
+
}
|
315
|
+
|
316
|
+
#define lcb_io_create_timer lcb_io_create_event
|
317
|
+
|
318
|
+
static int
|
319
|
+
lcb_io_update_timer(struct lcb_io_opt_st *iops, void *timer,
|
320
|
+
lcb_uint32_t usec, void *cb_data,
|
321
|
+
void (*handler)(lcb_socket_t sock, short which, void *cb_data))
|
322
|
+
{
|
323
|
+
rb_em_event *ev = timer;
|
324
|
+
|
325
|
+
if (ev->holder) {
|
326
|
+
rb_funcall_1(em_m, cb_id_cancel_timer, ev->holder);
|
327
|
+
ev->holder = 0;
|
328
|
+
}
|
329
|
+
|
330
|
+
ev->socket = (lcb_socket_t)-1;
|
331
|
+
ev->cb_data = cb_data;
|
332
|
+
ev->handler = handler;
|
333
|
+
ev->usec = usec;
|
334
|
+
ev->canceled = 0;
|
335
|
+
ev->holder = rb_funcall_2(em_m, cb_id_add_timer, rb_float_new((double)usec / 1.0e6), ev->self);
|
336
|
+
|
337
|
+
(void)iops;
|
338
|
+
return 0;
|
339
|
+
}
|
340
|
+
|
341
|
+
static void
|
342
|
+
lcb_io_delete_timer(struct lcb_io_opt_st *iops, void *timer)
|
343
|
+
{
|
344
|
+
rb_em_event *ev = timer;
|
345
|
+
|
346
|
+
if (ev->holder) {
|
347
|
+
rb_funcall_1(em_m, cb_id_cancel_timer, ev->holder);
|
348
|
+
ev->holder = 0;
|
349
|
+
}
|
350
|
+
ev->canceled = 1;
|
351
|
+
(void)iops;
|
352
|
+
}
|
353
|
+
|
354
|
+
static void
|
355
|
+
lcb_io_destroy_timer(struct lcb_io_opt_st *iops, void *timer)
|
356
|
+
{
|
357
|
+
rb_em_loop *loop = iops->v.v0.cookie;
|
358
|
+
rb_em_event *ev = timer;
|
359
|
+
if (!ev->canceled) {
|
360
|
+
lcb_io_delete_timer(iops, timer);
|
361
|
+
}
|
362
|
+
rb_em_event_dealloc(ev, loop);
|
363
|
+
}
|
364
|
+
|
365
|
+
static void
|
366
|
+
lcb_io_run_event_loop(struct lcb_io_opt_st *iops)
|
367
|
+
{
|
368
|
+
rb_em_loop *loop = iops->v.v0.cookie;
|
369
|
+
VALUE fiber = rb_fiber_current();
|
370
|
+
VALUE event;
|
371
|
+
rb_em_event *ev;
|
372
|
+
loop->fiber = fiber;
|
373
|
+
for(;;) {
|
374
|
+
event = rb_fiber_yield(0, NULL);
|
375
|
+
if (!RTEST(event)) break;
|
376
|
+
Data_Get_Struct(event, rb_em_event, ev);
|
377
|
+
ev->handler(ev->socket, ev->current_flags, ev->cb_data);
|
378
|
+
}
|
379
|
+
}
|
380
|
+
|
381
|
+
static void
|
382
|
+
lcb_io_stop_event_loop(struct lcb_io_opt_st *iops)
|
383
|
+
{
|
384
|
+
rb_em_loop *loop = iops->v.v0.cookie;
|
385
|
+
VALUE fiber = loop->fiber;
|
386
|
+
loop->fiber = 0;
|
387
|
+
if (fiber) {
|
388
|
+
VALUE method = rb_obj_method(fiber, cb_sym_resume);
|
389
|
+
rb_funcall_1(em_m, cb_id_next_tick, method);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
static void
|
394
|
+
lcb_destroy_io_opts(struct lcb_io_opt_st *iops)
|
395
|
+
{
|
396
|
+
rb_em_loop_destroy((rb_em_loop*)iops->v.v0.cookie);
|
397
|
+
}
|
398
|
+
|
399
|
+
LIBCOUCHBASE_API lcb_error_t
|
400
|
+
cb_create_ruby_em_io_opts(int version, lcb_io_opt_t *io, void *arg)
|
401
|
+
{
|
402
|
+
struct lcb_io_opt_st *ret;
|
403
|
+
rb_em_loop *loop;
|
404
|
+
struct cb_bucket_st *bucket = arg;
|
405
|
+
|
406
|
+
if (version != 0) {
|
407
|
+
return LCB_PLUGIN_VERSION_MISMATCH;
|
408
|
+
}
|
409
|
+
|
410
|
+
if (!em_m) initialize_event_machine_plugin();
|
411
|
+
|
412
|
+
ret = calloc(1, sizeof(*ret));
|
413
|
+
if (ret == NULL) {
|
414
|
+
free(ret);
|
415
|
+
return LCB_CLIENT_ENOMEM;
|
416
|
+
}
|
417
|
+
|
418
|
+
ret->version = 0;
|
419
|
+
ret->dlhandle = NULL;
|
420
|
+
ret->destructor = lcb_destroy_io_opts;
|
421
|
+
/* consider that struct isn't allocated by the library,
|
422
|
+
* `need_cleanup' flag might be set in lcb_create() */
|
423
|
+
ret->v.v0.need_cleanup = 0;
|
424
|
+
ret->v.v0.recv = cb_io_recv;
|
425
|
+
ret->v.v0.send = cb_io_send;
|
426
|
+
ret->v.v0.recvv = cb_io_recvv;
|
427
|
+
ret->v.v0.sendv = cb_io_sendv;
|
428
|
+
ret->v.v0.socket = cb_io_socket;
|
429
|
+
ret->v.v0.close = cb_io_close;
|
430
|
+
ret->v.v0.connect = cb_io_connect;
|
431
|
+
ret->v.v0.delete_event = lcb_io_delete_event;
|
432
|
+
ret->v.v0.destroy_event = lcb_io_destroy_event;
|
433
|
+
ret->v.v0.create_event = lcb_io_create_event;
|
434
|
+
ret->v.v0.update_event = lcb_io_update_event;
|
435
|
+
|
436
|
+
ret->v.v0.delete_timer = lcb_io_delete_timer;
|
437
|
+
ret->v.v0.destroy_timer = lcb_io_destroy_timer;
|
438
|
+
ret->v.v0.create_timer = lcb_io_create_timer;
|
439
|
+
ret->v.v0.update_timer = lcb_io_update_timer;
|
440
|
+
|
441
|
+
ret->v.v0.run_event_loop = lcb_io_run_event_loop;
|
442
|
+
ret->v.v0.stop_event_loop = lcb_io_stop_event_loop;
|
443
|
+
|
444
|
+
loop = rb_em_loop_create(bucket);
|
445
|
+
ret->v.v0.cookie = loop;
|
446
|
+
|
447
|
+
*io = ret;
|
448
|
+
return LCB_SUCCESS;
|
449
|
+
}
|
450
|
+
|
451
|
+
#endif
|
452
|
+
#endif
|