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";
case DataClusterState::REMOVING:
return "removing";
case DataClusterState::RESTORING:
return "restoring";
default:
UNREACHABLE();
}
@ -40,6 +42,8 @@ DataClusterState DataClusterEntry::stringToClusterState(std::string stateStr) {
return DataClusterState::READY;
} else if (stateStr == "removing") {
return DataClusterState::REMOVING;
} else if (stateStr == "restoring") {
return DataClusterState::RESTORING;
}
UNREACHABLE();

View File

@ -47,6 +47,10 @@ std::string TenantMapEntry::tenantStateToString(TenantState tenantState) {
return "removing";
case TenantState::UPDATING_CONFIGURATION:
return "updating configuration";
case TenantState::RENAMING_FROM:
return "renaming from";
case TenantState::RENAMING_TO:
return "renaming to";
case TenantState::ERROR:
return "error";
default:
@ -63,6 +67,10 @@ TenantState TenantMapEntry::stringToTenantState(std::string stateStr) {
return TenantState::REMOVING;
} else if (stateStr == "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") {
return TenantState::ERROR;
}
@ -127,7 +135,7 @@ std::string TenantMapEntry::toJson(int apiVersion) 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) {

View File

@ -57,7 +57,9 @@ struct Traceable<ClusterUsage> : std::true_type {
//
// READY - the data cluster is active
// 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 {
constexpr static FileIdentifier file_identifier = 929511;

View File

@ -108,10 +108,10 @@ struct ManagementClusterMetadata {
// A map from cluster name to a count of tenants
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;
// 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;
};
@ -793,6 +793,7 @@ struct RemoveClusterImpl {
for (Tuple entry : tenantEntries.results) {
ASSERT(entry.getString(0) == self->ctx.clusterName.get());
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
@ -1114,12 +1115,15 @@ struct CreateTenantImpl {
// 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
// this transaction.
ManagementClusterMetadata::tenantMetadata().tenantIdIndex.erase(tr, existingEntry.get().id);
ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue);
ManagementClusterMetadata::clusterTenantCount.atomicOp(
tr, existingEntry.get().assignedCluster.get(), -1, MutationRef::AddValue);
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 =
wait(getClusterTransaction(tr, existingEntry.get().assignedCluster.get()));
@ -1221,6 +1225,7 @@ struct CreateTenantImpl {
self->tenantEntry.tenantState = TenantState::REGISTERING;
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::clusterTenantCount.atomicOp(
@ -1235,7 +1240,7 @@ struct CreateTenantImpl {
// Updated indexes to include the new tenant
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);
@ -1402,6 +1407,7 @@ struct DeleteTenantImpl {
// Erase the tenant entry itself
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
ManagementClusterMetadata::tenantMetadata().tenantCount.atomicOp(tr, -1, MutationRef::AddValue);
@ -1410,7 +1416,7 @@ struct DeleteTenantImpl {
// Remove the tenant from the cluster -> tenant index
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
wait(managementClusterRemoveTenantFromGroup(

View File

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

View File

@ -177,6 +177,8 @@ Future<std::pair<Optional<TenantMapEntry>, bool>> createTenantTransaction(
tenantEntry.assignedCluster = Optional<ClusterName>();
TenantMetadata::tenantMap().set(tr, name, tenantEntry);
TenantMetadata::tenantIdIndex().set(tr, tenantEntry.id, name);
if (tenantEntry.tenantGroup.present()) {
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
TenantMetadata::tenantMap().erase(tr, name);
TenantMetadata::tenantIdIndex().erase(tr, tenantEntry.get().id);
TenantMetadata::tenantCount().atomicOp(tr, -1, MutationRef::AddValue);
if (tenantEntry.get().tenantGroup.present()) {
@ -407,6 +410,8 @@ Future<Void> configureTenantTransaction(Transaction tr,
TenantNameRef tenantName,
TenantMapEntry originalEntry,
TenantMapEntry updatedTenantEntry) {
ASSERT(updatedTenantEntry.id == originalEntry.id);
tr->setOption(FDBTransactionOptions::RAW_ACCESS);
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().set(tr, newName, oldEntry.get());
TenantMetadata::tenantIdIndex().set(tr, oldEntry.get().id, newName);
// Update the tenant group index to reflect the new tenant name
if (oldEntry.get().tenantGroup.present()) {

View File

@ -116,8 +116,11 @@ private:
self->managementMetadata.tenantMap = std::map<TenantName, TenantMapEntry>(tenantList.begin(), tenantList.end());
for (auto t : self->managementMetadata.clusterTenantTuples.results) {
ASSERT(t.size() == 2);
self->managementMetadata.clusterTenantMap[t.getString(0)].insert(t.getString(1));
ASSERT(t.size() == 3);
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) {

View File

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