couchbase 3.2.4 → 3.2.6
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.
- 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,
|