libcouchbase 1.2.8 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }