couchbase 3.2.4 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. package/binding.gyp +5 -0
  2. package/deps/lcb/CMakeLists.txt +28 -6
  3. package/deps/lcb/README.markdown +5 -9
  4. package/deps/lcb/RELEASE_NOTES.markdown +80 -5
  5. package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
  6. package/deps/lcb/doc/Doxyfile +1 -1
  7. package/deps/lcb/doc/cbc.markdown +10 -0
  8. package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
  9. package/deps/lcb/include/libcouchbase/couchbase.h +52 -0
  10. package/deps/lcb/include/libcouchbase/error.h +5 -2
  11. package/deps/lcb/libcouchbase.gyp +7 -1
  12. package/deps/lcb/packaging/rpm/libcouchbase.spec.in +1 -1
  13. package/deps/lcb/plugins/io/iocp/iocp_iops.h +1 -1
  14. package/deps/lcb/plugins/io/iocp/iocp_loop.c +3 -3
  15. package/deps/lcb/plugins/io/iocp/iocp_util.c +2 -2
  16. package/deps/lcb/src/bucketconfig/bc_file.cc +29 -15
  17. package/deps/lcb/src/capi/cmd_counter.hh +12 -0
  18. package/deps/lcb/src/capi/cmd_exists.hh +12 -0
  19. package/deps/lcb/src/capi/cmd_get.hh +12 -0
  20. package/deps/lcb/src/capi/cmd_get_replica.hh +14 -1
  21. package/deps/lcb/src/capi/cmd_query.cc +13 -0
  22. package/deps/lcb/src/capi/cmd_query.hh +22 -14
  23. package/deps/lcb/src/capi/cmd_remove.hh +12 -0
  24. package/deps/lcb/src/capi/cmd_store.hh +12 -0
  25. package/deps/lcb/src/capi/cmd_subdoc.hh +12 -0
  26. package/deps/lcb/src/capi/cmd_touch.hh +12 -0
  27. package/deps/lcb/src/capi/cmd_unlock.hh +12 -0
  28. package/deps/lcb/src/capi/collection_qualifier.hh +4 -9
  29. package/deps/lcb/src/instance.cc +19 -0
  30. package/deps/lcb/src/internal.h +2 -1
  31. package/deps/lcb/src/mcserver/negotiate.cc +3 -0
  32. package/deps/lcb/src/n1ql/n1ql.cc +5 -1
  33. package/deps/lcb/src/n1ql/query_handle.cc +55 -30
  34. package/deps/lcb/src/n1ql/query_handle.hh +14 -2
  35. package/deps/lcb/src/operations/counter.cc +12 -0
  36. package/deps/lcb/src/operations/exists.cc +12 -0
  37. package/deps/lcb/src/operations/get.cc +12 -0
  38. package/deps/lcb/src/operations/get_replica.cc +18 -6
  39. package/deps/lcb/src/operations/ping.cc +2 -2
  40. package/deps/lcb/src/operations/remove.cc +12 -0
  41. package/deps/lcb/src/operations/store.cc +12 -0
  42. package/deps/lcb/src/operations/subdoc.cc +12 -0
  43. package/deps/lcb/src/operations/touch.cc +12 -0
  44. package/deps/lcb/src/operations/unlock.cc +12 -0
  45. package/deps/lcb/src/search/search_handle.cc +1 -2
  46. package/deps/lcb/src/settings.cc +1 -0
  47. package/deps/lcb/src/ssl/ssl_common.c +111 -22
  48. package/deps/lcb/src/utilities.cc +21 -0
  49. package/deps/lcb/src/utilities.h +3 -0
  50. package/deps/lcb/src/vbucket/vbucket.c +16 -7
  51. package/deps/lcb/tests/CMakeLists.txt +1 -1
  52. package/deps/lcb/tests/iotests/mock-environment.cc +13 -1
  53. package/deps/lcb/tests/iotests/mock-environment.h +3 -1
  54. package/deps/lcb/tests/iotests/serverparams.h +7 -2
  55. package/deps/lcb/tests/iotests/t_ratelimit.cc +739 -0
  56. package/deps/lcb/tests/iotests/testutil.cc +174 -0
  57. package/deps/lcb/tests/iotests/testutil.h +53 -0
  58. package/deps/lcb/tools/CMakeLists.txt +1 -1
  59. package/deps/lcb/tools/cbc-handlers.h +39 -0
  60. package/deps/lcb/tools/cbc-n1qlback.cc +1 -0
  61. package/deps/lcb/tools/cbc-pillowfight.cc +45 -35
  62. package/deps/lcb/tools/cbc.cc +31 -0
  63. package/deps/lcb/tools/docgen/docgen.h +11 -10
  64. package/dist/analyticsexecutor.js +2 -2
  65. package/dist/analyticsindexmanager.js +3 -3
  66. package/dist/binarycollection.d.ts +17 -0
  67. package/dist/binding.js +1 -1
  68. package/dist/bindingutilities.js +5 -1
  69. package/dist/bucketmanager.d.ts +1 -22
  70. package/dist/bucketmanager.js +5 -5
  71. package/dist/cluster.js +1 -1
  72. package/dist/collection.js +6 -6
  73. package/dist/collectionmanager.js +2 -2
  74. package/dist/connection.js +3 -3
  75. package/dist/connspec.js +5 -1
  76. package/dist/couchbase.js +5 -1
  77. package/dist/httpexecutor.d.ts +1 -0
  78. package/dist/httpexecutor.js +5 -1
  79. package/dist/logging.js +1 -1
  80. package/dist/queryexecutor.js +3 -3
  81. package/dist/searchindexmanager.js +1 -1
  82. package/dist/usermanager.js +2 -2
  83. package/dist/utilities.d.ts +1 -2
  84. package/dist/utilities.js +9 -2
  85. package/dist/viewexecutor.js +1 -1
  86. package/package.json +1 -1
  87. package/src/uv-plugin-all.cpp +1 -0
  88. package/dist/cas.d.ts +0 -0
  89. package/dist/cas.js +0 -1
@@ -629,3 +629,177 @@ void TestMeter::destroy_lcb_meter()
629
629
  lcbmeter_ = nullptr;
630
630
  }
631
631
  }
632
+
633
+ void enforce_rate_limits(lcb_INSTANCE *instance)
634
+ {
635
+ (void)lcb_install_callback(instance, LCB_CALLBACK_HTTP, (lcb_RESPCALLBACK)http_callback);
636
+
637
+ lcb_CMDHTTP *cmd;
638
+ std::string path = "/internalSettings";
639
+ std::string body = "enforceLimits=true";
640
+
641
+ lcb_cmdhttp_create(&cmd, LCB_HTTP_TYPE_MANAGEMENT);
642
+ lcb_cmdhttp_method(cmd, LCB_HTTP_METHOD_POST);
643
+ lcb_cmdhttp_path(cmd, path.c_str(), path.size());
644
+ lcb_cmdhttp_body(cmd, body.c_str(), body.size());
645
+
646
+ http_result result{};
647
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_http(instance, &result, cmd));
648
+ lcb_cmdhttp_destroy(cmd);
649
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_wait(instance, LCB_WAIT_DEFAULT));
650
+ ASSERT_STATUS_EQ(LCB_SUCCESS, result.rc);
651
+ }
652
+
653
+ void create_rate_limited_user(lcb_INSTANCE *instance, const std::string &username, const rate_limits &limits)
654
+ {
655
+ (void)lcb_install_callback(instance, LCB_CALLBACK_HTTP, (lcb_RESPCALLBACK)http_callback);
656
+
657
+ lcb_CMDHTTP *cmd;
658
+ std::string path = "/settings/rbac/users/local/" + username;
659
+ std::string body = "password=password&roles=admin";
660
+ Json::Value json_limits;
661
+ if (limits.kv_limits.enforce) {
662
+ Json::Value kv_limits;
663
+ if (limits.kv_limits.num_connections > 0) {
664
+ kv_limits["num_connections"] = limits.kv_limits.num_connections;
665
+ }
666
+ if (limits.kv_limits.num_ops_per_min > 0) {
667
+ kv_limits["num_ops_per_min"] = limits.kv_limits.num_ops_per_min;
668
+ }
669
+ if (limits.kv_limits.ingress_mib_per_min > 0) {
670
+ kv_limits["ingress_mib_per_min"] = limits.kv_limits.ingress_mib_per_min;
671
+ }
672
+ if (limits.kv_limits.egress_mib_per_min > 0) {
673
+ kv_limits["egress_mib_per_min"] = limits.kv_limits.egress_mib_per_min;
674
+ }
675
+ json_limits["kv"] = kv_limits;
676
+ }
677
+ if (limits.query_limits.enforce) {
678
+ Json::Value query_limits;
679
+ if (limits.query_limits.num_concurrent_requests > 0) {
680
+ query_limits["num_concurrent_requests"] = limits.query_limits.num_concurrent_requests;
681
+ }
682
+ if (limits.query_limits.num_queries_per_min > 0) {
683
+ query_limits["num_queries_per_min"] = limits.query_limits.num_queries_per_min;
684
+ }
685
+ if (limits.query_limits.ingress_mib_per_min > 0) {
686
+ query_limits["ingress_mib_per_min"] = limits.query_limits.ingress_mib_per_min;
687
+ }
688
+ if (limits.query_limits.egress_mib_per_min > 0) {
689
+ query_limits["egress_mib_per_min"] = limits.query_limits.egress_mib_per_min;
690
+ }
691
+ json_limits["query"] = query_limits;
692
+ }
693
+ if (limits.search_limits.enforce) {
694
+ Json::Value fts_limits;
695
+ if (limits.search_limits.num_concurrent_requests > 0) {
696
+ fts_limits["num_concurrent_requests"] = limits.search_limits.num_concurrent_requests;
697
+ }
698
+ if (limits.search_limits.num_queries_per_min > 0) {
699
+ fts_limits["num_queries_per_min"] = limits.search_limits.num_queries_per_min;
700
+ }
701
+ if (limits.search_limits.ingress_mib_per_min > 0) {
702
+ fts_limits["ingress_mib_per_min"] = limits.search_limits.ingress_mib_per_min;
703
+ }
704
+ if (limits.search_limits.egress_mib_per_min > 0) {
705
+ fts_limits["egress_mib_per_min"] = limits.search_limits.egress_mib_per_min;
706
+ }
707
+ json_limits["fts"] = fts_limits;
708
+ }
709
+ std::string j_limits = Json::FastWriter().write(json_limits);
710
+ body += "&limits=" + j_limits;
711
+ std::string content_type = "application/x-www-form-urlencoded";
712
+
713
+ lcb_cmdhttp_create(&cmd, LCB_HTTP_TYPE_MANAGEMENT);
714
+ lcb_cmdhttp_method(cmd, LCB_HTTP_METHOD_PUT);
715
+ lcb_cmdhttp_path(cmd, path.c_str(), path.size());
716
+ lcb_cmdhttp_body(cmd, body.c_str(), body.size());
717
+ lcb_cmdhttp_content_type(cmd, content_type.c_str(), content_type.size());
718
+
719
+ http_result result{};
720
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_http(instance, &result, cmd));
721
+ lcb_cmdhttp_destroy(cmd);
722
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_wait(instance, LCB_WAIT_DEFAULT));
723
+ ASSERT_STATUS_EQ(LCB_SUCCESS, result.rc);
724
+ }
725
+
726
+ void create_rate_limited_scope(lcb_INSTANCE *instance, const std::string &bucket, std::string &scope,
727
+ const scope_rate_limits &limits)
728
+ {
729
+ (void)lcb_install_callback(instance, LCB_CALLBACK_HTTP, (lcb_RESPCALLBACK)http_callback);
730
+
731
+ lcb_CMDHTTP *cmd;
732
+ std::string path = "/pools/default/buckets/" + bucket + "/scopes";
733
+ std::string body = "name=" + scope;
734
+ Json::Value json_limits;
735
+ if (limits.kv_scope_limits.enforce) {
736
+ Json::Value kv_limits;
737
+ kv_limits["data_size"] = limits.kv_scope_limits.data_size;
738
+ json_limits["kv"] = kv_limits;
739
+ }
740
+ if (limits.index_scope_limits.enforce) {
741
+ Json::Value index_limits;
742
+ index_limits["num_indexes"] = limits.index_scope_limits.num_indexes;
743
+ json_limits["index"] = index_limits;
744
+ }
745
+ std::string j_limits = Json::FastWriter().write(json_limits);
746
+ body += "&limits=" + j_limits;
747
+ std::string content_type = "application/x-www-form-urlencoded";
748
+
749
+ lcb_cmdhttp_create(&cmd, LCB_HTTP_TYPE_MANAGEMENT);
750
+ lcb_cmdhttp_method(cmd, LCB_HTTP_METHOD_POST);
751
+ lcb_cmdhttp_path(cmd, path.c_str(), path.size());
752
+ lcb_cmdhttp_body(cmd, body.c_str(), body.size());
753
+ lcb_cmdhttp_content_type(cmd, content_type.c_str(), content_type.size());
754
+
755
+ http_result result{};
756
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_http(instance, &result, cmd));
757
+ lcb_cmdhttp_destroy(cmd);
758
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_wait(instance, LCB_WAIT_DEFAULT));
759
+ ASSERT_STATUS_EQ(LCB_SUCCESS, result.rc);
760
+ }
761
+
762
+ void drop_user(lcb_INSTANCE *instance, const std::string &username)
763
+ {
764
+ (void)lcb_install_callback(instance, LCB_CALLBACK_HTTP, (lcb_RESPCALLBACK)http_callback);
765
+
766
+ lcb_CMDHTTP *cmd;
767
+ std::string path = "/settings/rbac/users/local/" + username;
768
+
769
+ lcb_cmdhttp_create(&cmd, LCB_HTTP_TYPE_MANAGEMENT);
770
+ lcb_cmdhttp_method(cmd, LCB_HTTP_METHOD_DELETE);
771
+ lcb_cmdhttp_path(cmd, path.c_str(), path.size());
772
+
773
+ http_result result{};
774
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_http(instance, &result, cmd));
775
+ lcb_cmdhttp_destroy(cmd);
776
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_wait(instance, LCB_WAIT_DEFAULT));
777
+ ASSERT_STATUS_EQ(LCB_SUCCESS, result.rc);
778
+ }
779
+
780
+ void create_search_index(lcb_INSTANCE *instance, const std::string &index_name, const std::string &type,
781
+ const std::string &source_type, const std::string &source_name)
782
+ {
783
+ (void)lcb_install_callback(instance, LCB_CALLBACK_HTTP, (lcb_RESPCALLBACK)http_callback);
784
+
785
+ lcb_CMDHTTP *cmd;
786
+ std::string path = "/api/index/" + index_name;
787
+ Json::Value json_body;
788
+ json_body["name"] = index_name;
789
+ json_body["type"] = type;
790
+ json_body["sourceName"] = source_name;
791
+ json_body["sourceType"] = source_type;
792
+
793
+ auto body = Json::FastWriter().write(json_body);
794
+
795
+ lcb_cmdhttp_create(&cmd, LCB_HTTP_TYPE_SEARCH);
796
+ lcb_cmdhttp_method(cmd, LCB_HTTP_METHOD_PUT);
797
+ lcb_cmdhttp_path(cmd, path.c_str(), path.size());
798
+ lcb_cmdhttp_body(cmd, body.c_str(), body.size());
799
+
800
+ http_result result{};
801
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_http(instance, &result, cmd));
802
+ lcb_cmdhttp_destroy(cmd);
803
+ ASSERT_STATUS_EQ(LCB_SUCCESS, lcb_wait(instance, LCB_WAIT_DEFAULT));
804
+ ASSERT_STATUS_EQ(LCB_SUCCESS, result.rc);
805
+ }
@@ -323,4 +323,57 @@ class TestMeter
323
323
  bool enabled_{false};
324
324
  };
325
325
 
326
+ struct kv_rate_limits {
327
+ uint32_t num_connections{0};
328
+ uint32_t num_ops_per_min{0};
329
+ uint32_t ingress_mib_per_min{0};
330
+ uint32_t egress_mib_per_min{0};
331
+ bool enforce{false};
332
+ };
333
+
334
+ struct query_rate_limits {
335
+ uint32_t ingress_mib_per_min{0};
336
+ uint32_t egress_mib_per_min{0};
337
+ uint32_t num_concurrent_requests{0};
338
+ uint32_t num_queries_per_min{0};
339
+ bool enforce{false};
340
+ };
341
+
342
+ struct search_rate_limits {
343
+ uint32_t ingress_mib_per_min{0};
344
+ uint32_t egress_mib_per_min{0};
345
+ uint32_t num_concurrent_requests{0};
346
+ uint32_t num_queries_per_min{0};
347
+ bool enforce{false};
348
+ };
349
+
350
+ struct rate_limits {
351
+ kv_rate_limits kv_limits{};
352
+ query_rate_limits query_limits{};
353
+ search_rate_limits search_limits{};
354
+ };
355
+
356
+ struct kv_scope_rate_limits {
357
+ uint32_t data_size;
358
+ bool enforce{false};
359
+ };
360
+
361
+ struct index_scope_rate_limits {
362
+ uint32_t num_indexes{0};
363
+ bool enforce{false};
364
+ };
365
+
366
+ struct scope_rate_limits {
367
+ kv_scope_rate_limits kv_scope_limits;
368
+ index_scope_rate_limits index_scope_limits;
369
+ };
370
+
371
+ void enforce_rate_limits(lcb_INSTANCE *instance);
372
+ void create_rate_limited_user(lcb_INSTANCE *instance, const std::string &username, const rate_limits &limits);
373
+ void drop_user(lcb_INSTANCE *instance, const std::string &username);
374
+ void create_rate_limited_scope(lcb_INSTANCE *instance, const std::string &bucket, std::string &scope,
375
+ const scope_rate_limits &limits);
376
+ void create_search_index(lcb_INSTANCE *instance, const std::string &index_name, const std::string &type,
377
+ const std::string &source_type, const std::string &source_name);
378
+
326
379
  #endif
@@ -75,7 +75,7 @@ IF(NOT WIN32)
75
75
  LIST(APPEND CBC_SUBCOMMANDS
76
76
  cat create observe observe-seqno incr decr hash lock
77
77
  unlock rm stats version verbosity view n1ql admin ping
78
- bucket-create bucket-delete bucket-flush connstr write-config strerror
78
+ bucket-list bucket-create bucket-delete bucket-flush connstr write-config strerror
79
79
  touch role-list user-list user-upsert user-delete watch
80
80
  mcversion keygen collection-manifest collection-id
81
81
  )
@@ -827,6 +827,45 @@ class UserUpsertHandler : public AdminHandler
827
827
  std::string body;
828
828
  };
829
829
 
830
+ class BucketListHandler : public AdminHandler
831
+ {
832
+ public:
833
+ HANDLER_DESCRIPTION("List buckets")
834
+ HANDLER_USAGE("NAME [OPTIONS ...]")
835
+ BucketListHandler() : AdminHandler("bucket-list"), o_raw('r', "raw")
836
+ {
837
+ o_raw.description("Do not reformat output from server (display JSON response)");
838
+ }
839
+
840
+ protected:
841
+ void run() override;
842
+ void format();
843
+
844
+ void addOptions() override
845
+ {
846
+ AdminHandler::addOptions();
847
+ parser.addOption(o_raw);
848
+ }
849
+
850
+ std::string getURI() override
851
+ {
852
+ return "/pools/default/buckets";
853
+ }
854
+
855
+ std::string getContentType() override
856
+ {
857
+ return "application/json";
858
+ }
859
+
860
+ lcb_HTTP_METHOD getMethod() override
861
+ {
862
+ return LCB_HTTP_METHOD_GET;
863
+ }
864
+
865
+ private:
866
+ cliopts::BoolOption o_raw;
867
+ };
868
+
830
869
  class BucketCreateHandler : public AdminHandler
831
870
  {
832
871
  public:
@@ -458,6 +458,7 @@ class ThreadContext
458
458
  lcb_STATUS rc = lcb_query(m_instance, &qctx, m_cmd);
459
459
  if (rc != LCB_SUCCESS) {
460
460
  log_error(rc, query.payload.c_str(), query.payload.size());
461
+ lcb_tick_nowait(m_instance);
461
462
  } else {
462
463
  lcb_wait(m_instance, LCB_WAIT_DEFAULT);
463
464
  m_metrics.lock();
@@ -104,7 +104,7 @@ class Configuration
104
104
  o_startAt("start-at"), o_rateLimit("rate-limit"), o_userdocs("docs"), o_writeJson("json"),
105
105
  o_templatePairs("template"), o_subdoc("subdoc"), o_noop("noop"), o_sdPathCount("pathcount"),
106
106
  o_populateOnly("populate-only"), o_exptime("expiry"), o_collection("collection"), o_durability("durability"),
107
- o_persist("persist-to"), o_replicate("replicate-to"), o_lock("lock")
107
+ o_persist("persist-to"), o_replicate("replicate-to"), o_lock("lock"), o_randSpace("rand-space-per-thread")
108
108
  {
109
109
  o_multiSize.setDefault(100).abbrev('B').description("Number of operations to batch");
110
110
  o_numItems.setDefault(1000).abbrev('I').description("Number of items to operate on");
@@ -138,6 +138,8 @@ class Configuration
138
138
  o_replicate.description("Wait until item is replicated to this number of nodes (-1 for all replicas)")
139
139
  .setDefault(0);
140
140
  o_lock.description("Lock keys for updates for given time (will not lock when set to zero)").setDefault(0);
141
+ o_randSpace.description("When set and --sequential is not set, threads will perform operations on different key"
142
+ " spaces").setDefault(false);
141
143
  params.getTimings().description("Enable command timings (second time to dump timings automatically)");
142
144
  }
143
145
 
@@ -218,25 +220,25 @@ class Configuration
218
220
 
219
221
  if (specs.empty()) {
220
222
  if (o_writeJson.result()) {
221
- docgen = new JsonDocGenerator(o_minSize.result(), o_maxSize.result(), o_randomBody.numSpecified());
223
+ docgen.reset(new JsonDocGenerator(o_minSize.result(), o_maxSize.result(), o_randomBody.numSpecified()));
222
224
  } else if (!userdocs.empty()) {
223
- docgen = new PresetDocGenerator(userdocs);
225
+ docgen.reset(new PresetDocGenerator(userdocs));
224
226
  } else {
225
- docgen = new RawDocGenerator(o_minSize.result(), o_maxSize.result(), o_randomBody.numSpecified());
227
+ docgen.reset(new RawDocGenerator(o_minSize.result(), o_maxSize.result(), o_randomBody.numSpecified()));
226
228
  }
227
229
  } else {
228
230
  if (o_writeJson.result()) {
229
231
  if (userdocs.empty()) {
230
- docgen = new PlaceholderJsonGenerator(o_minSize.result(), o_maxSize.result(), specs,
231
- o_randomBody.numSpecified());
232
+ docgen.reset(new PlaceholderJsonGenerator(o_minSize.result(), o_maxSize.result(), specs,
233
+ o_randomBody.numSpecified()));
232
234
  } else {
233
- docgen = new PlaceholderJsonGenerator(userdocs, specs);
235
+ docgen.reset(new PlaceholderJsonGenerator(userdocs, specs));
234
236
  }
235
237
  } else {
236
238
  if (userdocs.empty()) {
237
239
  throw std::runtime_error("Must provide documents with placeholders!");
238
240
  }
239
- docgen = new PlaceholderDocGenerator(userdocs, specs);
241
+ docgen.reset(new PlaceholderDocGenerator(userdocs, specs));
240
242
  }
241
243
  }
242
244
 
@@ -279,6 +281,7 @@ class Configuration
279
281
  parser.addOption(o_persist);
280
282
  parser.addOption(o_replicate);
281
283
  parser.addOption(o_lock);
284
+ parser.addOption(o_randSpace);
282
285
  params.addToParser(parser);
283
286
  depr.addOptions(parser);
284
287
  }
@@ -357,6 +360,10 @@ class Configuration
357
360
  {
358
361
  return o_exptime;
359
362
  }
363
+ bool useRandSpacePerThread()
364
+ {
365
+ return o_randSpace;
366
+ }
360
367
 
361
368
  uint32_t opsPerCycle{};
362
369
  uint32_t sdOpsPerCmd{};
@@ -365,7 +372,7 @@ class Configuration
365
372
  volatile int maxCycles{};
366
373
  bool shouldPopulate{};
367
374
  ConnParams params;
368
- const DocGeneratorBase *docgen{};
375
+ std::unique_ptr<DocGeneratorBase> docgen;
369
376
  vector<string> collections{};
370
377
  lcb_DURABILITY_LEVEL durabilityLevel{LCB_DURABILITYLEVEL_NONE};
371
378
  int replicateTo{};
@@ -411,6 +418,7 @@ class Configuration
411
418
  IntOption o_replicate;
412
419
 
413
420
  IntOption o_lock;
421
+ BoolOption o_randSpace;
414
422
  DeprecatedOptions depr;
415
423
  } config;
416
424
 
@@ -569,12 +577,14 @@ class KeyGenerator : public OpGenerator
569
577
  explicit KeyGenerator(int ix)
570
578
  : OpGenerator(ix), m_gencount(0), m_force_sequential(false), m_in_population(config.shouldPopulate)
571
579
  {
572
- srand(config.getRandomSeed());
580
+ if(!config.useRandSpacePerThread()) {
581
+ srand(config.getRandomSeed());
582
+ }
573
583
 
574
- m_genrandom = new SeqGenerator(config.firstKeyOffset(), config.getNumItems() + config.firstKeyOffset());
584
+ m_genrandom.reset(new SeqGenerator(config.firstKeyOffset(), config.getNumItems() + config.firstKeyOffset()));
575
585
 
576
- m_gensequence = new SeqGenerator(config.firstKeyOffset(), config.getNumItems() + config.firstKeyOffset(),
577
- config.getNumThreads(), ix);
586
+ m_gensequence.reset(new SeqGenerator(config.firstKeyOffset(), config.getNumItems() + config.firstKeyOffset(),
587
+ config.getNumThreads(), ix));
578
588
 
579
589
  if (m_in_population) {
580
590
  m_force_sequential = true;
@@ -701,16 +711,16 @@ class KeyGenerator : public OpGenerator
701
711
  }
702
712
  }
703
713
 
704
- SeqGenerator *m_genrandom;
705
- SeqGenerator *m_gensequence;
714
+ std::unique_ptr<SeqGenerator> m_genrandom;
715
+ std::unique_ptr<SeqGenerator> m_gensequence;
706
716
  size_t m_gencount;
707
717
 
708
718
  bool m_force_sequential;
709
719
  bool m_in_population;
710
720
  NextOp::Mode m_mode_read;
711
721
  NextOp::Mode m_mode_write;
712
- GeneratorState *m_local_genstate;
713
- SubdocGeneratorState *m_sdgenstate;
722
+ std::unique_ptr<GeneratorState> m_local_genstate;
723
+ std::unique_ptr<SubdocGeneratorState> m_sdgenstate;
714
724
  };
715
725
 
716
726
  #define OPFLAGS_LOCKED 0x01
@@ -721,16 +731,15 @@ class ThreadContext
721
731
  ThreadContext(lcb_INSTANCE *handle, int ix) : niter(0), instance(handle)
722
732
  {
723
733
  if (config.isNoop()) {
724
- gen = new NoopGenerator(ix);
734
+ gen.reset(new NoopGenerator(ix));
725
735
  } else {
726
- gen = new KeyGenerator(ix);
736
+ gen.reset(new KeyGenerator(ix));
727
737
  }
728
738
  }
729
739
 
730
740
  ~ThreadContext()
731
741
  {
732
- delete gen;
733
- gen = nullptr;
742
+ lcb_destroy(instance);
734
743
  }
735
744
 
736
745
  bool inPopulation()
@@ -993,7 +1002,7 @@ class ThreadContext
993
1002
  previous_time = now;
994
1003
  }
995
1004
 
996
- OpGenerator *gen;
1005
+ std::unique_ptr<OpGenerator> gen;
997
1006
  size_t niter;
998
1007
  lcb_STATUS error{LCB_SUCCESS};
999
1008
  lcb_INSTANCE *instance{nullptr};
@@ -1197,7 +1206,8 @@ static void storeCallback(lcb_INSTANCE *instance, int, const lcb_RESPSTORE *resp
1197
1206
  updateOpsPerSecDisplay();
1198
1207
  }
1199
1208
 
1200
- std::list<ThreadContext *> contexts;
1209
+ std::list<InstanceCookie> cookies;
1210
+ std::list<ThreadContext> contexts;
1201
1211
 
1202
1212
  extern "C" {
1203
1213
  typedef void (*handler_t)(int);
@@ -1205,8 +1215,8 @@ typedef void (*handler_t)(int);
1205
1215
  static void dump_metrics()
1206
1216
  {
1207
1217
  std::list<ThreadContext *>::iterator it;
1208
- for (it = contexts.begin(); it != contexts.end(); ++it) {
1209
- lcb_INSTANCE *instance = (*it)->getInstance();
1218
+ for (auto& context : contexts) {
1219
+ lcb_INSTANCE *instance = context.getInstance();
1210
1220
  lcb_CMDDIAG *req;
1211
1221
  lcb_cmddiag_create(&req);
1212
1222
  lcb_cmddiag_prettify(req, true);
@@ -1284,10 +1294,6 @@ static void sigint_handler(int)
1284
1294
  return;
1285
1295
  }
1286
1296
 
1287
- std::list<ThreadContext *>::iterator it;
1288
- for (it = contexts.begin(); it != contexts.end(); ++it) {
1289
- delete *it;
1290
- }
1291
1297
  contexts.clear();
1292
1298
  exit(EXIT_FAILURE);
1293
1299
  }
@@ -1315,10 +1321,10 @@ static void start_worker(ThreadContext *ctx)
1315
1321
  exit(EXIT_FAILURE);
1316
1322
  }
1317
1323
  }
1318
- static void join_worker(ThreadContext *ctx)
1324
+ static void join_worker(ThreadContext& ctx)
1319
1325
  {
1320
1326
  void *arg = nullptr;
1321
- int rc = pthread_join(ctx->thr, &arg);
1327
+ int rc = pthread_join(ctx.thr, &arg);
1322
1328
  if (rc != 0) {
1323
1329
  log("Couldn't join thread (%d)", errno);
1324
1330
  exit(EXIT_FAILURE);
@@ -1332,7 +1338,7 @@ static void start_worker(ThreadContext *ctx)
1332
1338
  {
1333
1339
  ctx->run();
1334
1340
  }
1335
- static void join_worker(ThreadContext *ctx)
1341
+ static void join_worker(ThreadContext& ctx)
1336
1342
  {
1337
1343
  (void)ctx;
1338
1344
  }
@@ -1373,6 +1379,9 @@ int main(int argc, char **argv)
1373
1379
  nthreads = 1;
1374
1380
  }
1375
1381
  #endif
1382
+ if(config.useRandSpacePerThread()) {
1383
+ srand(config.getRandomSeed());
1384
+ }
1376
1385
 
1377
1386
  lcb_CREATEOPTS *options = nullptr;
1378
1387
  ConnParams &cp = config.params;
@@ -1406,7 +1415,8 @@ int main(int argc, char **argv)
1406
1415
  lcb_cntl(instance, LCB_CNTL_SET, LCB_CNTL_ENABLE_COLLECTIONS, &use);
1407
1416
  }
1408
1417
 
1409
- auto *cookie = new InstanceCookie(instance);
1418
+ cookies.emplace_back(instance);
1419
+ auto* cookie = &cookies.back();
1410
1420
 
1411
1421
  lcb_connect(instance);
1412
1422
  lcb_wait(instance, LCB_WAIT_DEFAULT);
@@ -1418,9 +1428,9 @@ int main(int argc, char **argv)
1418
1428
  exit(EXIT_FAILURE);
1419
1429
  }
1420
1430
 
1421
- auto *ctx = new ThreadContext(instance, ii);
1431
+ contexts.emplace_back(instance, ii);
1432
+ auto* ctx = &contexts.back();
1422
1433
  cookie->setContext(ctx);
1423
- contexts.push_back(ctx);
1424
1434
  start_worker(ctx);
1425
1435
  }
1426
1436
 
@@ -2023,6 +2023,35 @@ void AdminHandler::run()
2023
2023
  printf("%s\n", resbuf.c_str());
2024
2024
  }
2025
2025
 
2026
+ void BucketListHandler::run()
2027
+ {
2028
+ fprintf(stderr, "Requesting %s\n", getURI().c_str());
2029
+ HttpBaseHandler::run();
2030
+ if (o_raw.result()) {
2031
+ printf("%s\n", resbuf.c_str());
2032
+ } else {
2033
+ format();
2034
+ }
2035
+ }
2036
+
2037
+ void BucketListHandler::format()
2038
+ {
2039
+ Json::Value json;
2040
+ if (!Json::Reader().parse(resbuf, json)) {
2041
+ fprintf(stderr, "Failed to parse response as JSON, falling back to raw mode\n");
2042
+ printf("%s\n", resbuf.c_str());
2043
+ }
2044
+
2045
+ printf("%-20s%-10s%s\n", "Name", "Type", "Items");
2046
+
2047
+ for (Json::Value::ArrayIndex i = 0; i < json.size(); ++i) {
2048
+ const char *name = json[i]["name"].asString().c_str();
2049
+ const char *bucketType = json[i]["bucketType"].asString().c_str();
2050
+ const int itemCount = json[i]["basicStats"]["itemCount"].asInt();
2051
+ printf("%-20s%-10s%i\n", name, bucketType, itemCount);
2052
+ }
2053
+ }
2054
+
2026
2055
  void BucketCreateHandler::run()
2027
2056
  {
2028
2057
  const string &name = getRequiredArg();
@@ -2278,6 +2307,7 @@ static const char *optionsOrder[] = {"help",
2278
2307
  "analytics",
2279
2308
  "search",
2280
2309
  "admin",
2310
+ "bucket-list",
2281
2311
  "bucket-create",
2282
2312
  "bucket-delete",
2283
2313
  "bucket-flush",
@@ -2369,6 +2399,7 @@ static void setupHandlers()
2369
2399
  handlers_s["incr"] = new IncrHandler();
2370
2400
  handlers_s["decr"] = new DecrHandler();
2371
2401
  handlers_s["admin"] = new AdminHandler();
2402
+ handlers_s["bucket-list"] = new BucketListHandler();
2372
2403
  handlers_s["bucket-create"] = new BucketCreateHandler();
2373
2404
  handlers_s["bucket-delete"] = new BucketDeleteHandler();
2374
2405
  handlers_s["bucket-flush"] = new BucketFlushHandler();
@@ -18,6 +18,7 @@
18
18
  #include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
19
19
  #include "placeholders.h"
20
20
  #include <algorithm>
21
+ #include <memory>
21
22
  #include <stdexcept>
22
23
 
23
24
  namespace Pillowfight
@@ -78,8 +79,8 @@ class DocGeneratorBase
78
79
  * @param cur_gen The index of the current generator thread
79
80
  * @return An opaque state object. This should be deleted by the caller
80
81
  */
81
- virtual GeneratorState *createState(int total_gens, int cur_gen) const = 0;
82
- virtual SubdocGeneratorState *createSubdocState(int, int) const
82
+ virtual std::unique_ptr<GeneratorState> createState(int total_gens, int cur_gen) const = 0;
83
+ virtual std::unique_ptr<SubdocGeneratorState> createSubdocState(int, int) const
83
84
  {
84
85
  return NULL;
85
86
  }
@@ -164,9 +165,9 @@ class RawDocGenerator : public DocGeneratorBase
164
165
  }
165
166
  };
166
167
 
167
- GeneratorState *createState(int, int) const
168
+ std::unique_ptr<GeneratorState> createState(int, int) const
168
169
  {
169
- return new MyState(this);
170
+ return std::unique_ptr<GeneratorState>(new MyState(this));
170
171
  }
171
172
 
172
173
  private:
@@ -207,9 +208,9 @@ class PresetDocGenerator : public DocGeneratorBase
207
208
  const PresetDocGenerator *m_parent;
208
209
  };
209
210
 
210
- GeneratorState *createState(int, int) const
211
+ std::unique_ptr<GeneratorState> createState(int, int) const
211
212
  {
212
- return new MyState(this);
213
+ return std::unique_ptr<GeneratorState>(new MyState(this));
213
214
  }
214
215
 
215
216
  protected:
@@ -371,9 +372,9 @@ class JsonDocGenerator : public PresetDocGenerator
371
372
  };
372
373
 
373
374
  public:
374
- virtual SubdocGeneratorState *createSubdocState(int, int) const
375
+ virtual std::unique_ptr<SubdocGeneratorState> createSubdocState(int, int) const
375
376
  {
376
- return new SDGenstate(m_docs);
377
+ return std::unique_ptr<SubdocGeneratorState>(new SDGenstate(m_docs));
377
378
  }
378
379
  };
379
380
 
@@ -424,9 +425,9 @@ class PlaceholderDocGenerator : public DocGeneratorBase
424
425
  }
425
426
 
426
427
  public:
427
- GeneratorState *createState(int total, int cur) const
428
+ std::unique_ptr<GeneratorState> createState(int total, int cur) const
428
429
  {
429
- return new MyState(this, total, cur);
430
+ return std::unique_ptr<GeneratorState>(new MyState(this, total, cur));
430
431
  }
431
432
 
432
433
  private:
@@ -82,8 +82,8 @@ class AnalyticsExecutor {
82
82
  }
83
83
  const metricsData = metaData.metrics || {};
84
84
  const metrics = new analyticstypes_1.AnalyticsMetrics({
85
- elapsedTime: utilities_1.goDurationStrToMs(metricsData.elapsedTime) || 0,
86
- executionTime: utilities_1.goDurationStrToMs(metricsData.executionTime) || 0,
85
+ elapsedTime: (0, utilities_1.goDurationStrToMs)(metricsData.elapsedTime) || 0,
86
+ executionTime: (0, utilities_1.goDurationStrToMs)(metricsData.executionTime) || 0,
87
87
  resultCount: metricsData.resultCount || 0,
88
88
  resultSize: metricsData.resultSize || 0,
89
89
  errorCount: metricsData.errorCount || 0,