More carefully validate tenant increments to avoid overflows

This commit is contained in:
A.J. Beamon 2023-03-15 14:56:12 -07:00
parent dbcab0b1bd
commit 3881f1ccc6
4 changed files with 22 additions and 26 deletions

View File

@ -77,17 +77,16 @@ bool tenantMapChanging(MutationRef const& mutation, KeyRangeRef const& tenantMap
return false;
}
// validates whether the lastTenantId and the nextTenantId share the same 2 byte prefix
bool nextTenantIdPrefixMatches(int64_t lastTenantId, int64_t nextTenantId) {
if (getTenantIdPrefix(nextTenantId) != getTenantIdPrefix(lastTenantId)) {
TraceEvent(g_network->isSimulated() ? SevWarnAlways : SevError, "TenantIdPrefixMismatch")
.detail("CurrentTenantId", lastTenantId)
.detail("NewTenantId", nextTenantId)
.detail("CurrentTenantIdPrefix", getTenantIdPrefix(lastTenantId))
.detail("NewTenantIdPrefix", getTenantIdPrefix(nextTenantId));
return false;
// validates whether the the ID created by adding delta to baseID is a valid ID in the same tenant prefix
int64_t computeNextTenantId(int64_t baseId, int64_t delta) {
if ((baseId & 0xFFFFFFFFFFFF) + delta > 0xFFFFFFFFFFFF) {
TraceEvent(g_network->isSimulated() ? SevWarnAlways : SevError, "NoMoreTenantIds")
.detail("LastTenantId", baseId)
.detail("TenantIdPrefix", getTenantIdPrefix(baseId));
throw cluster_no_capacity();
}
return true;
return baseId + delta;
}
// returns the maximum allowable tenant id in which the 2 byte prefix is not overriden

View File

@ -2603,10 +2603,7 @@ struct CreateTenantImpl {
ASSERT(tenantIdPrefix.present());
lastId = tenantIdPrefix.get() << 48;
}
if (!TenantAPI::nextTenantIdPrefixMatches(lastId.get(), lastId.get() + 1)) {
throw cluster_no_capacity();
}
self->tenantEntry.setId(lastId.get() + 1);
self->tenantEntry.setId(TenantAPI::computeNextTenantId(lastId.get(), 1));
ManagementClusterMetadata::tenantMetadata().lastTenantId.set(tr, self->tenantEntry.id);
self->tenantEntry.tenantState = MetaclusterAPI::TenantState::REGISTERING;

View File

@ -127,7 +127,7 @@ TenantMode tenantModeForClusterType(ClusterType clusterType, TenantMode tenantMo
int64_t extractTenantIdFromMutation(MutationRef m);
int64_t extractTenantIdFromKeyRef(StringRef s);
bool tenantMapChanging(MutationRef const& mutation, KeyRangeRef const& tenantMapRange);
bool nextTenantIdPrefixMatches(int64_t lastTenantId, int64_t nextTenantId);
int64_t computeNextTenantId(int64_t tenantId, int64_t delta);
int64_t getMaxAllowableTenantId(int64_t curTenantId);
int64_t getTenantIdPrefix(int64_t tenantId);
@ -230,14 +230,13 @@ Future<int64_t> getNextTenantId(Transaction tr) {
// Shift by 6 bytes to make the prefix the first two bytes of the tenant id
lastId = tenantIdPrefix << 48;
}
int64_t tenantId = lastId.get() + 1;
int64_t delta = 1;
if (BUGGIFY) {
tenantId += deterministicRandom()->randomSkewedUInt32(1, 1e9);
delta += deterministicRandom()->randomSkewedUInt32(1, 1e9);
}
if (!TenantAPI::nextTenantIdPrefixMatches(lastId.get(), tenantId)) {
throw cluster_no_capacity();
}
return tenantId;
return TenantAPI::computeNextTenantId(lastId.get(), delta);
}
ACTOR template <class DB>

View File

@ -134,17 +134,18 @@ private:
TenantMetadata::tenantCount().getD(&ryw->getTransaction(), Snapshot::False, 0);
int64_t _nextId = wait(TenantAPI::getNextTenantId(&ryw->getTransaction()));
state int64_t nextId = _nextId;
ASSERT(nextId > 0);
ASSERT(nextId >= 0);
state std::vector<Future<bool>> createFutures;
int itrCount = 0;
for (auto const& [tenant, config] : tenants) {
if (!TenantAPI::nextTenantIdPrefixMatches(nextId - 1, nextId)) {
throw cluster_no_capacity();
createFutures.push_back(createTenant(ryw, tenant, config, nextId, tenantGroupNetTenantDelta));
if (++itrCount < tenants.size()) {
nextId = TenantAPI::computeNextTenantId(nextId, 1);
}
createFutures.push_back(createTenant(ryw, tenant, config, nextId++, tenantGroupNetTenantDelta));
}
TenantMetadata::lastTenantId().set(&ryw->getTransaction(), nextId - 1);
TenantMetadata::lastTenantId().set(&ryw->getTransaction(), nextId);
wait(waitForAll(createFutures));
state int numCreatedTenants = 0;