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
@@ -131,6 +131,7 @@ have_header("mach/mach_time.h")
|
|
131
131
|
have_header("stdint.h") or die("Failed to locate stdint.h")
|
132
132
|
have_header("sys/time.h")
|
133
133
|
have_header("fcntl.h")
|
134
|
+
have_type("st_index_t")
|
134
135
|
have_func("clock_gettime")
|
135
136
|
have_func("gettimeofday")
|
136
137
|
have_func("QueryPerformanceCounter")
|
@@ -139,6 +140,7 @@ have_func("rb_thread_fd_select")
|
|
139
140
|
have_func("rb_thread_blocking_region")
|
140
141
|
have_func("poll", "poll.h")
|
141
142
|
have_func("ppoll", "poll.h")
|
143
|
+
have_func("rb_fiber_yield")
|
142
144
|
define("_GNU_SOURCE")
|
143
145
|
create_header("couchbase_config.h")
|
144
146
|
create_makefile("couchbase_ext")
|
data/ext/couchbase_ext/get.c
CHANGED
@@ -22,7 +22,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
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, val, flags, cas,
|
25
|
+
VALUE key, val, flags, cas, 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_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
32
32
|
exc = cb_check_error(error, "failed to get value", key);
|
33
33
|
if (exc != Qnil) {
|
34
34
|
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_get);
|
35
|
-
ctx->exception =
|
35
|
+
ctx->exception = exc;
|
36
36
|
}
|
37
37
|
}
|
38
38
|
|
@@ -46,14 +46,10 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
46
46
|
VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
|
47
47
|
VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
|
48
48
|
rb_str_new2("unable to convert value for key '%s': %s"), key, exc_str);
|
49
|
-
if (ctx->exception != Qnil) {
|
50
|
-
cb_gc_unprotect(bucket, ctx->exception);
|
51
|
-
}
|
52
49
|
ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
|
53
50
|
rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
|
54
51
|
rb_ivar_set(ctx->exception, cb_id_iv_key, key);
|
55
52
|
rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
|
56
|
-
cb_gc_protect(bucket, ctx->exception);
|
57
53
|
val = raw;
|
58
54
|
}
|
59
55
|
} else if (cb_flags_get_format(resp->v.v0.flags) == cb_sym_plain) {
|
@@ -73,17 +69,17 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
73
69
|
} else { /* synchronous */
|
74
70
|
if (NIL_P(exc) && error != LCB_KEY_ENOENT) {
|
75
71
|
if (ctx->extended) {
|
76
|
-
rb_hash_aset(
|
72
|
+
rb_hash_aset(ctx->rv, key, rb_ary_new3(3, val, flags, cas));
|
77
73
|
} else {
|
78
|
-
rb_hash_aset(
|
74
|
+
rb_hash_aset(ctx->rv, key, val);
|
79
75
|
}
|
80
76
|
}
|
81
77
|
}
|
82
78
|
|
83
79
|
if (ctx->nqueries == 0) {
|
84
|
-
|
80
|
+
ctx->proc = Qnil;
|
85
81
|
if (bucket->async) {
|
86
|
-
|
82
|
+
cb_context_free(ctx);
|
87
83
|
}
|
88
84
|
}
|
89
85
|
(void)handle;
|
@@ -222,36 +218,28 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
|
|
222
218
|
{
|
223
219
|
struct cb_bucket_st *bucket = DATA_PTR(self);
|
224
220
|
struct cb_context_st *ctx;
|
225
|
-
VALUE
|
221
|
+
VALUE rv, proc, exc;
|
226
222
|
size_t ii;
|
227
223
|
lcb_error_t err = LCB_SUCCESS;
|
228
224
|
struct cb_params_st params;
|
229
225
|
|
230
|
-
if (bucket
|
231
|
-
|
226
|
+
if (!cb_bucket_connected_bang(bucket, cb_sym_get)) {
|
227
|
+
return Qnil;
|
232
228
|
}
|
233
|
-
|
229
|
+
|
230
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
231
|
+
rb_scan_args(argc, argv, "0*&", ¶ms.args, &proc);
|
234
232
|
if (!bucket->async && proc != Qnil) {
|
235
233
|
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
236
234
|
}
|
237
|
-
memset(¶ms, 0, sizeof(struct cb_params_st));
|
238
235
|
params.type = cb_cmd_get;
|
239
236
|
params.bucket = bucket;
|
240
|
-
params.cmd.get.keys_ary =
|
241
|
-
cb_params_build(¶ms
|
242
|
-
ctx =
|
243
|
-
if (ctx == NULL) {
|
244
|
-
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
|
245
|
-
}
|
237
|
+
params.cmd.get.keys_ary = rb_ary_new();
|
238
|
+
cb_params_build(¶ms);
|
239
|
+
ctx = cb_context_alloc_common(bucket, proc, params.cmd.get.num);
|
246
240
|
ctx->extended = params.cmd.get.extended;
|
247
241
|
ctx->quiet = params.cmd.get.quiet;
|
248
242
|
ctx->force_format = params.cmd.get.forced_format;
|
249
|
-
ctx->proc = cb_gc_protect(bucket, proc);
|
250
|
-
ctx->bucket = bucket;
|
251
|
-
rv = rb_hash_new();
|
252
|
-
ctx->rv = &rv;
|
253
|
-
ctx->exception = Qnil;
|
254
|
-
ctx->nqueries = params.cmd.get.num;
|
255
243
|
if (params.cmd.get.replica) {
|
256
244
|
err = lcb_get_replica(bucket->handle, (const void *)ctx,
|
257
245
|
params.cmd.get.num, params.cmd.get.ptr_gr);
|
@@ -260,10 +248,9 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
|
|
260
248
|
params.cmd.get.num, params.cmd.get.ptr);
|
261
249
|
}
|
262
250
|
cb_params_destroy(¶ms);
|
263
|
-
cb_gc_unprotect(bucket, params.cmd.get.keys_ary);
|
264
251
|
exc = cb_check_error(err, "failed to schedule get request", Qnil);
|
265
252
|
if (exc != Qnil) {
|
266
|
-
|
253
|
+
cb_context_free(ctx);
|
267
254
|
rb_exc_raise(exc);
|
268
255
|
}
|
269
256
|
bucket->nbytes += params.npayload;
|
@@ -276,9 +263,9 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
|
|
276
263
|
lcb_wait(bucket->handle);
|
277
264
|
}
|
278
265
|
exc = ctx->exception;
|
279
|
-
|
266
|
+
rv = ctx->rv;
|
267
|
+
cb_context_free(ctx);
|
280
268
|
if (exc != Qnil) {
|
281
|
-
cb_gc_unprotect(bucket, exc);
|
282
269
|
rb_exc_raise(exc);
|
283
270
|
}
|
284
271
|
exc = bucket->exception;
|
data/ext/couchbase_ext/http.c
CHANGED
@@ -22,24 +22,35 @@ cb_http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *
|
|
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
|
25
|
+
VALUE key, val, res, exc;
|
26
26
|
lcb_http_status_t status;
|
27
27
|
|
28
28
|
ctx->request->completed = 1;
|
29
|
+
|
30
|
+
if (bucket->destroying) {
|
31
|
+
cb_context_free(ctx);
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
29
35
|
key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
|
30
36
|
val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
|
31
|
-
exc =
|
32
|
-
if (exc
|
33
|
-
|
37
|
+
exc = ctx->exception;
|
38
|
+
if (!RTEST(exc)) {
|
39
|
+
exc = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status);
|
40
|
+
if (exc != Qnil && val != Qnil) {
|
34
41
|
rb_ivar_set(exc, cb_id_iv_body, val);
|
35
42
|
}
|
36
|
-
|
37
|
-
|
43
|
+
}
|
44
|
+
if (RTEST(exc)) {
|
45
|
+
if (rb_obj_is_kind_of(exc, cb_eHTTPError)) {
|
46
|
+
rb_funcall(exc, cb_id_parse_body_bang, 0);
|
47
|
+
}
|
48
|
+
ctx->exception = exc;
|
38
49
|
}
|
39
50
|
status = resp->v.v0.status;
|
40
51
|
if (resp->v.v0.headers) {
|
41
52
|
cb_build_headers(ctx, resp->v.v0.headers);
|
42
|
-
|
53
|
+
ctx->headers_val = Qnil;
|
43
54
|
}
|
44
55
|
if (ctx->extended) {
|
45
56
|
res = rb_class_new_instance(0, NULL, cb_cResult);
|
@@ -55,10 +66,13 @@ cb_http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *
|
|
55
66
|
}
|
56
67
|
if (ctx->proc != Qnil) {
|
57
68
|
cb_proc_call(bucket, ctx->proc, 1, res);
|
58
|
-
|
69
|
+
ctx->proc = Qnil;
|
59
70
|
}
|
60
71
|
if (!bucket->async && ctx->exception == Qnil) {
|
61
|
-
|
72
|
+
ctx->rv = res;
|
73
|
+
}
|
74
|
+
if (bucket->async) {
|
75
|
+
cb_context_free(ctx);
|
62
76
|
}
|
63
77
|
(void)handle;
|
64
78
|
(void)request;
|
@@ -81,14 +95,11 @@ cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cook
|
|
81
95
|
if (ctx->exception != Qnil) {
|
82
96
|
VALUE body_str = rb_ivar_get(ctx->exception, cb_id_iv_body);
|
83
97
|
if (NIL_P(body_str)) {
|
84
|
-
cb_gc_protect(bucket, ctx->exception);
|
85
98
|
rb_ivar_set(ctx->exception, cb_id_iv_body, val);
|
86
99
|
} else {
|
87
100
|
rb_str_concat(body_str, val);
|
88
101
|
}
|
89
|
-
|
90
|
-
lcb_cancel_http_request(bucket->handle, request);
|
91
|
-
}
|
102
|
+
return;
|
92
103
|
}
|
93
104
|
}
|
94
105
|
if (resp->v.v0.headers) {
|
@@ -97,7 +108,7 @@ cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cook
|
|
97
108
|
if (ctx->proc != Qnil) {
|
98
109
|
if (ctx->extended) {
|
99
110
|
res = rb_class_new_instance(0, NULL, cb_cResult);
|
100
|
-
rb_ivar_set(res, cb_id_iv_error,
|
111
|
+
rb_ivar_set(res, cb_id_iv_error, Qnil);
|
101
112
|
rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
|
102
113
|
rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
|
103
114
|
rb_ivar_set(res, cb_id_iv_key, key);
|
@@ -110,6 +121,7 @@ cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cook
|
|
110
121
|
cb_proc_call(bucket, ctx->proc, 1, res);
|
111
122
|
}
|
112
123
|
(void)handle;
|
124
|
+
(void)request;
|
113
125
|
}
|
114
126
|
|
115
127
|
void
|
@@ -278,27 +290,25 @@ cb_http_request_perform(VALUE self)
|
|
278
290
|
struct cb_context_st *ctx;
|
279
291
|
VALUE rv, exc;
|
280
292
|
lcb_error_t err;
|
281
|
-
struct cb_bucket_st *bucket;
|
293
|
+
struct cb_bucket_st *bucket = req->bucket;
|
282
294
|
|
283
|
-
|
284
|
-
|
285
|
-
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory");
|
295
|
+
if (!cb_bucket_connected_bang(bucket, cb_sym_http_request)) {
|
296
|
+
return Qnil;
|
286
297
|
}
|
287
|
-
|
288
|
-
ctx
|
289
|
-
ctx->
|
290
|
-
ctx->proc = rb_block_given_p() ?
|
298
|
+
|
299
|
+
ctx = cb_context_alloc(bucket);
|
300
|
+
ctx->rv = Qnil;
|
301
|
+
ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback;
|
291
302
|
ctx->extended = req->extended;
|
292
303
|
ctx->request = req;
|
293
|
-
ctx->headers_val =
|
294
|
-
ctx->exception = Qnil;
|
304
|
+
ctx->headers_val = rb_hash_new();
|
295
305
|
|
296
306
|
err = lcb_make_http_request(bucket->handle, (const void *)ctx,
|
297
307
|
req->type, &req->cmd, &req->request);
|
298
308
|
exc = cb_check_error(err, "failed to schedule document request",
|
299
309
|
STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath));
|
300
310
|
if (exc != Qnil) {
|
301
|
-
|
311
|
+
lcb_cancel_http_request(bucket->handle, req->request);
|
302
312
|
rb_exc_raise(exc);
|
303
313
|
}
|
304
314
|
req->running = 1;
|
@@ -308,10 +318,10 @@ cb_http_request_perform(VALUE self)
|
|
308
318
|
} else {
|
309
319
|
lcb_wait(bucket->handle);
|
310
320
|
if (req->completed) {
|
321
|
+
rv = ctx->rv;
|
311
322
|
exc = ctx->exception;
|
312
|
-
|
323
|
+
cb_context_free(ctx);
|
313
324
|
if (exc != Qnil) {
|
314
|
-
cb_gc_unprotect(bucket, exc);
|
315
325
|
rb_exc_raise(exc);
|
316
326
|
}
|
317
327
|
return rv;
|
@@ -333,7 +343,7 @@ cb_http_request_pause(VALUE self)
|
|
333
343
|
VALUE
|
334
344
|
cb_http_request_continue(VALUE self)
|
335
345
|
{
|
336
|
-
VALUE exc,
|
346
|
+
VALUE exc, rv;
|
337
347
|
struct cb_http_request_st *req = DATA_PTR(self);
|
338
348
|
|
339
349
|
if (req->running) {
|
@@ -341,12 +351,11 @@ cb_http_request_continue(VALUE self)
|
|
341
351
|
if (req->completed) {
|
342
352
|
exc = req->ctx->exception;
|
343
353
|
rv = req->ctx->rv;
|
344
|
-
|
354
|
+
cb_context_free(req->ctx);
|
345
355
|
if (exc != Qnil) {
|
346
|
-
cb_gc_unprotect(req->bucket, exc);
|
347
356
|
rb_exc_raise(exc);
|
348
357
|
}
|
349
|
-
return
|
358
|
+
return rv;
|
350
359
|
}
|
351
360
|
} else {
|
352
361
|
cb_http_request_perform(self);
|
@@ -24,149 +24,9 @@
|
|
24
24
|
#include <rubysig.h>
|
25
25
|
#endif
|
26
26
|
#include <errno.h>
|
27
|
-
#include <sys/types.h>
|
28
|
-
#include <sys/socket.h>
|
29
|
-
#include <unistd.h>
|
30
|
-
#ifdef HAVE_FCNTL_H
|
31
|
-
#include <fcntl.h>
|
32
|
-
#endif
|
33
27
|
#ifdef HAVE_POLL
|
34
28
|
#include <poll.h>
|
35
29
|
#endif
|
36
|
-
#define INVALID_SOCKET (-1)
|
37
|
-
|
38
|
-
/* Copied from libev plugin */
|
39
|
-
static lcb_ssize_t
|
40
|
-
lcb_io_recv(struct lcb_io_opt_st *iops, lcb_socket_t sock,
|
41
|
-
void *buffer, lcb_size_t len, int flags)
|
42
|
-
{
|
43
|
-
lcb_ssize_t ret = recv(sock, buffer, len, flags);
|
44
|
-
if (ret < 0) {
|
45
|
-
iops->v.v0.error = errno;
|
46
|
-
}
|
47
|
-
return ret;
|
48
|
-
}
|
49
|
-
|
50
|
-
static lcb_ssize_t
|
51
|
-
lcb_io_recvv(struct lcb_io_opt_st *iops, lcb_socket_t sock,
|
52
|
-
struct lcb_iovec_st *iov, lcb_size_t niov)
|
53
|
-
{
|
54
|
-
struct msghdr msg;
|
55
|
-
struct iovec vec[2];
|
56
|
-
lcb_ssize_t ret;
|
57
|
-
|
58
|
-
if (niov != 2) {
|
59
|
-
return -1;
|
60
|
-
}
|
61
|
-
memset(&msg, 0, sizeof(msg));
|
62
|
-
msg.msg_iov = vec;
|
63
|
-
msg.msg_iovlen = iov[1].iov_len ? (lcb_size_t)2 : (lcb_size_t)1;
|
64
|
-
msg.msg_iov[0].iov_base = iov[0].iov_base;
|
65
|
-
msg.msg_iov[0].iov_len = iov[0].iov_len;
|
66
|
-
msg.msg_iov[1].iov_base = iov[1].iov_base;
|
67
|
-
msg.msg_iov[1].iov_len = iov[1].iov_len;
|
68
|
-
ret = recvmsg(sock, &msg, 0);
|
69
|
-
|
70
|
-
if (ret < 0) {
|
71
|
-
iops->v.v0.error = errno;
|
72
|
-
}
|
73
|
-
|
74
|
-
return ret;
|
75
|
-
}
|
76
|
-
|
77
|
-
static lcb_ssize_t
|
78
|
-
lcb_io_send(struct lcb_io_opt_st *iops, lcb_socket_t sock,
|
79
|
-
const void *msg, lcb_size_t len, int flags)
|
80
|
-
{
|
81
|
-
lcb_ssize_t ret = send(sock, msg, len, flags);
|
82
|
-
if (ret < 0) {
|
83
|
-
iops->v.v0.error = errno;
|
84
|
-
}
|
85
|
-
return ret;
|
86
|
-
}
|
87
|
-
|
88
|
-
static lcb_ssize_t
|
89
|
-
lcb_io_sendv(struct lcb_io_opt_st *iops, lcb_socket_t sock,
|
90
|
-
struct lcb_iovec_st *iov, lcb_size_t niov)
|
91
|
-
{
|
92
|
-
struct msghdr msg;
|
93
|
-
struct iovec vec[2];
|
94
|
-
lcb_ssize_t ret;
|
95
|
-
|
96
|
-
if (niov != 2) {
|
97
|
-
return -1;
|
98
|
-
}
|
99
|
-
memset(&msg, 0, sizeof(msg));
|
100
|
-
msg.msg_iov = vec;
|
101
|
-
msg.msg_iovlen = iov[1].iov_len ? (lcb_size_t)2 : (lcb_size_t)1;
|
102
|
-
msg.msg_iov[0].iov_base = iov[0].iov_base;
|
103
|
-
msg.msg_iov[0].iov_len = iov[0].iov_len;
|
104
|
-
msg.msg_iov[1].iov_base = iov[1].iov_base;
|
105
|
-
msg.msg_iov[1].iov_len = iov[1].iov_len;
|
106
|
-
ret = sendmsg(sock, &msg, 0);
|
107
|
-
|
108
|
-
if (ret < 0) {
|
109
|
-
iops->v.v0.error = errno;
|
110
|
-
}
|
111
|
-
return ret;
|
112
|
-
}
|
113
|
-
|
114
|
-
static int
|
115
|
-
make_socket_nonblocking(lcb_socket_t sock)
|
116
|
-
{
|
117
|
-
int flags;
|
118
|
-
if ((flags = fcntl(sock, F_GETFL, NULL)) < 0) {
|
119
|
-
return -1;
|
120
|
-
}
|
121
|
-
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
|
122
|
-
return -1;
|
123
|
-
}
|
124
|
-
|
125
|
-
return 0;
|
126
|
-
}
|
127
|
-
|
128
|
-
static int
|
129
|
-
close_socket(lcb_socket_t sock)
|
130
|
-
{
|
131
|
-
return close(sock);
|
132
|
-
}
|
133
|
-
|
134
|
-
static lcb_socket_t
|
135
|
-
lcb_io_socket(struct lcb_io_opt_st *iops, int domain, int type,
|
136
|
-
int protocol)
|
137
|
-
{
|
138
|
-
lcb_socket_t sock = socket(domain, type, protocol);
|
139
|
-
if (sock == INVALID_SOCKET) {
|
140
|
-
iops->v.v0.error = errno;
|
141
|
-
} else {
|
142
|
-
if (make_socket_nonblocking(sock) != 0) {
|
143
|
-
int error = errno;
|
144
|
-
iops->v.v0.close(iops, sock);
|
145
|
-
iops->v.v0.error = error;
|
146
|
-
sock = INVALID_SOCKET;
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
return sock;
|
151
|
-
}
|
152
|
-
|
153
|
-
static void
|
154
|
-
lcb_io_close(struct lcb_io_opt_st *iops, lcb_socket_t sock)
|
155
|
-
{
|
156
|
-
close_socket(sock);
|
157
|
-
(void)iops;
|
158
|
-
}
|
159
|
-
|
160
|
-
static int
|
161
|
-
lcb_io_connect(struct lcb_io_opt_st *iops, lcb_socket_t sock,
|
162
|
-
const struct sockaddr *name, unsigned int namelen)
|
163
|
-
{
|
164
|
-
int ret = connect(sock, name, (socklen_t)namelen);
|
165
|
-
if (ret < 0) {
|
166
|
-
iops->v.v0.error = errno;
|
167
|
-
}
|
168
|
-
return ret;
|
169
|
-
}
|
170
30
|
|
171
31
|
/* events sorted array */
|
172
32
|
typedef struct rb_mt_event rb_mt_event;
|
@@ -807,45 +667,33 @@ loop_select_cleanup(VALUE argp)
|
|
807
667
|
/* code influenced by ruby's source and cool.io */
|
808
668
|
#define POLLIN_SET (POLLIN | POLLHUP | POLLERR)
|
809
669
|
#define POLLOUT_SET (POLLOUT | POLLHUP | POLLERR)
|
670
|
+
#define HRTIME_INFINITY ((hrtime_t)~0)
|
810
671
|
|
811
|
-
#
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
672
|
+
#ifdef HAVE_PPOLL
|
673
|
+
static int
|
674
|
+
xpoll(struct pollfd *fds, nfds_t nfds, hrtime_t timeout)
|
675
|
+
{
|
676
|
+
if (timeout != HRTIME_INFINITY) {
|
677
|
+
struct timespec ts;
|
678
|
+
ts.tv_sec = (long)(timeout / (1000 * 1000 * 1000));
|
679
|
+
ts.tv_nsec = (long)(timeout % (1000 * 1000 * 1000));
|
680
|
+
return ppoll(fds, nfds, &ts, NULL);
|
681
|
+
}
|
682
|
+
return ppoll(fds, nfds, NULL, NULL);
|
683
|
+
}
|
818
684
|
#else
|
819
|
-
#
|
820
|
-
#endif
|
821
|
-
#define TIMET_MAX (~(time_t)0 <= 0 ? (time_t)((~(unsigned_time_t)0) >> 1) : (time_t)(~(unsigned_time_t)0))
|
685
|
+
#define TIMEOUT_MAX ((hrtime_t)(((unsigned int)~0) >> 1))
|
822
686
|
static int
|
823
|
-
|
824
|
-
const struct timespec *ts, const sigset_t *sigmask)
|
687
|
+
xpoll(struct pollfd *fds, nfds_t nfds, hrtime_t timeout)
|
825
688
|
{
|
826
|
-
int
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
if (ts->tv_sec > TIMET_MAX/1000) {
|
832
|
-
timeout_ms = -1;
|
833
|
-
} else {
|
834
|
-
tmp = ts->tv_sec * 1000;
|
835
|
-
tmp2 = (ts->tv_nsec + 999999) / (1000 * 1000);
|
836
|
-
if (TIMET_MAX - tmp < tmp2) {
|
837
|
-
timeout_ms = -1;
|
838
|
-
} else {
|
839
|
-
timeout_ms = tmp + tmp2;
|
840
|
-
}
|
689
|
+
int ts = -1;
|
690
|
+
if (timeout != HRTIME_INFINITY) {
|
691
|
+
timeout = (timeout + 999999) / (1000 * 1000);
|
692
|
+
if (timeout <= TIMEOUT_MAX) {
|
693
|
+
ts = (int)timeout;
|
841
694
|
}
|
842
|
-
} else {
|
843
|
-
timeout_ms = -1;
|
844
695
|
}
|
845
|
-
|
846
|
-
(void)sigmask;
|
847
|
-
|
848
|
-
return poll(fds, nfds, timeout_ms);
|
696
|
+
return poll(fds, nfds, ts);
|
849
697
|
}
|
850
698
|
#endif
|
851
699
|
|
@@ -854,7 +702,7 @@ struct poll_args {
|
|
854
702
|
rb_mt_loop *loop;
|
855
703
|
struct pollfd *fds;
|
856
704
|
nfds_t nfd;
|
857
|
-
|
705
|
+
hrtime_t ts;
|
858
706
|
int result;
|
859
707
|
int lerrno;
|
860
708
|
};
|
@@ -882,7 +730,7 @@ lp_arg_alloc(lp_arg **args)
|
|
882
730
|
loop_blocking_poll(void *argp)
|
883
731
|
{
|
884
732
|
lp_arg *args = argp;
|
885
|
-
args->result =
|
733
|
+
args->result = xpoll(args->fds, args->nfd, args->ts);
|
886
734
|
if (args->result < 0) args->lerrno = errno;
|
887
735
|
return Qnil;
|
888
736
|
}
|
@@ -893,7 +741,6 @@ loop_run_poll(VALUE argp)
|
|
893
741
|
{
|
894
742
|
lp_arg *args = (lp_arg*)argp;
|
895
743
|
rb_mt_loop *loop = args->loop;
|
896
|
-
struct timespec ts;
|
897
744
|
hrtime_t now, next_time;
|
898
745
|
|
899
746
|
if (loop->events.count) {
|
@@ -916,17 +763,9 @@ retry:
|
|
916
763
|
next_time = timers_minimum(&loop->timers);
|
917
764
|
if (next_time) {
|
918
765
|
now = gethrtime();
|
919
|
-
|
920
|
-
ts.tv_sec = 0;
|
921
|
-
ts.tv_nsec = 0;
|
922
|
-
} else {
|
923
|
-
hrtime_t hrto = next_time - now;
|
924
|
-
ts.tv_sec = (long)(hrto / 1000000000);
|
925
|
-
ts.tv_nsec = (long)(hrto % 1000000000);
|
926
|
-
}
|
927
|
-
args->ts = &ts;
|
766
|
+
args->ts = next_time <= now ? 0 : next_time - now;
|
928
767
|
} else {
|
929
|
-
args->ts =
|
768
|
+
args->ts = HRTIME_INFINITY;
|
930
769
|
}
|
931
770
|
|
932
771
|
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
@@ -934,21 +773,19 @@ retry:
|
|
934
773
|
#else
|
935
774
|
if (rb_thread_alone()) {
|
936
775
|
TRAP_BEG;
|
937
|
-
args->result =
|
776
|
+
args->result = xpoll(args->fds, args->nfd, args->ts);
|
938
777
|
if (args->result < 0) args->lerrno = errno;
|
939
778
|
TRAP_END;
|
940
779
|
} else {
|
941
|
-
struct timespec mini_pause;
|
942
|
-
int exact = 0;
|
943
|
-
mini_pause.tv_sec = 0;
|
944
780
|
/* 5 millisecond pause */
|
945
|
-
mini_pause
|
946
|
-
|
947
|
-
|
781
|
+
hrtime_t mini_pause = 5000000;
|
782
|
+
int exact = 0;
|
783
|
+
if (args->ts != HRTIME_INFINITY && args->ts < mini_pause) {
|
784
|
+
mini_pause = args->ts;
|
948
785
|
exact = 1;
|
949
786
|
}
|
950
787
|
TRAP_BEG;
|
951
|
-
args->result =
|
788
|
+
args->result = xpoll(args->fds, args->nfd, mini_pause);
|
952
789
|
if (args->result < 0) args->lerrno = errno;
|
953
790
|
TRAP_END;
|
954
791
|
if (args->result == 0 && !exact) {
|
@@ -1206,13 +1043,13 @@ cb_create_ruby_mt_io_opts(int version, lcb_io_opt_t *io, void *arg)
|
|
1206
1043
|
/* consider that struct isn't allocated by the library,
|
1207
1044
|
* `need_cleanup' flag might be set in lcb_create() */
|
1208
1045
|
ret->v.v0.need_cleanup = 0;
|
1209
|
-
ret->v.v0.recv =
|
1210
|
-
ret->v.v0.send =
|
1211
|
-
ret->v.v0.recvv =
|
1212
|
-
ret->v.v0.sendv =
|
1213
|
-
ret->v.v0.socket =
|
1214
|
-
ret->v.v0.close =
|
1215
|
-
ret->v.v0.connect =
|
1046
|
+
ret->v.v0.recv = cb_io_recv;
|
1047
|
+
ret->v.v0.send = cb_io_send;
|
1048
|
+
ret->v.v0.recvv = cb_io_recvv;
|
1049
|
+
ret->v.v0.sendv = cb_io_sendv;
|
1050
|
+
ret->v.v0.socket = cb_io_socket;
|
1051
|
+
ret->v.v0.close = cb_io_close;
|
1052
|
+
ret->v.v0.connect = cb_io_connect;
|
1216
1053
|
ret->v.v0.delete_event = lcb_io_delete_event;
|
1217
1054
|
ret->v.v0.destroy_event = lcb_io_destroy_event;
|
1218
1055
|
ret->v.v0.create_event = lcb_io_create_event;
|