Merge pull request #7881 from sfc-gh-ajbeamon/metacluster-restore-prep
Metacluster restore preparation
This commit is contained in:
commit
ae1fc191f1
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue