libcouchbase 1.2.8 → 1.3.0

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.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/README.md +16 -8
  4. data/ext/libcouchbase/CMakeLists.txt +34 -32
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +277 -6
  6. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +14 -0
  7. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +2 -0
  8. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +2 -1
  9. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
  10. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +8 -1
  11. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  12. data/ext/libcouchbase/cmake/config-cmake.h.in +14 -0
  13. data/ext/libcouchbase/cmake/configure +8 -26
  14. data/ext/libcouchbase/cmake/defs.mk.in +2 -2
  15. data/ext/libcouchbase/cmake/libcouchbase.stp.in +829 -0
  16. data/ext/libcouchbase/cmake/source_files.cmake +11 -2
  17. data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +18 -2
  18. data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +44 -2
  19. data/ext/libcouchbase/contrib/cbsasl/src/client.c +285 -73
  20. data/ext/libcouchbase/contrib/cbsasl/src/common.c +4 -0
  21. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.c +500 -0
  22. data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.h +99 -0
  23. data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +1 -1
  24. data/ext/libcouchbase/contrib/cliopts/cliopts.h +14 -1
  25. data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +2 -3
  26. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +4 -0
  27. data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +7 -5
  28. data/ext/libcouchbase/contrib/snappy/snappy.cc +7 -2
  29. data/ext/libcouchbase/example/crypto/.gitignore +2 -0
  30. data/ext/libcouchbase/example/crypto/Makefile +13 -0
  31. data/ext/libcouchbase/example/crypto/common_provider.c +24 -0
  32. data/ext/libcouchbase/example/crypto/common_provider.h +31 -0
  33. data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +139 -0
  34. data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +147 -0
  35. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +281 -0
  36. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.h +29 -0
  37. data/ext/libcouchbase/example/tracing/.gitignore +2 -0
  38. data/ext/libcouchbase/example/tracing/Makefile +8 -0
  39. data/ext/libcouchbase/example/tracing/cJSON.c +1 -0
  40. data/ext/libcouchbase/example/tracing/cJSON.h +1 -0
  41. data/ext/libcouchbase/example/tracing/tracing.c +439 -0
  42. data/ext/libcouchbase/example/tracing/views.c +444 -0
  43. data/ext/libcouchbase/include/libcouchbase/auth.h +56 -4
  44. data/ext/libcouchbase/include/libcouchbase/cbft.h +8 -0
  45. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +55 -1
  46. data/ext/libcouchbase/include/libcouchbase/cntl.h +101 -1
  47. data/ext/libcouchbase/include/libcouchbase/configuration.h.in +6 -0
  48. data/ext/libcouchbase/include/libcouchbase/couchbase.h +109 -6
  49. data/ext/libcouchbase/include/libcouchbase/crypto.h +140 -0
  50. data/ext/libcouchbase/include/libcouchbase/error.h +38 -2
  51. data/ext/libcouchbase/include/libcouchbase/kvbuf.h +6 -1
  52. data/ext/libcouchbase/include/libcouchbase/metrics.h +79 -0
  53. data/ext/libcouchbase/include/libcouchbase/n1ql.h +9 -0
  54. data/ext/libcouchbase/include/libcouchbase/tracing.h +319 -0
  55. data/ext/libcouchbase/include/libcouchbase/vbucket.h +1 -1
  56. data/ext/libcouchbase/include/libcouchbase/views.h +8 -0
  57. data/ext/libcouchbase/include/memcached/protocol_binary.h +40 -10
  58. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +6 -14
  59. data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +3 -0
  60. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +1 -0
  61. data/ext/libcouchbase/plugins/io/select/plugin-select.c +4 -1
  62. data/ext/libcouchbase/src/auth-priv.h +36 -4
  63. data/ext/libcouchbase/src/auth.cc +66 -27
  64. data/ext/libcouchbase/src/bootstrap.cc +1 -1
  65. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +12 -7
  66. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +26 -17
  67. data/ext/libcouchbase/src/bucketconfig/bc_http.h +1 -1
  68. data/ext/libcouchbase/src/bucketconfig/clconfig.h +4 -2
  69. data/ext/libcouchbase/src/bucketconfig/confmon.cc +6 -3
  70. data/ext/libcouchbase/src/cbft.cc +48 -0
  71. data/ext/libcouchbase/src/cntl.cc +138 -2
  72. data/ext/libcouchbase/src/config_static.h +17 -0
  73. data/ext/libcouchbase/src/connspec.cc +54 -6
  74. data/ext/libcouchbase/src/connspec.h +9 -1
  75. data/ext/libcouchbase/src/crypto.cc +386 -0
  76. data/ext/libcouchbase/src/ctx-log-inl.h +23 -6
  77. data/ext/libcouchbase/src/dump.cc +4 -0
  78. data/ext/libcouchbase/src/getconfig.cc +1 -2
  79. data/ext/libcouchbase/src/handler.cc +65 -27
  80. data/ext/libcouchbase/src/hostlist.cc +35 -7
  81. data/ext/libcouchbase/src/hostlist.h +7 -0
  82. data/ext/libcouchbase/src/http/http-priv.h +2 -0
  83. data/ext/libcouchbase/src/http/http.cc +77 -37
  84. data/ext/libcouchbase/src/http/http_io.cc +19 -2
  85. data/ext/libcouchbase/src/instance.cc +90 -17
  86. data/ext/libcouchbase/src/internal.h +5 -0
  87. data/ext/libcouchbase/src/lcbio/connect.cc +39 -4
  88. data/ext/libcouchbase/src/lcbio/connect.h +27 -0
  89. data/ext/libcouchbase/src/lcbio/ctx.c +49 -23
  90. data/ext/libcouchbase/src/lcbio/ioutils.cc +30 -3
  91. data/ext/libcouchbase/src/lcbio/ioutils.h +2 -0
  92. data/ext/libcouchbase/src/lcbio/manager.cc +44 -8
  93. data/ext/libcouchbase/src/lcbio/manager.h +2 -0
  94. data/ext/libcouchbase/src/lcbio/rw-inl.h +1 -0
  95. data/ext/libcouchbase/src/lcbio/ssl.h +3 -5
  96. data/ext/libcouchbase/src/logging.c +1 -1
  97. data/ext/libcouchbase/src/logging.h +2 -0
  98. data/ext/libcouchbase/src/mc/compress.cc +164 -0
  99. data/ext/libcouchbase/src/mc/compress.h +7 -12
  100. data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +5 -1
  101. data/ext/libcouchbase/src/mc/mcreq.c +11 -1
  102. data/ext/libcouchbase/src/mc/mcreq.h +35 -4
  103. data/ext/libcouchbase/src/mcserver/mcserver.cc +30 -7
  104. data/ext/libcouchbase/src/mcserver/mcserver.h +7 -0
  105. data/ext/libcouchbase/src/mcserver/negotiate.cc +103 -57
  106. data/ext/libcouchbase/src/mcserver/negotiate.h +2 -2
  107. data/ext/libcouchbase/src/mctx-helper.h +11 -0
  108. data/ext/libcouchbase/src/metrics.cc +132 -0
  109. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
  110. data/ext/libcouchbase/src/n1ql/n1ql.cc +66 -0
  111. data/ext/libcouchbase/src/newconfig.cc +9 -2
  112. data/ext/libcouchbase/src/operations/counter.cc +2 -1
  113. data/ext/libcouchbase/src/operations/durability-cas.cc +11 -0
  114. data/ext/libcouchbase/src/operations/durability-seqno.cc +3 -0
  115. data/ext/libcouchbase/src/operations/durability.cc +24 -2
  116. data/ext/libcouchbase/src/operations/durability_internal.h +19 -0
  117. data/ext/libcouchbase/src/operations/get.cc +4 -2
  118. data/ext/libcouchbase/src/operations/observe-seqno.cc +1 -0
  119. data/ext/libcouchbase/src/operations/observe.cc +113 -62
  120. data/ext/libcouchbase/src/operations/ping.cc +246 -67
  121. data/ext/libcouchbase/src/operations/remove.cc +2 -1
  122. data/ext/libcouchbase/src/operations/store.cc +17 -14
  123. data/ext/libcouchbase/src/operations/touch.cc +3 -0
  124. data/ext/libcouchbase/src/packetutils.h +68 -4
  125. data/ext/libcouchbase/src/probes.d +132 -161
  126. data/ext/libcouchbase/src/rdb/bigalloc.c +1 -1
  127. data/ext/libcouchbase/src/retryq.cc +6 -2
  128. data/ext/libcouchbase/src/rnd.cc +68 -0
  129. data/ext/libcouchbase/src/rnd.h +39 -0
  130. data/ext/libcouchbase/src/settings.c +27 -0
  131. data/ext/libcouchbase/src/settings.h +67 -3
  132. data/ext/libcouchbase/src/ssl/CMakeLists.txt +0 -12
  133. data/ext/libcouchbase/src/ssl/ssl_common.c +23 -4
  134. data/ext/libcouchbase/src/strcodecs/base64.c +141 -16
  135. data/ext/libcouchbase/src/strcodecs/strcodecs.h +16 -1
  136. data/ext/libcouchbase/src/trace.h +68 -61
  137. data/ext/libcouchbase/src/tracing/span.cc +289 -0
  138. data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +171 -0
  139. data/ext/libcouchbase/src/tracing/tracer.cc +53 -0
  140. data/ext/libcouchbase/src/tracing/tracing-internal.h +213 -0
  141. data/ext/libcouchbase/src/utilities.c +5 -0
  142. data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -2
  143. data/ext/libcouchbase/src/vbucket/vbucket.c +50 -18
  144. data/ext/libcouchbase/src/views/docreq.cc +26 -1
  145. data/ext/libcouchbase/src/views/docreq.h +17 -0
  146. data/ext/libcouchbase/src/views/viewreq.cc +64 -1
  147. data/ext/libcouchbase/src/views/viewreq.h +21 -0
  148. data/ext/libcouchbase/tests/CMakeLists.txt +6 -6
  149. data/ext/libcouchbase/tests/basic/t_base64.cc +34 -6
  150. data/ext/libcouchbase/tests/basic/t_connstr.cc +14 -0
  151. data/ext/libcouchbase/tests/basic/t_creds.cc +10 -10
  152. data/ext/libcouchbase/tests/basic/t_host.cc +22 -2
  153. data/ext/libcouchbase/tests/basic/t_scram.cc +514 -0
  154. data/ext/libcouchbase/tests/check-all.cc +6 -2
  155. data/ext/libcouchbase/tests/iotests/mock-environment.cc +64 -0
  156. data/ext/libcouchbase/tests/iotests/mock-environment.h +27 -1
  157. data/ext/libcouchbase/tests/iotests/t_confmon.cc +2 -2
  158. data/ext/libcouchbase/tests/iotests/t_forward.cc +8 -0
  159. data/ext/libcouchbase/tests/iotests/t_netfail.cc +124 -0
  160. data/ext/libcouchbase/tests/iotests/t_smoke.cc +1 -1
  161. data/ext/libcouchbase/tests/iotests/t_snappy.cc +316 -0
  162. data/ext/libcouchbase/tests/socktests/socktest.cc +2 -2
  163. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  164. data/ext/libcouchbase/tests/socktests/t_manager.cc +1 -1
  165. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  166. data/ext/libcouchbase/tools/CMakeLists.txt +1 -1
  167. data/ext/libcouchbase/tools/cbc-handlers.h +17 -0
  168. data/ext/libcouchbase/tools/cbc-n1qlback.cc +7 -4
  169. data/ext/libcouchbase/tools/cbc-pillowfight.cc +408 -100
  170. data/ext/libcouchbase/tools/cbc-proxy.cc +134 -3
  171. data/ext/libcouchbase/tools/cbc-subdoc.cc +1 -2
  172. data/ext/libcouchbase/tools/cbc.cc +113 -8
  173. data/ext/libcouchbase/tools/common/histogram.cc +1 -0
  174. data/ext/libcouchbase/tools/common/options.cc +28 -1
  175. data/ext/libcouchbase/tools/common/options.h +5 -0
  176. data/ext/libcouchbase/tools/docgen/docgen.h +36 -10
  177. data/ext/libcouchbase/tools/docgen/loc.h +5 -4
  178. data/ext/libcouchbase/tools/docgen/seqgen.h +28 -0
  179. data/lib/libcouchbase/ext/libcouchbase/enums.rb +10 -0
  180. data/lib/libcouchbase/n1ql.rb +6 -1
  181. data/lib/libcouchbase/version.rb +1 -1
  182. data/spec/connection_spec.rb +6 -6
  183. metadata +38 -5
  184. data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +0 -11
  185. data/ext/libcouchbase/src/mc/compress.c +0 -90
  186. data/ext/libcouchbase/tools/common/my_inttypes.h +0 -22
@@ -25,18 +25,16 @@
25
25
  #define CTX_FD(ctx) (ctx)->fd
26
26
  #define CTX_SD(ctx) (ctx)->sd
27
27
  #define CTX_IOT(ctx) (ctx)->io
28
+ #define CTX_INCR_METRIC(ctx, metric, n) do { \
29
+ if (ctx->sock->metrics) { \
30
+ ctx->sock->metrics->metric += n; \
31
+ } \
32
+ } while (0)
33
+
28
34
  #include "rw-inl.h"
35
+ #include "ctx-log-inl.h"
29
36
 
30
37
  #define LOGARGS(c, lvl) (c)->sock->settings, "ioctx", LCB_LOG_##lvl, __FILE__, __LINE__
31
- static const lcb_host_t * get_ctx_host(const lcbio_CTX *ctx) {
32
- static lcb_host_t host = { "NOHOST", "NOPORT" };
33
- if (!ctx) { return &host; }
34
- if (!ctx->sock) { return &host; }
35
- if (!ctx->sock->info) { return &host; }
36
- return &ctx->sock->info->ep;
37
- }
38
- #define CTX_LOGFMT "<%s:%s> (CTX=%p,%s) "
39
- #define CTX_LOGID(ctx) get_ctx_host(ctx)->host, get_ctx_host(ctx)->port, (void*)ctx, ctx?ctx->subsys : ""
40
38
 
41
39
  typedef enum {
42
40
  ES_ACTIVE = 0,
@@ -84,6 +82,8 @@ lcbio_ctx_new(lcbio_SOCKET *sock, void *data, const lcbio_CTXPROCS *procs)
84
82
  ctx->state = ES_ACTIVE;
85
83
  ctx->as_err = lcbio_timer_new(ctx->io, ctx, err_handler);
86
84
  ctx->subsys = "unknown";
85
+ sock->service = LCBIO_SERVICE_UNSPEC;
86
+ sock->atime = LCB_NS2US(gethrtime());
87
87
 
88
88
  rdb_init(&ctx->ior, sock->settings->allocator_factory());
89
89
  lcbio_ref(sock);
@@ -98,7 +98,7 @@ lcbio_ctx_new(lcbio_SOCKET *sock, void *data, const lcbio_CTXPROCS *procs)
98
98
  ctx->procs = *procs;
99
99
  ctx->state = ES_ACTIVE;
100
100
 
101
- lcb_log(LOGARGS(ctx, DEBUG), CTX_LOGFMT "Pairing with SOCK=%p", CTX_LOGID(ctx), (void*)sock);
101
+ lcb_log(LOGARGS(ctx, DEBUG), CTX_LOGFMT "Pairing with SOCK=%016" PRIx64, CTX_LOGID(ctx), sock->id);
102
102
  return ctx;
103
103
  }
104
104
 
@@ -160,6 +160,7 @@ lcbio_ctx_close_ex(lcbio_CTX *ctx, lcbio_CTXCLOSE_cb cb, void *arg,
160
160
  cb(ctx->sock, reusable, arg);
161
161
  }
162
162
 
163
+ ctx->sock->ctx = NULL;
163
164
  if (oldrc == ctx->sock->refcount) {
164
165
  lcbio_shutdown(ctx->sock);
165
166
  }
@@ -274,6 +275,17 @@ invoke_read_cb(lcbio_CTX *ctx, unsigned nb)
274
275
  ctx->entered--;
275
276
  }
276
277
 
278
+ static void
279
+ send_io_error(lcbio_CTX *ctx, lcbio_IOSTATUS status)
280
+ {
281
+ lcb_error_t rc = convert_lcberr(ctx, status);
282
+ CTX_INCR_METRIC(ctx, io_error, 1);
283
+ if (status == LCBIO_SHUTDOWN) {
284
+ CTX_INCR_METRIC(ctx, io_close, 1);
285
+ }
286
+ lcbio_ctx_senderr(ctx, rc);
287
+ }
288
+
277
289
  static void
278
290
  E_handler(lcb_socket_t sock, short which, void *arg)
279
291
  {
@@ -286,6 +298,7 @@ E_handler(lcb_socket_t sock, short which, void *arg)
286
298
  status = lcbio_E_rdb_slurp(ctx, &ctx->ior);
287
299
  nb = rdb_get_nused(&ctx->ior);
288
300
 
301
+ ctx->sock->atime = LCB_NS2US(gethrtime());
289
302
  if (nb >= ctx->rdwant) {
290
303
  invoke_read_cb(ctx, nb);
291
304
  if (E_free_detached(ctx)) {
@@ -293,10 +306,10 @@ E_handler(lcb_socket_t sock, short which, void *arg)
293
306
  }
294
307
  }
295
308
  if (!LCBIO_IS_OK(status)) {
296
- lcb_error_t err = convert_lcberr(ctx, status);
297
- lcbio_ctx_senderr(ctx, err);
309
+ send_io_error(ctx, status);
298
310
  return;
299
311
  }
312
+ CTX_INCR_METRIC(ctx, bytes_received, nb);
300
313
  }
301
314
 
302
315
  if (which & LCB_WRITE_EVENT) {
@@ -308,10 +321,9 @@ E_handler(lcb_socket_t sock, short which, void *arg)
308
321
  }
309
322
  } else if (ctx->output) {
310
323
  status = lcbio_E_rb_write(ctx, &ctx->output->rb);
324
+ /** Metrics are logged by E_rb_write */
311
325
  if (!LCBIO_IS_OK(status)) {
312
- deactivate_watcher(ctx);
313
- ctx->err = convert_lcberr(ctx, status);
314
- err_handler(ctx);
326
+ send_io_error(ctx, status);
315
327
  return;
316
328
  }
317
329
  }
@@ -337,6 +349,7 @@ Cw_handler(lcb_sockdata_t *sd, int status, void *arg)
337
349
  (void)sd;
338
350
 
339
351
  ctx->npending--;
352
+ CTX_INCR_METRIC(ctx, bytes_sent, erb->rb.nbytes);
340
353
 
341
354
  if (!ctx->output) {
342
355
  ctx->output = erb;
@@ -366,6 +379,7 @@ Cr_handler(lcb_sockdata_t *sd, lcb_ssize_t nr, void *arg)
366
379
  ctx->npending--;
367
380
 
368
381
  if (ctx->state == ES_ACTIVE) {
382
+ ctx->sock->atime = LCB_NS2US(gethrtime());
369
383
  if (nr > 0) {
370
384
  unsigned total;
371
385
  rdb_rdend(&ctx->ior, nr);
@@ -373,11 +387,21 @@ Cr_handler(lcb_sockdata_t *sd, lcb_ssize_t nr, void *arg)
373
387
  if (total >= ctx->rdwant) {
374
388
  invoke_read_cb(ctx, total);
375
389
  }
376
-
390
+ CTX_INCR_METRIC(ctx, bytes_received, total);
377
391
  lcbio_ctx_schedule(ctx);
378
392
  } else {
379
- lcb_error_t err =
380
- convert_lcberr(ctx, nr ? LCBIO_SHUTDOWN : LCBIO_IOERR);
393
+ lcbio_IOSTATUS iostatus;
394
+ lcb_error_t err;
395
+
396
+ CTX_INCR_METRIC(ctx, io_error, 1);
397
+ if (nr) {
398
+ iostatus = LCBIO_IOERR;
399
+ } else {
400
+ iostatus = LCBIO_SHUTDOWN;
401
+ CTX_INCR_METRIC(ctx, io_close, 1);
402
+ }
403
+
404
+ err = convert_lcberr(ctx, iostatus);
381
405
  ctx->rdwant = 0;
382
406
  invoke_entered_errcb(ctx, err);
383
407
  }
@@ -404,7 +428,7 @@ C_schedule(lcbio_CTX *ctx)
404
428
  niov = iov[1].iov_len ? 2 : 1;
405
429
  rv = IOT_V1(io).write2(IOT_ARG(io), sd, iov, niov, ctx->output, Cw_handler);
406
430
  if (rv) {
407
- lcbio_ctx_senderr(ctx, convert_lcberr(ctx, LCBIO_IOERR));
431
+ send_io_error(ctx, LCBIO_IOERR);
408
432
  return;
409
433
  } else {
410
434
  ctx->output = NULL;
@@ -429,8 +453,7 @@ C_schedule(lcbio_CTX *ctx)
429
453
 
430
454
  rv = IOT_V1(io).read2(IOT_ARG(io), sd, iov, niov, ctx, Cr_handler);
431
455
  if (rv) {
432
- lcbio_ctx_senderr(ctx, convert_lcberr(ctx, LCBIO_IOERR));
433
-
456
+ send_io_error(ctx, LCBIO_IOERR);
434
457
  } else {
435
458
  sd->is_reading = 1;
436
459
  ctx->npending++;
@@ -486,6 +509,7 @@ E_put_ex(lcbio_CTX *ctx, lcb_IOV *iov, unsigned niov, unsigned nb)
486
509
  nw = IOT_V0IO(iot).sendv(IOT_ARG(iot), fd, iov,
487
510
  niov <= RWINL_IOVSIZE ? niov : RWINL_IOVSIZE);
488
511
  if (nw > 0) {
512
+ CTX_INCR_METRIC(ctx, bytes_sent, nw);
489
513
  ctx->procs.cb_flush_done(ctx, nb, nw);
490
514
  return 1;
491
515
 
@@ -504,13 +528,13 @@ E_put_ex(lcbio_CTX *ctx, lcb_IOV *iov, unsigned niov, unsigned nb)
504
528
  /* pretend all the bytes were written and deliver an error during
505
529
  * the next event loop iteration. */
506
530
  nw = nb;
507
- lcbio_ctx_senderr(ctx, convert_lcberr(ctx, LCBIO_IOERR));
531
+ send_io_error(ctx, LCBIO_IOERR);
508
532
  goto GT_WRITE0;
509
533
  }
510
534
  } else {
511
535
  /* connection closed. pretend everything was written and send an error */
512
536
  nw = nb;
513
- lcbio_ctx_senderr(ctx, convert_lcberr(ctx, LCBIO_SHUTDOWN));
537
+ send_io_error(ctx, LCBIO_SHUTDOWN);
514
538
  goto GT_WRITE0;
515
539
  }
516
540
 
@@ -526,11 +550,13 @@ Cw_ex_handler(lcb_sockdata_t *sd, int status, void *wdata)
526
550
  unsigned nflushed = (uintptr_t)wdata;
527
551
  ctx->npending--;
528
552
 
553
+ CTX_INCR_METRIC(ctx, bytes_sent, nflushed);
529
554
  ctx->entered = 1;
530
555
  ctx->procs.cb_flush_done(ctx, nflushed, nflushed);
531
556
  ctx->entered = 0;
532
557
 
533
558
  if (ctx->state == ES_ACTIVE && status) {
559
+ CTX_INCR_METRIC(ctx, io_error, 1);
534
560
  invoke_entered_errcb(ctx, convert_lcberr(ctx, LCBIO_IOERR));
535
561
  }
536
562
  if (ctx->state != ES_ACTIVE && !ctx->npending) {
@@ -300,9 +300,7 @@ lcbio_ssl_supported(void)
300
300
  #endif
301
301
  }
302
302
 
303
- lcbio_pSSLCTX
304
- lcbio_ssl_new__fallback(const char *, int, lcb_error_t *errp,
305
- lcb_settings *)
303
+ lcbio_pSSLCTX lcbio_ssl_new__fallback(const char *, const char *, const char *, int, lcb_error_t *errp, lcb_settings *)
306
304
  {
307
305
  if (errp) { *errp = LCB_CLIENT_FEATURE_UNAVAILABLE; }
308
306
  return NULL;
@@ -327,3 +325,32 @@ lcb_error_t lcbio_sslify_if_needed(lcbio_SOCKET *, lcb_settings *) {
327
325
  return LCB_SUCCESS;
328
326
  }
329
327
  #endif
328
+
329
+ std::string lcbio__inet_ntop(sockaddr_storage *ss)
330
+ {
331
+ char buf[4096] = {0};
332
+ switch(ss->ss_family) {
333
+ case AF_INET:
334
+ {
335
+ struct sockaddr_in *addr = (struct sockaddr_in *)ss;
336
+ inet_ntop(AF_INET, &(addr->sin_addr), buf, sizeof(buf));
337
+ size_t len = strlen(buf);
338
+ snprintf(buf + len, 10, ":%d", (int)ntohs(addr->sin_port));
339
+ }
340
+ break;
341
+
342
+ case AF_INET6:
343
+ {
344
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ss;
345
+ inet_ntop(AF_INET6, &(addr->sin6_addr), buf, sizeof(buf));
346
+ size_t len = strlen(buf);
347
+ snprintf(buf + len, 10, ":%d", (int)ntohs(addr->sin6_port));
348
+ }
349
+ break;
350
+
351
+ default:
352
+ strncpy(buf, "Unknown AF", sizeof(buf));
353
+ }
354
+
355
+ return std::string(buf);
356
+ }
@@ -116,6 +116,8 @@ lcbio__load_socknames(lcbio_SOCKET *sock);
116
116
  #ifdef __cplusplus
117
117
  }
118
118
 
119
+ std::string lcbio__inet_ntop(sockaddr_storage *ss);
120
+
119
121
  namespace lcb {
120
122
  namespace io {
121
123
 
@@ -159,14 +159,19 @@ struct PoolRequest : ReqNode, ConnectionRequest {
159
159
  }
160
160
  }
161
161
 
162
- static const char *get_hehost(PoolHost *h) {
162
+ static const char *get_hehost(const PoolHost *h) {
163
163
  if (!h) { return "NOHOST:NOPORT"; }
164
164
  return h->key.c_str();
165
165
  }
166
166
 
167
167
  /** Format string arguments for %p%s:%s */
168
- #define HE_LOGID(h) get_hehost(h), (void*)h
169
- #define HE_LOGFMT "<%s> (HE=%p) "
168
+ #define HE_LOGID(h) \
169
+ (h && h->parent && h->parent->settings->log_redaction) ? LCB_LOG_SD_OTAG : "", \
170
+ get_hehost(h), \
171
+ (h && h->parent && h->parent->settings->log_redaction) ? LCB_LOG_SD_CTAG : "", \
172
+ (void*)h
173
+ #define HE_LOGFMT "<" LCB_LOG_SPEC("%s") "> (HE=%p) "
174
+
170
175
 
171
176
  PoolConnInfo::~PoolConnInfo() {
172
177
  parent->n_total--;
@@ -238,13 +243,39 @@ void Pool::shutdown() {
238
243
  unref();
239
244
  }
240
245
 
246
+ static void endpointToJSON(hrtime_t now, Json::Value &node, const PoolHost *host, const PoolConnInfo *info) {
247
+ Json::Value endpoint;
248
+ char id[20] = {0};
249
+ snprintf(id, sizeof(id), "%p", (void *)info->sock);
250
+ endpoint["id"] = id;
251
+ endpoint["remote"] = get_hehost(host);
252
+ endpoint["local"] = lcbio__inet_ntop(&info->sock->info->sa_local);
253
+ endpoint["last_activity_us"] = (Json::Value::UInt64)(now - info->sock->atime);
254
+ endpoint["status"] = "connected";
255
+ node[lcbio_svcstr(info->sock->service)].append(endpoint);
256
+ }
257
+
258
+ void Pool::toJSON(hrtime_t now, Json::Value &node) {
259
+ lcbio_MGR::HostMap::const_iterator it;
260
+ for (it = ht.begin(); it != ht.end(); ++it) {
261
+ const PoolHost *host = it->second;
262
+ lcb_list_t *llcur;
263
+ LCB_LIST_FOR(llcur, (lcb_list_t *)&host->ll_idle) {
264
+ endpointToJSON(now, node, host, PoolConnInfo::from_llnode(llcur));
265
+ }
266
+ LCB_LIST_FOR(llcur, (lcb_list_t *)&host->ll_pending) {
267
+ endpointToJSON(now, node, host, PoolConnInfo::from_llnode(llcur));
268
+ }
269
+ }
270
+ }
271
+
241
272
  void
242
273
  PoolRequest::invoke() {
243
274
  if (sock) {
244
275
  PoolConnInfo *info = PoolConnInfo::from_sock(sock);
245
276
  info->set_leased();
246
277
  state = ASSIGNED;
247
- lcb_log(LOGARGS(info->parent->parent, DEBUG), HE_LOGFMT "Assigning R=%p SOCKET=%p",HE_LOGID(info->parent), (void*)this, (void*)sock);
278
+ lcb_log(LOGARGS(info->parent->parent, DEBUG), HE_LOGFMT "Assigning R=%p SOCKET=%p", HE_LOGID(info->parent), (void*)this, (void*)sock);
248
279
  }
249
280
 
250
281
  callback(sock, arg, err, 0);
@@ -318,7 +349,7 @@ PoolConnInfo::PoolConnInfo(PoolHost *he, uint32_t timeout)
318
349
  id = LCBIO_PROTOCTX_POOL;
319
350
  dtor = cinfo_protoctx_dtor;
320
351
 
321
- lcb_host_t tmphost;
352
+ lcb_host_t tmphost = {"", "", 0};
322
353
  lcb_error_t err = lcb_host_parsez(&tmphost, he->key.c_str(), 80);
323
354
  if (err != LCB_SUCCESS) {
324
355
  lcb_log(LOGARGS(he->parent, ERROR), HE_LOGFMT "Could not parse host! Will supply dummy host (I=%p)", HE_LOGID(he), (void*)this);
@@ -371,8 +402,12 @@ Pool::get(const lcb_host_t& dest, uint32_t timeout, lcbio_CONNDONE_cb cb,
371
402
  PoolHost *he;
372
403
  lcb_list_t *cur;
373
404
 
374
- std::string key(dest.host);
375
- key.append(":").append(dest.port);
405
+ std::string key;
406
+ if (dest.ipv6) {
407
+ key.append("[").append(dest.host).append("]:").append(dest.port);
408
+ } else {
409
+ key.append(dest.host).append(":").append(dest.port);
410
+ }
376
411
 
377
412
  HostMap::iterator m = ht.find(key);
378
413
  if (m == ht.end()) {
@@ -506,7 +541,8 @@ PoolHost::dump(FILE *out) const {
506
541
  lcb_list_t *llcur;
507
542
  fprintf(out, "HOST=%s", key.c_str());
508
543
  fprintf(out, "Requests=%lu, Idle=%lu, Pending=%lu, Leased=%lu\n",
509
- num_requests(), num_idle(), num_pending(), num_leased());
544
+ (unsigned long int)num_requests(), (unsigned long int)num_idle(),
545
+ (unsigned long int)num_pending(), (unsigned long int)num_leased());
510
546
 
511
547
  fprintf(out, CONN_INDENT "Idle Connections:\n");
512
548
  write_he_list(&ll_idle, out);
@@ -173,6 +173,8 @@ public:
173
173
  return options;
174
174
  }
175
175
 
176
+ void toJSON(hrtime_t now, Json::Value &node);
177
+
176
178
  private:
177
179
  friend struct PoolRequest;
178
180
  friend struct PoolConnInfo;
@@ -109,6 +109,7 @@ lcbio_E_rb_write(lcbio_CTX *ctx, ringbuffer_t *buf)
109
109
  }
110
110
  if (nw) {
111
111
  ringbuffer_consumed(buf, nw);
112
+ CTX_INCR_METRIC(ctx, bytes_sent, nw);
112
113
  }
113
114
  }
114
115
  return LCBIO_COMPLETED;
@@ -61,8 +61,7 @@ typedef struct lcbio_SSLCTX *lcbio_pSSLCTX;
61
61
  int
62
62
  lcbio_ssl_supported(void);
63
63
 
64
- lcbio_pSSLCTX
65
- lcbio_ssl_new__fallback(const char *, int, lcb_error_t *, lcb_settings *);
64
+ lcbio_pSSLCTX lcbio_ssl_new__fallback(const char *, const char *, const char *, int, lcb_error_t *, lcb_settings *);
66
65
 
67
66
  #ifndef LCB_NO_SSL
68
67
  /**
@@ -74,9 +73,8 @@ lcbio_ssl_new__fallback(const char *, int, lcb_error_t *, lcb_settings *);
74
73
  *
75
74
  * @return A new SSL context, or NULL on error.
76
75
  */
77
- lcbio_pSSLCTX
78
- lcbio_ssl_new(const char *cafile, int noverify, lcb_error_t *errp,
79
- lcb_settings *settings);
76
+ lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *keyfile, int noverify,
77
+ lcb_error_t *errp, lcb_settings *settings);
80
78
  #else
81
79
  #define lcbio_ssl_new lcbio_ssl_new__fallback
82
80
  #endif
@@ -147,7 +147,7 @@ static void console_log(struct lcb_logprocs_st *procs,
147
147
  flockfile(fp);
148
148
  fprintf(fp, "%lums ", (unsigned long)(now - start_time) / 1000000);
149
149
 
150
- fprintf(fp, "[I%d] {%"THREAD_ID_FMT"} [%s] (%s - L:%d) ",
150
+ fprintf(fp, "[I%08x] {%"THREAD_ID_FMT"} [%s] (%s - L:%d) ",
151
151
  iid,
152
152
  GET_THREAD_ID(),
153
153
  level_to_string(severity),
@@ -78,6 +78,8 @@ lcb_logprocs * lcb_init_console_logger(void);
78
78
 
79
79
  /** Macro for overcoming Win32 identifiers */
80
80
  #define LCB_LOG_ERR LCB_LOG_ERROR
81
+ /** Undefine DEBUG macro to fix environments which are defining it */
82
+ #undef DEBUG
81
83
 
82
84
  #ifdef __cplusplus
83
85
  }
@@ -0,0 +1,164 @@
1
+ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2014-2018 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 "mcreq.h"
19
+ #include "compress.h"
20
+
21
+ #include <snappy.h>
22
+ #include <snappy-sinksource.h>
23
+
24
+ class FragBufSource : public snappy::Source
25
+ {
26
+ public:
27
+ explicit FragBufSource(const lcb_FRAGBUF *buf_) : buf(buf_)
28
+ {
29
+ if (buf->total_length) {
30
+ left = buf->total_length;
31
+ } else {
32
+ left = 0;
33
+ for (unsigned int ii = 0; ii < buf->niov; ii++) {
34
+ left += buf->iov[ii].iov_len;
35
+ }
36
+ }
37
+ idx = 0;
38
+ ptr = static_cast< const char * >(buf->iov[idx].iov_base);
39
+ }
40
+
41
+ virtual ~FragBufSource() {}
42
+
43
+ virtual size_t Available() const
44
+ {
45
+ return left;
46
+ }
47
+
48
+ virtual const char *Peek(size_t *len)
49
+ {
50
+ *len =
51
+ buf->iov[idx].iov_len - static_cast< size_t >((ptr - static_cast< const char * >(buf->iov[idx].iov_base)));
52
+ return ptr;
53
+ }
54
+
55
+ virtual void Skip(size_t n)
56
+ {
57
+ lcb_IOV &v = buf->iov[idx];
58
+ if (ptr == static_cast< const char * >(v.iov_base) && n == v.iov_len) {
59
+ ptr = static_cast< const char * >(buf->iov[++idx].iov_base);
60
+ } else {
61
+ ptr += n;
62
+ if (static_cast< size_t >(ptr - static_cast< const char * >(v.iov_base)) == v.iov_len) {
63
+ ptr = static_cast< const char * >(buf->iov[++idx].iov_base);
64
+ }
65
+ }
66
+ left -= n;
67
+ if (left == 0) {
68
+ ptr = NULL;
69
+ }
70
+ }
71
+
72
+ private:
73
+ const lcb_FRAGBUF *buf;
74
+ const char *ptr;
75
+ size_t left;
76
+ unsigned int idx;
77
+ };
78
+
79
+ int mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_VALBUF *vbuf, lcb_settings *settings,
80
+ int *should_compress)
81
+ {
82
+ size_t maxsize, compsize = 0, origsize = 0;
83
+
84
+ snappy::Source *source = NULL;
85
+ switch (vbuf->vtype) {
86
+ case LCB_KV_COPY:
87
+ case LCB_KV_CONTIG:
88
+ origsize = vbuf->u_buf.contig.nbytes;
89
+ if (origsize < settings->compress_min_size) {
90
+ *should_compress = 0;
91
+ mcreq_reserve_value(pl, pkt, vbuf);
92
+ return 0;
93
+ }
94
+ source = new snappy::ByteArraySource(static_cast< const char * >(vbuf->u_buf.contig.bytes),
95
+ vbuf->u_buf.contig.nbytes);
96
+ break;
97
+
98
+ case LCB_KV_IOV:
99
+ case LCB_KV_IOVCOPY:
100
+ if (vbuf->u_buf.multi.total_length == 0) {
101
+ for (unsigned int ii = 0; ii < vbuf->u_buf.multi.niov; ii++) {
102
+ origsize += vbuf->u_buf.multi.iov[ii].iov_len;
103
+ }
104
+ }
105
+ if (origsize < settings->compress_min_size) {
106
+ *should_compress = 0;
107
+ mcreq_reserve_value(pl, pkt, vbuf);
108
+ return 0;
109
+ }
110
+ source = new FragBufSource(&vbuf->u_buf.multi);
111
+ break;
112
+
113
+ default:
114
+ return -1;
115
+ }
116
+
117
+ maxsize = snappy::MaxCompressedLength(source->Available());
118
+ if (mcreq_reserve_value2(pl, pkt, maxsize) != LCB_SUCCESS) {
119
+ return -1;
120
+ }
121
+ nb_SPAN *outspan = &pkt->u_value.single;
122
+ snappy::UncheckedByteArraySink sink(SPAN_BUFFER(outspan));
123
+
124
+ Compress(source, &sink);
125
+ compsize = sink.CurrentDestination() - SPAN_BUFFER(outspan);
126
+ delete source;
127
+
128
+ if (compsize == 0 || compsize / origsize > settings->compress_min_ratio) {
129
+ netbuf_mblock_release(&pl->nbmgr, outspan);
130
+ *should_compress = 0;
131
+ mcreq_reserve_value(pl, pkt, vbuf);
132
+ return 0;
133
+ }
134
+
135
+ if (compsize < maxsize) {
136
+ /* chop off some bytes? */
137
+ nb_SPAN trailspan = *outspan;
138
+ trailspan.offset += compsize;
139
+ trailspan.size = maxsize - compsize;
140
+ netbuf_mblock_release(&pl->nbmgr, &trailspan);
141
+ outspan->size = compsize;
142
+ }
143
+ return 0;
144
+ }
145
+
146
+ int mcreq_inflate_value(const void *compressed, lcb_SIZE ncompressed, const void **bytes, lcb_SIZE *nbytes,
147
+ void **freeptr)
148
+ {
149
+ size_t compsize = 0;
150
+
151
+ if (!snappy::GetUncompressedLength(static_cast< const char * >(compressed), (size_t)ncompressed, &compsize)) {
152
+ return -1;
153
+ }
154
+ *freeptr = malloc(compsize);
155
+ if (!snappy::RawUncompress(static_cast< const char * >(compressed), ncompressed, static_cast< char * >(*freeptr))) {
156
+ free(*freeptr);
157
+ *freeptr = NULL;
158
+ return -1;
159
+ }
160
+
161
+ *bytes = *freeptr;
162
+ *nbytes = compsize;
163
+ return 0;
164
+ }