add documentation and fix merge errors

This commit is contained in:
Jon Fu 2022-07-26 11:58:49 -07:00
parent 21309c2af8
commit 0950d82fe5
3 changed files with 2 additions and 130 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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();