Merge pull request #7881 from sfc-gh-ajbeamon/metacluster-restore-prep

Metacluster restore preparation
This commit is contained in:
A.J. Beamon 2022-08-14 11:00:07 -07:00 committed by GitHub
commit ae1fc191f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 13 deletions

View File

@ -30,6 +30,8 @@ std::string DataClusterEntry::clusterStateToString(DataClusterState clusterState
return "ready"; return "ready";
case DataClusterState::REMOVING: case DataClusterState::REMOVING:
return "removing"; return "removing";
case DataClusterState::RESTORING:
return "restoring";
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -40,6 +42,8 @@ DataClusterState DataClusterEntry::stringToClusterState(std::string stateStr) {
return DataClusterState::READY; return DataClusterState::READY;
} else if (stateStr == "removing") { } else if (stateStr == "removing") {
return DataClusterState::REMOVING; return DataClusterState::REMOVING;
} else if (stateStr == "restoring") {
return DataClusterState::RESTORING;
} }
UNREACHABLE(); UNREACHABLE();

View File

@ -47,6 +47,10 @@ std::string TenantMapEntry::tenantStateToString(TenantState tenantState) {
return "removing"; return "removing";
case TenantState::UPDATING_CONFIGURATION: case TenantState::UPDATING_CONFIGURATION:
return "updating configuration"; return "updating configuration";
case TenantState::RENAMING_FROM:
return "renaming from";
case TenantState::RENAMING_TO:
return "renaming to";
case TenantState::ERROR: case TenantState::ERROR:
return "error"; return "error";
default: default:
@ -63,6 +67,10 @@ TenantState TenantMapEntry::stringToTenantState(std::string stateStr) {
return TenantState::REMOVING; return TenantState::REMOVING;
} else if (stateStr == "updating configuration") { } else if (stateStr == "updating configuration") {
return TenantState::UPDATING_CONFIGURATION; return TenantState::UPDATING_CONFIGURATION;
} else if (stateStr == "renaming from") {
return TenantState::RENAMING_FROM;
} else if (stateStr == "renaming to") {
return TenantState::RENAMING_TO;
} else if (stateStr == "error") { } else if (stateStr == "error") {
return TenantState::ERROR; return TenantState::ERROR;
} }
@ -127,7 +135,7 @@ std::string TenantMapEntry::toJson(int apiVersion) const {
} }
bool TenantMapEntry::matchesConfiguration(TenantMapEntry const& other) const { bool TenantMapEntry::matchesConfiguration(TenantMapEntry const& other) const {
return tenantGroup == other.tenantGroup; return tenantGroup == other.tenantGroup && encrypted == other.encrypted;
} }
void TenantMapEntry::configure(Standalone<StringRef> parameter, Optional<Value> value) { void TenantMapEntry::configure(Standalone<StringRef> parameter, Optional<Value> value) {

View File

@ -57,7 +57,9 @@ struct Traceable<ClusterUsage> : std::true_type {
// //
// READY - the data cluster is active // READY - the data cluster is active
// REMOVING - the data cluster is being removed and cannot have its configuration changed or any tenants created // REMOVING - the data cluster is being removed and cannot have its configuration changed or any tenants created
enum class DataClusterState { READY, REMOVING }; // RESTORING - the data cluster is being restored and cannot have its configuration changed or any tenants
// created/updated/deleted.
enum class DataClusterState { READY, REMOVING, RESTORING };
struct DataClusterEntry { struct DataClusterEntry {
constexpr static FileIdentifier file_identifier = 929511; constexpr static FileIdentifier file_identifier = 929511;

View File

@ -108,10 +108,10 @@ struct ManagementClusterMetadata {
// A map from cluster name to a count of tenants // A map from cluster name to a count of tenants
static KeyBackedMap<ClusterName, int64_t, TupleCodec<ClusterName>, BinaryCodec<int64_t>> clusterTenantCount; static KeyBackedMap<ClusterName, int64_t, TupleCodec<ClusterName>, BinaryCodec<int64_t>> clusterTenantCount;
// A set of cluster/tenant pairings ordered by cluster // A set of (cluster name, tenant name, tenant ID) tuples ordered by cluster
static KeyBackedSet<Tuple> clusterTenantIndex; static KeyBackedSet<Tuple> clusterTenantIndex;
// A set of cluster/tenant group pairings ordered by cluster // A set of (cluster, tenant group name) tuples ordered by cluster
static KeyBackedSet<Tuple> clusterTenantGroupIndex; static KeyBackedSet<Tuple> clusterTenantGroupIndex;
}; };
@ -793,6 +793,7 @@ struct RemoveClusterImpl {
for (Tuple entry : tenantEntries.results) { for (Tuple entry : tenantEntries.results) {
ASSERT(entry.getString(0) == self->ctx.clusterName.get()); ASSERT(entry.getString(0) == self->ctx.clusterName.get());
ManagementClusterMetadata::tenantMetadata().tenantMap.erase(tr, entry.getString(1)); ManagementClusterMetadata::tenantMetadata().tenantMap.erase(tr, entry.getString(1));
ManagementClusterMetadata::tenantMetadata().tenantIdIndex.erase(tr, entry.getInt(2));
} }
// Erase all of the tenants processed in this transaction from the cluster tenant index // Erase all of the tenants processed in this transaction from the cluster tenant index
@ -1114,12 +1115,15 @@ struct CreateTenantImpl {
// The previous creation is permanently failed, so cleanup the tenant and create it again from scratch // The previous creation is permanently failed, so cleanup the tenant and create it again from scratch
// We don't need to remove it from the tenant map because we will overwrite the existing entry later in // We don't need to remove it from the tenant map because we will overwrite the existing entry later in
// this transaction. // this transaction.
ManagementClusterMetadata::tenantMetadata().tenantIdIndex.erase(tr, existingEntry.get().id);
ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue); ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue);
ManagementClusterMetadata::clusterTenantCount.atomicOp( ManagementClusterMetadata::clusterTenantCount.atomicOp(
tr, existingEntry.get().assignedCluster.get(), -1, MutationRef::AddValue); tr, existingEntry.get().assignedCluster.get(), -1, MutationRef::AddValue);
ManagementClusterMetadata::clusterTenantIndex.erase( ManagementClusterMetadata::clusterTenantIndex.erase(
tr, Tuple::makeTuple(existingEntry.get().assignedCluster.get(), self->tenantName)); tr,
Tuple::makeTuple(
existingEntry.get().assignedCluster.get(), self->tenantName, existingEntry.get().id));
state DataClusterMetadata previousAssignedClusterMetadata = state DataClusterMetadata previousAssignedClusterMetadata =
wait(getClusterTransaction(tr, existingEntry.get().assignedCluster.get())); wait(getClusterTransaction(tr, existingEntry.get().assignedCluster.get()));
@ -1221,6 +1225,7 @@ struct CreateTenantImpl {
self->tenantEntry.tenantState = TenantState::REGISTERING; self->tenantEntry.tenantState = TenantState::REGISTERING;
ManagementClusterMetadata::tenantMetadata().tenantMap.set(tr, self->tenantName, self->tenantEntry); ManagementClusterMetadata::tenantMetadata().tenantMap.set(tr, self->tenantName, self->tenantEntry);
ManagementClusterMetadata::tenantMetadata().tenantIdIndex.set(tr, self->tenantEntry.id, self->tenantName);
ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, 1, MutationRef::AddValue); ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, 1, MutationRef::AddValue);
ManagementClusterMetadata::clusterTenantCount.atomicOp( ManagementClusterMetadata::clusterTenantCount.atomicOp(
@ -1235,7 +1240,7 @@ struct CreateTenantImpl {
// Updated indexes to include the new tenant // Updated indexes to include the new tenant
ManagementClusterMetadata::clusterTenantIndex.insert( ManagementClusterMetadata::clusterTenantIndex.insert(
tr, Tuple::makeTuple(self->tenantEntry.assignedCluster.get(), self->tenantName)); tr, Tuple::makeTuple(self->tenantEntry.assignedCluster.get(), self->tenantName, self->tenantEntry.id));
wait(setClusterFuture); wait(setClusterFuture);
@ -1402,6 +1407,7 @@ struct DeleteTenantImpl {
// Erase the tenant entry itself // Erase the tenant entry itself
ManagementClusterMetadata::tenantMetadata().tenantMap.erase(tr, self->tenantName); ManagementClusterMetadata::tenantMetadata().tenantMap.erase(tr, self->tenantName);
ManagementClusterMetadata::tenantMetadata().tenantIdIndex.erase(tr, tenantEntry.get().id);
// This is idempotent because this function is only called if the tenant is in the map // This is idempotent because this function is only called if the tenant is in the map
ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue); ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue);
@ -1410,7 +1416,7 @@ struct DeleteTenantImpl {
// Remove the tenant from the cluster -> tenant index // Remove the tenant from the cluster -> tenant index
ManagementClusterMetadata::clusterTenantIndex.erase( ManagementClusterMetadata::clusterTenantIndex.erase(
tr, Tuple::makeTuple(tenantEntry.get().assignedCluster.get(), self->tenantName)); tr, Tuple::makeTuple(tenantEntry.get().assignedCluster.get(), self->tenantName, tenantEntry.get().id));
// Remove the tenant from its tenant group // Remove the tenant from its tenant group
wait(managementClusterRemoveTenantFromGroup( wait(managementClusterRemoveTenantFromGroup(

View File

@ -164,6 +164,7 @@ struct TenantMetadataSpecification {
Key subspace; Key subspace;
KeyBackedObjectMap<TenantName, TenantMapEntry, decltype(IncludeVersion()), NullCodec> tenantMap; KeyBackedObjectMap<TenantName, TenantMapEntry, decltype(IncludeVersion()), NullCodec> tenantMap;
KeyBackedMap<int64_t, TenantName> tenantIdIndex;
KeyBackedProperty<int64_t> lastTenantId; KeyBackedProperty<int64_t> lastTenantId;
KeyBackedBinaryValue<int64_t> tenantCount; KeyBackedBinaryValue<int64_t> tenantCount;
KeyBackedSet<int64_t> tenantTombstones; KeyBackedSet<int64_t> tenantTombstones;
@ -173,8 +174,8 @@ struct TenantMetadataSpecification {
TenantMetadataSpecification(KeyRef prefix) TenantMetadataSpecification(KeyRef prefix)
: subspace(prefix.withSuffix("tenant/"_sr)), tenantMap(subspace.withSuffix("map/"_sr), IncludeVersion()), : subspace(prefix.withSuffix("tenant/"_sr)), tenantMap(subspace.withSuffix("map/"_sr), IncludeVersion()),
lastTenantId(subspace.withSuffix("lastId"_sr)), tenantCount(subspace.withSuffix("count"_sr)), tenantIdIndex(subspace.withSuffix("idIndex/"_sr)), lastTenantId(subspace.withSuffix("lastId"_sr)),
tenantTombstones(subspace.withSuffix("tombstones/"_sr)), tenantCount(subspace.withSuffix("count"_sr)), tenantTombstones(subspace.withSuffix("tombstones/"_sr)),
tombstoneCleanupData(subspace.withSuffix("tombstoneCleanup"_sr), IncludeVersion()), tombstoneCleanupData(subspace.withSuffix("tombstoneCleanup"_sr), IncludeVersion()),
tenantGroupTenantIndex(subspace.withSuffix("tenantGroup/tenantIndex/"_sr)), tenantGroupTenantIndex(subspace.withSuffix("tenantGroup/tenantIndex/"_sr)),
tenantGroupMap(subspace.withSuffix("tenantGroup/map/"_sr), IncludeVersion()) {} tenantGroupMap(subspace.withSuffix("tenantGroup/map/"_sr), IncludeVersion()) {}
@ -185,6 +186,7 @@ struct TenantMetadata {
static inline auto& subspace() { return instance().subspace; } static inline auto& subspace() { return instance().subspace; }
static inline auto& tenantMap() { return instance().tenantMap; } static inline auto& tenantMap() { return instance().tenantMap; }
static inline auto& tenantIdIndex() { return instance().tenantIdIndex; }
static inline auto& lastTenantId() { return instance().lastTenantId; } static inline auto& lastTenantId() { return instance().lastTenantId; }
static inline auto& tenantCount() { return instance().tenantCount; } static inline auto& tenantCount() { return instance().tenantCount; }
static inline auto& tenantTombstones() { return instance().tenantTombstones; } static inline auto& tenantTombstones() { return instance().tenantTombstones; }

View File

@ -177,6 +177,8 @@ Future<std::pair<Optional<TenantMapEntry>, bool>> createTenantTransaction(
tenantEntry.assignedCluster = Optional<ClusterName>(); tenantEntry.assignedCluster = Optional<ClusterName>();
TenantMetadata::tenantMap().set(tr, name, tenantEntry); TenantMetadata::tenantMap().set(tr, name, tenantEntry);
TenantMetadata::tenantIdIndex().set(tr, tenantEntry.id, name);
if (tenantEntry.tenantGroup.present()) { if (tenantEntry.tenantGroup.present()) {
TenantMetadata::tenantGroupTenantIndex().insert(tr, Tuple::makeTuple(tenantEntry.tenantGroup.get(), name)); TenantMetadata::tenantGroupTenantIndex().insert(tr, Tuple::makeTuple(tenantEntry.tenantGroup.get(), name));
@ -298,6 +300,7 @@ Future<Void> deleteTenantTransaction(Transaction tr,
// This is idempotent because we only erase an entry from the tenant map if it is present // This is idempotent because we only erase an entry from the tenant map if it is present
TenantMetadata::tenantMap().erase(tr, name); TenantMetadata::tenantMap().erase(tr, name);
TenantMetadata::tenantIdIndex().erase(tr, tenantEntry.get().id);
TenantMetadata::tenantCount().atomicOp(tr, -1, MutationRef::AddValue); TenantMetadata::tenantCount().atomicOp(tr, -1, MutationRef::AddValue);
if (tenantEntry.get().tenantGroup.present()) { if (tenantEntry.get().tenantGroup.present()) {
@ -407,6 +410,8 @@ Future<Void> configureTenantTransaction(Transaction tr,
TenantNameRef tenantName, TenantNameRef tenantName,
TenantMapEntry originalEntry, TenantMapEntry originalEntry,
TenantMapEntry updatedTenantEntry) { TenantMapEntry updatedTenantEntry) {
ASSERT(updatedTenantEntry.id == originalEntry.id);
tr->setOption(FDBTransactionOptions::RAW_ACCESS); tr->setOption(FDBTransactionOptions::RAW_ACCESS);
TenantMetadata::tenantMap().set(tr, tenantName, updatedTenantEntry); TenantMetadata::tenantMap().set(tr, tenantName, updatedTenantEntry);
@ -497,6 +502,7 @@ Future<Void> renameTenantTransaction(Transaction tr, TenantNameRef oldName, Tena
} }
TenantMetadata::tenantMap().erase(tr, oldName); TenantMetadata::tenantMap().erase(tr, oldName);
TenantMetadata::tenantMap().set(tr, newName, oldEntry.get()); TenantMetadata::tenantMap().set(tr, newName, oldEntry.get());
TenantMetadata::tenantIdIndex().set(tr, oldEntry.get().id, newName);
// Update the tenant group index to reflect the new tenant name // Update the tenant group index to reflect the new tenant name
if (oldEntry.get().tenantGroup.present()) { if (oldEntry.get().tenantGroup.present()) {

View File

@ -116,8 +116,11 @@ private:
self->managementMetadata.tenantMap = std::map<TenantName, TenantMapEntry>(tenantList.begin(), tenantList.end()); self->managementMetadata.tenantMap = std::map<TenantName, TenantMapEntry>(tenantList.begin(), tenantList.end());
for (auto t : self->managementMetadata.clusterTenantTuples.results) { for (auto t : self->managementMetadata.clusterTenantTuples.results) {
ASSERT(t.size() == 2); ASSERT(t.size() == 3);
self->managementMetadata.clusterTenantMap[t.getString(0)].insert(t.getString(1)); TenantName tenantName = t.getString(1);
int64_t tenantId = t.getInt(2);
ASSERT(tenantId == self->managementMetadata.tenantMap[tenantName].id);
self->managementMetadata.clusterTenantMap[t.getString(0)].insert(tenantName);
} }
for (auto t : self->managementMetadata.clusterTenantGroupTuples.results) { for (auto t : self->managementMetadata.clusterTenantGroupTuples.results) {

View File

@ -46,6 +46,7 @@ private:
struct TenantData { struct TenantData {
Optional<MetaclusterRegistrationEntry> metaclusterRegistration; Optional<MetaclusterRegistrationEntry> metaclusterRegistration;
std::map<TenantName, TenantMapEntry> tenantMap; std::map<TenantName, TenantMapEntry> tenantMap;
std::map<int64_t, TenantName> tenantIdIndex;
int64_t lastTenantId; int64_t lastTenantId;
int64_t tenantCount; int64_t tenantCount;
std::set<int64_t> tenantTombstones; std::set<int64_t> tenantTombstones;
@ -67,6 +68,7 @@ private:
ACTOR static Future<Void> loadTenantMetadata(TenantConsistencyCheck* self) { ACTOR static Future<Void> loadTenantMetadata(TenantConsistencyCheck* self) {
state Reference<typename DB::TransactionT> tr = self->db->createTransaction(); state Reference<typename DB::TransactionT> tr = self->db->createTransaction();
state KeyBackedRangeResult<std::pair<TenantName, TenantMapEntry>> tenantList; state KeyBackedRangeResult<std::pair<TenantName, TenantMapEntry>> tenantList;
state KeyBackedRangeResult<std::pair<int64_t, TenantName>> tenantIdIndexList;
state KeyBackedRangeResult<int64_t> tenantTombstoneList; state KeyBackedRangeResult<int64_t> tenantTombstoneList;
state KeyBackedRangeResult<std::pair<TenantGroupName, TenantGroupEntry>> tenantGroupList; state KeyBackedRangeResult<std::pair<TenantGroupName, TenantGroupEntry>> tenantGroupList;
state KeyBackedRangeResult<Tuple> tenantGroupTenantTuples; state KeyBackedRangeResult<Tuple> tenantGroupTenantTuples;
@ -90,6 +92,8 @@ private:
wait( wait(
store(tenantList, tenantMetadata->tenantMap.getRange(tr, {}, {}, metaclusterMaxTenants)) && store(tenantList, tenantMetadata->tenantMap.getRange(tr, {}, {}, metaclusterMaxTenants)) &&
store(tenantIdIndexList,
tenantMetadata->tenantIdIndex.getRange(tr, {}, {}, metaclusterMaxTenants)) &&
store(self->metadata.lastTenantId, tenantMetadata->lastTenantId.getD(tr, Snapshot::False, -1)) && store(self->metadata.lastTenantId, tenantMetadata->lastTenantId.getD(tr, Snapshot::False, -1)) &&
store(self->metadata.tenantCount, tenantMetadata->tenantCount.getD(tr, Snapshot::False, 0)) && store(self->metadata.tenantCount, tenantMetadata->tenantCount.getD(tr, Snapshot::False, 0)) &&
store(tenantTombstoneList, store(tenantTombstoneList,
@ -108,8 +112,16 @@ private:
ASSERT(!tenantList.more); ASSERT(!tenantList.more);
self->metadata.tenantMap = self->metadata.tenantMap =
std::map<TenantName, TenantMapEntry>(tenantList.results.begin(), tenantList.results.end()); std::map<TenantName, TenantMapEntry>(tenantList.results.begin(), tenantList.results.end());
ASSERT(!tenantIdIndexList.more);
self->metadata.tenantIdIndex =
std::map<int64_t, TenantName>(tenantIdIndexList.results.begin(), tenantIdIndexList.results.end());
ASSERT(!tenantTombstoneList.more);
self->metadata.tenantTombstones = self->metadata.tenantTombstones =
std::set<int64_t>(tenantTombstoneList.results.begin(), tenantTombstoneList.results.end()); std::set<int64_t>(tenantTombstoneList.results.begin(), tenantTombstoneList.results.end());
ASSERT(!tenantGroupList.more);
self->metadata.tenantGroupMap = self->metadata.tenantGroupMap =
std::map<TenantGroupName, TenantGroupEntry>(tenantGroupList.results.begin(), tenantGroupList.results.end()); std::map<TenantGroupName, TenantGroupEntry>(tenantGroupList.results.begin(), tenantGroupList.results.end());
@ -135,13 +147,13 @@ private:
} }
ASSERT(metadata.tenantMap.size() == metadata.tenantCount); ASSERT(metadata.tenantMap.size() == metadata.tenantCount);
ASSERT(metadata.tenantIdIndex.size() == metadata.tenantCount);
std::set<int64_t> tenantIds;
for (auto [tenantName, tenantMapEntry] : metadata.tenantMap) { for (auto [tenantName, tenantMapEntry] : metadata.tenantMap) {
if (metadata.clusterType != ClusterType::METACLUSTER_DATA) { if (metadata.clusterType != ClusterType::METACLUSTER_DATA) {
ASSERT(tenantMapEntry.id <= metadata.lastTenantId); ASSERT(tenantMapEntry.id <= metadata.lastTenantId);
} }
ASSERT(tenantIds.insert(tenantMapEntry.id).second); ASSERT(metadata.tenantIdIndex[tenantMapEntry.id] == tenantName);
ASSERT(!metadata.tenantTombstones.count(tenantMapEntry.id)); ASSERT(!metadata.tenantTombstones.count(tenantMapEntry.id));
if (tenantMapEntry.tenantGroup.present()) { if (tenantMapEntry.tenantGroup.present()) {