mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-14 09:58:50 +08:00
add documentation and fix merge errors
This commit is contained in:
parent
21309c2af8
commit
0950d82fe5
@ -209,6 +209,7 @@ that process, and wait for necessary data to be moved away.
|
||||
#. ``\xff\xff/management/options/excluded_locality/force`` Read/write. Setting this key disables safety checks for writes to ``\xff\xff/management/excluded_locality/<locality>``. Setting this key only has an effect in the current transaction and is not persisted on commit.
|
||||
#. ``\xff\xff/management/options/failed_locality/force`` Read/write. Setting this key disables safety checks for writes to ``\xff\xff/management/failed_locality/<locality>``. Setting this key only has an effect in the current transaction and is not persisted on commit.
|
||||
#. ``\xff\xff/management/tenant/map/<tenant>`` Read/write. Setting a key in this range to any value will result in a tenant being created with name ``<tenant>``. Clearing a key in this range will delete the tenant with name ``<tenant>``. Reading all or a portion of this range will return the list of tenants currently present in the cluster, excluding any changes in this transaction. Values read in this range will be JSON objects containing the metadata for the associated tenants.
|
||||
#. ``\xff\xff/management/tenant/rename/<tenant>`` Read/write. Setting a key in this range to an unused tenant name will result in the tenant with the name ``<tenant>`` to be renamed to the value provided. If the rename operation is a transaction retried in a loop outside of ``fdbcli``, it is possible for the rename to have already occurred, in which case ``tenant_not_found`` or ``tenant_already_exists`` errors may be returned. This can be avoided by checking for the tenant's existence first.
|
||||
|
||||
An exclusion is syntactically either an ip address (e.g. ``127.0.0.1``), or
|
||||
an ip address and port (e.g. ``127.0.0.1:4500``) or any locality (e.g ``locality_dcid:primary-satellite`` or
|
||||
|
@ -443,7 +443,7 @@ Future<Void> renameTenant(Reference<DB> db, TenantName oldName, TenantName newNa
|
||||
}
|
||||
}
|
||||
wait(renameTenantTransaction(tr, oldName, newName));
|
||||
wait(safeThreadFutureToFuture(tr->commit()));
|
||||
wait(buggifiedCommit(tr, BUGGIFY_WITH_PROB(0.1)));
|
||||
TraceEvent("RenameTenantSuccess").detail("OldName", oldName).detail("NewName", newName);
|
||||
return Void();
|
||||
} catch (Error& e) {
|
||||
|
@ -1057,135 +1057,6 @@ struct TenantManagementWorkload : TestWorkload {
|
||||
}
|
||||
}
|
||||
|
||||
// Changes the configuration of a tenant
|
||||
ACTOR static Future<Void> configureImpl(Reference<ReadYourWritesTransaction> tr,
|
||||
TenantName tenant,
|
||||
std::map<Standalone<StringRef>, Optional<Value>> configParameters,
|
||||
OperationType operationType,
|
||||
bool specialKeysUseInvalidTuple,
|
||||
TenantManagementWorkload* self) {
|
||||
if (operationType == OperationType::SPECIAL_KEYS) {
|
||||
tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES);
|
||||
for (auto const& [config, value] : configParameters) {
|
||||
Tuple t;
|
||||
if (specialKeysUseInvalidTuple) {
|
||||
// Wrong number of items
|
||||
if (deterministicRandom()->coinflip()) {
|
||||
int numItems = deterministicRandom()->randomInt(0, 3);
|
||||
if (numItems > 0) {
|
||||
t.append(tenant);
|
||||
}
|
||||
if (numItems > 1) {
|
||||
t.append(config).append(""_sr);
|
||||
}
|
||||
}
|
||||
// Wrong data types
|
||||
else {
|
||||
if (deterministicRandom()->coinflip()) {
|
||||
t.append(0).append(config);
|
||||
} else {
|
||||
t.append(tenant).append(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t.append(tenant).append(config);
|
||||
}
|
||||
if (value.present()) {
|
||||
tr->set(self->specialKeysTenantConfigPrefix.withSuffix(t.pack()), value.get());
|
||||
} else {
|
||||
tr->clear(self->specialKeysTenantConfigPrefix.withSuffix(t.pack()));
|
||||
}
|
||||
}
|
||||
|
||||
wait(tr->commit());
|
||||
ASSERT(!specialKeysUseInvalidTuple);
|
||||
} else {
|
||||
// We don't have a transaction or database variant of this function
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
ACTOR static Future<Void> configureTenant(Database cx, TenantManagementWorkload* self) {
|
||||
state OperationType operationType = OperationType::SPECIAL_KEYS;
|
||||
|
||||
state TenantName tenant = self->chooseTenantName(true);
|
||||
auto itr = self->createdTenants.find(tenant);
|
||||
state bool exists = itr != self->createdTenants.end();
|
||||
state Reference<ReadYourWritesTransaction> tr = makeReference<ReadYourWritesTransaction>(cx);
|
||||
|
||||
state std::map<Standalone<StringRef>, Optional<Value>> configuration;
|
||||
state Optional<TenantGroupName> newTenantGroup;
|
||||
|
||||
// If true, the options generated may include an unknown option
|
||||
state bool hasInvalidOption = deterministicRandom()->random01() < 0.1;
|
||||
|
||||
// True if any tenant group name starts with \xff
|
||||
state bool hasSystemTenantGroup = false;
|
||||
|
||||
state bool specialKeysUseInvalidTuple =
|
||||
operationType == OperationType::SPECIAL_KEYS && deterministicRandom()->random01() < 0.1;
|
||||
|
||||
// Generate a tenant group. Sometimes do this at the same time that we include an invalid option to ensure
|
||||
// that the configure function still fails
|
||||
if (!hasInvalidOption || deterministicRandom()->coinflip()) {
|
||||
newTenantGroup = self->chooseTenantGroup(true);
|
||||
hasSystemTenantGroup = hasSystemTenantGroup || newTenantGroup.orDefault(""_sr).startsWith("\xff"_sr);
|
||||
configuration["tenant_group"_sr] = newTenantGroup;
|
||||
}
|
||||
if (hasInvalidOption) {
|
||||
configuration["invalid_option"_sr] = ""_sr;
|
||||
}
|
||||
|
||||
loop {
|
||||
try {
|
||||
wait(configureImpl(tr, tenant, configuration, operationType, specialKeysUseInvalidTuple, self));
|
||||
|
||||
ASSERT(exists);
|
||||
ASSERT(!hasInvalidOption);
|
||||
ASSERT(!hasSystemTenantGroup);
|
||||
ASSERT(!specialKeysUseInvalidTuple);
|
||||
|
||||
auto itr = self->createdTenants.find(tenant);
|
||||
if (itr->second.tenantGroup.present()) {
|
||||
auto tenantGroupItr = self->createdTenantGroups.find(itr->second.tenantGroup.get());
|
||||
ASSERT(tenantGroupItr != self->createdTenantGroups.end());
|
||||
if (--tenantGroupItr->second.tenantCount == 0) {
|
||||
self->createdTenantGroups.erase(tenantGroupItr);
|
||||
}
|
||||
}
|
||||
if (newTenantGroup.present()) {
|
||||
self->createdTenantGroups[newTenantGroup.get()].tenantCount++;
|
||||
}
|
||||
itr->second.tenantGroup = newTenantGroup;
|
||||
return Void();
|
||||
} catch (Error& e) {
|
||||
state Error error = e;
|
||||
if (e.code() == error_code_tenant_not_found) {
|
||||
ASSERT(!exists);
|
||||
return Void();
|
||||
} else if (e.code() == error_code_special_keys_api_failure) {
|
||||
ASSERT(hasInvalidOption || specialKeysUseInvalidTuple);
|
||||
return Void();
|
||||
} else if (e.code() == error_code_invalid_tenant_configuration) {
|
||||
ASSERT(hasInvalidOption);
|
||||
return Void();
|
||||
} else if (e.code() == error_code_invalid_tenant_group_name) {
|
||||
ASSERT(hasSystemTenantGroup);
|
||||
return Void();
|
||||
}
|
||||
|
||||
try {
|
||||
wait(tr->onError(e));
|
||||
} catch (Error&) {
|
||||
TraceEvent(SevError, "ConfigureTenantFailure").error(error).detail("TenantName", tenant);
|
||||
return Void();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<Void> start(Database const& cx) override { return _start(cx, this); }
|
||||
ACTOR Future<Void> _start(Database cx, TenantManagementWorkload* self) {
|
||||
state double start = now();
|
||||
|
Loading…
x
Reference in New Issue
Block a user