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
@@ -74,7 +74,8 @@ lcb_get3(lcb_t instance, const void *cookie, const lcb_CMDGET *cmd)
74
74
 
75
75
  memcpy(SPAN_BUFFER(&pkt->kh_span), gcmd.bytes, MCREQ_PKT_BASESIZE + extlen);
76
76
  LCB_SCHED_ADD(instance, pl, pkt);
77
- TRACE_GET_BEGIN(hdr, cmd);
77
+ LCBTRACE_KV_START(instance->settings, cmd, LCBTRACE_OP_GET, pkt->opaque, rdata->span);
78
+ TRACE_GET_BEGIN(instance, hdr, cmd);
78
79
 
79
80
  return LCB_SUCCESS;
80
81
  }
@@ -144,8 +145,9 @@ lcb_unlock3(lcb_t instance, const void *cookie, const lcb_CMDUNLOCK *cmd)
144
145
  hdr.request.cas = lcb_htonll(cmd->cas);
145
146
 
146
147
  memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes));
147
- TRACE_UNLOCK_BEGIN(&hdr, cmd);
148
148
  LCB_SCHED_ADD(instance, pl, pkt);
149
+ LCBTRACE_KV_START(instance->settings, cmd, LCBTRACE_OP_UNLOCK, pkt->opaque, rd->span);
150
+ TRACE_UNLOCK_BEGIN(instance, &hdr, cmd);
149
151
  return LCB_SUCCESS;
150
152
  }
151
153
 
@@ -50,6 +50,7 @@ lcb_observe_seqno3(lcb_t instance, const void *cookie, const lcb_CMDOBSEQNO *cmd
50
50
  uuid = lcb_htonll(cmd->uuid);
51
51
  memcpy(SPAN_BUFFER(&pkt->u_value.single), &uuid, sizeof uuid);
52
52
  LCB_SCHED_ADD(instance, server, pkt);
53
+ LCBTRACE_KV_START(instance->settings, cmd, LCBTRACE_OP_OBSERVE_SEQNO, pkt->opaque, MCREQ_PKT_RDATA(pkt)->span);
53
54
  return LCB_SUCCESS;
54
55
  }
55
56
 
@@ -19,50 +19,61 @@
19
19
  #include "durability_internal.h"
20
20
  #include "trace.h"
21
21
  #include "mctx-helper.h"
22
+ #include "sllist-inl.h"
22
23
 
23
- struct ObserveCtx : mc_REQDATAEX, lcb::MultiCmdContext {
24
- void clear_requests() { requests.clear(); }
24
+ struct ObserveCtx : lcb::MultiCmdContext {
25
+ void clear_requests()
26
+ {
27
+ requests.clear();
28
+ num_requests.clear();
29
+ }
25
30
  ObserveCtx(lcb_t instance_);
26
31
 
27
32
  // Overrides
28
- lcb_error_t MCTX_addcmd(const lcb_CMDBASE*);
33
+ lcb_error_t MCTX_addcmd(const lcb_CMDBASE *);
29
34
  lcb_error_t MCTX_done(const void *);
30
35
  void MCTX_fail();
36
+ #ifdef LCB_TRACING
37
+ void MCTX_setspan(lcbtrace_SPAN *span);
38
+ #endif
31
39
 
32
40
  lcb_t instance;
33
41
  size_t remaining;
34
42
  unsigned oflags;
35
43
 
36
- typedef std::vector<uint8_t> ServerBuf;
44
+ typedef std::vector< uint8_t > ServerBuf;
37
45
  /* requests array contains one buffer per server. nrequest essentially
38
46
  * says how many elements (and thus how many servers) */
39
- std::vector<ServerBuf> requests;
47
+ std::vector< ServerBuf > requests;
48
+ std::vector< size_t > num_requests;
49
+ #ifdef LCB_TRACING
50
+ lcbtrace_SPAN *span;
51
+ #endif
52
+ };
53
+
54
+ struct OperationCtx : mc_REQDATAEX {
55
+ OperationCtx(ObserveCtx *parent_, size_t remaining_);
56
+
57
+ ObserveCtx *parent;
58
+ size_t remaining;
40
59
  };
41
60
 
42
- typedef enum {
43
- F_DURABILITY = 0x01,
44
- F_DESTROY = 0x02,
45
- F_SCHEDFAILED = 0x04
46
- } obs_flags;
61
+ typedef enum { F_DURABILITY = 0x01, F_DESTROY = 0x02, F_SCHEDFAILED = 0x04 } obs_flags;
47
62
 
48
63
  // TODO: Move this to a common file
49
- template <typename ContainerType, typename ValueType>
50
- void add_to_buf(ContainerType& c, ValueType v) {
51
- typename ContainerType::value_type *p =
52
- reinterpret_cast<typename ContainerType::value_type*>(&v);
64
+ template < typename ContainerType, typename ValueType > void add_to_buf(ContainerType &c, ValueType v)
65
+ {
66
+ typename ContainerType::value_type *p = reinterpret_cast< typename ContainerType::value_type * >(&v);
53
67
  c.insert(c.end(), p, p + sizeof(ValueType));
54
68
  }
55
69
 
56
- static void
57
- handle_observe_callback(mc_PIPELINE *pl,
58
- mc_PACKET *pkt, lcb_error_t err, const void *arg)
70
+ static void handle_observe_callback(mc_PIPELINE *pl, mc_PACKET *pkt, lcb_error_t err, const void *arg)
59
71
  {
60
- ObserveCtx *oc = static_cast<ObserveCtx*>(pkt->u_rdata.exdata);
61
- lcb_RESPOBSERVE *resp = reinterpret_cast<lcb_RESPOBSERVE*>(const_cast<void*>(arg));
72
+ OperationCtx *opc = static_cast< OperationCtx * >(pkt->u_rdata.exdata);
73
+ ObserveCtx *oc = opc->parent;
74
+ lcb_RESPOBSERVE *resp = reinterpret_cast< lcb_RESPOBSERVE * >(const_cast< void * >(arg));
62
75
  lcb_t instance = oc->instance;
63
76
 
64
- (void)pl;
65
-
66
77
  if (resp == NULL) {
67
78
  int nfailed = 0;
68
79
  /** We need to fail the request manually.. */
@@ -70,7 +81,7 @@ handle_observe_callback(mc_PIPELINE *pl,
70
81
  const char *end = ptr + pkt->u_value.single.size;
71
82
  while (ptr < end) {
72
83
  lcb_uint16_t nkey;
73
- lcb_RESPOBSERVE cur = { 0 };
84
+ lcb_RESPOBSERVE cur = {0};
74
85
  cur.rflags = LCB_RESP_F_CLIENTGEN;
75
86
 
76
87
  ptr += 2;
@@ -81,7 +92,7 @@ handle_observe_callback(mc_PIPELINE *pl,
81
92
  memset(&cur, 0, sizeof(cur));
82
93
  cur.key = ptr;
83
94
  cur.nkey = nkey;
84
- cur.cookie = (void *)oc->cookie;
95
+ cur.cookie = (void *)opc->cookie;
85
96
  cur.rc = err;
86
97
  handle_observe_callback(NULL, pkt, err, &cur);
87
98
  ptr += nkey;
@@ -91,11 +102,18 @@ handle_observe_callback(mc_PIPELINE *pl,
91
102
  return;
92
103
  }
93
104
 
94
- resp->cookie = (void *)oc->cookie;
105
+ resp->cookie = (void *)opc->cookie;
95
106
  resp->rc = err;
107
+ oc->remaining--;
108
+ #ifdef LCB_TRACING
109
+ if (oc->remaining == 0 && oc->span) {
110
+ lcbtrace_span_finish(oc->span, LCBTRACE_NOW);
111
+ oc->span = NULL;
112
+ }
113
+ #endif
96
114
  if (oc->oflags & F_DURABILITY) {
97
115
  resp->ttp = pl ? pl->index : -1;
98
- lcbdur_cas_update(instance, (void*)MCREQ_PKT_COOKIE(pkt), err, resp);
116
+ lcbdur_cas_update(instance, (void *)MCREQ_PKT_COOKIE(pkt), err, resp);
99
117
 
100
118
  } else if ((oc->oflags & F_SCHEDFAILED) == 0) {
101
119
  lcb_RESPCALLBACK callback = lcb_find_callback(instance, LCB_CALLBACK_OBSERVE);
@@ -105,27 +123,35 @@ handle_observe_callback(mc_PIPELINE *pl,
105
123
  if (oc->oflags & F_DESTROY) {
106
124
  return;
107
125
  }
108
-
109
- if (--oc->remaining) {
110
- return;
111
- } else {
112
- lcb_RESPOBSERVE resp2 = { 0 };
126
+ if (oc->remaining == 0) {
127
+ lcb_RESPOBSERVE resp2 = {0};
113
128
  resp2.rc = err;
114
- resp2.rflags = LCB_RESP_F_CLIENTGEN|LCB_RESP_F_FINAL;
129
+ resp2.rflags = LCB_RESP_F_CLIENTGEN | LCB_RESP_F_FINAL;
115
130
  oc->oflags |= F_DESTROY;
116
131
  handle_observe_callback(NULL, pkt, err, &resp2);
117
132
  delete oc;
118
133
  }
134
+ opc->remaining--;
135
+ if (opc->remaining == 0) {
136
+ delete opc;
137
+ }
119
138
  }
120
139
 
121
- static void
122
- handle_schedfail(mc_PACKET *pkt)
140
+ static void handle_schedfail(mc_PACKET *pkt)
123
141
  {
124
- ObserveCtx *oc = static_cast<ObserveCtx*>(pkt->u_rdata.exdata);
142
+ OperationCtx *opc = static_cast< OperationCtx * >(pkt->u_rdata.exdata);
143
+ ObserveCtx *oc = opc->parent;
125
144
  oc->oflags |= F_SCHEDFAILED;
126
145
  handle_observe_callback(NULL, pkt, LCB_SCHEDFAIL_INTERNAL, NULL);
127
146
  }
128
147
 
148
+ #ifdef LCB_TRACING
149
+ void ObserveCtx::MCTX_setspan(lcbtrace_SPAN *span_)
150
+ {
151
+ span = span_;
152
+ }
153
+ #endif
154
+
129
155
  lcb_error_t ObserveCtx::MCTX_addcmd(const lcb_CMDBASE *cmdbase)
130
156
  {
131
157
  int vbid, srvix_dummy;
@@ -182,22 +208,18 @@ lcb_error_t ObserveCtx::MCTX_addcmd(const lcb_CMDBASE *cmdbase)
182
208
 
183
209
  lcb_assert(ix < requests.size());
184
210
 
185
- ServerBuf& rr = requests[ix];
211
+ ServerBuf &rr = requests[ix];
186
212
  add_to_buf(rr, uint16_t(htons(vbid)));
187
213
  add_to_buf(rr, uint16_t(htons(cmd->key.contig.nbytes)));
188
- rr.insert(rr.end(),
189
- reinterpret_cast<const uint8_t*>(cmd->key.contig.bytes),
190
- reinterpret_cast<const uint8_t*>(cmd->key.contig.bytes) +
191
- cmd->key.contig.nbytes);
214
+ rr.insert(rr.end(), reinterpret_cast< const uint8_t * >(cmd->key.contig.bytes),
215
+ reinterpret_cast< const uint8_t * >(cmd->key.contig.bytes) + cmd->key.contig.nbytes);
192
216
  remaining++;
217
+ num_requests[ii]++;
193
218
  }
194
219
  return LCB_SUCCESS;
195
220
  }
196
221
 
197
- static mc_REQDATAPROCS obs_procs = {
198
- handle_observe_callback,
199
- handle_schedfail
200
- };
222
+ static mc_REQDATAPROCS obs_procs = {handle_observe_callback, handle_schedfail};
201
223
 
202
224
  lcb_error_t ObserveCtx::MCTX_done(const void *cookie_)
203
225
  {
@@ -208,7 +230,7 @@ lcb_error_t ObserveCtx::MCTX_done(const void *cookie_)
208
230
  protocol_binary_request_header hdr;
209
231
  mc_PACKET *pkt;
210
232
  mc_PIPELINE *pipeline;
211
- ServerBuf& rr = requests[ii];
233
+ ServerBuf &rr = requests[ii];
212
234
  pipeline = cq->pipelines[ii];
213
235
 
214
236
  if (rr.empty()) {
@@ -234,15 +256,30 @@ lcb_error_t ObserveCtx::MCTX_done(const void *cookie_)
234
256
  memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes));
235
257
  memcpy(SPAN_BUFFER(&pkt->u_value.single), &rr[0], rr.size());
236
258
 
259
+ OperationCtx *ctx = new OperationCtx(this, this->num_requests[ii]);
260
+ ctx->start = gethrtime();
261
+ ctx->cookie = cookie_;
262
+
237
263
  pkt->flags |= MCREQ_F_REQEXT;
238
- pkt->u_rdata.exdata = this;
264
+ pkt->u_rdata.exdata = ctx;
265
+ #ifdef LCB_TRACING
266
+ if (instance->settings->tracer) {
267
+ lcbtrace_REF ref;
268
+ char opid[20] = {};
269
+ snprintf(opid, sizeof(opid), "0x%x", (int)pkt->opaque);
270
+ ref.type = LCBTRACE_REF_CHILD_OF;
271
+ ref.span = span;
272
+ MCREQ_PKT_RDATA(pkt)->span =
273
+ lcbtrace_span_start(instance->settings->tracer, LCBTRACE_OP_OBSERVE_CAS, LCBTRACE_NOW, &ref);
274
+ lcbtrace_span_add_tag_str(MCREQ_PKT_RDATA(pkt)->span, LCBTRACE_TAG_OPERATION_ID, opid);
275
+ lcbtrace_span_add_system_tags(MCREQ_PKT_RDATA(pkt)->span, instance->settings, LCBTRACE_TAG_SERVICE_KV);
276
+ }
277
+ #endif
278
+
239
279
  mcreq_sched_add(pipeline, pkt);
240
- TRACE_OBSERVE_BEGIN(&hdr, SPAN_BUFFER(&pkt->u_value.single));
280
+ TRACE_OBSERVE_BEGIN(instance, &hdr, SPAN_BUFFER(&pkt->u_value.single));
241
281
  }
242
282
 
243
- start = gethrtime();
244
- cookie = cookie_;
245
-
246
283
  if (requests.size() == 0 || remaining == 0) {
247
284
  delete this;
248
285
  return LCB_EINVAL;
@@ -252,35 +289,49 @@ lcb_error_t ObserveCtx::MCTX_done(const void *cookie_)
252
289
  }
253
290
  }
254
291
 
255
- void ObserveCtx::MCTX_fail() {
292
+ void ObserveCtx::MCTX_fail()
293
+ {
294
+ #ifdef LCB_TRACING
295
+ if (span) {
296
+ lcbtrace_span_finish(span, LCBTRACE_NOW);
297
+ span = NULL;
298
+ }
299
+ #endif
256
300
  delete this;
257
301
  }
258
302
 
259
303
  ObserveCtx::ObserveCtx(lcb_t instance_)
260
- : mc_REQDATAEX(NULL, obs_procs, 0),
261
- instance(instance_),
262
- remaining(0),
263
- oflags(0) {
264
-
304
+ : instance(instance_), remaining(0), oflags(0)
305
+ #ifdef LCB_TRACING
306
+ ,
307
+ span(NULL)
308
+ #endif
309
+ {
265
310
  requests.resize(LCBT_NSERVERS(instance));
311
+ num_requests.resize(requests.size());
312
+ }
313
+
314
+ OperationCtx::OperationCtx(ObserveCtx *parent_, size_t remaining_)
315
+ : mc_REQDATAEX(NULL, obs_procs, 0), parent(parent_), remaining(remaining_)
316
+ {
266
317
  }
267
318
 
268
319
  LIBCOUCHBASE_API
269
- lcb_MULTICMD_CTX * lcb_observe3_ctxnew(lcb_t instance) {
320
+ lcb_MULTICMD_CTX *lcb_observe3_ctxnew(lcb_t instance)
321
+ {
270
322
  return new ObserveCtx(instance);
271
323
  }
272
324
 
273
- lcb_MULTICMD_CTX *
274
- lcb_observe_ctx_dur_new(lcb_t instance) {
325
+ lcb_MULTICMD_CTX *lcb_observe_ctx_dur_new(lcb_t instance)
326
+ {
275
327
  ObserveCtx *ctx = new ObserveCtx(instance);
276
328
  ctx->oflags |= F_DURABILITY;
277
329
  return ctx;
278
330
  }
279
331
 
280
332
  LIBCOUCHBASE_API
281
- lcb_error_t lcb_observe(lcb_t instance,
282
- const void *command_cookie, lcb_size_t num,
283
- const lcb_observe_cmd_t *const *items)
333
+ lcb_error_t lcb_observe(lcb_t instance, const void *command_cookie, lcb_size_t num,
334
+ const lcb_observe_cmd_t *const *items)
284
335
  {
285
336
  unsigned ii;
286
337
  lcb_error_t err;
@@ -294,7 +345,7 @@ lcb_error_t lcb_observe(lcb_t instance,
294
345
  }
295
346
 
296
347
  for (ii = 0; ii < num; ii++) {
297
- lcb_CMDOBSERVE cmd = { 0 };
348
+ lcb_CMDOBSERVE cmd = {0};
298
349
  const lcb_observe_cmd_t *src = items[ii];
299
350
  if (src->version == 1 && (src->v.v1.options & LCB_OBSERVE_MASTER_ONLY)) {
300
351
  cmd.cmdflags |= LCB_CMDOBSERVE_F_MASTER_ONLY;
@@ -32,6 +32,7 @@ struct PingCookie : mc_REQDATAEX {
32
32
  int remaining;
33
33
  int options;
34
34
  std::list<lcb_PINGSVC> responses;
35
+ std::string id;
35
36
 
36
37
  PingCookie(const void *cookie_, int _options)
37
38
  : mc_REQDATAEX(cookie_, ping_procs, gethrtime()),
@@ -41,8 +42,12 @@ struct PingCookie : mc_REQDATAEX {
41
42
  ~PingCookie() {
42
43
  for (std::list<lcb_PINGSVC>::iterator it = responses.begin(); it != responses.end(); it++) {
43
44
  if (it->server) {
44
- free(it->server);
45
+ free((void *)it->server);
45
46
  it->server = NULL;
47
+ free((void *)it->local);
48
+ it->local = NULL;
49
+ free((void *)it->id);
50
+ it->id = NULL;
46
51
  }
47
52
  }
48
53
  }
@@ -73,23 +78,6 @@ refcnt_dtor_ping(mc_PACKET *pkt)
73
78
  }
74
79
  }
75
80
 
76
- static std::string latency_to_string(lcb_U64 latency)
77
- {
78
- std::stringstream ss;
79
- ss.precision(3);
80
- ss.setf(std::ios::fixed);
81
- if (latency < 1000) {
82
- ss << latency << "ns";
83
- } else if (latency < LCB_US2NS(1000)) {
84
- ss << (latency / (double)LCB_US2NS(1)) << "us";
85
- } else if (latency < LCB_MS2NS(1000)) {
86
- ss << (latency / (double)LCB_MS2NS(1)) << "ms";
87
- } else {
88
- ss << (latency / (double)LCB_S2NS(1)) << "s";
89
- }
90
- return ss.str();
91
- }
92
-
93
81
  static const char* svc_to_string(lcb_PINGSVCTYPE type)
94
82
  {
95
83
  switch (type) {
@@ -107,21 +95,55 @@ static const char* svc_to_string(lcb_PINGSVCTYPE type)
107
95
  }
108
96
 
109
97
  static void
110
- build_ping_json(lcb_RESPPING &ping, Json::Value &root, bool details)
98
+ build_ping_json(lcb_t instance, lcb_RESPPING &ping, Json::Value &root, PingCookie *ck)
111
99
  {
112
100
  Json::Value services;
113
101
  for (size_t ii = 0; ii < ping.nservices; ii++) {
114
102
  lcb_PINGSVC &svc = ping.services[ii];
115
103
  Json::Value service;
116
- service["server"] = svc.server;
117
- service["latency"] = latency_to_string(svc.latency);
118
- service["status"] = svc.status;
119
- if (details) {
120
- service["details"] = lcb_strerror(NULL, svc.status);
104
+ service["remote"] = svc.server;
105
+ if (svc.local) {
106
+ service["local"] = svc.local;
107
+ }
108
+ if (svc.id) {
109
+ service["id"] = svc.id;
110
+ }
111
+ if (svc.scope) {
112
+ service["scope"] = svc.scope;
113
+ }
114
+
115
+ service["latency_us"] = (Json::Value::UInt64)LCB_NS2US(svc.latency);
116
+ switch (svc.status) {
117
+ case LCB_PINGSTATUS_OK:
118
+ service["status"] = "ok";
119
+ break;
120
+ case LCB_PINGSTATUS_TIMEOUT:
121
+ service["status"] = "timeout";
122
+ break;
123
+ default:
124
+ service["status"] = "error";
125
+ if (ck->needDetails()) {
126
+ service["details"] = lcb_strerror_long(svc.rc);
127
+ }
121
128
  }
122
129
  services[svc_to_string(svc.type)].append(service);
123
130
  }
124
131
  root["services"] = services;
132
+ root["version"] = 1;
133
+
134
+ std::string sdk("libcouchbase/" LCB_VERSION_STRING);
135
+ if (LCBT_SETTING(instance, client_string)) {
136
+ sdk.append(" ").append(LCBT_SETTING(instance, client_string));
137
+ }
138
+ root["sdk"] = sdk.c_str();
139
+ root["id"] = ck->id;
140
+
141
+ int config_rev = -1;
142
+ if (instance->cur_configinfo) {
143
+ lcb::clconfig::ConfigInfo *cfg = instance->cur_configinfo;
144
+ config_rev = cfg->vbc->revid;
145
+ }
146
+ root["config_rev"] = config_rev;
125
147
  }
126
148
 
127
149
  static void
@@ -139,7 +161,7 @@ invoke_ping_callback(lcb_t instance, PingCookie *ck)
139
161
  }
140
162
  if (ck->needJSON()) {
141
163
  Json::Value root;
142
- build_ping_json(ping, root, ck->needDetails());
164
+ build_ping_json(instance, ping, root, ck);
143
165
  Json::Writer *w;
144
166
  if (ck->needPretty()) {
145
167
  w = new Json::StyledWriter();
@@ -169,15 +191,38 @@ handle_ping(mc_PIPELINE *pipeline, mc_PACKET *req, lcb_error_t err, const void *
169
191
  PingCookie *ck = (PingCookie *)req->u_rdata.exdata;
170
192
 
171
193
  if (ck->needMetrics()) {
172
- std::string hh(server->get_host().host);
173
- hh.append(":");
174
- hh.append(server->get_host().port);
175
-
176
- lcb_PINGSVC svc;
194
+ const lcb_host_t &remote = server->get_host();
195
+ std::string hh;
196
+ if (remote.ipv6) {
197
+ hh.append("[").append(remote.host).append("]:").append(remote.port);
198
+ } else {
199
+ hh.append(remote.host).append(":").append(remote.port);
200
+ }
201
+ lcb_PINGSVC svc = {};
177
202
  svc.type = LCB_PINGSVC_KV;
178
203
  svc.server = strdup(hh.c_str());
179
204
  svc.latency = gethrtime() - MCREQ_PKT_RDATA(req)->start;
180
- svc.status = err;
205
+ svc.rc = err;
206
+ switch (err) {
207
+ case LCB_ETIMEDOUT:
208
+ svc.status = LCB_PINGSTATUS_TIMEOUT;
209
+ break;
210
+ case LCB_SUCCESS:
211
+ svc.status = LCB_PINGSTATUS_OK;
212
+ break;
213
+ default:
214
+ svc.status = LCB_PINGSTATUS_ERROR;
215
+ break;
216
+ }
217
+ lcbio_CTX *ctx = server->connctx;
218
+ if (ctx) {
219
+ char id[20] = {0};
220
+ svc.local = strdup(lcbio__inet_ntop(&ctx->sock->info->sa_local).c_str());
221
+ snprintf(id, sizeof(id), "%p", (void *)ctx->sock);
222
+ svc.id = strdup(id);
223
+ }
224
+ svc.scope = server->get_instance()->get_bucketname();
225
+
181
226
  ck->responses.push_back(svc);
182
227
  }
183
228
 
@@ -196,11 +241,35 @@ static void handle_http(lcb_t instance, lcb_PINGSVCTYPE type, const lcb_RESPHTTP
196
241
  lcb::http::Request *htreq = reinterpret_cast<lcb::http::Request*>(resp->_htreq);
197
242
 
198
243
  if (ck->needMetrics()) {
199
- lcb_PINGSVC svc;
244
+ lcb_PINGSVC svc = {};
200
245
  svc.type = type;
201
- svc.server = strdup((htreq->host + ":" + htreq->port).c_str());
246
+ std::string hh;
247
+ if (htreq->ipv6) {
248
+ hh = "[" + std::string(htreq->host) + "]:" + std::string(htreq->port);
249
+ } else {
250
+ hh = std::string(htreq->host) + ":" + std::string(htreq->port);
251
+ }
252
+ svc.server = strdup(hh.c_str());
202
253
  svc.latency = gethrtime() - htreq->start;
203
- svc.status = resp->rc;
254
+ svc.rc = resp->rc;
255
+ switch (resp->rc) {
256
+ case LCB_ETIMEDOUT:
257
+ svc.status = LCB_PINGSTATUS_TIMEOUT;
258
+ break;
259
+ case LCB_SUCCESS:
260
+ svc.status = LCB_PINGSTATUS_OK;
261
+ break;
262
+ default:
263
+ svc.status = LCB_PINGSTATUS_ERROR;
264
+ break;
265
+ }
266
+ lcbio_CTX *ctx = htreq->ioctx;
267
+ if (ctx) {
268
+ char id[20] = {0};
269
+ snprintf(id, sizeof(id), "%p", (void *)ctx->sock);
270
+ svc.id = strdup(id);
271
+ svc.local = strdup(lcbio__inet_ntop(&ctx->sock->info->sa_local).c_str());
272
+ }
204
273
  ck->responses.push_back(svc);
205
274
  }
206
275
  if (--ck->remaining) {
@@ -236,9 +305,25 @@ lcb_ping3(lcb_t instance, const void *cookie, const lcb_CMDPING *cmd)
236
305
  }
237
306
 
238
307
  PingCookie *ckwrap = new PingCookie(cookie, cmd->options);
308
+ {
309
+ char id[20] = {0};
310
+ snprintf(id, sizeof(id), "%p", (void *)instance);
311
+ ckwrap->id = id;
312
+ if (cmd->id) {
313
+ ckwrap->id.append("/").append(cmd->id);
314
+ }
315
+ }
239
316
 
317
+ lcbvb_CONFIG *cfg = LCBT_VBCONFIG(instance);
318
+ const lcbvb_SVCMODE mode = LCBT_SETTING(instance, sslopts) ?
319
+ LCBVB_SVCMODE_SSL : LCBVB_SVCMODE_PLAIN;
240
320
  if (cmd->services & LCB_PINGSVC_F_KV) {
241
321
  for (ii = 0; ii < cq->npipelines; ii++) {
322
+ unsigned port = lcbvb_get_port(cfg, ii, LCBVB_SVCTYPE_DATA, mode);
323
+ if (!port) {
324
+ continue;
325
+ }
326
+
242
327
  mc_PIPELINE *pl = cq->pipelines[ii];
243
328
  mc_PACKET *pkt = mcreq_allocate_packet(pl);
244
329
  protocol_binary_request_header hdr;
@@ -262,46 +347,43 @@ lcb_ping3(lcb_t instance, const void *cookie, const lcb_CMDPING *cmd)
262
347
  }
263
348
  }
264
349
 
265
- lcbvb_CONFIG *cfg = LCBT_VBCONFIG(instance);
266
- const lcbvb_SVCMODE mode = LCBT_SETTING(instance, sslopts) ?
267
- LCBVB_SVCMODE_SSL : LCBVB_SVCMODE_PLAIN;
268
350
  for (int idx = 0; idx < (int)LCBVB_NSERVERS(cfg); idx++) {
269
- #define PING_HTTP(SVC, QUERY, TMO, CB) \
270
- do { \
271
- lcb_error_t rc; \
272
- struct lcb_http_request_st *htreq; \
273
- lcb_CMDHTTP htcmd = {0}; \
274
- htcmd.host = lcbvb_get_resturl(cfg, idx, SVC, mode); \
275
- if (htcmd.host == NULL) { \
276
- continue; \
277
- } \
278
- htcmd.body = QUERY; \
279
- htcmd.nbody = strlen(htcmd.body); \
280
- htcmd.content_type = "application/json"; \
281
- htcmd.method = LCB_HTTP_METHOD_POST; \
282
- htcmd.type = LCB_HTTP_TYPE_RAW; \
283
- htcmd.reqhandle = &htreq; \
284
- const lcb::Authenticator& auth = *instance->settings->auth; \
285
- htcmd.username = auth.username_for(LCBT_SETTING(instance, bucket)).c_str(); \
286
- htcmd.password = auth.password_for(LCBT_SETTING(instance, bucket)).c_str(); \
287
- htcmd.cmdflags = LCB_CMDHTTP_F_CASTMO; \
288
- htcmd.cas = LCBT_SETTING(instance, TMO); \
289
- rc = lcb_http3(instance, ckwrap, &htcmd); \
290
- if (rc == LCB_SUCCESS) { \
291
- htreq->set_callback(CB); \
292
- } \
293
- ckwrap->remaining++; \
294
- } while (0);
351
+ #define PING_HTTP(SVC, PATH, TMO, CB) \
352
+ lcb_error_t rc; \
353
+ struct lcb_http_request_st *htreq; \
354
+ lcb_CMDHTTP htcmd = {0}; \
355
+ char buf[1024] = {0}; \
356
+ unsigned port; \
357
+ port = lcbvb_get_port(cfg, idx, SVC, mode); \
358
+ if (port) { \
359
+ lcbvb_SERVER *srv = LCBVB_GET_SERVER(cfg, idx); \
360
+ bool ipv6 = strchr(srv->hostname, ':'); \
361
+ snprintf(buf, sizeof(buf), "%s://%s%s%s:%d%s", (mode == LCBVB_SVCMODE_PLAIN) ? "http" : "https", \
362
+ ipv6 ? "[" : "", srv->hostname, ipv6 ? "]" : "", port, PATH); \
363
+ htcmd.host = buf; \
364
+ htcmd.method = LCB_HTTP_METHOD_GET; \
365
+ htcmd.type = LCB_HTTP_TYPE_RAW; \
366
+ htcmd.reqhandle = &htreq; \
367
+ const lcb::Authenticator& auth = *instance->settings->auth; \
368
+ htcmd.username = auth.username_for(NULL, NULL, LCBT_SETTING(instance, bucket)).c_str(); \
369
+ htcmd.password = auth.password_for(NULL, NULL, LCBT_SETTING(instance, bucket)).c_str(); \
370
+ htcmd.cmdflags = LCB_CMDHTTP_F_CASTMO; \
371
+ htcmd.cas = LCBT_SETTING(instance, TMO); \
372
+ rc = lcb_http3(instance, ckwrap, &htcmd); \
373
+ if (rc == LCB_SUCCESS) { \
374
+ htreq->set_callback(CB); \
375
+ ckwrap->remaining++; \
376
+ } \
377
+ }
295
378
 
296
379
  if (cmd->services & LCB_PINGSVC_F_N1QL) {
297
- PING_HTTP(LCBVB_SVCTYPE_N1QL, "{\"statement\":\"select 1\"}",
298
- n1ql_timeout, handle_n1ql);
380
+ PING_HTTP(LCBVB_SVCTYPE_N1QL, "/admin/ping", n1ql_timeout, handle_n1ql);
299
381
  }
300
382
  if (cmd->services & LCB_PINGSVC_F_VIEWS) {
301
- PING_HTTP(LCBVB_SVCTYPE_VIEWS, "", views_timeout, handle_views);
383
+ PING_HTTP(LCBVB_SVCTYPE_VIEWS, "/", views_timeout, handle_views);
302
384
  }
303
385
  if (cmd->services & LCB_PINGSVC_F_FTS) {
304
- PING_HTTP(LCBVB_SVCTYPE_FTS, "", n1ql_timeout, handle_fts);
386
+ PING_HTTP(LCBVB_SVCTYPE_FTS, "/api/ping", http_timeout, handle_fts);
305
387
  }
306
388
  #undef PING_HTTP
307
389
  }
@@ -313,3 +395,100 @@ lcb_ping3(lcb_t instance, const void *cookie, const lcb_CMDPING *cmd)
313
395
  MAYBE_SCHEDLEAVE(instance);
314
396
  return LCB_SUCCESS;
315
397
  }
398
+
399
+
400
+ LIBCOUCHBASE_API
401
+ lcb_error_t
402
+ lcb_diag(lcb_t instance, const void *cookie, const lcb_CMDDIAG *cmd)
403
+ {
404
+ Json::Value root;
405
+ hrtime_t now = LCB_NS2US(gethrtime());
406
+
407
+ root["version"] = 1;
408
+
409
+ std::string sdk("libcouchbase/" LCB_VERSION_STRING);
410
+ if (LCBT_SETTING(instance, client_string)) {
411
+ sdk.append(" ").append(LCBT_SETTING(instance, client_string));
412
+ }
413
+ root["sdk"] = sdk.c_str();
414
+ {
415
+ char id[20] = {0};
416
+ snprintf(id, sizeof(id), "%p", (void *)instance);
417
+ std::string idstr(id);
418
+ if (cmd->id) {
419
+ idstr.append("/").append(cmd->id);
420
+ }
421
+ root["id"] = idstr;
422
+ }
423
+
424
+ size_t ii;
425
+ Json::Value kv;
426
+ for (ii = 0; ii < instance->cmdq.npipelines; ii++) {
427
+ lcb::Server *server = static_cast<lcb::Server*>(instance->cmdq.pipelines[ii]);
428
+ lcbio_CTX *ctx = server->connctx;
429
+ if (ctx) {
430
+ Json::Value endpoint;
431
+ char id[20] = {0};
432
+ snprintf(id, sizeof(id), "%016" PRIx64, ctx->sock ? ctx->sock->id : (lcb_U64)0);
433
+ endpoint["id"] = id;
434
+ if (server->curhost->ipv6) {
435
+ endpoint["remote"] = "[" + std::string(server->curhost->host) + "]:" + std::string(server->curhost->port);
436
+ } else {
437
+ endpoint["remote"] = std::string(server->curhost->host) + ":" + std::string(server->curhost->port);
438
+ }
439
+ endpoint["local"] = lcbio__inet_ntop(&ctx->sock->info->sa_local);
440
+ endpoint["last_activity_us"] = (Json::Value::UInt64)(now > ctx->sock->atime ? now - ctx->sock->atime : 0);
441
+ endpoint["status"] = "connected";
442
+ root[lcbio_svcstr(ctx->sock->service)].append(endpoint);
443
+ }
444
+ }
445
+ instance->memd_sockpool->toJSON(now, root);
446
+ instance->http_sockpool->toJSON(now, root);
447
+ {
448
+ Json::Value cur;
449
+ lcb_ASPEND_SETTYPE::iterator it;
450
+ lcb_ASPEND_SETTYPE *pendq;
451
+ if ((pendq = instance->pendops.items[LCB_PENDTYPE_HTTP])) {
452
+ for (it = pendq->begin(); it != pendq->end(); ++it) {
453
+ lcb::http::Request *htreq = reinterpret_cast<lcb::http::Request*>(*it);
454
+ lcbio_CTX *ctx = htreq->ioctx;
455
+ if (ctx) {
456
+ Json::Value endpoint;
457
+ char id[20] = {0};
458
+ snprintf(id, sizeof(id), "%016" PRIx64, ctx->sock ? ctx->sock->id : (lcb_U64)0);
459
+ endpoint["id"] = id;
460
+ if (htreq->ipv6) {
461
+ endpoint["remote"] = "[" + std::string(htreq->host) + "]:" + std::string(htreq->port);
462
+ } else {
463
+ endpoint["remote"] = std::string(htreq->host) + ":" + std::string(htreq->port);
464
+ }
465
+ endpoint["local"] = lcbio__inet_ntop(&ctx->sock->info->sa_local);
466
+ endpoint["last_activity_us"] = (Json::Value::UInt64)(now > ctx->sock->atime ? now - ctx->sock->atime : 0);
467
+ endpoint["status"] = "connected";
468
+ root[lcbio_svcstr(ctx->sock->service)].append(endpoint);
469
+ }
470
+ }
471
+ }
472
+ }
473
+
474
+ Json::Writer *w;
475
+ if (cmd->options & LCB_PINGOPT_F_JSONPRETTY) {
476
+ w = new Json::StyledWriter();
477
+ } else {
478
+ w = new Json::FastWriter();
479
+ }
480
+ std::string json = w->write(root);
481
+ delete w;
482
+
483
+ lcb_RESPDIAG resp = {0};
484
+ lcb_RESPCALLBACK callback;
485
+
486
+ resp.njson = json.size();
487
+ resp.json = json.c_str();
488
+
489
+ callback = lcb_find_callback(instance, LCB_CALLBACK_DIAG);
490
+ resp.cookie = const_cast<void*>(cookie);
491
+ callback(instance, LCB_CALLBACK_DIAG, (lcb_RESPBASE *)&resp);
492
+
493
+ return LCB_SUCCESS;
494
+ }