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
@@ -16,6 +16,7 @@
16
16
  */
17
17
 
18
18
  #include "mcreq.h"
19
+ #include "settings.h"
19
20
  #ifndef LCB_MCCOMPRESS_H
20
21
  #define LCB_MCCOMPRESS_H
21
22
 
@@ -28,11 +29,12 @@ extern "C" {
28
29
  * @param pl The pipeline which hosts the packet
29
30
  * @param pkt The packet which hosts the value
30
31
  * @param vbuf The user input to be compressed
32
+ * @param settings The instance settings
33
+ * @param should_compress The pointer, which stores zero if the value is not compressed
31
34
  * @return 0 if successful, nonzero on error.
32
35
  */
33
- int
34
- mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_CONTIGBUF *vbuf);
35
-
36
+ int mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_VALBUF *vbuf, lcb_settings *settings,
37
+ int *should_compress);
36
38
 
37
39
  /**
38
40
  * Inflate a compressed value
@@ -45,15 +47,8 @@ mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_CONTIGBUF *vbuf)
45
47
  * longer required.
46
48
  * @return 0 if successful, nonzero on error.
47
49
  */
48
- int
49
- mcreq_inflate_value(const void *compressed, lcb_SIZE ncompressed,
50
- const void **bytes, lcb_SIZE *nbytes, void **freeptr);
51
-
52
- #ifndef LCB_NO_SNAPPY
53
- #define mcreq_compression_supported() 1
54
- #else
55
- #define mcreq_compression_supported() 0
56
- #endif
50
+ int mcreq_inflate_value(const void *compressed, lcb_SIZE ncompressed, const void **bytes, lcb_SIZE *nbytes,
51
+ void **freeptr);
57
52
 
58
53
  #ifdef __cplusplus
59
54
  }
@@ -67,6 +67,11 @@ mcreq__pktflush_callback(void *p, nb_SIZE hint, void *arg)
67
67
  if (pkt->flags & MCREQ_F_INVOKED) {
68
68
  mcreq_packet_done(info->pl, pkt);
69
69
  }
70
+ if (info->pl->metrics) {
71
+ info->pl->metrics->packets_sent++;
72
+ info->pl->metrics->packets_queued--;
73
+ info->pl->metrics->bytes_queued -= pktsize;
74
+ }
70
75
  return pktsize;
71
76
  }
72
77
 
@@ -89,7 +94,6 @@ mcreq_flush_done_ex(mc_PIPELINE *pl,
89
94
  {
90
95
  if (nflushed) {
91
96
  mc__FLUSHINFO info = { pl, now };
92
-
93
97
  netbuf_end_flush2(&pl->nbmgr, nflushed,
94
98
  mcreq__pktflush_callback,
95
99
  offsetof(mc_PACKET, sl_flushq), &info);
@@ -206,6 +206,7 @@ mcreq_enqueue_packet(mc_PIPELINE *pipeline, mc_PACKET *packet)
206
206
  nb_SPAN *vspan = &packet->u_value.single;
207
207
  sllist_append(&pipeline->requests, &packet->slnode);
208
208
  netbuf_enqueue_span(&pipeline->nbmgr, &packet->kh_span);
209
+ MC_INCR_METRIC(pipeline, bytes_queued, packet->kh_span.size);
209
210
 
210
211
  if (!(packet->flags & MCREQ_F_HASVALUE)) {
211
212
  goto GT_ENQUEUE_PDU;
@@ -216,14 +217,17 @@ mcreq_enqueue_packet(mc_PIPELINE *pipeline, mc_PACKET *packet)
216
217
  lcb_FRAGBUF *multi = &packet->u_value.multi;
217
218
  for (ii = 0; ii < multi->niov; ii++) {
218
219
  netbuf_enqueue(&pipeline->nbmgr, (nb_IOV *)multi->iov + ii);
220
+ MC_INCR_METRIC(pipeline, bytes_queued, multi->iov[ii].iov_len);
219
221
  }
220
222
 
221
223
  } else if (vspan->size) {
224
+ MC_INCR_METRIC(pipeline, bytes_queued, vspan->size);
222
225
  netbuf_enqueue_span(&pipeline->nbmgr, vspan);
223
226
  }
224
227
 
225
228
  GT_ENQUEUE_PDU:
226
229
  netbuf_pdu_enqueue(&pipeline->nbmgr, packet, offsetof(mc_PACKET, sl_flushq));
230
+ MC_INCR_METRIC(pipeline, packets_queued, 1);
227
231
  }
228
232
 
229
233
  void
@@ -275,6 +279,9 @@ mcreq_allocate_packet(mc_PIPELINE *pipeline)
275
279
  ret->flags = 0;
276
280
  ret->retries = 0;
277
281
  ret->opaque = pipeline->parent->seq++;
282
+ #ifdef LCB_TRACING
283
+ ret->u_rdata.reqdata.span = NULL;
284
+ #endif
278
285
  return ret;
279
286
  }
280
287
 
@@ -568,6 +575,7 @@ mcreq_pipeline_init(mc_PIPELINE *pipeline)
568
575
  /** Initialize request pool */
569
576
  settings.data_basealloc = sizeof(mc_PACKET) * 32;
570
577
  netbuf_init(&pipeline->reqpool, &settings);;
578
+ pipeline->metrics = NULL;
571
579
  return 0;
572
580
  }
573
581
 
@@ -866,8 +874,10 @@ do_fallback_flush(mc_PIPELINE *pipeline)
866
874
  void
867
875
  mcreq_set_fallback_handler(mc_CMDQUEUE *cq, mcreq_fallback_cb handler)
868
876
  {
877
+ mc_FALLBACKPL *fallback;
869
878
  assert(!cq->fallback);
870
- cq->fallback = calloc(1, sizeof (mc_FALLBACKPL));
879
+ fallback = calloc(1, sizeof (mc_FALLBACKPL));
880
+ cq->fallback = (mc_PIPELINE *)fallback;
871
881
  mcreq_pipeline_init(cq->fallback);
872
882
  cq->fallback->parent = cq;
873
883
  cq->fallback->index = cq->npipelines;
@@ -22,6 +22,7 @@
22
22
  #include <libcouchbase/api3.h>
23
23
  #include <libcouchbase/vbucket.h>
24
24
  #include <memcached/protocol_binary.h>
25
+ #include <libcouchbase/metrics.h>
25
26
  #include "netbuf/netbuf.h"
26
27
  #include "sllist.h"
27
28
  #include "config.h"
@@ -141,9 +142,17 @@ extern "C" {
141
142
  #define MCREQ_PKT_BASESIZE 24
142
143
 
143
144
  /** @brief Embedded user data for a simple request. */
144
- typedef struct {
145
+ typedef struct mc_REQDATA {
145
146
  const void *cookie; /**< User pointer to place in callbacks */
146
147
  hrtime_t start; /**< Time of the initial request. Used for timeouts */
148
+ /**
149
+ * Time when dispatching response has begun for the command.
150
+ * Used for metrics/tracing. Might be zero, when tracing is not enabled.
151
+ */
152
+ hrtime_t dispatch;
153
+ #ifdef LCB_TRACING
154
+ lcbtrace_SPAN *span;
155
+ #endif
147
156
  } mc_REQDATA;
148
157
 
149
158
  struct mc_packet_st;
@@ -182,12 +191,24 @@ typedef struct {
182
191
  typedef struct mc_REQDATAEX {
183
192
  const void *cookie; /**< User data */
184
193
  hrtime_t start; /**< Start time */
194
+ /**
195
+ * Time when dispatching response has begun for the command.
196
+ * Used for metrics/tracing. Might be zero, when tracing is not enabled.
197
+ */
198
+ hrtime_t dispatch;
199
+ #ifdef LCB_TRACING
200
+ lcbtrace_SPAN *span;
201
+ #endif
185
202
  const mc_REQDATAPROCS *procs; /**< Common routines for the packet */
186
203
 
187
204
  #ifdef __cplusplus
188
- mc_REQDATAEX(const void *cookie_,
189
- const mc_REQDATAPROCS &procs_, hrtime_t start_)
190
- : cookie(cookie_), start(start_), procs(&procs_) {
205
+ mc_REQDATAEX(const void *cookie_, const mc_REQDATAPROCS &procs_, hrtime_t start_)
206
+ : cookie(cookie_), start(start_), dispatch(0),
207
+ #ifdef LCB_TRACING
208
+ span(NULL),
209
+ #endif
210
+ procs(&procs_)
211
+ {
191
212
  }
192
213
  #endif
193
214
  } mc_REQDATAEX;
@@ -400,6 +421,9 @@ typedef struct mc_pipeline_st {
400
421
 
401
422
  /** Allocator for packet structures */
402
423
  nb_MGR reqpool;
424
+
425
+ /** Optional metrics structure for server */
426
+ struct lcb_SERVERMETRICS_st *metrics;
403
427
  } mc_PIPELINE;
404
428
 
405
429
  typedef struct mc_cmdqueue_st {
@@ -976,6 +1000,13 @@ mcreq_dump_chain(const mc_PIPELINE *pipeline, FILE *fp, mcreq_payload_dump_fn du
976
1000
  SLLIST_IS_EMPTY(&(pipeline)->requests) ? NULL : \
977
1001
  SLLIST_ITEM(SLLIST_FIRST(&(pipeline)->requests), mc_PACKET, slnode)
978
1002
 
1003
+ /* Increment a metric */
1004
+ #define MC_INCR_METRIC(pipeline, metric, amount) do { \
1005
+ if ((pipeline)->metrics) { \
1006
+ (pipeline)->metrics->metric += amount; \
1007
+ } \
1008
+ } while (0)
1009
+
979
1010
  /**@}*/
980
1011
 
981
1012
  #ifdef __cplusplus
@@ -28,11 +28,11 @@
28
28
  #define LOGARGS(c, lvl) (c)->settings, "server", LCB_LOG_##lvl, __FILE__, __LINE__
29
29
  #define LOGARGS_T(lvl) LOGARGS(this, lvl)
30
30
 
31
- #define LOGFMT "<%s:%s> (SRV=%p,IX=%d) "
31
+ #define LOGFMT CTX_LOGFMT_PRE ",SRV=%p,IX=%d) "
32
32
  #define PKTFMT "OP=0x%x, RC=0x%x, SEQ=%u"
33
33
  #define PKTARGS(pkt) (pkt).opcode(), (pkt).status(), (pkt).opaque()
34
34
 
35
- #define LOGID(server) get_ctx_host(server->connctx), get_ctx_port(server->connctx), (void*)server, server->index
35
+ #define LOGID(server) CTX_LOGID(server->connctx), (void *)server, server->index
36
36
  #define LOGID_T() LOGID(this)
37
37
 
38
38
  #define MCREQ_MAXIOV 32
@@ -125,6 +125,8 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
125
125
  lcb::clconfig::Provider *cccp =
126
126
  instance->confmon->get_provider(lcb::clconfig::CLCONFIG_CCCP);
127
127
 
128
+ MC_INCR_METRIC(this, packets_nmv, 1);
129
+
128
130
  mcreq_read_hdr(oldpkt, &hdr);
129
131
  vbid = ntohs(hdr.request.vbucket);
130
132
  lcb_log(LOGARGS_T(WARN), LOGFMT "NOT_MY_VBUCKET. Packet=%p (S=%u). VBID=%u", LOGID_T(), (void*)oldpkt, oldpkt->opaque, vbid);
@@ -132,8 +134,8 @@ Server::handle_nmv(MemcachedResponse& resinfo, mc_PACKET *oldpkt)
132
134
  /* Notify of new map */
133
135
  lcb_vbguess_remap(instance, vbid, index);
134
136
 
135
- if (resinfo.bodylen() && cccp->enabled) {
136
- std::string s(resinfo.body<const char*>(), resinfo.vallen());
137
+ if (resinfo.vallen() && cccp->enabled) {
138
+ std::string s(resinfo.value(), resinfo.vallen());
137
139
  err = lcb::clconfig::cccp_update(cccp, curhost->host, s.c_str());
138
140
  }
139
141
 
@@ -334,6 +336,8 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
334
336
  RETURN_NEED_MORE(pktsize)
335
337
  }
336
338
 
339
+ MC_INCR_METRIC(this, packets_read, 1);
340
+
337
341
  /* copy bytes into the info structure */
338
342
  rdb_copyread(ior, mcresp.hdrbytes(), mcresp.hdrsize());
339
343
 
@@ -352,6 +356,7 @@ Server::try_read(lcbio_CTX *ctx, rdb_IOROPE *ior)
352
356
  }
353
357
 
354
358
  if (!request) {
359
+ MC_INCR_METRIC(this, packets_ownerless, 1);
355
360
  lcb_log(LOGARGS_T(WARN), LOGFMT "Server sent us reply for a timed-out command. (OP=0x%x, RC=0x%x, SEQ=%u)", LOGID_T(), mcresp.opcode(), mcresp.status(), mcresp.opaque());
356
361
  rdb_consumed(ior, pktsize);
357
362
  return PKT_READ_COMPLETE;
@@ -494,6 +499,9 @@ void Server::purge_single(mc_PACKET *pkt, lcb_error_t err) {
494
499
  hdr.request.opaque,
495
500
  PROTOCOL_BINARY_RESPONSE_EINVAL);
496
501
 
502
+ #ifdef LCB_TRACING
503
+ lcbtrace_span_set_orphaned(MCREQ_PKT_RDATA(pkt)->span, true);
504
+ #endif
497
505
  lcb_log(LOGARGS_T(WARN), LOGFMT "Failing command (pkt=%p, opaque=%lu, opcode=0x%x) with error %s", LOGID_T(), (void*)pkt, (unsigned long)pkt->opaque, hdr.request.opcode, lcb_strerror_short(err));
498
506
  int rv = mcreq_dispatch_response(this, pkt, &resp, err);
499
507
  lcb_assert(rv == 0);
@@ -514,6 +522,7 @@ Server::purge(lcb_error_t error, hrtime_t thresh, hrtime_t *next,
514
522
  affected = -1;
515
523
  }
516
524
 
525
+ MC_INCR_METRIC(this, packets_errored, affected);
517
526
  if (policy == REFRESH_NEVER) {
518
527
  return affected;
519
528
  }
@@ -569,6 +578,7 @@ void Server::io_timeout()
569
578
  int npurged = purge(LCB_ETIMEDOUT, min_valid, &next_ns,
570
579
  Server::REFRESH_ONFAILED);
571
580
  if (npurged) {
581
+ MC_INCR_METRIC(this, packets_timeout, npurged);
572
582
  lcb_log(LOGARGS_T(ERR), LOGFMT "Server timed out. Some commands have failed", LOGID_T());
573
583
  }
574
584
 
@@ -619,6 +629,7 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
619
629
 
620
630
  if (err != LCB_SUCCESS) {
621
631
  lcb_log(LOGARGS_T(ERR), LOGFMT "Connection attempt failed. Received %s from libcouchbase, received %d from operating system", LOGID_T(), lcb_strerror_short(err), syserr);
632
+ MC_INCR_METRIC(this, iometrics.io_error, 1);
622
633
  if (!maybe_reconnect_on_fake_timeout(err)) {
623
634
  socket_failed(err);
624
635
  }
@@ -626,6 +637,9 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
626
637
  }
627
638
 
628
639
  lcb_assert(sock);
640
+ if (metrics) {
641
+ lcbio_set_metrics(sock, &metrics->iometrics);
642
+ }
629
643
 
630
644
  /** Do we need sasl? */
631
645
  SessionInfo* sessinfo = SessionInfo::get(sock);
@@ -635,7 +649,8 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
635
649
  sock, settings, default_timeout(), on_connected, this);
636
650
  return;
637
651
  } else {
638
- compsupport = sessinfo->has_feature(PROTOCOL_BINARY_FEATURE_DATATYPE);
652
+ jsonsupport = sessinfo->has_feature(PROTOCOL_BINARY_FEATURE_JSON);
653
+ compsupport = sessinfo->has_feature(PROTOCOL_BINARY_FEATURE_SNAPPY);
639
654
  mutation_tokens = sessinfo->has_feature(PROTOCOL_BINARY_FEATURE_MUTATION_SEQNO);
640
655
  }
641
656
 
@@ -646,6 +661,7 @@ Server::handle_connected(lcbio_SOCKET *sock, lcb_error_t err, lcbio_OSERR syserr
646
661
  procs.cb_flush_ready = on_flush_ready;
647
662
  connctx = lcbio_ctx_new(sock, this, &procs);
648
663
  connctx->subsys = "memcached";
664
+ sock->service = LCBIO_SERVICE_KV;
649
665
  flush_start = (mcreq_flushstart_fn)mcserver_flush;
650
666
 
651
667
  uint32_t tmo = next_timeout();
@@ -675,6 +691,7 @@ Server::Server(lcb_t instance_, int ix)
675
691
  instance(instance_),
676
692
  settings(lcb_settings_ref2(instance_->settings)),
677
693
  compsupport(0),
694
+ jsonsupport(0),
678
695
  mutation_tokens(0),
679
696
  connctx(NULL),
680
697
  curhost(new lcb_host_t())
@@ -694,11 +711,17 @@ Server::Server(lcb_t instance_, int ix)
694
711
  if (datahost) {
695
712
  lcb_host_parsez(curhost, datahost, LCB_CONFIG_MCD_PORT);
696
713
  }
714
+
715
+ if (settings->metrics) {
716
+ /** Allocate / reinitialize the metrics here */
717
+ metrics = lcb_metrics_getserver(settings->metrics, curhost->host, curhost->port, 1);
718
+ lcb_metrics_reset_pipeline_gauges(metrics);
719
+ }
697
720
  }
698
721
 
699
722
  Server::Server()
700
723
  : state(S_TEMPORARY),
701
- io_timer(NULL), instance(NULL), settings(NULL), compsupport(0),
724
+ io_timer(NULL), instance(NULL), settings(NULL), compsupport(0), jsonsupport(0),
702
725
  mutation_tokens(0), connctx(NULL), connreq(NULL), curhost(NULL)
703
726
  {
704
727
  }
@@ -829,7 +852,7 @@ Server::finalize_errored_ctx()
829
852
  return;
830
853
  }
831
854
 
832
- lcb_log(LOGARGS_T(DEBUG), LOGFMT "Finalizing ctx %p", LOGID_T(), (void*)connctx);
855
+ lcb_log(LOGARGS_T(DEBUG), LOGFMT "Finalizing context", LOGID_T());
833
856
 
834
857
  /* Always close the existing context. */
835
858
  lcbio_ctx_close(connctx, close_cb, NULL);
@@ -110,6 +110,10 @@ public:
110
110
  return compsupport;
111
111
  }
112
112
 
113
+ bool supports_json() const {
114
+ return jsonsupport;
115
+ }
116
+
113
117
  bool is_connected() const {
114
118
  return connctx != NULL;
115
119
  }
@@ -200,6 +204,9 @@ public:
200
204
  /** Whether compression is supported */
201
205
  short compsupport;
202
206
 
207
+ /** Whether JSON datatype is supported */
208
+ short jsonsupport;
209
+
203
210
  /** Whether extended 'UUID' and 'seqno' are available for each mutation */
204
211
  short mutation_tokens;
205
212
 
@@ -37,12 +37,12 @@ using namespace lcb;
37
37
  #define LOGARGS(ctx, lvl) ctx->settings, "negotiation", LCB_LOG_##lvl, __FILE__, __LINE__
38
38
  static void cleanup_negotiated(SessionInfo* info);
39
39
  static void handle_ioerr(lcbio_CTX *ctx, lcb_error_t err);
40
- #define SESSREQ_LOGFMT "<%s:%s> (SASLREQ=%p) "
41
40
 
41
+ #define LOGFMT CTX_LOGFMT_PRE ",SASLREQ=%p) "
42
+ #define LOGID(s) CTX_LOGID(s->ctx), (void *)s
42
43
 
43
44
  static void timeout_handler(void *arg);
44
45
 
45
- #define SESSREQ_LOGID(s) get_ctx_host(s->ctx), get_ctx_port(s->ctx), (void*)s
46
46
 
47
47
  static void
48
48
  close_cb(lcbio_SOCKET *s, int reusable, void *arg)
@@ -67,8 +67,10 @@ public:
67
67
  const lcb::Authenticator& auth);
68
68
  void start(lcbio_SOCKET *sock);
69
69
  void send_list_mechs();
70
+ std::string generate_agent_json();
70
71
  bool send_hello();
71
72
  bool send_step(const lcb::MemcachedResponse& packet);
73
+ bool check_auth(const lcb::MemcachedResponse& packet);
72
74
  bool read_hello(const lcb::MemcachedResponse& packet);
73
75
  void send_auth(const char *sasl_data, unsigned ndata);
74
76
  void handle_read(lcbio_CTX *ioctx);
@@ -144,12 +146,12 @@ public:
144
146
  }
145
147
  emsg << "context: \"" << err_ctx << "\"";
146
148
  }
147
- lcb_log(LOGARGS(this, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s (%s)",
148
- SESSREQ_LOGID(this), error, msg, emsg.str().c_str());
149
+ lcb_log(LOGARGS(this, ERR), LOGFMT "Error: 0x%x, %s (%s)",
150
+ LOGID(this), error, msg, emsg.str().c_str());
149
151
  free(err_ref);
150
152
  free(err_ctx);
151
153
  } else {
152
- lcb_log(LOGARGS(this, ERR), SESSREQ_LOGFMT "Error: 0x%x, %s", SESSREQ_LOGID(this), error, msg);
154
+ lcb_log(LOGARGS(this, ERR), LOGFMT "Error: 0x%x, %s", LOGID(this), error, msg);
153
155
  }
154
156
  if (last_err == LCB_SUCCESS) {
155
157
  last_err = error;
@@ -236,8 +238,8 @@ SessionRequestImpl::setup(const lcbio_NAMEINFO& nistrs, const lcb_host_t& host,
236
238
  }
237
239
 
238
240
  // Get the credentials
239
- username = auth.username_for(settings->bucket);
240
- const std::string& pass = auth.password_for(settings->bucket);
241
+ username = auth.username_for(host.host, host.port, settings->bucket);
242
+ const std::string pass = auth.password_for(host.host, host.port, settings->bucket);
241
243
 
242
244
  if (!pass.empty()) {
243
245
  size_t maxlen = sizeof(u_auth.buffer) - offsetof(cbsasl_secret_t, data);
@@ -273,6 +275,13 @@ SessionRequestImpl::set_chosen_mech(std::string& mechlist,
273
275
  const char **data, unsigned int *ndata)
274
276
  {
275
277
  cbsasl_error_t saslerr;
278
+ int allow_scram_sha = 0;
279
+
280
+ if (mechlist.empty()) {
281
+ lcb_log(LOGARGS(this, WARN), LOGFMT "Server does not support SASL (no mechanisms supported)", LOGID(this));
282
+ return MECH_NOT_NEEDED;
283
+ }
284
+
276
285
  if (settings->sasl_mech_force) {
277
286
  char *forcemech = settings->sasl_mech_force;
278
287
  if (mechlist.find(forcemech) == std::string::npos) {
@@ -281,21 +290,22 @@ SessionRequestImpl::set_chosen_mech(std::string& mechlist,
281
290
  return MECH_UNAVAILABLE;
282
291
  }
283
292
  mechlist.assign(forcemech);
293
+ if (memcmp(forcemech, "SCRAM-SHA", sizeof("SCRAM-SHA") - 1) == 0) {
294
+ allow_scram_sha = 1;
295
+ }
284
296
  }
285
297
 
286
298
  const char *chosenmech;
287
- saslerr = cbsasl_client_start(sasl_client, mechlist.c_str(),
288
- NULL, data, ndata, &chosenmech);
299
+ saslerr = cbsasl_client_start(sasl_client, mechlist.c_str(), NULL, data, ndata, &chosenmech, allow_scram_sha);
289
300
  switch (saslerr) {
290
301
  case SASL_OK:
291
302
  info->mech.assign(chosenmech);
292
303
  return MECH_OK;
293
304
  case SASL_NOMECH:
294
- lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(this));
295
- return MECH_NOT_NEEDED;
296
- break;
305
+ lcb_log(LOGARGS(this, WARN), LOGFMT "Server does not support SASL (no mechanisms supported)", LOGID(this));
306
+ return MECH_UNAVAILABLE;
297
307
  default:
298
- lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(this), saslerr);
308
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "cbsasl_client_start returned %d", LOGID(this), saslerr);
299
309
  set_error(LCB_EINTERNAL, "Couldn't start SASL client");
300
310
  return MECH_UNAVAILABLE;
301
311
  }
@@ -323,8 +333,7 @@ SessionRequestImpl::send_step(const lcb::MemcachedResponse& packet)
323
333
  const char *step_data;
324
334
  unsigned int ndata;
325
335
 
326
- saslerr = cbsasl_client_step(sasl_client,
327
- packet.body<const char*>(), packet.bodylen(), NULL, &step_data, &ndata);
336
+ saslerr = cbsasl_client_step(sasl_client, packet.value(), packet.vallen(), NULL, &step_data, &ndata);
328
337
 
329
338
  if (saslerr != SASL_CONTINUE) {
330
339
  set_error(LCB_EINTERNAL, "Unable to perform SASL STEP");
@@ -340,8 +349,50 @@ SessionRequestImpl::send_step(const lcb::MemcachedResponse& packet)
340
349
  return true;
341
350
  }
342
351
 
343
- #define LCB_HELLO_DEFL_STRING "libcouchbase/" LCB_VERSION_STRING
344
- #define LCB_HELLO_DEFL_LENGTH (sizeof(LCB_HELLO_DEFL_STRING)-1)
352
+ std::string
353
+ SessionRequestImpl::generate_agent_json()
354
+ {
355
+ std::string client_string(LCB_CLIENT_ID);
356
+ if (settings->client_string) {
357
+ client_string += " ";
358
+ client_string += settings->client_string;
359
+ }
360
+ if (client_string.size() > 200) {
361
+ client_string.resize(200);
362
+ }
363
+ char id[34] = {};
364
+ snprintf(id, sizeof(id), "%016" PRIx64 "/%016" PRIx64, (lcb_U64)settings->iid, ctx->sock->id);
365
+
366
+ Json::Value ua;
367
+ ua["a"] = client_string;
368
+ ua["i"] = id;
369
+ Json::FastWriter w;
370
+ std::string res = w.write(ua);
371
+ if (res[res.size() - 1] == '\n') {
372
+ res.resize(res.size() - 1);
373
+ }
374
+ return res;
375
+ }
376
+
377
+ /**
378
+ * Final step for SASL authentication: in SCRAM-SHA mechanisms,
379
+ * we have to validate the server signature returned in the final
380
+ * message.
381
+ */
382
+ bool
383
+ SessionRequestImpl::check_auth(const lcb::MemcachedResponse& packet)
384
+ {
385
+ cbsasl_error_t saslerr;
386
+
387
+ saslerr = cbsasl_client_check(sasl_client,
388
+ packet.body<const char*>(), packet.bodylen());
389
+
390
+ if (saslerr != SASL_OK) {
391
+ set_error(LCB_AUTH_ERROR, "Invalid SASL check");
392
+ return false;
393
+ }
394
+ return true;
395
+ }
345
396
 
346
397
  bool
347
398
  SessionRequestImpl::send_hello()
@@ -351,6 +402,7 @@ SessionRequestImpl::send_hello()
351
402
  unsigned nfeatures = 0;
352
403
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TLS;
353
404
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XATTR;
405
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_JSON;
354
406
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_SELECT_BUCKET;
355
407
  if (settings->use_errmap) {
356
408
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_XERROR;
@@ -358,38 +410,29 @@ SessionRequestImpl::send_hello()
358
410
  if (settings->tcp_nodelay) {
359
411
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TCPNODELAY;
360
412
  }
361
-
362
- #ifndef LCB_NO_SNAPPY
363
413
  if (settings->compressopts != LCB_COMPRESS_NONE) {
364
- features[nfeatures++] = PROTOCOL_BINARY_FEATURE_DATATYPE;
414
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_SNAPPY;
365
415
  }
366
- #endif
367
-
368
416
  if (settings->fetch_mutation_tokens) {
369
417
  features[nfeatures++] = PROTOCOL_BINARY_FEATURE_MUTATION_SEQNO;
370
418
  }
371
-
372
- std::string client_string;
373
- const char *clistr = LCB_HELLO_DEFL_STRING;
374
- size_t nclistr = LCB_HELLO_DEFL_LENGTH;
375
-
376
- if (settings->client_string) {
377
- client_string.assign(LCB_HELLO_DEFL_STRING);
378
- client_string += ", ";
379
- client_string += settings->client_string;
380
-
381
- clistr = client_string.c_str();
382
- nclistr = client_string.size();
419
+ if (settings->use_collections) {
420
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_COLLECTIONS;
421
+ }
422
+ if (settings->use_tracing) {
423
+ features[nfeatures++] = PROTOCOL_BINARY_FEATURE_TRACING;
383
424
  }
384
425
 
426
+ std::string agent = generate_agent_json();
385
427
  lcb::MemcachedRequest hdr(PROTOCOL_BINARY_CMD_HELLO);
386
- hdr.sizes(0, nclistr, (sizeof features[0]) * nfeatures);
387
-
428
+ hdr.sizes(0, agent.size(), (sizeof features[0]) * nfeatures);
388
429
  lcbio_ctx_put(ctx, hdr.data(), hdr.size());
389
- lcbio_ctx_put(ctx, clistr, nclistr);
430
+ lcbio_ctx_put(ctx, agent.c_str(), agent.size());
431
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "HELLO identificator: %.*s", LOGID(this), (int)agent.size(), agent.c_str());
390
432
  for (size_t ii = 0; ii < nfeatures; ii++) {
391
433
  lcb_U16 tmp = htons(features[ii]);
392
434
  lcbio_ctx_put(ctx, &tmp, sizeof tmp);
435
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Request feature: 0x%x (%s)", LOGID(this), features[ii], protocol_feature_2_text(features[ii]));
393
436
  }
394
437
 
395
438
  lcbio_ctx_rwant(ctx, 24);
@@ -409,13 +452,13 @@ SessionRequestImpl::read_hello(const lcb::MemcachedResponse& resp)
409
452
  {
410
453
  /* some caps */
411
454
  const char *cur;
412
- const char *payload = resp.body<const char*>();
413
- const char *limit = payload + resp.bodylen();
455
+ const char *payload = resp.value();
456
+ const char *limit = payload + resp.vallen();
414
457
  for (cur = payload; cur < limit; cur += 2) {
415
458
  lcb_U16 tmp;
416
459
  memcpy(&tmp, cur, sizeof(tmp));
417
460
  tmp = ntohs(tmp);
418
- lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server supports feature: 0x%x (%s)", SESSREQ_LOGID(this), tmp, protocol_feature_2_text(tmp));
461
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Server supports feature: 0x%x (%s)", LOGID(this), tmp, protocol_feature_2_text(tmp));
419
462
  info->server_features.push_back(tmp);
420
463
  }
421
464
  return true;
@@ -442,8 +485,7 @@ SessionRequestImpl::update_errmap(const lcb::MemcachedResponse& resp)
442
485
 
443
486
  std::string errmsg;
444
487
  ErrorMap& mm = *settings->errmap;
445
- ErrorMap::ParseStatus status = mm.parse(
446
- resp.body<const char*>(), resp.bodylen(), errmsg);
488
+ ErrorMap::ParseStatus status = mm.parse(resp.value(), resp.vallen(), errmsg);
447
489
 
448
490
  if (status != ErrorMap::UPDATED && status != ErrorMap::NOT_UPDATED) {
449
491
  errmsg = "Couldn't update error map: " + errmsg;
@@ -464,12 +506,12 @@ SessionRequestImpl::maybe_select_bucket() {
464
506
  }
465
507
 
466
508
  if (!settings->select_bucket) {
467
- lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SELECT_BUCKET Disabled by application", SESSREQ_LOGID(this));
509
+ lcb_log(LOGARGS(this, WARN), LOGFMT "SELECT_BUCKET Disabled by application", LOGID(this));
468
510
  return false;
469
511
  }
470
512
 
471
513
  // send the SELECT_BUCKET command:
472
- lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "Sending SELECT_BUCKET", SESSREQ_LOGID(this));
514
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Sending SELECT_BUCKET", LOGID(this));
473
515
  lcb::MemcachedRequest req(PROTOCOL_BINARY_CMD_SELECT_BUCKET);
474
516
  req.sizes(0, strlen(settings->bucket), 0);
475
517
  lcbio_ctx_put(ctx, req.data(), req.size());
@@ -507,7 +549,7 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
507
549
  case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: {
508
550
  const char *mechlist_data;
509
551
  unsigned int nmechlist_data;
510
- std::string mechs(resp.body<const char*>(), resp.bodylen());
552
+ std::string mechs(resp.value(), resp.vallen());
511
553
 
512
554
  MechStatus mechrc = set_chosen_mech(mechs, &mechlist_data, &nmechlist_data);
513
555
  if (mechrc == MECH_OK) {
@@ -534,10 +576,10 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
534
576
  }
535
577
 
536
578
  case PROTOCOL_BINARY_CMD_SASL_STEP: {
537
- if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
579
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS && check_auth(resp)) {
538
580
  completed = !maybe_select_bucket();
539
581
  } else {
540
- lcb_log(LOGARGS(this, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(this), status);
582
+ lcb_log(LOGARGS(this, WARN), LOGFMT "SASL auth failed with STATUS=0x%x", LOGID(this), status);
541
583
  set_error(LCB_AUTH_ERROR, "SASL Step failed", &resp);
542
584
  }
543
585
  break;
@@ -550,9 +592,9 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
550
592
  break;
551
593
  }
552
594
  } else if (isUnsupported(status)) {
553
- lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(this));
595
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Server does not support HELLO", LOGID(this));
554
596
  } else {
555
- lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for HELLO", SESSREQ_LOGID(this), status);
597
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for HELLO", LOGID(this), status);
556
598
  set_error(LCB_PROTOCOL_ERROR, "Hello response unexpected", &resp);
557
599
  break;
558
600
  }
@@ -560,11 +602,15 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
560
602
  if (info->has_feature(PROTOCOL_BINARY_FEATURE_XERROR)) {
561
603
  request_errmap();
562
604
  } else {
563
- lcb_log(LOGARGS(this, TRACE), SESSREQ_LOGFMT "GET_ERRORMAP unsupported/disabled", SESSREQ_LOGID(this));
605
+ lcb_log(LOGARGS(this, TRACE), LOGFMT "GET_ERRORMAP unsupported/disabled", LOGID(this));
564
606
  }
565
607
 
566
- // In any event, it's also time to send the LIST_MECHS request
567
- send_list_mechs();
608
+ if (settings->keypath) {
609
+ completed = !maybe_select_bucket();
610
+ } else {
611
+ // In any event, it's also time to send the LIST_MECHS request
612
+ send_list_mechs();
613
+ }
568
614
  break;
569
615
  }
570
616
 
@@ -573,9 +619,9 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
573
619
  if (!update_errmap(resp)) {
574
620
  }
575
621
  } else if (isUnsupported(status)) {
576
- lcb_log(LOGARGS(this, DEBUG), SESSREQ_LOGFMT "Server does not support GET_ERRMAP (0x%x)", SESSREQ_LOGID(this), status);
622
+ lcb_log(LOGARGS(this, DEBUG), LOGFMT "Server does not support GET_ERRMAP (0x%x)", LOGID(this), status);
577
623
  } else {
578
- lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for GET_ERRMAP", SESSREQ_LOGID(this), status);
624
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for GET_ERRMAP", LOGID(this), status);
579
625
  set_error(LCB_PROTOCOL_ERROR, "GET_ERRMAP response unexpected", &resp);
580
626
  }
581
627
  // Note, there is no explicit state transition here. LIST_MECHS is
@@ -589,14 +635,14 @@ SessionRequestImpl::handle_read(lcbio_CTX *ioctx)
589
635
  } else if (status == PROTOCOL_BINARY_RESPONSE_EACCESS) {
590
636
  set_error(LCB_AUTH_ERROR, "Provided credentials not allowed for bucket", &resp);
591
637
  } else {
592
- lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET", SESSREQ_LOGID(this), status);
638
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Unexpected status 0x%x received for SELECT_BUCKET", LOGID(this), status);
593
639
  set_error(LCB_PROTOCOL_ERROR, "Other auth error", &resp);
594
640
  }
595
641
  break;
596
642
  }
597
643
 
598
644
  default: {
599
- lcb_log(LOGARGS(this, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(this), resp.opcode(), resp.status());
645
+ lcb_log(LOGARGS(this, ERROR), LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", LOGID(this), resp.opcode(), resp.status());
600
646
  set_error(LCB_NOT_SUPPORTED, "Received unknown response", &resp);
601
647
  break;
602
648
  }
@@ -658,7 +704,7 @@ SessionRequestImpl::start(lcbio_SOCKET *sock) {
658
704
  if (settings->send_hello) {
659
705
  send_hello();
660
706
  } else {
661
- lcb_log(LOGARGS(this, INFO), SESSREQ_LOGFMT "HELLO negotiation disabled by user", SESSREQ_LOGID(this));
707
+ lcb_log(LOGARGS(this, WARN), LOGFMT "HELLO negotiation disabled by user", LOGID(this));
662
708
  send_list_mechs();
663
709
  }
664
710
  LCBIO_CTX_RSCHEDULE(ctx, 24);