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
@@ -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);