couchbase 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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")
@@ -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, *rv = ctx->rv, exc = Qnil, res;
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 = cb_gc_protect(bucket, exc);
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(*rv, key, rb_ary_new3(3, val, flags, cas));
72
+ rb_hash_aset(ctx->rv, key, rb_ary_new3(3, val, flags, cas));
77
73
  } else {
78
- rb_hash_aset(*rv, key, val);
74
+ rb_hash_aset(ctx->rv, key, val);
79
75
  }
80
76
  }
81
77
  }
82
78
 
83
79
  if (ctx->nqueries == 0) {
84
- cb_gc_unprotect(bucket, ctx->proc);
80
+ ctx->proc = Qnil;
85
81
  if (bucket->async) {
86
- free(ctx);
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 args, rv, proc, exc;
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->handle == NULL) {
231
- rb_raise(cb_eConnectError, "closed connection");
226
+ if (!cb_bucket_connected_bang(bucket, cb_sym_get)) {
227
+ return Qnil;
232
228
  }
233
- rb_scan_args(argc, argv, "0*&", &args, &proc);
229
+
230
+ memset(&params, 0, sizeof(struct cb_params_st));
231
+ rb_scan_args(argc, argv, "0*&", &params.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(&params, 0, sizeof(struct cb_params_st));
238
235
  params.type = cb_cmd_get;
239
236
  params.bucket = bucket;
240
- params.cmd.get.keys_ary = cb_gc_protect(bucket, rb_ary_new());
241
- cb_params_build(&params, RARRAY_LEN(args), args);
242
- ctx = calloc(1, sizeof(struct cb_context_st));
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(&params);
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(&params);
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
- free(ctx);
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
- free(ctx);
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;
@@ -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 *rv = ctx->rv, key, val, res, exc;
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 = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status);
32
- if (exc != Qnil) {
33
- if (val != Qnil) {
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
- rb_funcall(exc, cb_id_parse_body_bang, 0);
37
- ctx->exception = cb_gc_protect(bucket, exc);
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
- cb_gc_unprotect(bucket, ctx->headers_val);
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
- cb_gc_unprotect(bucket, ctx->proc);
69
+ ctx->proc = Qnil;
59
70
  }
60
71
  if (!bucket->async && ctx->exception == Qnil) {
61
- *rv = res;
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
- if (ctx->http_cancel_on_error) {
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, ctx->exception);
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
- ctx = calloc(1, sizeof(struct cb_context_st));
284
- if (ctx == NULL) {
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
- rv = Qnil;
288
- ctx->rv = &rv;
289
- ctx->bucket = bucket = req->bucket;
290
- ctx->proc = rb_block_given_p() ? cb_gc_protect(bucket, rb_block_proc()) : req->on_body_callback;
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 = cb_gc_protect(bucket, rb_hash_new());
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
- free(ctx);
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
- free(ctx);
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, *rv;
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
- free(req->ctx);
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 *rv;
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
- #ifndef HAVE_PPOLL
812
- #if SIZEOF_TIME_T == SIZEOF_LONG
813
- typedef unsigned long unsigned_time_t;
814
- #elif SIZEOF_TIME_T == SIZEOF_INT
815
- typedef unsigned int unsigned_time_t;
816
- #elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
817
- typedef unsigned LONG_LONG unsigned_time_t;
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
- # error cannot find integer type which size is same as time_t.
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
- ppoll(struct pollfd *fds, nfds_t nfds,
824
- const struct timespec *ts, const sigset_t *sigmask)
687
+ xpoll(struct pollfd *fds, nfds_t nfds, hrtime_t timeout)
825
688
  {
826
- int timeout_ms;
827
-
828
- if (ts) {
829
- int tmp, tmp2;
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
- struct timespec *ts;
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 = ppoll(args->fds, args->nfd, args->ts, NULL);
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
- if (next_time <= now) {
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 = NULL;
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 = ppoll(args->fds, args->nfd, args->ts, NULL);
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.tv_nsec = 5000000;
946
- if (args->ts && ts.tv_sec == 0 && ts.tv_nsec < 5000000) {
947
- mini_pause.tv_nsec = ts.tv_nsec;
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 = ppoll(args->fds, args->nfd, &mini_pause, NULL);
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 = lcb_io_recv;
1210
- ret->v.v0.send = lcb_io_send;
1211
- ret->v.v0.recvv = lcb_io_recvv;
1212
- ret->v.v0.sendv = lcb_io_sendv;
1213
- ret->v.v0.socket = lcb_io_socket;
1214
- ret->v.v0.close = lcb_io_close;
1215
- ret->v.v0.connect = lcb_io_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;