libcouchbase 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +11 -8
  3. data/ext/libcouchbase/CMakeLists.txt +1 -1
  4. data/ext/libcouchbase/README.markdown +38 -6
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +151 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -2
  7. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  8. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  9. data/ext/libcouchbase/contrib/cJSON/cJSON.c +686 -288
  10. data/ext/libcouchbase/contrib/cJSON/cJSON.h +0 -0
  11. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +17 -17
  12. data/ext/libcouchbase/contrib/cliopts/cliopts.c +76 -0
  13. data/ext/libcouchbase/contrib/cliopts/cliopts.h +66 -15
  14. data/ext/libcouchbase/contrib/genhash/genhash.c +1 -2
  15. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4 -3
  16. data/ext/libcouchbase/example/instancepool/main.cc +12 -2
  17. data/ext/libcouchbase/example/libeventdirect/main.c +99 -25
  18. data/ext/libcouchbase/example/minimal/minimal.c +7 -5
  19. data/ext/libcouchbase/example/observe/durability.c +102 -0
  20. data/ext/libcouchbase/example/observe/observe.c +19 -6
  21. data/ext/libcouchbase/example/subdoc/subdoc-xattrs.c +1 -2
  22. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +6 -8
  23. data/ext/libcouchbase/include/libcouchbase/cntl.h +84 -64
  24. data/ext/libcouchbase/include/libcouchbase/couchbase.h +295 -78
  25. data/ext/libcouchbase/include/libcouchbase/deprecated.h +2 -2
  26. data/ext/libcouchbase/include/libcouchbase/error.h +1 -1
  27. data/ext/libcouchbase/include/libcouchbase/iops.h +9 -9
  28. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +2 -2
  29. data/ext/libcouchbase/include/libcouchbase/n1ql.h +69 -7
  30. data/ext/libcouchbase/include/libcouchbase/vbucket.h +17 -0
  31. data/ext/libcouchbase/include/libcouchbase/views.h +3 -3
  32. data/ext/libcouchbase/include/memcached/protocol_binary.h +62 -1
  33. data/ext/libcouchbase/packaging/deb/control +1 -1
  34. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +37 -36
  35. data/ext/libcouchbase/src/bootstrap.cc +22 -8
  36. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +1 -1
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +0 -1
  38. data/ext/libcouchbase/src/bucketconfig/confmon.cc +13 -8
  39. data/ext/libcouchbase/src/callbacks.c +2 -0
  40. data/ext/libcouchbase/src/cntl.cc +28 -17
  41. data/ext/libcouchbase/src/dns-srv.cc +1 -2
  42. data/ext/libcouchbase/src/dump.cc +4 -0
  43. data/ext/libcouchbase/src/errmap.h +89 -16
  44. data/ext/libcouchbase/src/handler.cc +28 -11
  45. data/ext/libcouchbase/src/http/http-priv.h +4 -1
  46. data/ext/libcouchbase/src/http/http.cc +3 -0
  47. data/ext/libcouchbase/src/instance.cc +1 -1
  48. data/ext/libcouchbase/src/internal.h +1 -0
  49. data/ext/libcouchbase/src/lcbio/connect.cc +2 -3
  50. data/ext/libcouchbase/src/lcbio/manager.cc +2 -2
  51. data/ext/libcouchbase/src/lcbio/ssl.h +10 -0
  52. data/ext/libcouchbase/src/mc/mcreq.c +8 -0
  53. data/ext/libcouchbase/src/mcserver/mcserver.cc +14 -1
  54. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +0 -3
  55. data/ext/libcouchbase/src/n1ql/n1ql.cc +22 -29
  56. data/ext/libcouchbase/src/n1ql/params.cc +46 -1
  57. data/ext/libcouchbase/src/newconfig.cc +4 -4
  58. data/ext/libcouchbase/src/operations/durability-seqno.cc +4 -0
  59. data/ext/libcouchbase/src/operations/durability.cc +3 -0
  60. data/ext/libcouchbase/src/operations/ping.cc +315 -0
  61. data/ext/libcouchbase/src/operations/stats.cc +10 -0
  62. data/ext/libcouchbase/src/operations/subdoc.cc +13 -1
  63. data/ext/libcouchbase/src/retrychk.cc +1 -0
  64. data/ext/libcouchbase/src/settings.c +2 -0
  65. data/ext/libcouchbase/src/settings.h +13 -7
  66. data/ext/libcouchbase/src/ssl/ssl_c.c +28 -2
  67. data/ext/libcouchbase/src/ssl/ssl_common.c +3 -0
  68. data/ext/libcouchbase/src/ssl/ssl_e.c +15 -1
  69. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +3 -1
  70. data/ext/libcouchbase/src/timings.c +0 -1
  71. data/ext/libcouchbase/src/vbucket/vbucket.c +49 -1
  72. data/ext/libcouchbase/tests/iotests/mock-environment.cc +58 -40
  73. data/ext/libcouchbase/tests/iotests/mock-environment.h +23 -4
  74. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +8 -8
  75. data/ext/libcouchbase/tests/iotests/t_behavior.cc +5 -5
  76. data/ext/libcouchbase/tests/iotests/t_durability.cc +50 -0
  77. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +4 -2
  78. data/ext/libcouchbase/tests/iotests/t_errmap.cc +6 -3
  79. data/ext/libcouchbase/tests/iotests/t_lock.cc +5 -6
  80. data/ext/libcouchbase/tests/iotests/t_misc.cc +44 -0
  81. data/ext/libcouchbase/tests/iotests/t_serverops.cc +1 -0
  82. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +28 -0
  83. data/ext/libcouchbase/tests/iotests/t_views.cc +22 -10
  84. data/ext/libcouchbase/tools/CMakeLists.txt +21 -1
  85. data/ext/libcouchbase/tools/cbc-handlers.h +23 -3
  86. data/ext/libcouchbase/tools/cbc-n1qlback.cc +1 -1
  87. data/ext/libcouchbase/tools/cbc-pillowfight.cc +126 -26
  88. data/ext/libcouchbase/tools/cbc-proxy.cc +403 -0
  89. data/ext/libcouchbase/tools/cbc-subdoc.cc +826 -0
  90. data/ext/libcouchbase/tools/cbc.cc +149 -37
  91. data/ext/libcouchbase/tools/common/options.h +5 -2
  92. data/ext/libcouchbase/tools/linenoise/linenoise.c +15 -15
  93. data/lib/libcouchbase.rb +4 -0
  94. data/lib/libcouchbase/bucket.rb +51 -0
  95. data/lib/libcouchbase/connection.rb +100 -13
  96. data/lib/libcouchbase/ext/libcouchbase.rb +40 -0
  97. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +13 -1
  98. data/lib/libcouchbase/ext/libcouchbase/enums.rb +2 -1
  99. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +5 -0
  100. data/lib/libcouchbase/subdoc_request.rb +129 -0
  101. data/lib/libcouchbase/version.rb +1 -1
  102. data/spec/bucket_spec.rb +15 -1
  103. data/spec/connection_spec.rb +1 -1
  104. data/spec/subdoc_spec.rb +192 -0
  105. metadata +13 -4
  106. data/ext/libcouchbase/.travis.yml +0 -19
@@ -184,6 +184,7 @@ handle_bcast(mc_PIPELINE *pipeline, mc_PACKET *req, lcb_error_t err,
184
184
  lcb_RESPVERBOSITY *verbosity;
185
185
  lcb_RESPMCVERSION *version;
186
186
  lcb_RESPFLUSH *flush;
187
+ lcb_RESPNOOP *noop;
187
188
  } u_resp;
188
189
 
189
190
  union {
@@ -191,6 +192,7 @@ handle_bcast(mc_PIPELINE *pipeline, mc_PACKET *req, lcb_error_t err,
191
192
  lcb_RESPVERBOSITY verbosity;
192
193
  lcb_RESPMCVERSION version;
193
194
  lcb_RESPFLUSH flush;
195
+ lcb_RESPNOOP noop;
194
196
  } u_empty;
195
197
 
196
198
  memset(&u_empty, 0, sizeof(u_empty));
@@ -258,6 +260,8 @@ pkt_bcast_simple(lcb_t instance, const void *cookie, lcb_CALLBACKTYPE type)
258
260
  hdr.request.opcode = PROTOCOL_BINARY_CMD_FLUSH;
259
261
  } else if (type == LCB_CALLBACK_VERSIONS) {
260
262
  hdr.request.opcode = PROTOCOL_BINARY_CMD_VERSION;
263
+ } else if (type == LCB_CALLBACK_NOOP) {
264
+ hdr.request.opcode = PROTOCOL_BINARY_CMD_NOOP;
261
265
  } else {
262
266
  fprintf(stderr, "pkt_bcast_simple passed unknown type %u\n", type);
263
267
  assert(0);
@@ -284,6 +288,12 @@ lcb_server_versions3(lcb_t instance, const void *cookie, const lcb_CMDBASE *)
284
288
  return pkt_bcast_simple(instance, cookie, LCB_CALLBACK_VERSIONS);
285
289
  }
286
290
 
291
+ LIBCOUCHBASE_API
292
+ lcb_error_t
293
+ lcb_noop3(lcb_t instance, const void *cookie, const lcb_CMDNOOP *)
294
+ {
295
+ return pkt_bcast_simple(instance, cookie, LCB_CALLBACK_NOOP);
296
+ }
287
297
 
288
298
  LIBCOUCHBASE_API
289
299
  lcb_error_t
@@ -234,8 +234,20 @@ make_doc_flags(const uint32_t user) {
234
234
  }
235
235
 
236
236
  struct MultiBuilder {
237
+ static unsigned infer_mode(const lcb_CMDSUBDOC *cmd) {
238
+ if (cmd->nspecs == 0) {
239
+ return 0;
240
+ }
241
+ const SubdocCmdTraits::Traits& trait = SubdocCmdTraits::find(cmd->specs[0].sdcmd);
242
+ if (!trait.valid()) {
243
+ return 0;
244
+ }
245
+ return trait.mode();
246
+ }
247
+
237
248
  MultiBuilder(const lcb_CMDSUBDOC *cmd_)
238
- : cmd(cmd_), payload_size(0), mode(0) {
249
+ : cmd(cmd_), payload_size(0) {
250
+ mode = infer_mode(cmd_);
239
251
  size_t ebufsz = is_lookup() ? cmd->nspecs * 4 : cmd->nspecs * 8;
240
252
  extra_body = new char[ebufsz];
241
253
  bodysz = 0;
@@ -35,6 +35,7 @@ lcb_should_retry(const lcb_settings *settings, const mc_PACKET *pkt, lcb_error_t
35
35
  case PROTOCOL_BINARY_CMD_STAT:
36
36
  case PROTOCOL_BINARY_CMD_VERBOSITY:
37
37
  case PROTOCOL_BINARY_CMD_VERSION:
38
+ case PROTOCOL_BINARY_CMD_NOOP:
38
39
  return 0;
39
40
  }
40
41
 
@@ -60,6 +60,8 @@ void lcb_default_settings(lcb_settings *settings)
60
60
  settings->select_bucket = LCB_DEFAULT_SELECT_BUCKET;
61
61
  settings->tcp_keepalive = LCB_DEFAULT_TCP_KEEPALIVE;
62
62
  settings->send_hello = 1;
63
+ settings->config_poll_interval = LCB_DEFAULT_CONFIG_POLL_INTERVAL;
64
+ settings->use_errmap = 1;
63
65
  }
64
66
 
65
67
  LCB_INTERNAL_API
@@ -23,21 +23,23 @@
23
23
  */
24
24
 
25
25
  /** Convert seconds to millis */
26
- #define LCB_S2MS(s) ((lcb_uint32_t)s) * 1000
26
+ #define LCB_S2MS(s) (((lcb_uint32_t)s) * 1000)
27
27
 
28
28
  /** Convert seconds to microseconds */
29
- #define LCB_S2US(s) ((lcb_uint32_t)s) * 1000000
29
+ #define LCB_S2US(s) (((lcb_uint32_t)s) * 1000000)
30
30
 
31
31
  /** Convert seconds to nanoseconds */
32
- #define LCB_S2NS(s) ((hrtime_t)s) * 1000000000
32
+ #define LCB_S2NS(s) (((hrtime_t)s) * 1000000000)
33
33
 
34
34
  /** Convert nanoseconds to microseconds */
35
35
  #define LCB_NS2US(s) (lcb_uint32_t) ((s) / 1000)
36
36
 
37
- #define LCB_MS2US(s) (s) * 1000
37
+ #define LCB_MS2US(s) ((s) * 1000)
38
38
 
39
39
  /** Convert microseconds to nanoseconds */
40
- #define LCB_US2NS(s) ((hrtime_t)s) * 1000
40
+ #define LCB_US2NS(s) (((hrtime_t)s) * 1000)
41
+ /** Convert milliseconds to nanoseconds */
42
+ #define LCB_MS2NS(s) (((hrtime_t)s) * 1000000)
41
43
 
42
44
 
43
45
  #define LCB_DEFAULT_TIMEOUT LCB_MS2US(2500)
@@ -56,8 +58,8 @@
56
58
  #define LCB_DEFAULT_CONFIG_MAXIMUM_REDIRECTS 3
57
59
  #define LCB_DEFAULT_CONFIG_ERRORS_THRESHOLD 100
58
60
 
59
- /* 10 seconds */
60
- #define LCB_DEFAULT_CONFIG_ERRORS_DELAY LCB_MS2US(10000)
61
+ /* 10 milliseconds */
62
+ #define LCB_DEFAULT_CONFIG_ERRORS_DELAY LCB_MS2US(10)
61
63
 
62
64
  /* 1 second */
63
65
  #define LCB_DEFAULT_CLCONFIG_GRACE_CYCLE LCB_MS2US(1000)
@@ -86,6 +88,10 @@
86
88
  #define LCB_DEFAULT_TCP_NODELAY 1
87
89
  #define LCB_DEFAULT_SELECT_BUCKET 1
88
90
  #define LCB_DEFAULT_TCP_KEEPALIVE 1
91
+ /* 2.5 s */
92
+ #define LCB_DEFAULT_CONFIG_POLL_INTERVAL LCB_MS2US(2500)
93
+ /* 50 ms */
94
+ #define LCB_CONFIG_POLL_INTERVAL_FLOOR LCB_MS2US(50)
89
95
 
90
96
  #include "config.h"
91
97
  #include <libcouchbase/couchbase.h>
@@ -189,16 +189,26 @@ appdata_read(lcbio_CSSL *cs)
189
189
  static void
190
190
  read_callback(lcb_sockdata_t *sd, lcb_ssize_t nr, void *arg)
191
191
  {
192
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
192
193
  lcbio_CSSL *cs = arg;
194
+ #else
195
+ my_WBUF *rb = arg;
196
+ lcbio_CSSL *cs = rb->parent;
197
+ #endif
198
+
193
199
  cs->rdactive = 0;
194
200
  cs->entered++;
195
201
 
196
202
  if (nr > 0) {
203
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
197
204
  BUF_MEM *mb;
198
205
 
199
206
  BIO_clear_retry_flags(cs->rbio);
200
207
  BIO_get_mem_ptr(cs->rbio, &mb);
201
208
  mb->length += nr;
209
+ #else
210
+ BIO_write(cs->rbio, rb->buf, nr);
211
+ #endif
202
212
 
203
213
  } else if (nr == 0) {
204
214
  cs->closed = 1;
@@ -208,6 +218,9 @@ read_callback(lcb_sockdata_t *sd, lcb_ssize_t nr, void *arg)
208
218
  cs->error = 1;
209
219
  IOTSSL_ERRNO(cs) = IOT_ERRNO(cs->orig);
210
220
  }
221
+ #if !LCB_CAN_OPTIMIZE_SSL_BIO
222
+ free(rb);
223
+ #endif
211
224
 
212
225
  appdata_encode(cs);
213
226
  appdata_read(cs);
@@ -271,17 +284,30 @@ schedule_wants(lcbio_CSSL *cs)
271
284
 
272
285
  } else if (SSL_want_read(cs->ssl) || (cs->urd_cb && has_appdata == 0)) {
273
286
  /* request more data from the socket */
274
- BUF_MEM *mb;
275
287
  lcb_IOV iov;
288
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
289
+ BUF_MEM *mb;
290
+ #else
291
+ #define BUFSZ 4096
292
+ my_WBUF *rb = malloc(sizeof(*rb) + BUFSZ);
293
+ rb->parent = cs;
294
+ #endif
276
295
 
277
296
  cs->rdactive = 1;
297
+ lcbio_table_ref(&cs->base_);
298
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
278
299
  BIO_get_mem_ptr(cs->rbio, &mb);
279
300
  iotssl_bm_reserve(mb);
280
301
  iov.iov_base = mb->data + mb->length;
281
302
  iov.iov_len = mb->max - mb->length;
282
- lcbio_table_ref(&cs->base_);
283
303
  IOT_V1(cs->orig).read2(
284
304
  IOT_ARG(cs->orig), cs->sd, &iov, 1, cs, read_callback);
305
+ #else
306
+ iov.iov_base = rb->buf;
307
+ iov.iov_len = BUFSZ;
308
+ IOT_V1(cs->orig).read2(
309
+ IOT_ARG(cs->orig), cs->sd, &iov, 1, rb, read_callback);
310
+ #endif
285
311
  }
286
312
 
287
313
  }
@@ -127,6 +127,7 @@ iotssl_destroy_common(lcbio_XSSL *xs)
127
127
  lcbio_table_unref(xs->orig);
128
128
  }
129
129
 
130
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
130
131
  void
131
132
  iotssl_bm_reserve(BUF_MEM *bm)
132
133
  {
@@ -139,6 +140,7 @@ iotssl_bm_reserve(BUF_MEM *bm)
139
140
  }
140
141
  bm->length = oldlen;
141
142
  }
143
+ #endif
142
144
 
143
145
  void
144
146
  iotssl_log_errors(lcbio_XSSL *xs)
@@ -428,6 +430,7 @@ ossl_init_locks(void)
428
430
  for (ii = 0; ii < nlocks; ii++) {
429
431
  ossl_lock_init(ossl_locks + ii);
430
432
  }
433
+ /* TODO: locking API has been removed in OpenSSL 1.1 */
431
434
  CRYPTO_set_locking_callback(ossl_lockfn);
432
435
  }
433
436
 
@@ -112,24 +112,38 @@ schedule_pending(lcbio_ESSL *es)
112
112
  static int
113
113
  read_ssl_data(lcbio_ESSL *es)
114
114
  {
115
- BUF_MEM *rmb;
116
115
  int nr;
117
116
  lcbio_pTABLE iot = es->orig;
118
117
 
118
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
119
+ BUF_MEM *rmb;
120
+
119
121
  /* This block is an optimization over BIO_write to avoid copying the memory
120
122
  * to a temporary buffer and _then_ copying it into the BIO */
121
123
 
122
124
  BIO_get_mem_ptr(es->rbio, &rmb);
125
+ #endif
126
+
123
127
  while (1) {
128
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
124
129
  /* I don't know why this is here, but it's found inside BIO_write */
125
130
  BIO_clear_retry_flags(es->rbio);
126
131
  iotssl_bm_reserve(rmb);
127
132
  nr = IOT_V0IO(iot).recv(IOT_ARG(iot), es->fd,
128
133
  rmb->data + rmb->length, rmb->max - rmb->length, 0);
134
+ #else
135
+ #define BUFSZ 4096
136
+ char buf[BUFSZ];
137
+ nr = IOT_V0IO(iot).recv(IOT_ARG(iot), es->fd, buf, BUFSZ, 0);
138
+ #endif
129
139
 
130
140
  if (nr > 0) {
141
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
131
142
  /* Extend the BIO used length */
132
143
  rmb->length += nr;
144
+ #else
145
+ BIO_write(es->rbio, buf, nr);
146
+ #endif
133
147
  } else if (nr == 0) {
134
148
  es->closed = 1;
135
149
  return -1;
@@ -31,7 +31,7 @@
31
31
  lcbio_pTABLE orig; /**< Table pointer we are wrapping */ \
32
32
  SSL *ssl; /**< SSL object */ \
33
33
  BIO *wbio; /**< BIO used for writing data to network */ \
34
- BIO *rbio; /**<< BIO used for reading data from network */\
34
+ BIO *rbio; /**< BIO used for reading data from network */\
35
35
  lcb_io_opt_t iops_dummy_; /**< Dummy IOPS structure which is exposed to LCB */ \
36
36
  int error; /**< Internal error flag set once a fatal error is detect */\
37
37
  lcb_error_t errcode; /**< The error, converted into libcouchbase */
@@ -113,6 +113,7 @@ iotssl_init_common(lcbio_XSSL *xs, lcbio_TABLE *orig, SSL_CTX *ctx);
113
113
  void
114
114
  iotssl_destroy_common(lcbio_XSSL *xs);
115
115
 
116
+ #if LCB_CAN_OPTIMIZE_SSL_BIO
116
117
  /**
117
118
  * Reserve a specified amount of bytes for reading into a `BUF_MEM*` structure.
118
119
  * Currently the amount reserved is hard coded.
@@ -132,6 +133,7 @@ iotssl_destroy_common(lcbio_XSSL *xs);
132
133
  */
133
134
  void
134
135
  iotssl_bm_reserve(BUF_MEM *bm);
136
+ #endif
135
137
 
136
138
  /**
137
139
  * Prepare the SSL structure so that a subsequent call to SSL_pending will
@@ -111,7 +111,6 @@ lcb_histogram_read(const lcb_HISTOGRAM *hg,
111
111
  start = end + 1;
112
112
  }
113
113
 
114
- start = 1000;
115
114
  for (ii = 1; ii < 9; ++ii) {
116
115
  start = ii * 1000;
117
116
  end = ((ii + 1) * 1000) - 1;
@@ -329,6 +329,7 @@ extract_services(lcbvb_CONFIG *cfg, cJSON *jsvc, lcbvb_SERVICES *svc, int is_ssl
329
329
  EXTRACT_SERVICE("fts", fts);
330
330
  EXTRACT_SERVICE("indexAdmin", ixadmin);
331
331
  EXTRACT_SERVICE("indexScan", ixquery);
332
+ EXTRACT_SERVICE("cbas", cbas);
332
333
 
333
334
  #undef EXTRACT_SERVICE
334
335
 
@@ -360,6 +361,9 @@ build_server_strings(lcbvb_CONFIG *cfg, lcbvb_SERVER *server)
360
361
  if (server->ftspath == NULL && server->svc.fts) {
361
362
  server->ftspath = strdup("/");
362
363
  }
364
+ if (server->cbaspath == NULL && server->svc.cbas) {
365
+ server->cbaspath = strdup("/query/service");
366
+ }
363
367
  return 1;
364
368
  }
365
369
 
@@ -538,6 +542,36 @@ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
538
542
  cfg->revid = -1;
539
543
  }
540
544
 
545
+ cfg->caps = 0;
546
+ {
547
+ cJSON *jcaps = NULL;
548
+ if (get_jarray(cj, "bucketCapabilities", &jcaps)) {
549
+ unsigned ncaps = cJSON_GetArraySize(jcaps);
550
+ for (ii = 0; ii < ncaps; ii++) {
551
+ cJSON *jcap = cJSON_GetArrayItem(jcaps, ii);
552
+ if (jcap || jcap->type == cJSON_String) {
553
+ if (strcmp(jcap->valuestring, "xattr") == 0) {
554
+ cfg->caps |= LCBVB_CAP_XATTR;
555
+ } else if (strcmp(jcap->valuestring, "dcp") == 0) {
556
+ cfg->caps |= LCBVB_CAP_DCP;
557
+ } else if (strcmp(jcap->valuestring, "cbhello") == 0) {
558
+ cfg->caps |= LCBVB_CAP_CBHELLO;
559
+ } else if (strcmp(jcap->valuestring, "touch") == 0) {
560
+ cfg->caps |= LCBVB_CAP_TOUCH;
561
+ } else if (strcmp(jcap->valuestring, "couchapi") == 0) {
562
+ cfg->caps |= LCBVB_CAP_COUCHAPI;
563
+ } else if (strcmp(jcap->valuestring, "cccp") == 0) {
564
+ cfg->caps |= LCBVB_CAP_CCCP;
565
+ } else if (strcmp(jcap->valuestring, "xdcrCheckpointing") == 0) {
566
+ cfg->caps |= LCBVB_CAP_XDCR_CHECKPOINTING;
567
+ } else if (strcmp(jcap->valuestring, "nodesExt") == 0) {
568
+ cfg->caps |= LCBVB_CAP_NODES_EXT;
569
+ }
570
+ }
571
+ }
572
+ }
573
+ }
574
+
541
575
  /** Get the number of nodes. This traverses the list. Yuck */
542
576
  cfg->nsrv = cJSON_GetArraySize(jnodes);
543
577
 
@@ -680,6 +714,7 @@ free_service_strs(lcbvb_SERVICES *svc)
680
714
  free(svc->views_base_);
681
715
  free(svc->query_base_);
682
716
  free(svc->fts_base_);
717
+ free(svc->cbas_base_);
683
718
  }
684
719
 
685
720
  void
@@ -692,6 +727,7 @@ lcbvb_destroy(lcbvb_CONFIG *conf)
692
727
  free(srv->viewpath);
693
728
  free(srv->querypath);
694
729
  free(srv->ftspath);
730
+ free(srv->cbaspath);
695
731
  free_service_strs(&srv->svc);
696
732
  free_service_strs(&srv->svc_ssl);
697
733
  }
@@ -1115,6 +1151,8 @@ lcbvb_get_port(lcbvb_CONFIG *cfg,
1115
1151
  return svc->n1ql;
1116
1152
  } else if (type == LCBVB_SVCTYPE_FTS) {
1117
1153
  return svc->fts;
1154
+ } else if (type == LCBVB_SVCTYPE_CBAS) {
1155
+ return svc->cbas;
1118
1156
  } else {
1119
1157
  return 0;
1120
1158
  }
@@ -1190,7 +1228,8 @@ lcbvb_get_randhost_ex(const lcbvb_CONFIG *cfg,
1190
1228
  (type == LCBVB_SVCTYPE_MGMT && svcs->mgmt) ||
1191
1229
  (type == LCBVB_SVCTYPE_N1QL && svcs->n1ql) ||
1192
1230
  (type == LCBVB_SVCTYPE_FTS && svcs->fts) ||
1193
- (type == LCBVB_SVCTYPE_VIEWS && svcs->views);
1231
+ (type == LCBVB_SVCTYPE_VIEWS && svcs->views) ||
1232
+ (type == LCBVB_SVCTYPE_CBAS && svcs->cbas);
1194
1233
 
1195
1234
  if (has_svc) {
1196
1235
  cfg->randbuf[oix++] = (int)nn;
@@ -1251,6 +1290,9 @@ lcbvb_get_resturl(lcbvb_CONFIG *cfg, unsigned ix,
1251
1290
  } else if (svc == LCBVB_SVCTYPE_FTS) {
1252
1291
  path = srv->ftspath;
1253
1292
  strp = &svcs->fts_base_;
1293
+ } else if (svc == LCBVB_SVCTYPE_CBAS) {
1294
+ path = srv->cbaspath;
1295
+ strp = &svcs->cbas_base_;
1254
1296
  } else {
1255
1297
  /* Unknown service! */
1256
1298
  return NULL;
@@ -1310,6 +1352,9 @@ copy_service(const char *hostname,
1310
1352
  if (src->fts_base_) {
1311
1353
  dst->fts_base_ = strdup(src->fts_base_);
1312
1354
  }
1355
+ if (src->cbas_base_) {
1356
+ dst->cbas_base_ = strdup(src->cbas_base_);
1357
+ }
1313
1358
  if (dst->data) {
1314
1359
  sprintf(buf, "%s:%d", hostname, dst->data);
1315
1360
  dst->hoststrs[LCBVB_SVCTYPE_DATA] = strdup(buf);
@@ -1401,6 +1446,9 @@ lcbvb_genconfig_ex(lcbvb_CONFIG *vb,
1401
1446
  if (src->ftspath) {
1402
1447
  dst->ftspath = strdup(src->ftspath);
1403
1448
  }
1449
+ if (src->cbaspath) {
1450
+ dst->cbaspath = strdup(src->cbaspath);
1451
+ }
1404
1452
 
1405
1453
  copy_service(src->hostname, &src->svc, &dst->svc);
1406
1454
  copy_service(src->hostname, &src->svc_ssl, &dst->svc_ssl);
@@ -21,6 +21,9 @@
21
21
  #include <mocksupport/server.h>
22
22
  #include "mock-environment.h"
23
23
  #include <sstream>
24
+ #include "internal.h" /* settings from lcb_t for logging */
25
+
26
+ #define LOGARGS(instance, lvl) instance->settings, "tests-ENV", LCB_LOG_##lvl, __FILE__, __LINE__
24
27
 
25
28
  MockEnvironment *MockEnvironment::instance;
26
29
 
@@ -66,9 +69,10 @@ MockEnvironment::MockEnvironment(const char **args, std::string bucketname)
66
69
  SetUp();
67
70
  }
68
71
 
69
- void MockEnvironment::failoverNode(int index, std::string bucket)
72
+ void MockEnvironment::failoverNode(int index, std::string bucket, bool rebalance)
70
73
  {
71
74
  MockBucketCommand bCmd(MockCommand::FAILOVER, index, bucket);
75
+ bCmd.set("rebalance", rebalance);
72
76
  sendCommand(bCmd);
73
77
  getResponse();
74
78
  }
@@ -250,44 +254,61 @@ void MockEnvironment::createConnection(lcb_t &instance)
250
254
 
251
255
  }
252
256
 
253
- #define STAT_EP_VERSION "ep_version"
257
+ #define STAT_VERSION "version"
254
258
 
255
259
  extern "C" {
256
- static void statsCallback(lcb_t, const void *cookie,
257
- lcb_error_t err,
258
- const lcb_server_stat_resp_t *resp)
259
- {
260
- MockEnvironment *me = (MockEnvironment *)cookie;
261
- ASSERT_EQ(LCB_SUCCESS, err);
262
-
263
- if (resp->v.v0.server_endpoint == NULL) {
264
- return;
265
- }
266
-
267
- if (!resp->v.v0.nkey) {
268
- return;
269
- }
260
+ static void statsCallback(lcb_t instance, const void *cookie, lcb_error_t err, const lcb_server_stat_resp_t *resp)
261
+ {
262
+ MockEnvironment *me = (MockEnvironment *)cookie;
263
+ ASSERT_EQ(LCB_SUCCESS, err);
270
264
 
271
- if (resp->v.v0.nkey != sizeof(STAT_EP_VERSION) - 1 ||
272
- memcmp(resp->v.v0.key, STAT_EP_VERSION,
273
- sizeof(STAT_EP_VERSION) - 1) != 0) {
274
- return;
275
- }
276
- int version = ((const char *)resp->v.v0.bytes)[0] - '0';
277
- if (version == 1) {
278
- me->setServerVersion(MockEnvironment::VERSION_10);
279
- } else if (version == 2) {
280
- me->setServerVersion(MockEnvironment::VERSION_20);
265
+ if (resp->v.v0.server_endpoint == NULL) {
266
+ return;
267
+ }
281
268
 
282
- } else {
283
- std::cerr << "Unable to determine version from string '";
284
- std::cerr.write((const char *)resp->v.v0.bytes,
285
- resp->v.v0.nbytes);
286
- std::cerr << "' assuming 1.x" << std::endl;
269
+ if (!resp->v.v0.nkey) {
270
+ return;
271
+ }
287
272
 
288
- me->setServerVersion(MockEnvironment::VERSION_10);
273
+ if (resp->v.v0.nkey != sizeof(STAT_VERSION) - 1 ||
274
+ memcmp(resp->v.v0.key, STAT_VERSION, sizeof(STAT_VERSION) - 1) != 0) {
275
+ return;
276
+ }
277
+ MockEnvironment::ServerVersion version = MockEnvironment::VERSION_UNKNOWN;
278
+ if (resp->v.v0.nbytes > 2) {
279
+ int major = ((const char *)resp->v.v0.bytes)[0] - '0';
280
+ int minor = ((const char *)resp->v.v0.bytes)[2] - '0';
281
+ switch (major) {
282
+ case 4:
283
+ switch (minor) {
284
+ case 0:
285
+ version = MockEnvironment::VERSION_40;
286
+ break;
287
+ case 1:
288
+ version = MockEnvironment::VERSION_41;
289
+ break;
290
+ case 5:
291
+ version = MockEnvironment::VERSION_45;
292
+ break;
293
+ case 6:
294
+ version = MockEnvironment::VERSION_46;
295
+ break;
296
+ }
297
+ break;
298
+ case 5:
299
+ version = MockEnvironment::VERSION_50;
300
+ break;
289
301
  }
290
302
  }
303
+ if (version == MockEnvironment::VERSION_UNKNOWN) {
304
+ lcb_log(LOGARGS(instance, ERROR), "Unable to determine version from string '%.*s', assuming 4.0",
305
+ (int)resp->v.v0.nbytes, (const char *)resp->v.v0.bytes);
306
+ version = MockEnvironment::VERSION_40;
307
+ }
308
+ me->setServerVersion(version);
309
+ lcb_log(LOGARGS(instance, INFO), "Using real cluster version %.*s (id=%d)", (int)resp->v.v0.nbytes,
310
+ (const char *)resp->v.v0.bytes, version);
311
+ }
291
312
  }
292
313
 
293
314
  void MockEnvironment::bootstrapRealCluster()
@@ -318,14 +339,11 @@ void MockEnvironment::bootstrapRealCluster()
318
339
  // no body
319
340
  }
320
341
 
321
- if (serverVersion == VERSION_20) {
322
- // Couchbase 2.0.x
323
- featureRegistry.insert("observe");
324
- featureRegistry.insert("views");
325
- featureRegistry.insert("http");
326
- featureRegistry.insert("replica_read");
327
- featureRegistry.insert("lock");
328
- }
342
+ featureRegistry.insert("observe");
343
+ featureRegistry.insert("views");
344
+ featureRegistry.insert("http");
345
+ featureRegistry.insert("replica_read");
346
+ featureRegistry.insert("lock");
329
347
 
330
348
  numNodes = ii;
331
349
  lcb_destroy(tmphandle);