libcouchbase 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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