From 4bafe77889e818e45223912dbd9eeb8877d10d79 Mon Sep 17 00:00:00 2001 From: "A.J. Beamon" Date: Wed, 22 Jun 2022 15:49:44 -0700 Subject: [PATCH] Some refactoring of tenant code: * extract tenant management into its own file and namespace * rename the tenant management workload source file * extract tenant special keys functions to a separate file * extract some helper functions to GenericTransactionHelper.h * convert StringRef -> TenantNameRef * move some TenantMapEntry implementation into the cpp file * add some helper functions to decode/encode a tenant mode --- fdbcli/fdbcli.actor.cpp | 5 +- fdbclient/CMakeLists.txt | 3 + fdbclient/DatabaseConfiguration.cpp | 3 +- fdbclient/FDBTypes.h | 17 + fdbclient/GenericManagementAPI.actor.h | 267 ---------------- fdbclient/GenericTransactionHelper.h | 42 +++ fdbclient/MultiVersionTransaction.actor.cpp | 4 +- fdbclient/MultiVersionTransaction.h | 6 +- fdbclient/SpecialKeySpace.actor.cpp | 120 -------- fdbclient/Tenant.cpp | 29 ++ fdbclient/Tenant.h | 29 +- fdbclient/TenantManagement.actor.h | 290 ++++++++++++++++++ fdbclient/TenantSpecialKeys.actor.cpp | 149 +++++++++ fdbclient/ThreadSafeTransaction.cpp | 2 +- fdbserver/ApplyMetadataMutation.cpp | 2 +- fdbserver/BlobManager.actor.cpp | 2 +- fdbserver/BlobWorker.actor.cpp | 2 +- fdbserver/CMakeLists.txt | 10 +- fdbserver/tester.actor.cpp | 5 +- .../BlobGranuleCorrectnessWorkload.actor.cpp | 3 +- .../workloads/FuzzApiCorrectness.actor.cpp | 3 +- ...cpp => TenantManagementWorkload.actor.cpp} | 26 +- fdbserver/workloads/WriteDuringRead.actor.cpp | 3 +- 23 files changed, 574 insertions(+), 448 deletions(-) create mode 100644 fdbclient/GenericTransactionHelper.h create mode 100644 fdbclient/TenantManagement.actor.h create mode 100644 fdbclient/TenantSpecialKeys.actor.cpp rename fdbserver/workloads/{TenantManagement.actor.cpp => TenantManagementWorkload.actor.cpp} (95%) diff --git a/fdbcli/fdbcli.actor.cpp b/fdbcli/fdbcli.actor.cpp index c147449463..7b439e3e29 100644 --- a/fdbcli/fdbcli.actor.cpp +++ b/fdbcli/fdbcli.actor.cpp @@ -39,6 +39,7 @@ #include "fdbclient/FDBOptions.g.h" #include "fdbclient/SystemData.h" #include "fdbclient/TagThrottle.actor.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbclient/Tuple.h" #include "fdbclient/ThreadSafeTransaction.h" @@ -1049,7 +1050,7 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { state Database localDb; state Reference db; state Reference tenant; - state Optional> tenantName; + state Optional tenantName; state Optional tenantEntry; // This tenant is kept empty for operations that perform management tasks (e.g. killing a process) @@ -1840,7 +1841,7 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { } } else { Optional entry = - wait(makeInterruptable(ManagementAPI::tryGetTenant(db, tokens[1]))); + wait(makeInterruptable(TenantAPI::tryGetTenant(db, tokens[1]))); if (!entry.present()) { fprintf(stderr, "ERROR: Tenant `%s' does not exist\n", printable(tokens[1]).c_str()); is_error = true; diff --git a/fdbclient/CMakeLists.txt b/fdbclient/CMakeLists.txt index 2a53247a53..79a06515e5 100644 --- a/fdbclient/CMakeLists.txt +++ b/fdbclient/CMakeLists.txt @@ -64,6 +64,7 @@ set(FDBCLIENT_SRCS FluentDSampleIngestor.cpp FileBackupAgent.actor.cpp GenericManagementAPI.actor.h + GenericTransactionHelper.h GlobalConfig.h GlobalConfig.actor.h GlobalConfig.actor.cpp @@ -153,6 +154,8 @@ set(FDBCLIENT_SRCS TaskBucket.h Tenant.cpp Tenant.h + TenantManagement.actor.h + TenantSpecialKeys.actor.cpp TestKnobCollection.cpp TestKnobCollection.h ThreadSafeTransaction.cpp diff --git a/fdbclient/DatabaseConfiguration.cpp b/fdbclient/DatabaseConfiguration.cpp index 7680e64fb1..f19782346a 100644 --- a/fdbclient/DatabaseConfiguration.cpp +++ b/fdbclient/DatabaseConfiguration.cpp @@ -637,8 +637,7 @@ bool DatabaseConfiguration::setInternal(KeyRef key, ValueRef value) { parse((&type), value); storageMigrationType = (StorageMigrationType::MigrationType)type; } else if (ck == LiteralStringRef("tenant_mode")) { - parse((&type), value); - tenantMode = (TenantMode::Mode)type; + tenantMode = TenantMode::fromValue(value); } else if (ck == LiteralStringRef("proxies")) { overwriteProxiesCount(); } else if (ck == LiteralStringRef("blob_granules_enabled")) { diff --git a/fdbclient/FDBTypes.h b/fdbclient/FDBTypes.h index ae5a59282b..373e28cd4e 100644 --- a/fdbclient/FDBTypes.h +++ b/fdbclient/FDBTypes.h @@ -1373,8 +1373,25 @@ struct TenantMode { return ""; } + Value toValue() const { return ValueRef(format("%d", (int)mode)); } + + static TenantMode fromValue(Optional val) { + if (!val.present()) { + return DISABLED; + } + + // A failed parsing returns 0 (DISABLED) + int num = atoi(val.get().toString().c_str()); + if (num < 0 || num >= END) { + return DISABLED; + } + + return static_cast(num); + } + uint32_t mode; }; + struct GRVCacheSpace { Version cachedReadVersion; double lastGrvTime; diff --git a/fdbclient/GenericManagementAPI.actor.h b/fdbclient/GenericManagementAPI.actor.h index 3268cd64d5..8fe0d08fd2 100644 --- a/fdbclient/GenericManagementAPI.actor.h +++ b/fdbclient/GenericManagementAPI.actor.h @@ -129,21 +129,6 @@ bool isCompleteConfiguration(std::map const& options); ConfigureAutoResult parseConfig(StatusObject const& status); -template -struct transaction_future_type { - using type = typename Transaction::template FutureT; -}; - -template -struct transaction_future_type { - using type = typename transaction_future_type::type; -}; - -template -struct transaction_future_type, T> { - using type = typename transaction_future_type::type; -}; - // Management API written in template code to support both IClientAPI and NativeAPI namespace ManagementAPI { @@ -666,258 +651,6 @@ Future changeConfig(Reference db, // used by special keys and fdbcli std::string generateErrorMessage(const CoordinatorsResult& res); -ACTOR template -Future> tryGetTenantTransaction(Transaction tr, TenantName name) { - state Key tenantMapKey = name.withPrefix(tenantMapPrefix); - - tr->setOption(FDBTransactionOptions::RAW_ACCESS); - - state typename transaction_future_type>::type tenantFuture = tr->get(tenantMapKey); - Optional val = wait(safeThreadFutureToFuture(tenantFuture)); - return val.map([](Optional v) { return decodeTenantEntry(v.get()); }); -} - -ACTOR template -Future> tryGetTenant(Reference db, TenantName name) { - state Reference tr = db->createTransaction(); - - loop { - try { - tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); - tr->setOption(FDBTransactionOptions::READ_LOCK_AWARE); - Optional entry = wait(tryGetTenantTransaction(tr, name)); - return entry; - } catch (Error& e) { - wait(safeThreadFutureToFuture(tr->onError(e))); - } - } -} - -ACTOR template -Future getTenantTransaction(Transaction tr, TenantName name) { - Optional entry = wait(tryGetTenantTransaction(tr, name)); - if (!entry.present()) { - throw tenant_not_found(); - } - - return entry.get(); -} - -ACTOR template -Future getTenant(Reference db, TenantName name) { - Optional entry = wait(tryGetTenant(db, name)); - if (!entry.present()) { - throw tenant_not_found(); - } - - return entry.get(); -} - -// Creates a tenant with the given name. If the tenant already exists, an empty optional will be returned. -// The caller must enforce that the tenant ID be unique from all current and past tenants, and it must also be unique -// from all other tenants created in the same transaction. -ACTOR template -Future> createTenantTransaction(Transaction tr, TenantNameRef name, int64_t tenantId) { - state Key tenantMapKey = name.withPrefix(tenantMapPrefix); - - if (name.startsWith("\xff"_sr)) { - throw invalid_tenant_name(); - } - - tr->setOption(FDBTransactionOptions::RAW_ACCESS); - - state Future> tenantEntryFuture = tryGetTenantTransaction(tr, name); - state typename transaction_future_type>::type tenantDataPrefixFuture = - tr->get(tenantDataPrefixKey); - state typename transaction_future_type>::type tenantModeFuture = - tr->get(configKeysPrefix.withSuffix("tenant_mode"_sr)); - - Optional tenantMode = wait(safeThreadFutureToFuture(tenantModeFuture)); - - if (!tenantMode.present() || tenantMode.get() == StringRef(format("%d", TenantMode::DISABLED))) { - throw tenants_disabled(); - } - - Optional tenantEntry = wait(tenantEntryFuture); - if (tenantEntry.present()) { - return std::make_pair(tenantEntry.get(), false); - } - - Optional tenantDataPrefix = wait(safeThreadFutureToFuture(tenantDataPrefixFuture)); - if (tenantDataPrefix.present() && - tenantDataPrefix.get().size() + TenantMapEntry::ROOT_PREFIX_SIZE > CLIENT_KNOBS->TENANT_PREFIX_SIZE_LIMIT) { - TraceEvent(SevWarnAlways, "TenantPrefixTooLarge") - .detail("TenantSubspace", tenantDataPrefix.get()) - .detail("TenantSubspaceLength", tenantDataPrefix.get().size()) - .detail("RootPrefixLength", TenantMapEntry::ROOT_PREFIX_SIZE) - .detail("MaxTenantPrefixSize", CLIENT_KNOBS->TENANT_PREFIX_SIZE_LIMIT); - - throw client_invalid_operation(); - } - - state TenantMapEntry newTenant(tenantId, tenantDataPrefix.present() ? (KeyRef)tenantDataPrefix.get() : ""_sr); - - state typename transaction_future_type::type prefixRangeFuture = - tr->getRange(prefixRange(newTenant.prefix), 1); - RangeResult contents = wait(safeThreadFutureToFuture(prefixRangeFuture)); - if (!contents.empty()) { - throw tenant_prefix_allocator_conflict(); - } - - tr->set(tenantMapKey, encodeTenantEntry(newTenant)); - - return std::make_pair(newTenant, true); -} - -ACTOR template -Future createTenant(Reference db, TenantName name) { - state Reference tr = db->createTransaction(); - - state bool firstTry = true; - loop { - try { - tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); - tr->setOption(FDBTransactionOptions::LOCK_AWARE); - state typename DB::TransactionT::template FutureT> lastIdFuture = tr->get(tenantLastIdKey); - - if (firstTry) { - Optional entry = wait(tryGetTenantTransaction(tr, name)); - if (entry.present()) { - throw tenant_already_exists(); - } - - firstTry = false; - } - - Optional lastIdVal = wait(safeThreadFutureToFuture(lastIdFuture)); - int64_t tenantId = lastIdVal.present() ? TenantMapEntry::prefixToId(lastIdVal.get()) + 1 : 0; - tr->set(tenantLastIdKey, TenantMapEntry::idToPrefix(tenantId)); - state std::pair newTenant = wait(createTenantTransaction(tr, name, tenantId)); - - if (BUGGIFY) { - throw commit_unknown_result(); - } - - wait(safeThreadFutureToFuture(tr->commit())); - - if (BUGGIFY) { - throw commit_unknown_result(); - } - - TraceEvent("CreatedTenant") - .detail("Tenant", name) - .detail("TenantId", newTenant.first.id) - .detail("Prefix", newTenant.first.prefix) - .detail("Version", tr->getCommittedVersion()); - - return newTenant.first; - } catch (Error& e) { - wait(safeThreadFutureToFuture(tr->onError(e))); - } - } -} - -ACTOR template -Future deleteTenantTransaction(Transaction tr, TenantNameRef name) { - state Key tenantMapKey = name.withPrefix(tenantMapPrefix); - - tr->setOption(FDBTransactionOptions::RAW_ACCESS); - - state Optional tenantEntry = wait(tryGetTenantTransaction(tr, name)); - if (!tenantEntry.present()) { - return Void(); - } - - state typename transaction_future_type::type prefixRangeFuture = - tr->getRange(prefixRange(tenantEntry.get().prefix), 1); - RangeResult contents = wait(safeThreadFutureToFuture(prefixRangeFuture)); - if (!contents.empty()) { - throw tenant_not_empty(); - } - - tr->clear(tenantMapKey); - - return Void(); -} - -ACTOR template -Future deleteTenant(Reference db, TenantName name) { - state Reference tr = db->createTransaction(); - - state bool firstTry = true; - loop { - try { - tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); - tr->setOption(FDBTransactionOptions::LOCK_AWARE); - - if (firstTry) { - Optional entry = wait(tryGetTenantTransaction(tr, name)); - if (!entry.present()) { - throw tenant_not_found(); - } - - firstTry = false; - } - - wait(deleteTenantTransaction(tr, name)); - - if (BUGGIFY) { - throw commit_unknown_result(); - } - - wait(safeThreadFutureToFuture(tr->commit())); - - if (BUGGIFY) { - throw commit_unknown_result(); - } - - TraceEvent("DeletedTenant").detail("Tenant", name).detail("Version", tr->getCommittedVersion()); - return Void(); - } catch (Error& e) { - wait(safeThreadFutureToFuture(tr->onError(e))); - } - } -} - -ACTOR template -Future> listTenantsTransaction(Transaction tr, - TenantNameRef begin, - TenantNameRef end, - int limit) { - state KeyRange range = KeyRangeRef(begin, end).withPrefix(tenantMapPrefix); - - tr->setOption(FDBTransactionOptions::RAW_ACCESS); - - state typename transaction_future_type::type listFuture = - tr->getRange(firstGreaterOrEqual(range.begin), firstGreaterOrEqual(range.end), limit); - RangeResult results = wait(safeThreadFutureToFuture(listFuture)); - - std::map tenants; - for (auto kv : results) { - tenants[kv.key.removePrefix(tenantMapPrefix)] = decodeTenantEntry(kv.value); - } - - return tenants; -} - -ACTOR template -Future> listTenants(Reference db, - TenantName begin, - TenantName end, - int limit) { - state Reference tr = db->createTransaction(); - - loop { - try { - tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); - tr->setOption(FDBTransactionOptions::READ_LOCK_AWARE); - std::map tenants = wait(listTenantsTransaction(tr, begin, end, limit)); - return tenants; - } catch (Error& e) { - wait(safeThreadFutureToFuture(tr->onError(e))); - } - } -} } // namespace ManagementAPI #include "flow/unactorcompiler.h" diff --git a/fdbclient/GenericTransactionHelper.h b/fdbclient/GenericTransactionHelper.h new file mode 100644 index 0000000000..ddff69e642 --- /dev/null +++ b/fdbclient/GenericTransactionHelper.h @@ -0,0 +1,42 @@ +/* + * GenericTransactionHelper.h + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2013-2022 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FDBCLIENT_GENERIC_TRANSACTION_HELPER_H +#define FDBCLIENT_GENERIC_TRANSACTION_HELPER_H +#pragma once + +#include "flow/FastRef.h" + +template +struct transaction_future_type { + using type = typename Transaction::template FutureT; +}; + +template +struct transaction_future_type { + using type = typename transaction_future_type::type; +}; + +template +struct transaction_future_type, T> { + using type = typename transaction_future_type::type; +}; + +#endif \ No newline at end of file diff --git a/fdbclient/MultiVersionTransaction.actor.cpp b/fdbclient/MultiVersionTransaction.actor.cpp index 1878042f91..57daade016 100644 --- a/fdbclient/MultiVersionTransaction.actor.cpp +++ b/fdbclient/MultiVersionTransaction.actor.cpp @@ -1340,7 +1340,7 @@ bool MultiVersionTransaction::isValid() { } // MultiVersionTenant -MultiVersionTenant::MultiVersionTenant(Reference db, StringRef tenantName) +MultiVersionTenant::MultiVersionTenant(Reference db, TenantNameRef tenantName) : tenantState(makeReference(db, tenantName)) {} MultiVersionTenant::~MultiVersionTenant() { @@ -1363,7 +1363,7 @@ ThreadFuture MultiVersionTenant::waitPurgeGranulesComplete(const KeyRef& p return abortableFuture(f, tenantState->db->dbState->dbVar->get().onChange); } -MultiVersionTenant::TenantState::TenantState(Reference db, StringRef tenantName) +MultiVersionTenant::TenantState::TenantState(Reference db, TenantNameRef tenantName) : tenantVar(new ThreadSafeAsyncVar>(Reference(nullptr))), tenantName(tenantName), db(db), closed(false) { updateTenant(); diff --git a/fdbclient/MultiVersionTransaction.h b/fdbclient/MultiVersionTransaction.h index 9f5c629330..c20b76f8b2 100644 --- a/fdbclient/MultiVersionTransaction.h +++ b/fdbclient/MultiVersionTransaction.h @@ -685,7 +685,7 @@ class MultiVersionApi; // it connects with a different version. class MultiVersionTenant final : public ITenant, ThreadSafeReferenceCounted { public: - MultiVersionTenant(Reference db, StringRef tenantName); + MultiVersionTenant(Reference db, TenantNameRef tenantName); ~MultiVersionTenant() override; Reference createTransaction() override; @@ -699,7 +699,7 @@ public: // A struct that manages the current connection state of the MultiVersionDatabase. This wraps the underlying // IDatabase object that is currently interacting with the cluster. struct TenantState : ThreadSafeReferenceCounted { - TenantState(Reference db, StringRef tenantName); + TenantState(Reference db, TenantNameRef tenantName); // Creates a new underlying tenant object whenever the database connection changes. This change is signaled // to open transactions via an AsyncVar. @@ -709,7 +709,7 @@ public: void close(); Reference>> tenantVar; - const Standalone tenantName; + const TenantName tenantName; Reference db; diff --git a/fdbclient/SpecialKeySpace.actor.cpp b/fdbclient/SpecialKeySpace.actor.cpp index 1ff19f442c..c64a361357 100644 --- a/fdbclient/SpecialKeySpace.actor.cpp +++ b/fdbclient/SpecialKeySpace.actor.cpp @@ -2730,123 +2730,3 @@ Future> FailedLocalitiesRangeImpl::commit(ReadYourWritesTr // exclude locality with failed option as true. return excludeLocalityCommitActor(ryw, true); } - -ACTOR Future getTenantList(ReadYourWritesTransaction* ryw, KeyRangeRef kr, GetRangeLimits limitsHint) { - state KeyRef managementPrefix = - kr.begin.substr(0, - SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin.size() + - TenantMapRangeImpl::submoduleRange.begin.size()); - - kr = kr.removePrefix(SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin); - TenantNameRef beginTenant = kr.begin.removePrefix(TenantMapRangeImpl::submoduleRange.begin); - - TenantNameRef endTenant = kr.end; - if (endTenant.startsWith(TenantMapRangeImpl::submoduleRange.begin)) { - endTenant = endTenant.removePrefix(TenantMapRangeImpl::submoduleRange.begin); - } else { - endTenant = "\xff"_sr; - } - - std::map tenants = - wait(ManagementAPI::listTenantsTransaction(&ryw->getTransaction(), beginTenant, endTenant, limitsHint.rows)); - - RangeResult results; - for (auto tenant : tenants) { - json_spirit::mObject tenantEntry; - tenantEntry["id"] = tenant.second.id; - tenantEntry["prefix"] = tenant.second.prefix.toString(); - std::string tenantEntryString = json_spirit::write_string(json_spirit::mValue(tenantEntry)); - ValueRef tenantEntryBytes(results.arena(), tenantEntryString); - results.push_back(results.arena(), - KeyValueRef(tenant.first.withPrefix(managementPrefix, results.arena()), tenantEntryBytes)); - } - - return results; -} - -TenantMapRangeImpl::TenantMapRangeImpl(KeyRangeRef kr) : SpecialKeyRangeRWImpl(kr) {} - -Future TenantMapRangeImpl::getRange(ReadYourWritesTransaction* ryw, - KeyRangeRef kr, - GetRangeLimits limitsHint) const { - return getTenantList(ryw, kr, limitsHint); -} - -ACTOR Future createTenants(ReadYourWritesTransaction* ryw, std::vector tenants) { - Optional lastIdVal = wait(ryw->getTransaction().get(tenantLastIdKey)); - int64_t previousId = lastIdVal.present() ? TenantMapEntry::prefixToId(lastIdVal.get()) : -1; - - std::vector> createFutures; - for (auto tenant : tenants) { - createFutures.push_back( - success(ManagementAPI::createTenantTransaction(&ryw->getTransaction(), tenant, ++previousId))); - } - - ryw->getTransaction().set(tenantLastIdKey, TenantMapEntry::idToPrefix(previousId)); - wait(waitForAll(createFutures)); - return Void(); -} - -ACTOR Future deleteTenantRange(ReadYourWritesTransaction* ryw, - TenantNameRef beginTenant, - TenantNameRef endTenant) { - std::map tenants = wait( - ManagementAPI::listTenantsTransaction(&ryw->getTransaction(), beginTenant, endTenant, CLIENT_KNOBS->TOO_MANY)); - - if (tenants.size() == CLIENT_KNOBS->TOO_MANY) { - TraceEvent(SevWarn, "DeleteTenantRangeTooLange") - .detail("BeginTenant", beginTenant) - .detail("EndTenant", endTenant); - ryw->setSpecialKeySpaceErrorMsg("too many tenants to range delete"); - throw special_keys_api_failure(); - } - - std::vector> deleteFutures; - for (auto tenant : tenants) { - deleteFutures.push_back(ManagementAPI::deleteTenantTransaction(&ryw->getTransaction(), tenant.first)); - } - - wait(waitForAll(deleteFutures)); - return Void(); -} - -Future> TenantMapRangeImpl::commit(ReadYourWritesTransaction* ryw) { - auto ranges = ryw->getSpecialKeySpaceWriteMap().containedRanges(range); - std::vector tenantsToCreate; - std::vector> tenantManagementFutures; - for (auto range : ranges) { - if (!range.value().first) { - continue; - } - - TenantNameRef tenantName = - range.begin() - .removePrefix(SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin) - .removePrefix(TenantMapRangeImpl::submoduleRange.begin); - - if (range.value().second.present()) { - tenantsToCreate.push_back(tenantName); - } else { - // For a single key clear, just issue the delete - if (KeyRangeRef(range.begin(), range.end()).singleKeyRange()) { - tenantManagementFutures.push_back( - ManagementAPI::deleteTenantTransaction(&ryw->getTransaction(), tenantName)); - } else { - TenantNameRef endTenant = range.end().removePrefix( - SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin); - if (endTenant.startsWith(submoduleRange.begin)) { - endTenant = endTenant.removePrefix(submoduleRange.begin); - } else { - endTenant = "\xff"_sr; - } - tenantManagementFutures.push_back(deleteTenantRange(ryw, tenantName, endTenant)); - } - } - } - - if (tenantsToCreate.size()) { - tenantManagementFutures.push_back(createTenants(ryw, tenantsToCreate)); - } - - return tag(waitForAll(tenantManagementFutures), Optional()); -} diff --git a/fdbclient/Tenant.cpp b/fdbclient/Tenant.cpp index e63bf9fead..79f369723a 100644 --- a/fdbclient/Tenant.cpp +++ b/fdbclient/Tenant.cpp @@ -22,6 +22,35 @@ #include "fdbclient/Tenant.h" #include "flow/UnitTest.h" +Key TenantMapEntry::idToPrefix(int64_t id) { + int64_t swapped = bigEndian64(id); + return StringRef(reinterpret_cast(&swapped), 8); +} + +int64_t TenantMapEntry::prefixToId(KeyRef prefix) { + ASSERT(prefix.size() == 8); + int64_t id = *reinterpret_cast(prefix.begin()); + id = bigEndian64(id); + ASSERT(id >= 0); + return id; +} + +void TenantMapEntry::initPrefix(KeyRef subspace) { + ASSERT(id >= 0); + prefix = makeString(8 + subspace.size()); + uint8_t* data = mutateString(prefix); + if (subspace.size() > 0) { + memcpy(data, subspace.begin(), subspace.size()); + } + int64_t swapped = bigEndian64(id); + memcpy(data + subspace.size(), &swapped, 8); +} + +TenantMapEntry::TenantMapEntry() : id(-1) {} +TenantMapEntry::TenantMapEntry(int64_t id, KeyRef subspace) : id(id) { + initPrefix(subspace); +} + TEST_CASE("/fdbclient/TenantMapEntry/Serialization") { TenantMapEntry entry1(1, ""_sr); ASSERT(entry1.prefix == "\x00\x00\x00\x00\x00\x00\x00\x01"_sr); diff --git a/fdbclient/Tenant.h b/fdbclient/Tenant.h index adfa06470a..01810a1c81 100644 --- a/fdbclient/Tenant.h +++ b/fdbclient/Tenant.h @@ -32,18 +32,8 @@ typedef Standalone TenantName; struct TenantMapEntry { constexpr static FileIdentifier file_identifier = 12247338; - static Key idToPrefix(int64_t id) { - int64_t swapped = bigEndian64(id); - return StringRef(reinterpret_cast(&swapped), 8); - } - - static int64_t prefixToId(KeyRef prefix) { - ASSERT(prefix.size() == 8); - int64_t id = *reinterpret_cast(prefix.begin()); - id = bigEndian64(id); - ASSERT(id >= 0); - return id; - } + static Key idToPrefix(int64_t id); + static int64_t prefixToId(KeyRef prefix); int64_t id; Key prefix; @@ -51,20 +41,11 @@ struct TenantMapEntry { constexpr static int ROOT_PREFIX_SIZE = sizeof(id); private: - void initPrefix(KeyRef subspace) { - ASSERT(id >= 0); - prefix = makeString(8 + subspace.size()); - uint8_t* data = mutateString(prefix); - if (subspace.size() > 0) { - memcpy(data, subspace.begin(), subspace.size()); - } - int64_t swapped = bigEndian64(id); - memcpy(data + subspace.size(), &swapped, 8); - } + void initPrefix(KeyRef subspace); public: - TenantMapEntry() : id(-1) {} - TenantMapEntry(int64_t id, KeyRef subspace) : id(id) { initPrefix(subspace); } + TenantMapEntry(); + TenantMapEntry(int64_t id, KeyRef subspace); template void serialize(Ar& ar) { diff --git a/fdbclient/TenantManagement.actor.h b/fdbclient/TenantManagement.actor.h new file mode 100644 index 0000000000..e480291ffd --- /dev/null +++ b/fdbclient/TenantManagement.actor.h @@ -0,0 +1,290 @@ +/* + * TenantManagement.actor.h + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2013-2022 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#if defined(NO_INTELLISENSE) && !defined(FDBCLIENT_TENANT_MANAGEMENT_ACTOR_G_H) +#define FDBCLIENT_TENANT_MANAGEMENT_ACTOR_G_H +#include "fdbclient/TenantManagement.actor.g.h" +#elif !defined(FDBCLIENT_TENANT_MANAGEMENT_ACTOR_H) +#define FDBCLIENT_TENANT_MANAGEMENT_ACTOR_H + +#include +#include +#include "fdbclient/GenericTransactionHelper.h" +#include "fdbclient/SystemData.h" +#include "flow/actorcompiler.h" // has to be last include + +namespace TenantAPI { +ACTOR template +Future> tryGetTenantTransaction(Transaction tr, TenantName name) { + state Key tenantMapKey = name.withPrefix(tenantMapPrefix); + + tr->setOption(FDBTransactionOptions::RAW_ACCESS); + + state typename transaction_future_type>::type tenantFuture = tr->get(tenantMapKey); + Optional val = wait(safeThreadFutureToFuture(tenantFuture)); + return val.map([](Optional v) { return decodeTenantEntry(v.get()); }); +} + +ACTOR template +Future> tryGetTenant(Reference db, TenantName name) { + state Reference tr = db->createTransaction(); + + loop { + try { + tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); + tr->setOption(FDBTransactionOptions::READ_LOCK_AWARE); + Optional entry = wait(tryGetTenantTransaction(tr, name)); + return entry; + } catch (Error& e) { + wait(safeThreadFutureToFuture(tr->onError(e))); + } + } +} + +ACTOR template +Future getTenantTransaction(Transaction tr, TenantName name) { + Optional entry = wait(tryGetTenantTransaction(tr, name)); + if (!entry.present()) { + throw tenant_not_found(); + } + + return entry.get(); +} + +ACTOR template +Future getTenant(Reference db, TenantName name) { + Optional entry = wait(tryGetTenant(db, name)); + if (!entry.present()) { + throw tenant_not_found(); + } + + return entry.get(); +} + +// Creates a tenant with the given name. If the tenant already exists, an empty optional will be returned. +// The caller must enforce that the tenant ID be unique from all current and past tenants, and it must also be unique +// from all other tenants created in the same transaction. +ACTOR template +Future> createTenantTransaction(Transaction tr, TenantNameRef name, int64_t tenantId) { + state Key tenantMapKey = name.withPrefix(tenantMapPrefix); + + if (name.startsWith("\xff"_sr)) { + throw invalid_tenant_name(); + } + + tr->setOption(FDBTransactionOptions::RAW_ACCESS); + + state Future> tenantEntryFuture = tryGetTenantTransaction(tr, name); + state typename transaction_future_type>::type tenantDataPrefixFuture = + tr->get(tenantDataPrefixKey); + state typename transaction_future_type>::type tenantModeFuture = + tr->get(configKeysPrefix.withSuffix("tenant_mode"_sr)); + + Optional tenantMode = wait(safeThreadFutureToFuture(tenantModeFuture)); + + if (!tenantMode.present() || tenantMode.get() == StringRef(format("%d", TenantMode::DISABLED))) { + throw tenants_disabled(); + } + + Optional tenantEntry = wait(tenantEntryFuture); + if (tenantEntry.present()) { + return std::make_pair(tenantEntry.get(), false); + } + + Optional tenantDataPrefix = wait(safeThreadFutureToFuture(tenantDataPrefixFuture)); + if (tenantDataPrefix.present() && + tenantDataPrefix.get().size() + TenantMapEntry::ROOT_PREFIX_SIZE > CLIENT_KNOBS->TENANT_PREFIX_SIZE_LIMIT) { + TraceEvent(SevWarnAlways, "TenantPrefixTooLarge") + .detail("TenantSubspace", tenantDataPrefix.get()) + .detail("TenantSubspaceLength", tenantDataPrefix.get().size()) + .detail("RootPrefixLength", TenantMapEntry::ROOT_PREFIX_SIZE) + .detail("MaxTenantPrefixSize", CLIENT_KNOBS->TENANT_PREFIX_SIZE_LIMIT); + + throw client_invalid_operation(); + } + + state TenantMapEntry newTenant(tenantId, tenantDataPrefix.present() ? (KeyRef)tenantDataPrefix.get() : ""_sr); + + state typename transaction_future_type::type prefixRangeFuture = + tr->getRange(prefixRange(newTenant.prefix), 1); + RangeResult contents = wait(safeThreadFutureToFuture(prefixRangeFuture)); + if (!contents.empty()) { + throw tenant_prefix_allocator_conflict(); + } + + tr->set(tenantMapKey, encodeTenantEntry(newTenant)); + + return std::make_pair(newTenant, true); +} + +ACTOR template +Future createTenant(Reference db, TenantName name) { + state Reference tr = db->createTransaction(); + + state bool firstTry = true; + loop { + try { + tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); + tr->setOption(FDBTransactionOptions::LOCK_AWARE); + state typename DB::TransactionT::template FutureT> lastIdFuture = tr->get(tenantLastIdKey); + + if (firstTry) { + Optional entry = wait(tryGetTenantTransaction(tr, name)); + if (entry.present()) { + throw tenant_already_exists(); + } + + firstTry = false; + } + + Optional lastIdVal = wait(safeThreadFutureToFuture(lastIdFuture)); + int64_t tenantId = lastIdVal.present() ? TenantMapEntry::prefixToId(lastIdVal.get()) + 1 : 0; + tr->set(tenantLastIdKey, TenantMapEntry::idToPrefix(tenantId)); + state std::pair newTenant = wait(createTenantTransaction(tr, name, tenantId)); + + if (BUGGIFY) { + throw commit_unknown_result(); + } + + wait(safeThreadFutureToFuture(tr->commit())); + + if (BUGGIFY) { + throw commit_unknown_result(); + } + + TraceEvent("CreatedTenant") + .detail("Tenant", name) + .detail("TenantId", newTenant.first.id) + .detail("Prefix", newTenant.first.prefix) + .detail("Version", tr->getCommittedVersion()); + + return newTenant.first; + } catch (Error& e) { + wait(safeThreadFutureToFuture(tr->onError(e))); + } + } +} + +ACTOR template +Future deleteTenantTransaction(Transaction tr, TenantNameRef name) { + state Key tenantMapKey = name.withPrefix(tenantMapPrefix); + + tr->setOption(FDBTransactionOptions::RAW_ACCESS); + + state Optional tenantEntry = wait(tryGetTenantTransaction(tr, name)); + if (!tenantEntry.present()) { + return Void(); + } + + state typename transaction_future_type::type prefixRangeFuture = + tr->getRange(prefixRange(tenantEntry.get().prefix), 1); + RangeResult contents = wait(safeThreadFutureToFuture(prefixRangeFuture)); + if (!contents.empty()) { + throw tenant_not_empty(); + } + + tr->clear(tenantMapKey); + + return Void(); +} + +ACTOR template +Future deleteTenant(Reference db, TenantName name) { + state Reference tr = db->createTransaction(); + + state bool firstTry = true; + loop { + try { + tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); + tr->setOption(FDBTransactionOptions::LOCK_AWARE); + + if (firstTry) { + Optional entry = wait(tryGetTenantTransaction(tr, name)); + if (!entry.present()) { + throw tenant_not_found(); + } + + firstTry = false; + } + + wait(deleteTenantTransaction(tr, name)); + + if (BUGGIFY) { + throw commit_unknown_result(); + } + + wait(safeThreadFutureToFuture(tr->commit())); + + if (BUGGIFY) { + throw commit_unknown_result(); + } + + TraceEvent("DeletedTenant").detail("Tenant", name).detail("Version", tr->getCommittedVersion()); + return Void(); + } catch (Error& e) { + wait(safeThreadFutureToFuture(tr->onError(e))); + } + } +} + +ACTOR template +Future> listTenantsTransaction(Transaction tr, + TenantNameRef begin, + TenantNameRef end, + int limit) { + state KeyRange range = KeyRangeRef(begin, end).withPrefix(tenantMapPrefix); + + tr->setOption(FDBTransactionOptions::RAW_ACCESS); + + state typename transaction_future_type::type listFuture = + tr->getRange(firstGreaterOrEqual(range.begin), firstGreaterOrEqual(range.end), limit); + RangeResult results = wait(safeThreadFutureToFuture(listFuture)); + + std::map tenants; + for (auto kv : results) { + tenants[kv.key.removePrefix(tenantMapPrefix)] = decodeTenantEntry(kv.value); + } + + return tenants; +} + +ACTOR template +Future> listTenants(Reference db, + TenantName begin, + TenantName end, + int limit) { + state Reference tr = db->createTransaction(); + + loop { + try { + tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); + tr->setOption(FDBTransactionOptions::READ_LOCK_AWARE); + std::map tenants = wait(listTenantsTransaction(tr, begin, end, limit)); + return tenants; + } catch (Error& e) { + wait(safeThreadFutureToFuture(tr->onError(e))); + } + } +} +} // namespace TenantAPI + +#include "flow/unactorcompiler.h" +#endif diff --git a/fdbclient/TenantSpecialKeys.actor.cpp b/fdbclient/TenantSpecialKeys.actor.cpp new file mode 100644 index 0000000000..7aed868f54 --- /dev/null +++ b/fdbclient/TenantSpecialKeys.actor.cpp @@ -0,0 +1,149 @@ +/* + * TenantSpecialKeys.actor.cpp + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2013-2022 Apple Inc. and the FoundationDB project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fdbclient/ActorLineageProfiler.h" +#include "fdbclient/FDBOptions.g.h" +#include "fdbclient/Knobs.h" +#include "fdbclient/DatabaseContext.h" +#include "fdbclient/SpecialKeySpace.actor.h" +#include "fdbclient/TenantManagement.actor.h" +#include "flow/Arena.h" +#include "flow/UnitTest.h" +#include "flow/actorcompiler.h" // This must be the last #include. + +ACTOR Future getTenantList(ReadYourWritesTransaction* ryw, KeyRangeRef kr, GetRangeLimits limitsHint) { + state KeyRef managementPrefix = + kr.begin.substr(0, + SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin.size() + + TenantMapRangeImpl::submoduleRange.begin.size()); + + kr = kr.removePrefix(SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin); + TenantNameRef beginTenant = kr.begin.removePrefix(TenantMapRangeImpl::submoduleRange.begin); + + TenantNameRef endTenant = kr.end; + if (endTenant.startsWith(TenantMapRangeImpl::submoduleRange.begin)) { + endTenant = endTenant.removePrefix(TenantMapRangeImpl::submoduleRange.begin); + } else { + endTenant = "\xff"_sr; + } + + std::map tenants = + wait(TenantAPI::listTenantsTransaction(&ryw->getTransaction(), beginTenant, endTenant, limitsHint.rows)); + + RangeResult results; + for (auto tenant : tenants) { + json_spirit::mObject tenantEntry; + tenantEntry["id"] = tenant.second.id; + tenantEntry["prefix"] = tenant.second.prefix.toString(); + std::string tenantEntryString = json_spirit::write_string(json_spirit::mValue(tenantEntry)); + ValueRef tenantEntryBytes(results.arena(), tenantEntryString); + results.push_back(results.arena(), + KeyValueRef(tenant.first.withPrefix(managementPrefix, results.arena()), tenantEntryBytes)); + } + + return results; +} + +TenantMapRangeImpl::TenantMapRangeImpl(KeyRangeRef kr) : SpecialKeyRangeRWImpl(kr) {} + +Future TenantMapRangeImpl::getRange(ReadYourWritesTransaction* ryw, + KeyRangeRef kr, + GetRangeLimits limitsHint) const { + return getTenantList(ryw, kr, limitsHint); +} + +ACTOR Future createTenants(ReadYourWritesTransaction* ryw, std::vector tenants) { + Optional lastIdVal = wait(ryw->getTransaction().get(tenantLastIdKey)); + int64_t previousId = lastIdVal.present() ? TenantMapEntry::prefixToId(lastIdVal.get()) : -1; + + std::vector> createFutures; + for (auto tenant : tenants) { + createFutures.push_back( + success(TenantAPI::createTenantTransaction(&ryw->getTransaction(), tenant, ++previousId))); + } + + ryw->getTransaction().set(tenantLastIdKey, TenantMapEntry::idToPrefix(previousId)); + wait(waitForAll(createFutures)); + return Void(); +} + +ACTOR Future deleteTenantRange(ReadYourWritesTransaction* ryw, + TenantNameRef beginTenant, + TenantNameRef endTenant) { + std::map tenants = + wait(TenantAPI::listTenantsTransaction(&ryw->getTransaction(), beginTenant, endTenant, CLIENT_KNOBS->TOO_MANY)); + + if (tenants.size() == CLIENT_KNOBS->TOO_MANY) { + TraceEvent(SevWarn, "DeleteTenantRangeTooLange") + .detail("BeginTenant", beginTenant) + .detail("EndTenant", endTenant); + ryw->setSpecialKeySpaceErrorMsg("too many tenants to range delete"); + throw special_keys_api_failure(); + } + + std::vector> deleteFutures; + for (auto tenant : tenants) { + deleteFutures.push_back(TenantAPI::deleteTenantTransaction(&ryw->getTransaction(), tenant.first)); + } + + wait(waitForAll(deleteFutures)); + return Void(); +} + +Future> TenantMapRangeImpl::commit(ReadYourWritesTransaction* ryw) { + auto ranges = ryw->getSpecialKeySpaceWriteMap().containedRanges(range); + std::vector tenantsToCreate; + std::vector> tenantManagementFutures; + for (auto range : ranges) { + if (!range.value().first) { + continue; + } + + TenantNameRef tenantName = + range.begin() + .removePrefix(SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin) + .removePrefix(TenantMapRangeImpl::submoduleRange.begin); + + if (range.value().second.present()) { + tenantsToCreate.push_back(tenantName); + } else { + // For a single key clear, just issue the delete + if (KeyRangeRef(range.begin(), range.end()).singleKeyRange()) { + tenantManagementFutures.push_back( + TenantAPI::deleteTenantTransaction(&ryw->getTransaction(), tenantName)); + } else { + TenantNameRef endTenant = range.end().removePrefix( + SpecialKeySpace::getModuleRange(SpecialKeySpace::MODULE::MANAGEMENT).begin); + if (endTenant.startsWith(submoduleRange.begin)) { + endTenant = endTenant.removePrefix(submoduleRange.begin); + } else { + endTenant = "\xff"_sr; + } + tenantManagementFutures.push_back(deleteTenantRange(ryw, tenantName, endTenant)); + } + } + } + + if (tenantsToCreate.size()) { + tenantManagementFutures.push_back(createTenants(ryw, tenantsToCreate)); + } + + return tag(waitForAll(tenantManagementFutures), Optional()); +} \ No newline at end of file diff --git a/fdbclient/ThreadSafeTransaction.cpp b/fdbclient/ThreadSafeTransaction.cpp index 3f6ea6347a..f2935c20bb 100644 --- a/fdbclient/ThreadSafeTransaction.cpp +++ b/fdbclient/ThreadSafeTransaction.cpp @@ -175,7 +175,7 @@ Reference ThreadSafeTenant::createTransaction() { ThreadFuture ThreadSafeTenant::purgeBlobGranules(const KeyRangeRef& keyRange, Version purgeVersion, bool force) { DatabaseContext* db = this->db->db; - Standalone tenantName = this->name; + TenantName tenantName = this->name; KeyRange range = keyRange; return onMainThread([db, range, purgeVersion, tenantName, force]() -> Future { return db->purgeBlobGranules(range, purgeVersion, tenantName, force); diff --git a/fdbserver/ApplyMetadataMutation.cpp b/fdbserver/ApplyMetadataMutation.cpp index 290e83efd4..4ec7ad5e3c 100644 --- a/fdbserver/ApplyMetadataMutation.cpp +++ b/fdbserver/ApplyMetadataMutation.cpp @@ -638,7 +638,7 @@ private: if (m.param1.startsWith(tenantMapPrefix)) { if (tenantMap) { ASSERT(version != invalidVersion); - Standalone tenantName = m.param1.removePrefix(tenantMapPrefix); + TenantName tenantName = m.param1.removePrefix(tenantMapPrefix); TenantMapEntry tenantEntry = decodeTenantEntry(m.param2); TraceEvent("CommitProxyInsertTenant", dbgid).detail("Tenant", tenantName).detail("Version", version); diff --git a/fdbserver/BlobManager.actor.cpp b/fdbserver/BlobManager.actor.cpp index 65517e3877..1f570589f2 100644 --- a/fdbserver/BlobManager.actor.cpp +++ b/fdbserver/BlobManager.actor.cpp @@ -844,7 +844,7 @@ ACTOR Future monitorClientRanges(Reference bmData) { std::vector> tenants; std::vector prefixes; for (auto& it : tenantResults) { - StringRef tenantName = it.key.removePrefix(tenantMapPrefix); + TenantNameRef tenantName = it.key.removePrefix(tenantMapPrefix); TenantMapEntry entry = decodeTenantEntry(it.value); tenants.push_back(std::pair(tenantName, entry)); prefixes.push_back(entry.prefix); diff --git a/fdbserver/BlobWorker.actor.cpp b/fdbserver/BlobWorker.actor.cpp index fac4a5a2a7..a144065253 100644 --- a/fdbserver/BlobWorker.actor.cpp +++ b/fdbserver/BlobWorker.actor.cpp @@ -3197,7 +3197,7 @@ ACTOR Future monitorTenants(Reference bwData) { std::vector> tenants; for (auto& it : tenantResults) { // FIXME: handle removing/moving tenants! - StringRef tenantName = it.key.removePrefix(tenantMapPrefix); + TenantNameRef tenantName = it.key.removePrefix(tenantMapPrefix); TenantMapEntry entry = decodeTenantEntry(it.value); tenants.push_back(std::pair(tenantName, entry)); } diff --git a/fdbserver/CMakeLists.txt b/fdbserver/CMakeLists.txt index 3388dfb7f0..b78f4c118e 100644 --- a/fdbserver/CMakeLists.txt +++ b/fdbserver/CMakeLists.txt @@ -307,7 +307,7 @@ set(FDBSERVER_SRCS workloads/TagThrottleApi.actor.cpp workloads/TargetedKill.actor.cpp workloads/TaskBucketCorrectness.actor.cpp - workloads/TenantManagement.actor.cpp + workloads/TenantManagementWorkload.actor.cpp workloads/ThreadSafety.actor.cpp workloads/Throttling.actor.cpp workloads/Throughput.actor.cpp @@ -346,7 +346,7 @@ add_library(fdb_sqlite STATIC sqlite/sqlite3.amalgamation.c) target_include_directories(fdb_sqlite PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/sqlite) -if (WITH_ROCKSDB_EXPERIMENTAL) +if(WITH_ROCKSDB_EXPERIMENTAL) add_definitions(-DSSD_ROCKSDB_EXPERIMENTAL) include(CompileRocksDB) @@ -354,7 +354,7 @@ if (WITH_ROCKSDB_EXPERIMENTAL) # statically, so find the static library here. find_library(lz4_STATIC_LIBRARIES NAMES liblz4.a REQUIRED) - if (WITH_LIBURING) + if(WITH_LIBURING) find_package(uring) endif() endif() @@ -374,7 +374,7 @@ target_include_directories(fdbserver PRIVATE ${CMAKE_BINARY_DIR}/bindings/c ${CMAKE_CURRENT_BINARY_DIR}/workloads ${CMAKE_CURRENT_SOURCE_DIR}/workloads) -if (WITH_ROCKSDB_EXPERIMENTAL) +if(WITH_ROCKSDB_EXPERIMENTAL) add_dependencies(fdbserver rocksdb) if(WITH_LIBURING) target_include_directories(fdbserver PRIVATE ${ROCKSDB_INCLUDE_DIR} ${uring_INCLUDE_DIR}) @@ -392,7 +392,7 @@ endif() target_link_libraries(fdbserver PRIVATE toml11_target jemalloc rapidjson) # target_compile_definitions(fdbserver PRIVATE -DENABLE_SAMPLING) -if (GPERFTOOLS_FOUND) +if(GPERFTOOLS_FOUND) target_link_libraries(fdbserver PRIVATE gperftools) endif() diff --git a/fdbserver/tester.actor.cpp b/fdbserver/tester.actor.cpp index 8df0a2c0ba..273cd9f6b0 100644 --- a/fdbserver/tester.actor.cpp +++ b/fdbserver/tester.actor.cpp @@ -31,6 +31,7 @@ #include "fdbclient/ClusterInterface.h" #include "fdbclient/NativeAPI.actor.h" #include "fdbclient/SystemData.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbserver/KnobProtectiveGroups.h" #include "fdbserver/TesterInterface.actor.h" #include "fdbserver/WorkerInterface.actor.h" @@ -779,7 +780,7 @@ ACTOR Future clearData(Database cx) { // it should disable the default tenant. if (!rangeResult.empty()) { if (cx->defaultTenant.present()) { - TenantMapEntry entry = wait(ManagementAPI::getTenant(cx.getReference(), cx->defaultTenant.get())); + TenantMapEntry entry = wait(TenantAPI::getTenant(cx.getReference(), cx->defaultTenant.get())); tenantPrefix = entry.prefix; } @@ -1629,7 +1630,7 @@ ACTOR Future runTests(Reference> tenantFutures; for (auto tenant : tenantsToCreate) { TraceEvent("CreatingTenant").detail("Tenant", tenant); - tenantFutures.push_back(success(ManagementAPI::createTenant(cx.getReference(), tenant))); + tenantFutures.push_back(success(TenantAPI::createTenant(cx.getReference(), tenant))); } wait(waitForAll(tenantFutures)); diff --git a/fdbserver/workloads/BlobGranuleCorrectnessWorkload.actor.cpp b/fdbserver/workloads/BlobGranuleCorrectnessWorkload.actor.cpp index 9dad5c15d7..8ecbb741a3 100644 --- a/fdbserver/workloads/BlobGranuleCorrectnessWorkload.actor.cpp +++ b/fdbserver/workloads/BlobGranuleCorrectnessWorkload.actor.cpp @@ -30,6 +30,7 @@ #include "fdbclient/NativeAPI.actor.h" #include "fdbclient/ReadYourWrites.h" #include "fdbclient/SystemData.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbserver/BlobGranuleServerCommon.actor.h" #include "fdbserver/BlobGranuleValidation.actor.h" #include "fdbserver/Knobs.h" @@ -207,7 +208,7 @@ struct BlobGranuleCorrectnessWorkload : TestWorkload { fmt::print("Setting up blob granule range for tenant {0}\n", name.printable()); } - TenantMapEntry entry = wait(ManagementAPI::createTenant(cx.getReference(), name)); + TenantMapEntry entry = wait(TenantAPI::createTenant(cx.getReference(), name)); if (BGW_DEBUG) { fmt::print("Set up blob granule range for tenant {0}: {1}\n", name.printable(), entry.prefix.printable()); diff --git a/fdbserver/workloads/FuzzApiCorrectness.actor.cpp b/fdbserver/workloads/FuzzApiCorrectness.actor.cpp index 096a20d551..390ff6f295 100644 --- a/fdbserver/workloads/FuzzApiCorrectness.actor.cpp +++ b/fdbserver/workloads/FuzzApiCorrectness.actor.cpp @@ -26,6 +26,7 @@ #include "fdbclient/FDBOptions.g.h" #include "fdbserver/TesterInterface.actor.h" #include "fdbclient/GenericManagementAPI.actor.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbclient/ThreadSafeTransaction.h" #include "flow/ActorCollection.h" #include "fdbserver/workloads/workloads.actor.h" @@ -225,7 +226,7 @@ struct FuzzApiCorrectnessWorkload : TestWorkload { // The last tenant will not be created if (i < self->numTenants) { - tenantFutures.push_back(::success(ManagementAPI::createTenant(cx.getReference(), tenantName))); + tenantFutures.push_back(::success(TenantAPI::createTenant(cx.getReference(), tenantName))); self->createdTenants.insert(tenantName); } } diff --git a/fdbserver/workloads/TenantManagement.actor.cpp b/fdbserver/workloads/TenantManagementWorkload.actor.cpp similarity index 95% rename from fdbserver/workloads/TenantManagement.actor.cpp rename to fdbserver/workloads/TenantManagementWorkload.actor.cpp index f9b7203d59..5bb2fa5573 100644 --- a/fdbserver/workloads/TenantManagement.actor.cpp +++ b/fdbserver/workloads/TenantManagementWorkload.actor.cpp @@ -1,5 +1,5 @@ /* - * TenantManagement.actor.cpp + * TenantManagementWorkload.actor.cpp * * This source file is part of the FoundationDB open source project * @@ -21,7 +21,7 @@ #include #include #include "fdbclient/FDBOptions.g.h" -#include "fdbclient/GenericManagementAPI.actor.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbrpc/simulator.h" #include "fdbserver/workloads/workloads.actor.h" #include "fdbserver/Knobs.h" @@ -163,7 +163,7 @@ struct TenantManagementWorkload : TestWorkload { wait(tr->commit()); } else if (operationType == OperationType::MANAGEMENT_DATABASE) { ASSERT(tenantsToCreate.size() == 1); - wait(success(ManagementAPI::createTenant(cx.getReference(), *tenantsToCreate.begin()))); + wait(success(TenantAPI::createTenant(cx.getReference(), *tenantsToCreate.begin()))); } else { tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); @@ -172,8 +172,7 @@ struct TenantManagementWorkload : TestWorkload { std::vector> createFutures; for (auto tenant : tenantsToCreate) { - createFutures.push_back( - success(ManagementAPI::createTenantTransaction(tr, tenant, ++previousId))); + createFutures.push_back(success(TenantAPI::createTenantTransaction(tr, tenant, ++previousId))); } tr->set(tenantLastIdKey, TenantMapEntry::idToPrefix(previousId)); wait(waitForAll(createFutures)); @@ -192,8 +191,7 @@ struct TenantManagementWorkload : TestWorkload { continue; } - state Optional entry = - wait(ManagementAPI::tryGetTenant(cx.getReference(), *tenantItr)); + state Optional entry = wait(TenantAPI::tryGetTenant(cx.getReference(), *tenantItr)); ASSERT(entry.present()); ASSERT(entry.get().id > self->maxId); ASSERT(entry.get().prefix.startsWith(self->tenantSubspace)); @@ -340,13 +338,13 @@ struct TenantManagementWorkload : TestWorkload { } else if (operationType == OperationType::MANAGEMENT_DATABASE) { ASSERT(tenants.size() == 1); for (tenantIndex = 0; tenantIndex != tenants.size(); ++tenantIndex) { - wait(ManagementAPI::deleteTenant(cx.getReference(), tenants[tenantIndex])); + wait(TenantAPI::deleteTenant(cx.getReference(), tenants[tenantIndex])); } } else { tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); std::vector> deleteFutures; for (tenantIndex = 0; tenantIndex != tenants.size(); ++tenantIndex) { - deleteFutures.push_back(ManagementAPI::deleteTenantTransaction(tr, tenants[tenantIndex])); + deleteFutures.push_back(TenantAPI::deleteTenantTransaction(tr, tenants[tenantIndex])); } wait(waitForAll(deleteFutures)); @@ -452,11 +450,11 @@ struct TenantManagementWorkload : TestWorkload { } entry = TenantManagementWorkload::jsonToTenantMapEntry(value.get()); } else if (operationType == OperationType::MANAGEMENT_DATABASE) { - TenantMapEntry _entry = wait(ManagementAPI::getTenant(cx.getReference(), tenant)); + TenantMapEntry _entry = wait(TenantAPI::getTenant(cx.getReference(), tenant)); entry = _entry; } else { tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); - TenantMapEntry _entry = wait(ManagementAPI::getTenantTransaction(tr, tenant)); + TenantMapEntry _entry = wait(TenantAPI::getTenantTransaction(tr, tenant)); entry = _entry; } ASSERT(alreadyExists); @@ -510,12 +508,12 @@ struct TenantManagementWorkload : TestWorkload { } } else if (operationType == OperationType::MANAGEMENT_DATABASE) { std::map _tenants = - wait(ManagementAPI::listTenants(cx.getReference(), beginTenant, endTenant, limit)); + wait(TenantAPI::listTenants(cx.getReference(), beginTenant, endTenant, limit)); tenants = _tenants; } else { tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS); std::map _tenants = - wait(ManagementAPI::listTenantsTransaction(tr, beginTenant, endTenant, limit)); + wait(TenantAPI::listTenantsTransaction(tr, beginTenant, endTenant, limit)); tenants = _tenants; } @@ -601,7 +599,7 @@ struct TenantManagementWorkload : TestWorkload { loop { std::map tenants = - wait(ManagementAPI::listTenants(cx.getReference(), beginTenant, endTenant, 1000)); + wait(TenantAPI::listTenants(cx.getReference(), beginTenant, endTenant, 1000)); TenantNameRef lastTenant; for (auto tenant : tenants) { diff --git a/fdbserver/workloads/WriteDuringRead.actor.cpp b/fdbserver/workloads/WriteDuringRead.actor.cpp index a462877aba..c7253748da 100644 --- a/fdbserver/workloads/WriteDuringRead.actor.cpp +++ b/fdbserver/workloads/WriteDuringRead.actor.cpp @@ -21,6 +21,7 @@ #include "fdbclient/ClusterConnectionMemoryRecord.h" #include "fdbclient/ManagementAPI.actor.h" #include "fdbclient/NativeAPI.actor.h" +#include "fdbclient/TenantManagement.actor.h" #include "fdbserver/TesterInterface.actor.h" #include "fdbclient/ReadYourWrites.h" #include "flow/ActorCollection.h" @@ -118,7 +119,7 @@ struct WriteDuringReadWorkload : TestWorkload { // If we are operating in the default tenant but enable raw access, we should only write keys // in the tenant's key-space. if (self->useSystemKeys && cx->defaultTenant.present() && self->keyPrefix < systemKeys.begin) { - TenantMapEntry entry = wait(ManagementAPI::getTenant(cx.getReference(), cx->defaultTenant.get())); + TenantMapEntry entry = wait(TenantAPI::getTenant(cx.getReference(), cx->defaultTenant.get())); self->keyPrefix = entry.prefix.withSuffix(self->keyPrefix).toString(); } return Void();