couchbase 3.2.5 → 3.2.6
Sign up to get free protection for your applications and to get access to all the features.
- package/deps/lcb/CMakeLists.txt +28 -6
- package/deps/lcb/README.markdown +5 -9
- package/deps/lcb/RELEASE_NOTES.markdown +75 -12
- 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/error.h +1 -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/collection_qualifier.hh +0 -3
- package/deps/lcb/src/instance.cc +19 -0
- package/deps/lcb/src/operations/ping.cc +2 -2
- package/deps/lcb/src/settings.cc +1 -0
- package/deps/lcb/src/ssl/ssl_common.c +111 -22
- 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 +3 -0
- package/deps/lcb/tests/iotests/mock-environment.h +1 -0
- package/deps/lcb/tests/iotests/t_ratelimit.cc +11 -1
- 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/httpexecutor.d.ts +1 -0
- package/package.json +1 -1
@@ -32,6 +32,26 @@
|
|
32
32
|
#define LOGARGS(ssl, lvl) ((lcbio_SOCKET *)SSL_get_app_data(ssl))->settings, "SSL", lvl, __FILE__, __LINE__
|
33
33
|
static char *global_event = "dummy event for ssl";
|
34
34
|
|
35
|
+
static const char *capella_ca_cert = "-----BEGIN CERTIFICATE-----\n"
|
36
|
+
"MIIDFTCCAf2gAwIBAgIRANLVkgOvtaXiQJi0V6qeNtswDQYJKoZIhvcNAQELBQAw\n"
|
37
|
+
"JDESMBAGA1UECgwJQ291Y2hiYXNlMQ4wDAYDVQQLDAVDbG91ZDAeFw0xOTEyMDYy\n"
|
38
|
+
"MjEyNTlaFw0yOTEyMDYyMzEyNTlaMCQxEjAQBgNVBAoMCUNvdWNoYmFzZTEOMAwG\n"
|
39
|
+
"A1UECwwFQ2xvdWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfvOIi\n"
|
40
|
+
"enG4Dp+hJu9asdxEMRmH70hDyMXv5ZjBhbo39a42QwR59y/rC/sahLLQuNwqif85\n"
|
41
|
+
"Fod1DkqgO6Ng3vecSAwyYVkj5NKdycQu5tzsZkghlpSDAyI0xlIPSQjoORA/pCOU\n"
|
42
|
+
"WOpymA9dOjC1bo6rDyw0yWP2nFAI/KA4Z806XeqLREuB7292UnSsgFs4/5lqeil6\n"
|
43
|
+
"rL3ooAw/i0uxr/TQSaxi1l8t4iMt4/gU+W52+8Yol0JbXBTFX6itg62ppb/Eugmn\n"
|
44
|
+
"mQRMgL67ccZs7cJ9/A0wlXencX2ohZQOR3mtknfol3FH4+glQFn27Q4xBCzVkY9j\n"
|
45
|
+
"KQ20T1LgmGSngBInAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE\n"
|
46
|
+
"FJQOBPvrkU2In1Sjoxt97Xy8+cKNMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0B\n"
|
47
|
+
"AQsFAAOCAQEARgM6XwcXPLSpFdSf0w8PtpNGehmdWijPM3wHb7WZiS47iNen3oq8\n"
|
48
|
+
"m2mm6V3Z57wbboPpfI+VEzbhiDcFfVnK1CXMC0tkF3fnOG1BDDvwt4jU95vBiNjY\n"
|
49
|
+
"xdzlTP/Z+qr0cnVbGBSZ+fbXstSiRaaAVcqQyv3BRvBadKBkCyPwo+7svQnScQ5P\n"
|
50
|
+
"Js7HEHKVms5tZTgKIw1fbmgR2XHleah1AcANB+MAPBCcTgqurqr5G7W2aPSBLLGA\n"
|
51
|
+
"fRIiVzm7VFLc7kWbp7ENH39HVG6TZzKnfl9zJYeiklo5vQQhGSMhzBsO70z4RRzi\n"
|
52
|
+
"DPFAN/4qZAgD5q3AFNIq2WWADFQGSwVJhg==\n"
|
53
|
+
"-----END CERTIFICATE-----\n";
|
54
|
+
|
35
55
|
/******************************************************************************
|
36
56
|
******************************************************************************
|
37
57
|
** Boilerplate lcbio_TABLE Wrappers **
|
@@ -221,6 +241,9 @@ static void log_callback(const SSL *ssl, int where, int ret)
|
|
221
241
|
{
|
222
242
|
int should_log = 0;
|
223
243
|
lcbio_SOCKET *sock = SSL_get_app_data(ssl);
|
244
|
+
if (sock == NULL) {
|
245
|
+
return;
|
246
|
+
}
|
224
247
|
/* Ignore low-level SSL stuff */
|
225
248
|
|
226
249
|
if (where & SSL_CB_ALERT) {
|
@@ -298,6 +321,48 @@ static long decode_ssl_protocol(const char *protocol)
|
|
298
321
|
return disallow;
|
299
322
|
}
|
300
323
|
|
324
|
+
static lcb_STATUS add_certificate_authority(const lcb_settings *settings, SSL_CTX *ctx, const char *certificate_value,
|
325
|
+
int certificate_length)
|
326
|
+
{
|
327
|
+
lcb_STATUS rc = LCB_SUCCESS;
|
328
|
+
ERR_clear_error();
|
329
|
+
|
330
|
+
BIO *bio = BIO_new_mem_buf(certificate_value, certificate_length);
|
331
|
+
if (bio) {
|
332
|
+
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
|
333
|
+
if (store) {
|
334
|
+
for (int added = 0;; added = 1) {
|
335
|
+
X509 *cert = PEM_read_bio_X509(bio, 0, 0, 0);
|
336
|
+
if (!cert) {
|
337
|
+
unsigned long err = ERR_get_error();
|
338
|
+
if (added && ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR),
|
342
|
+
"Unable to load default certificate: lib=%s, func=%s, reason=%s", ERR_lib_error_string(err),
|
343
|
+
ERR_func_error_string(err), ERR_reason_error_string(err));
|
344
|
+
rc = LCB_ERR_SSL_ERROR;
|
345
|
+
goto GT_CLEANUP;
|
346
|
+
}
|
347
|
+
|
348
|
+
int ok = X509_STORE_add_cert(store, cert);
|
349
|
+
X509_free(cert);
|
350
|
+
if (ok != 1) {
|
351
|
+
unsigned long err = ERR_get_error();
|
352
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR),
|
353
|
+
"Unable to add default certificate: lib=%s, func=%s, reason=%s", ERR_lib_error_string(err),
|
354
|
+
ERR_func_error_string(err), ERR_reason_error_string(err));
|
355
|
+
rc = LCB_ERR_SSL_ERROR;
|
356
|
+
goto GT_CLEANUP;
|
357
|
+
}
|
358
|
+
}
|
359
|
+
}
|
360
|
+
}
|
361
|
+
GT_CLEANUP:
|
362
|
+
BIO_free(bio);
|
363
|
+
return rc;
|
364
|
+
}
|
365
|
+
|
301
366
|
lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *keyfile, int noverify, lcb_STATUS *errp,
|
302
367
|
lcb_settings *settings)
|
303
368
|
{
|
@@ -351,28 +416,41 @@ lcbio_pSSLCTX lcbio_ssl_new(const char *tsfile, const char *cafile, const char *
|
|
351
416
|
}
|
352
417
|
#endif
|
353
418
|
|
354
|
-
if (
|
419
|
+
if (tsfile) {
|
355
420
|
lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Load verify locations from \"%s\"", tsfile ? tsfile : cafile);
|
356
421
|
if (!SSL_CTX_load_verify_locations(ret->ctx, tsfile ? tsfile : cafile, NULL)) {
|
357
422
|
*errp = LCB_ERR_SSL_ERROR;
|
358
423
|
goto GT_ERR;
|
359
424
|
}
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
425
|
+
} else {
|
426
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Use default CA for TLS verify");
|
427
|
+
if (SSL_CTX_set_default_verify_paths(ret->ctx) != 1) {
|
428
|
+
unsigned long err = ERR_get_error();
|
429
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_WARN), "Unable to load system certificates: lib=%s, reason=%s",
|
430
|
+
ERR_lib_error_string(err), ERR_reason_error_string(err));
|
431
|
+
}
|
432
|
+
// add the capella Root CA if no other CA was specified.
|
433
|
+
*errp = add_certificate_authority(settings, ret->ctx, capella_ca_cert, strlen(capella_ca_cert));
|
434
|
+
if (*errp != LCB_SUCCESS) {
|
435
|
+
goto GT_ERR;
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
if (cafile && keyfile) {
|
440
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_DEBUG), "Authenticate with key \"%s\", cert \"%s\"", keyfile, cafile);
|
441
|
+
if (!SSL_CTX_use_certificate_chain_file(ret->ctx, cafile)) {
|
442
|
+
*errp = LCB_ERR_SSL_ERROR;
|
443
|
+
goto GT_ERR;
|
444
|
+
}
|
445
|
+
if (!SSL_CTX_use_PrivateKey_file(ret->ctx, keyfile, SSL_FILETYPE_PEM)) {
|
446
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to load private key \"%s\"", keyfile);
|
447
|
+
*errp = LCB_ERR_SSL_ERROR;
|
448
|
+
goto GT_ERR;
|
449
|
+
}
|
450
|
+
if (!SSL_CTX_check_private_key(ret->ctx)) {
|
451
|
+
lcb_log(LOGARGS_S(settings, LCB_LOG_ERROR), "Unable to verify private key \"%s\"", keyfile);
|
452
|
+
*errp = LCB_ERR_SSL_ERROR;
|
453
|
+
goto GT_ERR;
|
376
454
|
}
|
377
455
|
}
|
378
456
|
|
@@ -422,15 +500,25 @@ GT_ERR:
|
|
422
500
|
return NULL;
|
423
501
|
}
|
424
502
|
|
503
|
+
struct proto_ctx_ssl {
|
504
|
+
lcbio_PROTOCTX proto;
|
505
|
+
SSL *ssl;
|
506
|
+
};
|
507
|
+
|
425
508
|
static void noop_dtor(lcbio_PROTOCTX *arg)
|
426
509
|
{
|
427
|
-
|
510
|
+
if (!arg) {
|
511
|
+
return;
|
512
|
+
}
|
513
|
+
struct proto_ctx_ssl *sproto = (struct proto_ctx_ssl *)arg;
|
514
|
+
SSL_set_app_data(sproto->ssl, NULL);
|
515
|
+
free(sproto);
|
428
516
|
}
|
429
517
|
|
430
518
|
lcb_STATUS lcbio_ssl_apply(lcbio_SOCKET *sock, lcbio_pSSLCTX sctx)
|
431
519
|
{
|
432
520
|
lcbio_pTABLE old_iot = sock->io, new_iot;
|
433
|
-
|
521
|
+
struct proto_ctx_ssl *sproto;
|
434
522
|
|
435
523
|
if (old_iot->model == LCB_IOMODEL_EVENT) {
|
436
524
|
new_iot = lcbio_Essl_new(old_iot, sock->u.fd, sctx->ctx);
|
@@ -440,12 +528,13 @@ lcb_STATUS lcbio_ssl_apply(lcbio_SOCKET *sock, lcbio_pSSLCTX sctx)
|
|
440
528
|
|
441
529
|
if (new_iot) {
|
442
530
|
sproto = calloc(1, sizeof(*sproto));
|
443
|
-
sproto->id = LCBIO_PROTOCTX_SSL;
|
444
|
-
sproto->dtor = noop_dtor;
|
445
|
-
lcbio_protoctx_add(sock, sproto);
|
531
|
+
sproto->proto.id = LCBIO_PROTOCTX_SSL;
|
532
|
+
sproto->proto.dtor = noop_dtor;
|
533
|
+
lcbio_protoctx_add(sock, &sproto->proto);
|
446
534
|
lcbio_table_unref(old_iot);
|
447
535
|
sock->io = new_iot;
|
448
536
|
/* just for logging */
|
537
|
+
sproto->ssl = ((lcbio_XSSL *)new_iot)->ssl;
|
449
538
|
SSL_set_app_data(((lcbio_XSSL *)new_iot)->ssl, sock);
|
450
539
|
return LCB_SUCCESS;
|
451
540
|
|
@@ -932,12 +932,19 @@ char *lcbvb_save_json(lcbvb_CONFIG *cfg)
|
|
932
932
|
cJSON *tmp = NULL, *nodes = NULL;
|
933
933
|
cJSON *root = cJSON_CreateObject();
|
934
934
|
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
935
|
+
switch (cfg->dtype) {
|
936
|
+
case LCBVB_DIST_VBUCKET:
|
937
|
+
tmp = cJSON_CreateString("vbucket");
|
938
|
+
break;
|
939
|
+
case LCBVB_DIST_KETAMA:
|
940
|
+
tmp = cJSON_CreateString("ketama");
|
941
|
+
break;
|
942
|
+
default:
|
943
|
+
break;
|
944
|
+
}
|
945
|
+
if (tmp) {
|
946
|
+
cJSON_AddItemToObject(root, "nodeLocator", tmp);
|
939
947
|
}
|
940
|
-
cJSON_AddItemToObject(root, "nodeLocator", tmp);
|
941
948
|
|
942
949
|
if (cfg->buuid) {
|
943
950
|
tmp = cJSON_CreateString(cfg->buuid);
|
@@ -951,8 +958,10 @@ char *lcbvb_save_json(lcbvb_CONFIG *cfg)
|
|
951
958
|
tmp = cJSON_CreateInt64(cfg->revid);
|
952
959
|
cJSON_AddItemToObject(root, "rev", tmp);
|
953
960
|
}
|
954
|
-
|
955
|
-
|
961
|
+
if (cfg->bname != NULL) {
|
962
|
+
tmp = cJSON_CreateString(cfg->bname);
|
963
|
+
cJSON_AddItemToObject(root, "name", tmp);
|
964
|
+
}
|
956
965
|
|
957
966
|
nodes = cJSON_CreateArray();
|
958
967
|
cJSON_AddItemToObject(root, "nodesExt", nodes);
|
@@ -173,7 +173,7 @@ MACRO(DEFINE_MOCKTEST plugin test)
|
|
173
173
|
--gtest_filter="ContaminatingUnitTest.*"
|
174
174
|
--gtest_throw_on_failure=1
|
175
175
|
--gtest_print_time=1
|
176
|
-
--gtest_output=xml:"${PROJECT_BINARY_DIR}/REPORT_${plugin}_${test}.xml")
|
176
|
+
--gtest_output=xml:"${PROJECT_BINARY_DIR}/REPORT_${plugin}_${test}_contaminating.xml")
|
177
177
|
SET_TESTS_PROPERTIES(check-contaminating-${plugin}-${test} PROPERTIES LABELS "contaminating" )
|
178
178
|
ENDMACRO()
|
179
179
|
|
@@ -89,6 +89,7 @@ TEST_F(RateLimitTest, testRateLimitsKVNumOps)
|
|
89
89
|
{
|
90
90
|
SKIP_IF_MOCK()
|
91
91
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
92
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
92
93
|
HandleWrap hw;
|
93
94
|
lcb_INSTANCE *instance;
|
94
95
|
createConnection(hw, &instance);
|
@@ -131,6 +132,7 @@ TEST_F(RateLimitTest, testRateLimitsKVIngress)
|
|
131
132
|
{
|
132
133
|
SKIP_IF_MOCK()
|
133
134
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
135
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
134
136
|
HandleWrap hw;
|
135
137
|
lcb_INSTANCE *instance;
|
136
138
|
createConnection(hw, &instance);
|
@@ -162,6 +164,7 @@ TEST_F(RateLimitTest, testRateLimitsKVEgress)
|
|
162
164
|
{
|
163
165
|
SKIP_IF_MOCK()
|
164
166
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
167
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
165
168
|
HandleWrap hw;
|
166
169
|
lcb_INSTANCE *instance;
|
167
170
|
createConnection(hw, &instance);
|
@@ -198,6 +201,7 @@ TEST_F(RateLimitTest, testRateLimitsKVMaxConnections)
|
|
198
201
|
{
|
199
202
|
SKIP_IF_MOCK()
|
200
203
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
204
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
201
205
|
HandleWrap hw;
|
202
206
|
lcb_INSTANCE *instance;
|
203
207
|
createConnection(hw, &instance);
|
@@ -438,6 +442,7 @@ TEST_F(RateLimitTest, testRateLimitsKVScopeDataSize)
|
|
438
442
|
{
|
439
443
|
SKIP_IF_MOCK()
|
440
444
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
445
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
441
446
|
HandleWrap hw;
|
442
447
|
lcb_INSTANCE *instance;
|
443
448
|
createConnection(hw, &instance);
|
@@ -478,6 +483,7 @@ TEST_F(RateLimitTest, testRateLimitsQueryNumIndexes)
|
|
478
483
|
{
|
479
484
|
SKIP_IF_MOCK()
|
480
485
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
486
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
481
487
|
HandleWrap hw;
|
482
488
|
lcb_INSTANCE *instance;
|
483
489
|
createConnection(hw, &instance);
|
@@ -527,6 +533,7 @@ TEST_F(RateLimitTest, testRateLimitsSearchNumQueries)
|
|
527
533
|
{
|
528
534
|
SKIP_IF_MOCK()
|
529
535
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
536
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
530
537
|
HandleWrap hw;
|
531
538
|
lcb_INSTANCE *instance;
|
532
539
|
createConnection(hw, &instance);
|
@@ -576,6 +583,7 @@ TEST_F(RateLimitTest, testRateLimitsSearchEgress)
|
|
576
583
|
{
|
577
584
|
SKIP_IF_MOCK()
|
578
585
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
586
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
579
587
|
HandleWrap hw;
|
580
588
|
lcb_INSTANCE *instance;
|
581
589
|
createConnection(hw, &instance);
|
@@ -631,6 +639,7 @@ TEST_F(RateLimitTest, testRateLimitsSearchIngress)
|
|
631
639
|
{
|
632
640
|
SKIP_IF_MOCK()
|
633
641
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
642
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
634
643
|
HandleWrap hw;
|
635
644
|
lcb_INSTANCE *instance;
|
636
645
|
createConnection(hw, &instance);
|
@@ -684,6 +693,7 @@ TEST_F(RateLimitTest, testRateLimitsSearchConcurrentRequests)
|
|
684
693
|
{
|
685
694
|
SKIP_IF_MOCK()
|
686
695
|
SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_71)
|
696
|
+
SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_72)
|
687
697
|
HandleWrap hw;
|
688
698
|
lcb_INSTANCE *instance;
|
689
699
|
createConnection(hw, &instance);
|
@@ -726,4 +736,4 @@ TEST_F(RateLimitTest, testRateLimitsSearchConcurrentRequests)
|
|
726
736
|
ASSERT_TRUE(found_error);
|
727
737
|
|
728
738
|
drop_user(instance, username);
|
729
|
-
}
|
739
|
+
}
|
@@ -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
|
|