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.
@@ -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, *rv = ctx->rv, exc = Qnil, res;
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 = cb_gc_protect(bucket, exc);
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(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
47
+ rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
48
48
  }
49
49
  if (ctx->nqueries == 0) {
50
- cb_gc_unprotect(bucket, ctx->proc);
50
+ ctx->proc = Qnil;
51
51
  if (bucket->async) {
52
- free(ctx);
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 args, proc;
106
+ VALUE proc;
107
107
  lcb_error_t err;
108
108
  struct cb_params_st params;
109
109
 
110
- if (bucket->handle == NULL) {
111
- rb_raise(cb_eConnectError, "closed connection");
110
+ if (!cb_bucket_connected_bang(bucket, cb_sym_delete)) {
111
+ return Qnil;
112
112
  }
113
- rb_scan_args(argc, argv, "0*&", &args, &proc);
113
+
114
+ memset(&params, 0, sizeof(struct cb_params_st));
115
+ rb_scan_args(argc, argv, "0*&", &params.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(&params, 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(&params, RARRAY_LEN(args), args);
122
+ cb_params_build(&params);
122
123
 
123
- ctx = calloc(1, sizeof(struct cb_context_st));
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(&params);
137
129
  exc = cb_check_error(err, "failed to schedule delete request", Qnil);
138
130
  if (exc != Qnil) {
139
- free(ctx);
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
- free(ctx);
144
+ rv = ctx->rv;
145
+ cb_context_free(ctx);
153
146
  if (exc != Qnil) {
154
- rb_exc_raise(cb_gc_unprotect(bucket, exc));
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