couchbase 3.2.4 → 3.2.6
Sign up to get free protection for your applications and to get access to all the features.
- package/binding.gyp +5 -0
- package/deps/lcb/CMakeLists.txt +28 -6
- package/deps/lcb/README.markdown +5 -9
- package/deps/lcb/RELEASE_NOTES.markdown +80 -5
- package/deps/lcb/cmake/Modules/GetVersionInfo.cmake +1 -1
- package/deps/lcb/doc/Doxyfile +1 -1
- package/deps/lcb/doc/cbc.markdown +10 -0
- package/deps/lcb/gyp_config/common/libcouchbase/configuration.h +3 -3
- package/deps/lcb/include/libcouchbase/couchbase.h +52 -0
- package/deps/lcb/include/libcouchbase/error.h +5 -2
- package/deps/lcb/libcouchbase.gyp +7 -1
- package/deps/lcb/packaging/rpm/libcouchbase.spec.in +1 -1
- package/deps/lcb/plugins/io/iocp/iocp_iops.h +1 -1
- package/deps/lcb/plugins/io/iocp/iocp_loop.c +3 -3
- package/deps/lcb/plugins/io/iocp/iocp_util.c +2 -2
- package/deps/lcb/src/bucketconfig/bc_file.cc +29 -15
- package/deps/lcb/src/capi/cmd_counter.hh +12 -0
- package/deps/lcb/src/capi/cmd_exists.hh +12 -0
- package/deps/lcb/src/capi/cmd_get.hh +12 -0
- package/deps/lcb/src/capi/cmd_get_replica.hh +14 -1
- package/deps/lcb/src/capi/cmd_query.cc +13 -0
- package/deps/lcb/src/capi/cmd_query.hh +22 -14
- package/deps/lcb/src/capi/cmd_remove.hh +12 -0
- package/deps/lcb/src/capi/cmd_store.hh +12 -0
- package/deps/lcb/src/capi/cmd_subdoc.hh +12 -0
- package/deps/lcb/src/capi/cmd_touch.hh +12 -0
- package/deps/lcb/src/capi/cmd_unlock.hh +12 -0
- package/deps/lcb/src/capi/collection_qualifier.hh +4 -9
- package/deps/lcb/src/instance.cc +19 -0
- package/deps/lcb/src/internal.h +2 -1
- package/deps/lcb/src/mcserver/negotiate.cc +3 -0
- package/deps/lcb/src/n1ql/n1ql.cc +5 -1
- package/deps/lcb/src/n1ql/query_handle.cc +55 -30
- package/deps/lcb/src/n1ql/query_handle.hh +14 -2
- package/deps/lcb/src/operations/counter.cc +12 -0
- package/deps/lcb/src/operations/exists.cc +12 -0
- package/deps/lcb/src/operations/get.cc +12 -0
- package/deps/lcb/src/operations/get_replica.cc +18 -6
- package/deps/lcb/src/operations/ping.cc +2 -2
- package/deps/lcb/src/operations/remove.cc +12 -0
- package/deps/lcb/src/operations/store.cc +12 -0
- package/deps/lcb/src/operations/subdoc.cc +12 -0
- package/deps/lcb/src/operations/touch.cc +12 -0
- package/deps/lcb/src/operations/unlock.cc +12 -0
- package/deps/lcb/src/search/search_handle.cc +1 -2
- package/deps/lcb/src/settings.cc +1 -0
- package/deps/lcb/src/ssl/ssl_common.c +111 -22
- package/deps/lcb/src/utilities.cc +21 -0
- package/deps/lcb/src/utilities.h +3 -0
- package/deps/lcb/src/vbucket/vbucket.c +16 -7
- package/deps/lcb/tests/CMakeLists.txt +1 -1
- package/deps/lcb/tests/iotests/mock-environment.cc +13 -1
- package/deps/lcb/tests/iotests/mock-environment.h +3 -1
- package/deps/lcb/tests/iotests/serverparams.h +7 -2
- package/deps/lcb/tests/iotests/t_ratelimit.cc +739 -0
- package/deps/lcb/tests/iotests/testutil.cc +174 -0
- package/deps/lcb/tests/iotests/testutil.h +53 -0
- package/deps/lcb/tools/CMakeLists.txt +1 -1
- package/deps/lcb/tools/cbc-handlers.h +39 -0
- package/deps/lcb/tools/cbc-n1qlback.cc +1 -0
- package/deps/lcb/tools/cbc-pillowfight.cc +45 -35
- package/deps/lcb/tools/cbc.cc +31 -0
- package/deps/lcb/tools/docgen/docgen.h +11 -10
- package/dist/analyticsexecutor.js +2 -2
- package/dist/analyticsindexmanager.js +3 -3
- package/dist/binarycollection.d.ts +17 -0
- package/dist/binding.js +1 -1
- package/dist/bindingutilities.js +5 -1
- package/dist/bucketmanager.d.ts +1 -22
- package/dist/bucketmanager.js +5 -5
- package/dist/cluster.js +1 -1
- package/dist/collection.js +6 -6
- package/dist/collectionmanager.js +2 -2
- package/dist/connection.js +3 -3
- package/dist/connspec.js +5 -1
- package/dist/couchbase.js +5 -1
- package/dist/httpexecutor.d.ts +1 -0
- package/dist/httpexecutor.js +5 -1
- package/dist/logging.js +1 -1
- package/dist/queryexecutor.js +3 -3
- package/dist/searchindexmanager.js +1 -1
- package/dist/usermanager.js +2 -2
- package/dist/utilities.d.ts +1 -2
- package/dist/utilities.js +9 -2
- package/dist/viewexecutor.js +1 -1
- package/package.json +1 -1
- package/src/uv-plugin-all.cpp +1 -0
- package/dist/cas.d.ts +0 -0
- 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
|
223
|
+
docgen.reset(new JsonDocGenerator(o_minSize.result(), o_maxSize.result(), o_randomBody.numSpecified()));
|
222
224
|
} else if (!userdocs.empty()) {
|
223
|
-
docgen
|
225
|
+
docgen.reset(new PresetDocGenerator(userdocs));
|
224
226
|
} else {
|
225
|
-
docgen
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
580
|
+
if(!config.useRandSpacePerThread()) {
|
581
|
+
srand(config.getRandomSeed());
|
582
|
+
}
|
573
583
|
|
574
|
-
m_genrandom
|
584
|
+
m_genrandom.reset(new SeqGenerator(config.firstKeyOffset(), config.getNumItems() + config.firstKeyOffset()));
|
575
585
|
|
576
|
-
m_gensequence
|
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
|
705
|
-
SeqGenerator
|
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
|
713
|
-
SubdocGeneratorState
|
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
|
734
|
+
gen.reset(new NoopGenerator(ix));
|
725
735
|
} else {
|
726
|
-
gen
|
736
|
+
gen.reset(new KeyGenerator(ix));
|
727
737
|
}
|
728
738
|
}
|
729
739
|
|
730
740
|
~ThreadContext()
|
731
741
|
{
|
732
|
-
|
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
|
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<
|
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 (
|
1209
|
-
lcb_INSTANCE *instance =
|
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
|
1324
|
+
static void join_worker(ThreadContext& ctx)
|
1319
1325
|
{
|
1320
1326
|
void *arg = nullptr;
|
1321
|
-
int rc = pthread_join(ctx
|
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
|
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
|
-
|
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
|
-
|
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
|
|
package/deps/lcb/tools/cbc.cc
CHANGED
@@ -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
|
82
|
-
virtual SubdocGeneratorState
|
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
|
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
|
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
|
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
|
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,
|