libcouchbase 0.3.3 → 1.0.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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -0,0 +1,31 @@
1
+ {
2
+ "bucketCapabilitiesVer" : "",
3
+ "name" : "memd",
4
+ "nodeLocator" : "ketama",
5
+ "nodes" : [
6
+ {
7
+ "ports" : {
8
+ "direct" : 11210
9
+ },
10
+ "hostname" : "192.168.1.103:8091"
11
+ },
12
+ {
13
+ "hostname" : "192.168.1.101:8091",
14
+ "ports" : {
15
+ "direct" : 11210
16
+ }
17
+ },
18
+ {
19
+ "hostname" : "192.168.1.102:8091",
20
+ "ports" : {
21
+ "direct" : 11210
22
+ }
23
+ },
24
+ {
25
+ "hostname" : "$HOST:8091",
26
+ "ports" : {
27
+ "direct" : 11210
28
+ }
29
+ }
30
+ ]
31
+ }
@@ -55,10 +55,10 @@ ConfigTest::testConfig(const char *fname, bool checkNew)
55
55
  ASSERT_TRUE(vbc != NULL);
56
56
  int rv = lcbvb_load_json(vbc, testData.c_str());
57
57
  ASSERT_EQ(0, rv);
58
- ASSERT_GT(vbc->nsrv, 0);
58
+ ASSERT_GT(vbc->nsrv, (unsigned int)0);
59
59
 
60
60
  if (vbc->dtype == LCBVB_DIST_VBUCKET) {
61
- ASSERT_GT(vbc->nvb, 0);
61
+ ASSERT_GT(vbc->nvb, (unsigned int)0);
62
62
 
63
63
  for (unsigned ii = 0; ii < vbc->nvb; ii++) {
64
64
  lcbvb_vbmaster(vbc, ii);
@@ -284,7 +284,7 @@ TEST_F(ConfigTest, testNondataNodes)
284
284
 
285
285
  lcbvb_map_key(cfg_old, s.c_str(), s.size(), &vbid, &ix_exp);
286
286
  lcbvb_map_key(cfg_ex, s.c_str(), s.size(), &vbid, &ix_cur);
287
- ASSERT_TRUE(ix_exp > -1 && ix_exp < cfg_ex->ndatasrv);
287
+ ASSERT_TRUE(ix_exp > -1 && ix_exp < (int)cfg_ex->ndatasrv);
288
288
  ASSERT_EQ(ix_exp, ix_cur);
289
289
  }
290
290
 
@@ -298,7 +298,7 @@ TEST_F(ConfigTest, testNondataNodes)
298
298
  if (newix == -1) {
299
299
  continue;
300
300
  } else {
301
- ASSERT_TRUE(newix < cfg_ex->ndatasrv);
301
+ ASSERT_TRUE(newix < (int)cfg_ex->ndatasrv);
302
302
  }
303
303
  }
304
304
  }
@@ -310,7 +310,7 @@ TEST_F(ConfigTest, testNondataNodes)
310
310
  const string& s = keys[ii];
311
311
  lcbvb_map_key(cfg_old, s.c_str(), s.size(), &vbid, &ix_exp);
312
312
  lcbvb_map_key(cfg_ex, s.c_str(), s.size(), &vbid, &ix_cur);
313
- ASSERT_TRUE(ix_exp > -1 && ix_exp < cfg_old->ndatasrv);
313
+ ASSERT_TRUE(ix_exp > -1 && ix_exp < (int)cfg_old->ndatasrv);
314
314
  ASSERT_EQ(ix_exp, ix_cur);
315
315
  }
316
316
 
@@ -339,3 +339,33 @@ TEST_F(ConfigTest, testKetamaUniformity)
339
339
  ASSERT_STREQ("localhost:12006", vbc->servers[3].authority);
340
340
  lcbvb_destroy(vbc);
341
341
  }
342
+
343
+ TEST_F(ConfigTest, testKetamaCompliance) {
344
+ string txt = getConfigFile("memd_ketama_config.json");
345
+ lcbvb_CONFIG *vbc = lcbvb_parse_json(txt.c_str());
346
+ ASSERT_TRUE(vbc != NULL);
347
+ ASSERT_EQ(4, vbc->nsrv);
348
+ ASSERT_EQ(LCBVB_DIST_KETAMA, vbc->dtype);
349
+
350
+ lcbvb_replace_host(vbc, "192.168.1.104");
351
+ // Now, load the hash file
352
+ string expected_txt = getConfigFile("ketama_expected.json");
353
+ Json::Value json;
354
+ ASSERT_TRUE(Json::Reader().parse(expected_txt, json));
355
+
356
+ ASSERT_EQ(json.size(), vbc->ncontinuum);
357
+
358
+ // Iterate over the continuum in the vbuckets
359
+ for (size_t ii = 0; ii < json.size(); ++ii) {
360
+ const Json::Value& cur = json[static_cast<int>(ii)];
361
+ unsigned exp_hash = cur["hash"].asUInt();
362
+ string exp_server = cur["hostname"].asString();
363
+ unsigned got_hash = vbc->continuum[ii].point;
364
+ unsigned got_index = vbc->continuum[ii].index;
365
+
366
+ ASSERT_EQ(exp_server, vbc->servers[got_index].authority);
367
+ ASSERT_EQ(exp_hash, got_hash);
368
+ }
369
+
370
+ lcbvb_destroy(vbc);
371
+ }
@@ -4,7 +4,7 @@ FILE(GLOB T_COMMONSRC common/*.cc)
4
4
  ADD_LIBRARY(lcbtools OBJECT ${T_COMMONSRC})
5
5
 
6
6
  ADD_EXECUTABLE(cbc cbc.cc
7
- $<TARGET_OBJECTS:lcbtools> $<TARGET_OBJECTS:cliopts>)
7
+ $<TARGET_OBJECTS:lcbtools> $<TARGET_OBJECTS:cliopts> $<TARGET_OBJECTS:lcb_jsoncpp>)
8
8
  TARGET_LINK_LIBRARIES(cbc couchbase)
9
9
 
10
10
  ADD_EXECUTABLE(cbc-pillowfight cbc-pillowfight.cc
@@ -38,7 +38,7 @@ IF(NOT WIN32)
38
38
  cat create observe observe-seqno incr decr mcflush hash lock
39
39
  unlock rm stats version verbosity view n1ql admin
40
40
  bucket-create bucket-delete bucket-flush connstr write-config strerror
41
- touch)
41
+ touch role-list user-list user-upsert user-delete)
42
42
 
43
43
  FOREACH(subcmd IN ITEMS ${CBC_SUBCOMMANDS})
44
44
  ADD_CUSTOM_COMMAND(TARGET cbc POST_BUILD
@@ -367,6 +367,134 @@ protected:
367
367
 
368
368
  };
369
369
 
370
+ class RbacHandler : public AdminHandler {
371
+ public:
372
+ HANDLER_USAGE("[OPTIONS ...]")
373
+ RbacHandler(const char *name) : AdminHandler(name),
374
+ o_raw('r', "raw")
375
+ {
376
+ o_raw.description("Do not reformat output from server (display JSON response)");
377
+ }
378
+
379
+ protected:
380
+ virtual void run();
381
+ virtual void format() = 0;
382
+ virtual void addOptions() {
383
+ AdminHandler::addOptions();
384
+ parser.addOption(o_raw);
385
+ }
386
+
387
+ private:
388
+ cliopts::BoolOption o_raw;
389
+ };
390
+
391
+ class RoleListHandler : public RbacHandler {
392
+ public:
393
+ HANDLER_DESCRIPTION("List roles")
394
+ RoleListHandler() : RbacHandler("role-list")
395
+ {
396
+ }
397
+
398
+ protected:
399
+ virtual void format();
400
+ virtual void addOptions() {
401
+ RbacHandler::addOptions();
402
+ }
403
+ std::string getURI() { return "/settings/rbac/roles"; }
404
+ const std::string& getBody() { static std::string e; return e; }
405
+ lcb_http_method_t getMethod() { return LCB_HTTP_METHOD_GET; }
406
+ };
407
+
408
+ class UserListHandler : public RbacHandler {
409
+ public:
410
+ HANDLER_DESCRIPTION("List users")
411
+ UserListHandler() : RbacHandler("user-list")
412
+ {
413
+ }
414
+
415
+ protected:
416
+ virtual void format();
417
+ virtual void addOptions() {
418
+ RbacHandler::addOptions();
419
+ }
420
+ std::string getURI() { return "/settings/rbac/users"; }
421
+ const std::string& getBody() { static std::string e; return e; }
422
+ lcb_http_method_t getMethod() { return LCB_HTTP_METHOD_GET; }
423
+ };
424
+
425
+ class UserDeleteHandler : public AdminHandler {
426
+ public:
427
+ HANDLER_DESCRIPTION("Delete a user")
428
+ HANDLER_USAGE("NAME [OPTIONS ...]")
429
+ UserDeleteHandler() : AdminHandler("user-delete"),
430
+ o_domain("domain")
431
+ {
432
+ o_domain.description("The domain, where user account defined {local,external}").setDefault("local");
433
+ }
434
+
435
+ protected:
436
+ virtual void addOptions() {
437
+ AdminHandler::addOptions();
438
+ parser.addOption(o_domain);
439
+ }
440
+ void run() {
441
+ name = getRequiredArg();
442
+ domain = o_domain.result();
443
+ if (domain != "local" && domain != "external") {
444
+ throw BadArg("Unrecognized domain type");
445
+ }
446
+ AdminHandler::run();
447
+ }
448
+ std::string getURI() { return std::string("/settings/rbac/users/") + domain + "/" + name; }
449
+ const std::string& getBody() { static std::string e; return e; }
450
+ lcb_http_method_t getMethod() { return LCB_HTTP_METHOD_DELETE; }
451
+
452
+ private:
453
+ cliopts::StringOption o_domain;
454
+ std::string name;
455
+ std::string domain;
456
+ };
457
+
458
+ class UserUpsertHandler : public AdminHandler {
459
+ public:
460
+ HANDLER_DESCRIPTION("Create or update a user")
461
+ HANDLER_USAGE("NAME [OPTIONS ...]")
462
+ UserUpsertHandler() : AdminHandler("user-upsert"),
463
+ o_domain("domain"),
464
+ o_full_name("full-name"),
465
+ o_password("user-password"),
466
+ o_roles("role")
467
+ {
468
+ o_domain.description("The domain, where user account defined {local,external}").setDefault("local");
469
+ o_full_name.description("The user's fullname");
470
+ o_roles.description("The role associated with user (can be specified multiple times if needed)");
471
+ o_password.description("The password for the user");
472
+ }
473
+
474
+ protected:
475
+ virtual void addOptions() {
476
+ AdminHandler::addOptions();
477
+ parser.addOption(o_domain);
478
+ parser.addOption(o_full_name);
479
+ parser.addOption(o_roles);
480
+ parser.addOption(o_password);
481
+ }
482
+ virtual void run();
483
+ std::string getURI() { return std::string("/settings/rbac/users/") + domain + "/" + name; }
484
+ const std::string& getBody() { return body; }
485
+ std::string getContentType() { return "application/x-www-form-urlencoded"; }
486
+ lcb_http_method_t getMethod() { return LCB_HTTP_METHOD_PUT; }
487
+
488
+ private:
489
+ cliopts::StringOption o_domain;
490
+ cliopts::StringOption o_full_name;
491
+ cliopts::StringOption o_password;
492
+ cliopts::ListOption o_roles;
493
+ std::string name;
494
+ std::string domain;
495
+ std::string body;
496
+ };
497
+
370
498
  class BucketCreateHandler : public AdminHandler {
371
499
  public:
372
500
  HANDLER_DESCRIPTION("Create a bucket")
@@ -74,6 +74,8 @@ public:
74
74
  start_time = last_update;
75
75
  }
76
76
 
77
+ size_t nerrors() { return n_errors; }
78
+
77
79
  void update_row(size_t n = 1) { n_rows += n; update_display(); }
78
80
  void update_done(size_t n = 1) { n_queries += n; update_display(); }
79
81
  void update_error(size_t n = 1) { n_errors += n; update_display(); }
@@ -139,8 +141,8 @@ private:
139
141
  final_suffix = "\n";
140
142
  }
141
143
 
142
- printf("%sQUERIES/SEC: %lu\n", prefix, n_queries / duration);
143
- printf("%sROWS/SEC: %lu\n", prefix, n_rows / duration);
144
+ printf("%sQUERIES/SEC: %lu\n", prefix, (long int)(n_queries / duration));
145
+ printf("%sROWS/SEC: %lu\n", prefix, (long int)(n_rows / duration));
144
146
  printf("%sERRORS: %lu%s", prefix, n_errors, final_suffix);
145
147
 
146
148
  if (hg != NULL) {
@@ -168,7 +170,7 @@ Metrics GlobalMetrics;
168
170
  class Configuration
169
171
  {
170
172
  public:
171
- Configuration() : o_file("queryfile"), o_threads("num-threads") {
173
+ Configuration() : o_file("queryfile"), o_threads("num-threads"), o_errlog("error-log"), m_errlog(NULL) {
172
174
  o_file.mandatory(true);
173
175
  o_file.description(
174
176
  "Path to a file containing all the queries to execute. "
@@ -178,12 +180,24 @@ public:
178
180
  o_threads.description("Number of threads to run");
179
181
  o_threads.abbrev('t');
180
182
  o_threads.setDefault(1);
183
+
184
+ o_errlog.description(
185
+ "Path to a file containing failed queries");
186
+ o_errlog.abbrev('e');
187
+ o_errlog.setDefault("");
181
188
  }
182
189
 
190
+ ~Configuration() {
191
+ if (m_errlog != NULL) {
192
+ delete m_errlog;
193
+ m_errlog = NULL;
194
+ }
195
+ }
183
196
  void addToParser(Parser& parser)
184
197
  {
185
198
  parser.addOption(o_file);
186
199
  parser.addOption(o_threads);
200
+ parser.addOption(o_errlog);
187
201
  m_params.addToParser(parser);
188
202
  }
189
203
 
@@ -200,22 +214,38 @@ public:
200
214
 
201
215
  string curline;
202
216
  while (std::getline(ifs, curline).good() && !ifs.eof()) {
203
- m_queries.push_back(curline);
217
+ if (!curline.empty()) {
218
+ m_queries.push_back(curline);
219
+ }
204
220
  }
205
221
  if (m_params.useTimings()) {
206
222
  GlobalMetrics.prepare_timings();
207
223
  }
224
+
225
+ if (o_errlog.passed()) {
226
+ m_errlog = new std::ofstream(o_errlog.const_result().c_str());
227
+ if (!m_errlog->is_open()) {
228
+ int ec_save = errno;
229
+ string errstr(o_file.const_result());
230
+ errstr += ": ";
231
+ errstr += strerror(ec_save);
232
+ throw std::runtime_error(errstr);
233
+ }
234
+ }
208
235
  }
209
236
 
210
237
  void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
211
238
  const vector<string>& queries() const { return m_queries; }
212
239
  size_t nthreads() { return o_threads.result(); }
240
+ std::ofstream* errlog() { return m_errlog; }
213
241
 
214
242
  private:
215
243
  vector<string> m_queries;
216
244
  StringOption o_file;
217
245
  UIntOption o_threads;
218
246
  ConnParams m_params;
247
+ StringOption o_errlog;
248
+ std::ofstream *m_errlog;
219
249
  };
220
250
 
221
251
  extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
@@ -287,16 +317,25 @@ public:
287
317
 
288
318
  if (resp->rflags & LCB_RESP_F_FINAL) {
289
319
  if (resp->rc != LCB_SUCCESS) {
290
- log_error(resp->rc);
320
+ if (m_errlog != NULL) {
321
+ std::stringstream ss;
322
+ ss.write(m_cmd.query, m_cmd.nquery);
323
+ ss << endl;
324
+ ss.write(resp->row, resp->nrow);
325
+ log_error(resp->rc, ss.str().c_str(), ss.str().size());
326
+ } else {
327
+ log_error(resp->rc, NULL, 0);
328
+ }
291
329
  }
292
330
  } else {
293
331
  last_nrow++;
294
332
  }
295
333
  }
296
334
 
297
- ThreadContext(lcb_t instance, const vector<string>& initial_queries)
335
+ ThreadContext(lcb_t instance, const vector<string>& initial_queries, std::ofstream *errlog)
298
336
  : m_instance(instance), last_nerr(0), last_nrow(0),
299
- m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL)
337
+ m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL),
338
+ m_errlog(errlog)
300
339
  {
301
340
  memset(&m_cmd, 0, sizeof m_cmd);
302
341
  m_cmd.content_type = "application/json";
@@ -309,11 +348,25 @@ public:
309
348
 
310
349
  private:
311
350
 
312
- void log_error(lcb_error_t)
351
+ void log_error(lcb_error_t err, const char* info, size_t ninfo)
313
352
  {
353
+ size_t erridx;
314
354
  m_metrics->lock();
315
355
  m_metrics->update_error();
356
+ erridx = m_metrics->nerrors();
316
357
  m_metrics->unlock();
358
+
359
+ if (m_errlog != NULL) {
360
+ std::stringstream ss;
361
+ ss << "[" << erridx << "] 0x" << std::hex << err << ", "
362
+ << lcb_strerror(NULL, err) << endl;
363
+ if (ninfo) {
364
+ ss.write(info, ninfo);
365
+ ss << endl;
366
+ }
367
+ *m_errlog << ss.str();
368
+ m_errlog->flush();
369
+ }
317
370
  }
318
371
 
319
372
  void run_one_query(const string& txt)
@@ -330,7 +383,7 @@ private:
330
383
 
331
384
  lcb_error_t rc = lcb_n1ql_query(m_instance, &qctx, &m_cmd);
332
385
  if (rc != LCB_SUCCESS) {
333
- log_error(rc);
386
+ log_error(rc, txt.c_str(), txt.size());
334
387
  } else {
335
388
  lcb_wait(m_instance);
336
389
  m_metrics->lock();
@@ -352,6 +405,7 @@ private:
352
405
  #else
353
406
  void *m_thr;
354
407
  #endif
408
+ std::ofstream *m_errlog;
355
409
  };
356
410
 
357
411
  static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
@@ -409,7 +463,7 @@ static void real_main(int argc, char **argv) {
409
463
  throw std::runtime_error("Cluster does not support N1QL!");
410
464
  }
411
465
 
412
- ThreadContext* cx = new ThreadContext(instance, config.queries());
466
+ ThreadContext* cx = new ThreadContext(instance, config.queries(), config.errlog());
413
467
  threads.push_back(cx);
414
468
  instances.push_back(instance);
415
469
  }
@@ -170,7 +170,7 @@ public:
170
170
  }
171
171
  maxCycles = est;
172
172
  o_sequential.setDefault(true);
173
- fprintf(stderr, "Populating using %lu cycles\n", maxCycles);
173
+ fprintf(stderr, "Populating using %d cycles\n", maxCycles);
174
174
  }
175
175
 
176
176
  if (depr.iterations.passed()) {
@@ -630,7 +630,7 @@ private:
630
630
 
631
631
  const lcb_U64 elapsed_ns = now - previous_time;
632
632
  const lcb_U64 wanted_duration_ns =
633
- config.opsPerCycle * 1e9 / config.getRateLimit();
633
+ (config.getNumThreads() * config.opsPerCycle * 1e9) / config.getRateLimit();
634
634
  // On first invocation no previous_time, so skip attempting to sleep.
635
635
  if (elapsed_ns > 0 && elapsed_ns < wanted_duration_ns) {
636
636
  // Dampen the sleep time by averaging with the previous