diff --git a/contrib/TestHarness/Program.cs b/contrib/TestHarness/Program.cs index 0b2bbc1127..9bd3d6df18 100644 --- a/contrib/TestHarness/Program.cs +++ b/contrib/TestHarness/Program.cs @@ -789,7 +789,7 @@ namespace SummarizeTest int stderrSeverity = (int)Magnesium.Severity.SevError; Dictionary, Magnesium.Severity> severityMap = new Dictionary, Magnesium.Severity>(); - Dictionary, bool> codeCoverage = new Dictionary, bool>(); + var codeCoverage = new Dictionary, bool>(); foreach (var traceFileName in traceFiles) { @@ -902,12 +902,17 @@ namespace SummarizeTest if (ev.Type == "CodeCoverage" && !willRestart) { bool covered = true; - if(ev.DDetails.ContainsKey("Covered")) + if (ev.DDetails.ContainsKey("Covered")) { covered = int.Parse(ev.Details.Covered) != 0; } - var key = new Tuple(ev.Details.File, ev.Details.Line); + var comment = ""; + if (ev.DDetails.ContainsKey("Comment")) + { + comment = ev.Details.Comment; + } + var key = new Tuple(ev.Details.File, ev.Details.Line, comment); if (covered || !codeCoverage.ContainsKey(key)) { codeCoverage[key] = covered; @@ -961,6 +966,9 @@ namespace SummarizeTest { element.Add(new XAttribute("Covered", "0")); } + if (kv.Key.Item3.Length > 0) { + element.Add(new XAttribute("Comment", kv.Key.Item3)); + } xout.Add(element); } diff --git a/fdbclient/BlobGranuleFiles.cpp b/fdbclient/BlobGranuleFiles.cpp index 3b1ee32eb9..da3eb38e69 100644 --- a/fdbclient/BlobGranuleFiles.cpp +++ b/fdbclient/BlobGranuleFiles.cpp @@ -1393,7 +1393,7 @@ const EncryptCipherRandomSalt encryptSalt = deterministicRandom()->randomUInt64( Standalone getBaseCipher() { Standalone baseCipher = makeString(AES_256_KEY_LENGTH); - generateRandomData(mutateString(baseCipher), baseCipher.size()); + deterministicRandom()->randomBytes(mutateString(baseCipher), baseCipher.size()); return baseCipher; } @@ -1413,7 +1413,7 @@ BlobGranuleCipherKeysCtx getCipherKeysCtx(Arena& arena) { cipherKeysCtx.headerCipherKey.baseCipher = StringRef(arena, encryptBaseCipher); cipherKeysCtx.ivRef = makeString(AES_256_IV_LENGTH, arena); - generateRandomData(mutateString(cipherKeysCtx.ivRef), AES_256_IV_LENGTH); + deterministicRandom()->randomBytes(mutateString(cipherKeysCtx.ivRef), AES_256_IV_LENGTH); return cipherKeysCtx; } @@ -2222,4 +2222,4 @@ TEST_CASE("/blobgranule/files/granuleReadUnitTest") { } return Void(); -} \ No newline at end of file +} diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index e67fd50e49..293bc58d2a 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -242,7 +242,7 @@ void DatabaseContext::getLatestCommitVersions(const Reference& loc return; } - if (ssVersionVectorCache.getMaxVersion() != invalidVersion && readVersion > ssVersionVectorCache.getMaxVersion()) { + if (readVersion > ssVersionVectorCache.getMaxVersion()) { if (!CLIENT_KNOBS->FORCE_GRV_CACHE_OFF && !info->options.skipGrvCache && info->options.useGrvCache) { return; } else { @@ -255,16 +255,32 @@ void DatabaseContext::getLatestCommitVersions(const Reference& loc std::map> versionMap; // order the versions to be returned for (int i = 0; i < locationInfo->locations()->size(); i++) { - UID uid = locationInfo->locations()->getId(i); - if (ssidTagMapping.find(uid) != ssidTagMapping.end()) { - Tag tag = ssidTagMapping[uid]; + bool updatedVersionMap = false; + Version commitVersion = invalidVersion; + Tag tag = invalidTag; + auto iter = ssidTagMapping.find(locationInfo->locations()->getId(i)); + if (iter != ssidTagMapping.end()) { + tag = iter->second; if (ssVersionVectorCache.hasVersion(tag)) { - Version commitVersion = ssVersionVectorCache.getVersion(tag); // latest commit version + commitVersion = ssVersionVectorCache.getVersion(tag); // latest commit version if (commitVersion < readVersion) { + updatedVersionMap = true; versionMap[commitVersion].insert(tag); } } } + // commitVersion == readVersion is common, do not log. + if (!updatedVersionMap && commitVersion != readVersion) { + TraceEvent(SevDebug, "CommitVersionNotFoundForSS") + .detail("InSSIDMap", iter != ssidTagMapping.end() ? 1 : 0) + .detail("Tag", tag) + .detail("CommitVersion", commitVersion) + .detail("ReadVersion", readVersion) + .detail("VersionVector", ssVersionVectorCache.toString()) + .setMaxEventLength(11000) + .setMaxFieldLength(10000); + ++transactionCommitVersionNotFoundForSS; + } } // insert the commit versions in the version vector. @@ -710,6 +726,7 @@ ACTOR static Future delExcessClntTxnEntriesActor(Transaction* tr, int64_t tr->clear(KeyRangeRef(txEntries[0].key, strinc(endKey))); TraceEvent(SevInfo, "DeletingExcessCntTxnEntries").detail("BytesToBeDeleted", numBytesToDel); int64_t bytesDel = -numBytesToDel; + tr->atomicOp(clientLatencyAtomicCtr, StringRef((uint8_t*)&bytesDel, 8), MutationRef::AddValue); wait(tr->commit()); } @@ -1466,13 +1483,13 @@ DatabaseContext::DatabaseContext(ReferenceSHARD_STAT_SMOOTH_AMOUNT), + transactionCommitVersionNotFoundForSS("CommitVersionNotFoundForSS", cc), latencies(1000), readLatencies(1000), + commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), bytesPerCommit(1000), bgLatencies(1000), + bgGranulesPerRequest(1000), outstandingWatches(0), sharedStatePtr(nullptr), lastGrvTime(0.0), cachedReadVersion(0), + lastRkBatchThrottleTime(0.0), lastRkDefaultThrottleTime(0.0), lastProxyRequestTime(0.0), + transactionTracingSample(false), taskID(taskID), clientInfo(clientInfo), clientInfoMonitor(clientInfoMonitor), + coordinator(coordinator), apiVersion(apiVersion), mvCacheInsertLocation(0), healthMetricsLastUpdated(0), + detailedHealthMetricsLastUpdated(0), smoothMidShardSize(CLIENT_KNOBS->SHARD_STAT_SMOOTH_AMOUNT), specialKeySpace(std::make_unique(specialKeys.begin, specialKeys.end, /* test */ false)), connectToDatabaseEventCacheHolder(format("ConnectToDatabase/%s", dbId.toString().c_str())) { @@ -1765,8 +1782,9 @@ DatabaseContext::DatabaseContext(const Error& err) transactionsProcessBehind("ProcessBehind", cc), transactionsThrottled("Throttled", cc), transactionsExpensiveClearCostEstCount("ExpensiveClearCostEstCount", cc), transactionGrvFullBatches("NumGrvFullBatches", cc), transactionGrvTimedOutBatches("NumGrvTimedOutBatches", cc), - latencies(1000), readLatencies(1000), commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), - bytesPerCommit(1000), bgLatencies(1000), bgGranulesPerRequest(1000), transactionTracingSample(false), + transactionCommitVersionNotFoundForSS("CommitVersionNotFoundForSS", cc), latencies(1000), readLatencies(1000), + commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), bytesPerCommit(1000), bgLatencies(1000), + bgGranulesPerRequest(1000), transactionTracingSample(false), smoothMidShardSize(CLIENT_KNOBS->SHARD_STAT_SMOOTH_AMOUNT), connectToDatabaseEventCacheHolder(format("ConnectToDatabase/%s", dbId.toString().c_str())) {} @@ -1812,7 +1830,7 @@ DatabaseContext::~DatabaseContext() { TraceEvent("DatabaseContextDestructed", dbId).backtrace(); } -Optional DatabaseContext::getCachedLocation(const Optional& tenantName, +Optional DatabaseContext::getCachedLocation(const Optional& tenantName, const KeyRef& key, Reverse isBackward) { TenantMapEntry tenantEntry; @@ -1838,7 +1856,7 @@ Optional DatabaseContext::getCachedLocation(const Optional return Optional(); } -bool DatabaseContext::getCachedLocations(const Optional& tenantName, +bool DatabaseContext::getCachedLocations(const Optional& tenantName, const KeyRangeRef& range, std::vector& result, int limit, @@ -1895,7 +1913,7 @@ void DatabaseContext::cacheTenant(const TenantName& tenant, const TenantMapEntry } } -Reference DatabaseContext::setCachedLocation(const Optional& tenant, +Reference DatabaseContext::setCachedLocation(const Optional& tenant, const TenantMapEntry& tenantEntry, const KeyRangeRef& absoluteKeys, const std::vector& servers) { @@ -2836,7 +2854,7 @@ void updateTagMappings(Database cx, const GetKeyServerLocationsReply& reply) { // If isBackward == true, returns the shard containing the key before 'key' (an infinitely long, inexpressible key). // Otherwise returns the shard containing key ACTOR Future getKeyLocation_internal(Database cx, - Optional tenant, + TenantInfo tenant, Key key, SpanContext spanContext, Optional debugID, @@ -2859,26 +2877,20 @@ ACTOR Future getKeyLocation_internal(Database cx, ++cx->transactionKeyServerLocationRequests; choose { when(wait(cx->onProxiesChanged())) {} - when(GetKeyServerLocationsReply rep = - wait(basicLoadBalance(cx->getCommitProxies(useProvisionalProxies), - &CommitProxyInterface::getKeyServersLocations, - GetKeyServerLocationsRequest(span.context, - tenant.castTo(), - key, - Optional(), - 100, - isBackward, - version, - key.arena()), - TaskPriority::DefaultPromiseEndpoint))) { + when(GetKeyServerLocationsReply rep = wait(basicLoadBalance( + cx->getCommitProxies(useProvisionalProxies), + &CommitProxyInterface::getKeyServersLocations, + GetKeyServerLocationsRequest( + span.context, tenant, key, Optional(), 100, isBackward, version, key.arena()), + TaskPriority::DefaultPromiseEndpoint))) { ++cx->transactionKeyServerLocationRequestsCompleted; if (debugID.present()) g_traceBatch.addEvent( "TransactionDebug", debugID.get().first(), "NativeAPI.getKeyLocation.After"); ASSERT(rep.results.size() == 1); - auto locationInfo = - cx->setCachedLocation(tenant, rep.tenantEntry, rep.results[0].first, rep.results[0].second); + auto locationInfo = cx->setCachedLocation( + tenant.name, rep.tenantEntry, rep.results[0].first, rep.results[0].second); updateTssMappings(cx, rep); updateTagMappings(cx, rep); @@ -2891,8 +2903,8 @@ ACTOR Future getKeyLocation_internal(Database cx, } } catch (Error& e) { if (e.code() == error_code_tenant_not_found) { - ASSERT(tenant.present()); - cx->invalidateCachedTenant(tenant.get()); + ASSERT(tenant.name.present()); + cx->invalidateCachedTenant(tenant.name.get()); } throw; @@ -2930,7 +2942,7 @@ bool checkOnlyEndpointFailed(const Database& cx, const Endpoint& endpoint) { template Future getKeyLocation(Database const& cx, - Optional const& tenant, + TenantInfo const& tenant, Key const& key, F StorageServerInterface::*member, SpanContext spanContext, @@ -2939,7 +2951,7 @@ Future getKeyLocation(Database const& cx, Reverse isBackward, Version version) { // we first check whether this range is cached - Optional locationInfo = cx->getCachedLocation(tenant, key, isBackward); + Optional locationInfo = cx->getCachedLocation(tenant.name, key, isBackward); if (!locationInfo.present()) { return getKeyLocation_internal( cx, tenant, key, spanContext, debugID, useProvisionalProxies, isBackward, version); @@ -2971,7 +2983,7 @@ Future getKeyLocation(Reference trState, UseTenant useTenant, Version version) { auto f = getKeyLocation(trState->cx, - useTenant ? trState->tenant() : Optional(), + useTenant ? trState->getTenantInfo(AllowInvalidTenantID::True) : TenantInfo(), key, member, trState->spanContext, @@ -2992,7 +3004,7 @@ Future getKeyLocation(Reference trState, ACTOR Future> getKeyRangeLocations_internal( Database cx, - Optional tenant, + TenantInfo tenant, KeyRange keys, int limit, Reverse reverse, @@ -3009,18 +3021,12 @@ ACTOR Future> getKeyRangeLocations_internal( ++cx->transactionKeyServerLocationRequests; choose { when(wait(cx->onProxiesChanged())) {} - when(GetKeyServerLocationsReply _rep = - wait(basicLoadBalance(cx->getCommitProxies(useProvisionalProxies), - &CommitProxyInterface::getKeyServersLocations, - GetKeyServerLocationsRequest(span.context, - tenant.castTo(), - keys.begin, - keys.end, - limit, - reverse, - version, - keys.arena()), - TaskPriority::DefaultPromiseEndpoint))) { + when(GetKeyServerLocationsReply _rep = wait(basicLoadBalance( + cx->getCommitProxies(useProvisionalProxies), + &CommitProxyInterface::getKeyServersLocations, + GetKeyServerLocationsRequest( + span.context, tenant, keys.begin, keys.end, limit, reverse, version, keys.arena()), + TaskPriority::DefaultPromiseEndpoint))) { ++cx->transactionKeyServerLocationRequestsCompleted; state GetKeyServerLocationsReply rep = _rep; if (debugID.present()) @@ -3037,7 +3043,7 @@ ACTOR Future> getKeyRangeLocations_internal( rep.tenantEntry, (toRelativeRange(rep.results[shard].first, rep.tenantEntry.prefix) & keys), cx->setCachedLocation( - tenant, rep.tenantEntry, rep.results[shard].first, rep.results[shard].second)); + tenant.name, rep.tenantEntry, rep.results[shard].first, rep.results[shard].second)); wait(yield()); } updateTssMappings(cx, rep); @@ -3049,8 +3055,8 @@ ACTOR Future> getKeyRangeLocations_internal( } } catch (Error& e) { if (e.code() == error_code_tenant_not_found) { - ASSERT(tenant.present()); - cx->invalidateCachedTenant(tenant.get()); + ASSERT(tenant.name.present()); + cx->invalidateCachedTenant(tenant.name.get()); } throw; @@ -3065,7 +3071,7 @@ ACTOR Future> getKeyRangeLocations_internal( // [([a, b1), locationInfo), ([b1, c), locationInfo), ([c, d1), locationInfo)]. template Future> getKeyRangeLocations(Database const& cx, - Optional tenant, + TenantInfo const& tenant, KeyRange const& keys, int limit, Reverse reverse, @@ -3078,7 +3084,7 @@ Future> getKeyRangeLocations(Database const& c ASSERT(!keys.empty()); std::vector locations; - if (!cx->getCachedLocations(tenant, keys, locations, limit, reverse)) { + if (!cx->getCachedLocations(tenant.name, keys, locations, limit, reverse)) { return getKeyRangeLocations_internal( cx, tenant, keys, limit, reverse, spanContext, debugID, useProvisionalProxies, version); } @@ -3116,7 +3122,7 @@ Future> getKeyRangeLocations(Referencecx, - useTenant ? trState->tenant() : Optional(), + useTenant ? trState->getTenantInfo(AllowInvalidTenantID::True) : TenantInfo(), keys, limit, reverse, @@ -3146,7 +3152,7 @@ ACTOR Future warmRange_impl(Reference trState, KeyRange loop { std::vector locations = wait(getKeyRangeLocations_internal(trState->cx, - trState->tenant(), + trState->getTenantInfo(), keys, CLIENT_KNOBS->WARM_RANGE_SHARD_LIMIT, Reverse::False, @@ -3196,6 +3202,8 @@ SpanContext generateSpanID(bool transactionTracingSample, SpanContext parentCont deterministicRandom()->randomUniqueID(), deterministicRandom()->randomUInt64(), TraceFlags::unsampled); } +FDB_DEFINE_BOOLEAN_PARAM(AllowInvalidTenantID); + TransactionState::TransactionState(Database cx, Optional tenant, TaskPriority taskID, @@ -3219,12 +3227,13 @@ Reference TransactionState::cloneAndReset(ReferencestartTime = startTime; newState->committedVersion = committedVersion; newState->conflictingKeys = conflictingKeys; + newState->authToken = authToken; newState->tenantSet = tenantSet; return newState; } -TenantInfo TransactionState::getTenantInfo() { +TenantInfo TransactionState::getTenantInfo(AllowInvalidTenantID allowInvalidId /* = false */) { Optional const& t = tenant(); if (options.rawAccess) { @@ -3246,8 +3255,8 @@ TenantInfo TransactionState::getTenantInfo() { } } - ASSERT(tenantId != TenantInfo::INVALID_TENANT); - return TenantInfo(t.get(), tenantId); + ASSERT(allowInvalidId || tenantId != TenantInfo::INVALID_TENANT); + return TenantInfo(t, authToken, tenantId); } // Returns the tenant used in this transaction. If the tenant is unset and raw access isn't specified, then the default @@ -3590,7 +3599,7 @@ ACTOR Future watchValue(Database cx, Reference p loop { state KeyRangeLocationInfo locationInfo = wait(getKeyLocation(cx, - parameters->tenant.name, + parameters->tenant, parameters->key, &StorageServerInterface::watchValue, parameters->spanContext, @@ -3721,7 +3730,7 @@ ACTOR Future watchStorageServerResp(int64_t tenantId, Key key, Database cx } ACTOR Future sameVersionDiffValue(Database cx, Reference parameters) { - state ReadYourWritesTransaction tr(cx, parameters->tenant.name); + state ReadYourWritesTransaction tr(cx, parameters->tenant.name.castTo()); loop { try { if (!parameters->tenant.name.present()) { @@ -5950,8 +5959,12 @@ ACTOR void checkWrites(Reference trState, } } -ACTOR static Future commitDummyTransaction(Reference trState, KeyRange range) { - state Transaction tr(trState->cx); +FDB_BOOLEAN_PARAM(TenantPrefixPrepended); + +ACTOR static Future commitDummyTransaction(Reference trState, + KeyRange range, + TenantPrefixPrepended tenantPrefixPrepended) { + state Transaction tr(trState->cx, trState->tenant()); state int retries = 0; state Span span("NAPI:dummyTransaction"_loc, trState->spanContext); tr.span.setParent(span.context); @@ -5960,7 +5973,13 @@ ACTOR static Future commitDummyTransaction(Reference trS TraceEvent("CommitDummyTransaction").detail("Key", range.begin).detail("Retries", retries); tr.trState->options = trState->options; tr.trState->taskID = trState->taskID; - tr.setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); + tr.trState->authToken = trState->authToken; + if (!trState->hasTenant()) { + tr.setOption(FDBTransactionOptions::RAW_ACCESS); + } else { + tr.trState->skipApplyTenantPrefix = tenantPrefixPrepended; + CODE_PROBE(true, "Commit of a dummy transaction in tenant keyspace"); + } tr.setOption(FDBTransactionOptions::CAUSAL_WRITE_RISKY); tr.setOption(FDBTransactionOptions::LOCK_AWARE); tr.addReadConflictRange(range); @@ -6122,6 +6141,7 @@ ACTOR static Future tryCommit(Reference trState, state double startTime = now(); state Span span("NAPI:tryCommit"_loc, trState->spanContext); state Optional debugID = trState->debugID; + state TenantPrefixPrepended tenantPrefixPrepended = TenantPrefixPrepended::False; if (debugID.present()) { TraceEvent(interval.begin()).detail("Parent", debugID.get()); } @@ -6146,12 +6166,16 @@ ACTOR static Future tryCommit(Reference trState, Reverse::False, UseTenant::True, req.transaction.read_snapshot)); - applyTenantPrefix(req, locationInfo.tenantEntry.prefix); + // skipApplyTenantPrefix is set only in the context of a commitDummyTransaction() + // (see member declaration) + if (!trState->skipApplyTenantPrefix) { + applyTenantPrefix(req, locationInfo.tenantEntry.prefix); + tenantPrefixPrepended = TenantPrefixPrepended::True; + } tenantPrefix = locationInfo.tenantEntry.prefix; } - + CODE_PROBE(trState->skipApplyTenantPrefix, "Tenant prefix prepend skipped for dummy transaction"); req.tenantInfo = trState->getTenantInfo(); - startTime = now(); state Optional commitID = Optional(); @@ -6277,7 +6301,8 @@ ACTOR static Future tryCommit(Reference trState, CODE_PROBE(true, "Waiting for dummy transaction to report commit_unknown_result"); - wait(commitDummyTransaction(trState, singleKeyRange(selfConflictingRange.begin))); + wait( + commitDummyTransaction(trState, singleKeyRange(selfConflictingRange.begin), tenantPrefixPrepended)); } // The user needs to be informed that we aren't sure whether the commit happened. Standard retry loops @@ -6657,6 +6682,13 @@ void Transaction::setOption(FDBTransactionOptions::Option option, Optionaloptions.rawAccess = true; break; + case FDBTransactionOptions::AUTHORIZATION_TOKEN: + if (value.present()) + trState->authToken = Standalone(value.get()); + else + trState->authToken.reset(); + break; + default: break; } @@ -7236,7 +7268,7 @@ ACTOR Future doGetStorageMetrics(Database cx, KeyRange keys, Ref ACTOR Future getStorageMetricsLargeKeyRange(Database cx, KeyRange keys) { state Span span("NAPI:GetStorageMetricsLargeKeyRange"_loc); std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, std::numeric_limits::max(), Reverse::False, @@ -7338,7 +7370,7 @@ ACTOR Future>> getReadHotRanges(Da // to find the read-hot sub ranges within a read-hot shard. std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, shardLimit, Reverse::False, @@ -7409,7 +7441,7 @@ ACTOR Future, int>> waitStorageMetrics(Databa state Span span("NAPI:WaitStorageMetrics"_loc, generateSpanID(cx->transactionTracingSample)); loop { std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, shardLimit, Reverse::False, @@ -7584,7 +7616,7 @@ ACTOR Future blobGranuleGetTenantEntry(Transaction* self, Key ra self->trState->cx->getCachedLocation(self->getTenant().get(), rangeStartKey, Reverse::False); if (!cachedLocationInfo.present()) { KeyRangeLocationInfo l = wait(getKeyLocation_internal(self->trState->cx, - self->getTenant().get(), + self->trState->getTenantInfo(AllowInvalidTenantID::True), rangeStartKey, self->trState->spanContext, self->trState->debugID, @@ -8014,7 +8046,7 @@ ACTOR Future splitStorageMetricsStream(PromiseStream resultStream, loop { state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), KeyRangeRef(beginKey, keys.end), CLIENT_KNOBS->STORAGE_METRICS_SHARD_LIMIT, Reverse::False, @@ -8114,7 +8146,7 @@ ACTOR Future>> splitStorageMetrics(Database cx, loop { state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, CLIENT_KNOBS->STORAGE_METRICS_SHARD_LIMIT, Reverse::False, @@ -8359,7 +8391,7 @@ ACTOR Future> getCheckpointMetaData(Database cx, try { state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, CLIENT_KNOBS->TOO_MANY, Reverse::False, @@ -9274,7 +9306,7 @@ ACTOR Future getChangeFeedStreamActor(Reference db, keys = fullRange & range; state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, CLIENT_KNOBS->CHANGE_FEED_LOCATION_LIMIT, Reverse::False, @@ -9453,7 +9485,7 @@ ACTOR Future getOverlappingChangeFeedsActor(Referenc try { state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), range, CLIENT_KNOBS->CHANGE_FEED_LOCATION_LIMIT, Reverse::False, @@ -9555,7 +9587,7 @@ ACTOR Future popChangeFeedMutationsActor(Reference db, Ke state std::vector locations = wait(getKeyRangeLocations(cx, - Optional(), + TenantInfo(), keys, 3, Reverse::False, diff --git a/fdbclient/StorageServerInterface.cpp b/fdbclient/StorageServerInterface.cpp index 8a9b6183a4..535ef8f98f 100644 --- a/fdbclient/StorageServerInterface.cpp +++ b/fdbclient/StorageServerInterface.cpp @@ -129,7 +129,7 @@ const char* TSS_mismatchTraceName(const GetKeyValuesRequest& req) { static void traceKeyValuesSummary(TraceEvent& event, const KeySelectorRef& begin, const KeySelectorRef& end, - Optional tenant, + Optional tenant, Version version, int limit, int limitBytes, @@ -152,7 +152,7 @@ static void traceKeyValuesSummary(TraceEvent& event, static void traceKeyValuesDiff(TraceEvent& event, const KeySelectorRef& begin, const KeySelectorRef& end, - Optional tenant, + Optional tenant, Version version, int limit, int limitBytes, diff --git a/fdbclient/include/fdbclient/CommitProxyInterface.h b/fdbclient/include/fdbclient/CommitProxyInterface.h index a331ea8043..e2cc86693d 100644 --- a/fdbclient/include/fdbclient/CommitProxyInterface.h +++ b/fdbclient/include/fdbclient/CommitProxyInterface.h @@ -179,6 +179,8 @@ struct CommitTransactionRequest : TimedRequest { CommitTransactionRequest() : CommitTransactionRequest(SpanContext()) {} CommitTransactionRequest(SpanContext const& context) : spanContext(context), flags(0) {} + bool verify() const { return tenantInfo.isAuthorized(); } + template void serialize(Ar& ar) { serializer( @@ -284,6 +286,8 @@ struct GetReadVersionRequest : TimedRequest { } } + bool verify() const { return true; } + bool operator<(GetReadVersionRequest const& rhs) const { return priority < rhs.priority; } template @@ -330,7 +334,7 @@ struct GetKeyServerLocationsRequest { constexpr static FileIdentifier file_identifier = 9144680; Arena arena; SpanContext spanContext; - Optional tenant; + TenantInfo tenant; KeyRef begin; Optional end; int limit; @@ -345,7 +349,7 @@ struct GetKeyServerLocationsRequest { GetKeyServerLocationsRequest() : limit(0), reverse(false), minTenantVersion(latestVersion) {} GetKeyServerLocationsRequest(SpanContext spanContext, - Optional const& tenant, + TenantInfo const& tenant, KeyRef const& begin, Optional const& end, int limit, @@ -355,6 +359,8 @@ struct GetKeyServerLocationsRequest { : arena(arena), spanContext(spanContext), tenant(tenant), begin(begin), end(end), limit(limit), reverse(reverse), minTenantVersion(minTenantVersion) {} + bool verify() const { return tenant.isAuthorized(); } + template void serialize(Ar& ar) { serializer(ar, begin, end, limit, reverse, reply, spanContext, tenant, minTenantVersion, arena); diff --git a/fdbclient/include/fdbclient/CoordinationInterface.h b/fdbclient/include/fdbclient/CoordinationInterface.h index 03e8966891..cc8042976d 100644 --- a/fdbclient/include/fdbclient/CoordinationInterface.h +++ b/fdbclient/include/fdbclient/CoordinationInterface.h @@ -242,6 +242,8 @@ struct GetLeaderRequest { GetLeaderRequest() {} explicit GetLeaderRequest(Key key, UID kl) : key(key), knownLeader(kl) {} + bool verify() const { return true; } + template void serialize(Ar& ar) { serializer(ar, key, knownLeader, reply); @@ -262,6 +264,8 @@ struct OpenDatabaseCoordRequest { std::vector coordinators; ReplyPromise> reply; + bool verify() const { return true; } + template void serialize(Ar& ar) { serializer(ar, diff --git a/fdbclient/include/fdbclient/DatabaseContext.h b/fdbclient/include/fdbclient/DatabaseContext.h index e4875b9d7c..092a290a4c 100644 --- a/fdbclient/include/fdbclient/DatabaseContext.h +++ b/fdbclient/include/fdbclient/DatabaseContext.h @@ -255,16 +255,16 @@ public: return cx; } - Optional getCachedLocation(const Optional& tenant, + Optional getCachedLocation(const Optional& tenant, const KeyRef&, Reverse isBackward = Reverse::False); - bool getCachedLocations(const Optional& tenant, + bool getCachedLocations(const Optional& tenant, const KeyRangeRef&, std::vector&, int limit, Reverse reverse); void cacheTenant(const TenantName& tenant, const TenantMapEntry& tenantEntry); - Reference setCachedLocation(const Optional& tenant, + Reference setCachedLocation(const Optional& tenant, const TenantMapEntry& tenantEntry, const KeyRangeRef&, const std::vector&); @@ -527,6 +527,7 @@ public: Counter transactionsExpensiveClearCostEstCount; Counter transactionGrvFullBatches; Counter transactionGrvTimedOutBatches; + Counter transactionCommitVersionNotFoundForSS; ContinuousSample latencies, readLatencies, commitLatencies, GRVLatencies, mutationsPerCommit, bytesPerCommit, bgLatencies, bgGranulesPerRequest; diff --git a/fdbclient/include/fdbclient/MetaclusterManagement.actor.h b/fdbclient/include/fdbclient/MetaclusterManagement.actor.h index be78c2a47e..2976f6fe16 100644 --- a/fdbclient/include/fdbclient/MetaclusterManagement.actor.h +++ b/fdbclient/include/fdbclient/MetaclusterManagement.actor.h @@ -199,8 +199,7 @@ struct MetaclusterOperationContext { Optional dataClusterMetadata; MetaclusterOperationContext(Reference managementDb, Optional clusterName = {}) - : managementDb(managementDb), clusterName(clusterName) { - } + : managementDb(managementDb), clusterName(clusterName) {} // Run a transaction on the management cluster. This verifies that the cluster is a management cluster and matches // the same metacluster that we've run any previous transactions on. If a clusterName is set, it also verifies that diff --git a/fdbclient/include/fdbclient/NativeAPI.actor.h b/fdbclient/include/fdbclient/NativeAPI.actor.h index 3abab222bb..53fa869e5b 100644 --- a/fdbclient/include/fdbclient/NativeAPI.actor.h +++ b/fdbclient/include/fdbclient/NativeAPI.actor.h @@ -235,9 +235,12 @@ struct Watch : public ReferenceCounted, NonCopyable { void setWatch(Future watchFuture); }; +FDB_DECLARE_BOOLEAN_PARAM(AllowInvalidTenantID); + struct TransactionState : ReferenceCounted { Database cx; int64_t tenantId = TenantInfo::INVALID_TENANT; + Optional> authToken; Reference trLogInfo; TransactionOptions options; @@ -247,6 +250,13 @@ struct TransactionState : ReferenceCounted { UseProvisionalProxies useProvisionalProxies = UseProvisionalProxies::False; bool readVersionObtainedFromGrvProxy; + // Special flag to skip prepending tenant prefix to mutations and conflict ranges + // when a dummy, internal transaction gets commited. The sole purpose of commitDummyTransaction() is to + // resolve the state of earlier transaction that returned commit_unknown_result or request_maybe_delivered. + // Therefore, the dummy transaction can simply reuse one conflict range of the earlier commit, if it already has + // been prefixed. + bool skipApplyTenantPrefix = false; + int numErrors = 0; double startTime = 0; Promise> versionstampPromise; @@ -270,7 +280,7 @@ struct TransactionState : ReferenceCounted { Reference trLogInfo); Reference cloneAndReset(Reference newTrLogInfo, bool generateNewSpan) const; - TenantInfo getTenantInfo(); + TenantInfo getTenantInfo(AllowInvalidTenantID allowInvalidId = AllowInvalidTenantID::False); Optional const& tenant(); bool hasTenant() const; diff --git a/fdbclient/include/fdbclient/StorageServerInterface.h b/fdbclient/include/fdbclient/StorageServerInterface.h index 8ec8e1009a..8e1d82d6a0 100644 --- a/fdbclient/include/fdbclient/StorageServerInterface.h +++ b/fdbclient/include/fdbclient/StorageServerInterface.h @@ -32,6 +32,7 @@ #include "fdbrpc/LoadBalance.actor.h" #include "fdbrpc/Stats.h" #include "fdbrpc/TimedRequest.h" +#include "fdbrpc/TenantInfo.h" #include "fdbrpc/TSSComparison.h" #include "fdbclient/CommitTransaction.h" #include "fdbclient/TagThrottle.actor.h" @@ -85,13 +86,13 @@ struct StorageServerInterface { RequestStream getReadHotRanges; RequestStream getRangeSplitPoints; PublicRequestStream getKeyValuesStream; - PublicRequestStream changeFeedStream; - PublicRequestStream overlappingChangeFeeds; - PublicRequestStream changeFeedPop; - PublicRequestStream changeFeedVersionUpdate; - PublicRequestStream checkpoint; - PublicRequestStream fetchCheckpoint; - PublicRequestStream fetchCheckpointKeyValues; + RequestStream changeFeedStream; + RequestStream overlappingChangeFeeds; + RequestStream changeFeedPop; + RequestStream changeFeedVersionUpdate; + RequestStream checkpoint; + RequestStream fetchCheckpoint; + RequestStream fetchCheckpointKeyValues; private: bool acceptingRequests; @@ -150,18 +151,17 @@ public: getMappedKeyValues = PublicRequestStream( getValue.getEndpoint().getAdjustedEndpoint(14)); changeFeedStream = - PublicRequestStream(getValue.getEndpoint().getAdjustedEndpoint(15)); - overlappingChangeFeeds = PublicRequestStream( - getValue.getEndpoint().getAdjustedEndpoint(16)); + RequestStream(getValue.getEndpoint().getAdjustedEndpoint(15)); + overlappingChangeFeeds = + RequestStream(getValue.getEndpoint().getAdjustedEndpoint(16)); changeFeedPop = - PublicRequestStream(getValue.getEndpoint().getAdjustedEndpoint(17)); - changeFeedVersionUpdate = PublicRequestStream( + RequestStream(getValue.getEndpoint().getAdjustedEndpoint(17)); + changeFeedVersionUpdate = RequestStream( getValue.getEndpoint().getAdjustedEndpoint(18)); - checkpoint = - PublicRequestStream(getValue.getEndpoint().getAdjustedEndpoint(19)); + checkpoint = RequestStream(getValue.getEndpoint().getAdjustedEndpoint(19)); fetchCheckpoint = - PublicRequestStream(getValue.getEndpoint().getAdjustedEndpoint(20)); - fetchCheckpointKeyValues = PublicRequestStream( + RequestStream(getValue.getEndpoint().getAdjustedEndpoint(20)); + fetchCheckpointKeyValues = RequestStream( getValue.getEndpoint().getAdjustedEndpoint(21)); } } else { @@ -242,21 +242,6 @@ struct ServerCacheInfo { } }; -struct TenantInfo { - static const int64_t INVALID_TENANT = -1; - - Optional name; - int64_t tenantId; - - TenantInfo() : tenantId(INVALID_TENANT) {} - TenantInfo(TenantName name, int64_t tenantId) : name(name), tenantId(tenantId) {} - - template - void serialize(Ar& ar) { - serializer(ar, name, tenantId); - } -}; - struct GetValueReply : public LoadBalancedReply { constexpr static FileIdentifier file_identifier = 1378929; Optional value; @@ -284,6 +269,8 @@ struct GetValueRequest : TimedRequest { // to this client, of all storage replicas that // serve the given key + bool verify() const { return tenantInfo.isAuthorized(); } + GetValueRequest() {} GetValueRequest(SpanContext spanContext, const TenantInfo& tenantInfo, @@ -338,6 +325,8 @@ struct WatchValueRequest { : spanContext(spanContext), tenantInfo(tenantInfo), key(key), value(value), version(ver), tags(tags), debugID(debugID) {} + bool verify() const { return tenantInfo.isAuthorized(); } + template void serialize(Ar& ar) { serializer(ar, key, value, version, tags, debugID, reply, spanContext, tenantInfo); @@ -381,6 +370,8 @@ struct GetKeyValuesRequest : TimedRequest { GetKeyValuesRequest() : isFetchKeys(false) {} + bool verify() const { return tenantInfo.isAuthorized(); } + template void serialize(Ar& ar) { serializer(ar, @@ -437,6 +428,9 @@ struct GetMappedKeyValuesRequest : TimedRequest { // serve the given key range GetMappedKeyValuesRequest() : isFetchKeys(false) {} + + bool verify() const { return tenantInfo.isAuthorized(); } + template void serialize(Ar& ar) { serializer(ar, @@ -503,6 +497,8 @@ struct GetKeyValuesStreamRequest { GetKeyValuesStreamRequest() : isFetchKeys(false) {} + bool verify() const { return tenantInfo.isAuthorized(); } + template void serialize(Ar& ar) { serializer(ar, @@ -550,6 +546,8 @@ struct GetKeyRequest : TimedRequest { // to this client, of all storage replicas that // serve the given key + bool verify() const { return tenantInfo.isAuthorized(); } + GetKeyRequest() {} GetKeyRequest(SpanContext spanContext, diff --git a/fdbclient/include/fdbclient/Tenant.h b/fdbclient/include/fdbclient/Tenant.h index 43d82db0c2..dbbc2eda2c 100644 --- a/fdbclient/include/fdbclient/Tenant.h +++ b/fdbclient/include/fdbclient/Tenant.h @@ -26,6 +26,7 @@ #include "fdbclient/KeyBackedTypes.h" #include "fdbclient/VersionedMap.h" #include "fdbclient/KeyBackedTypes.h" +#include "fdbrpc/TenantInfo.h" #include "flow/flat_buffers.h" typedef StringRef TenantNameRef; @@ -174,4 +175,4 @@ public: typedef VersionedMap TenantMap; typedef VersionedMap TenantPrefixIndex; -#endif \ No newline at end of file +#endif diff --git a/fdbclient/vexillographer/fdb.options b/fdbclient/vexillographer/fdb.options index 57ae180a07..242675e0b1 100644 --- a/fdbclient/vexillographer/fdb.options +++ b/fdbclient/vexillographer/fdb.options @@ -302,6 +302,10 @@ description is not currently required but encouraged.