SERVER-79274 Fix race where FCV is uninitialized in between FCV checks

This commit is contained in:
Huayu Ouyang 2023-11-07 21:11:15 +00:00 committed by Evergreen Agent
parent 60a2f259be
commit a5da6271d5
157 changed files with 584 additions and 427 deletions

View File

@ -20,6 +20,7 @@ GENERIC_FCV = [
r'::kDowngradingFromLatestToLastLTS',
r'::kDowngradingFromLatestToLastContinuous',
r'\.isUpgradingOrDowngrading',
r'->isUpgradingOrDowngrading',
r'::kDowngradingFromLatestToLastContinuous',
r'::kUpgradingFromLastLTSToLastContinuous',
]

View File

@ -297,7 +297,7 @@ StatusWith<std::pair<ParsedCollModRequest, BSONObj>> parseCollModRequest(
}
if (coll->isCapped() &&
!feature_flags::gFeatureFlagTTLIndexesOnCappedCollections.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
return {ErrorCodes::InvalidOptions,
"TTL indexes are not supported for capped collections."};
}
@ -502,8 +502,8 @@ StatusWith<std::pair<ParsedCollModRequest, BSONObj>> parseCollModRequest(
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
multiversion::FeatureCompatibilityVersion fcv;
if (serverGlobalParams.validateFeaturesAsPrimary.load() &&
serverGlobalParams.featureCompatibility.isLessThan(multiversion::GenericFCV::kLatest,
&fcv)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isLessThan(
multiversion::GenericFCV::kLatest, &fcv)) {
maxFeatureCompatibilityVersion = fcv;
}
auto validatorObj = *validator;
@ -980,7 +980,7 @@ Status _collModInternal(OperationContext* opCtx,
if (changed) {
coll.getWritableCollection(opCtx)->setTimeseriesOptions(opCtx, newOptions);
if (feature_flags::gTSBucketingParametersUnchanged.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
coll.getWritableCollection(opCtx)->setTimeseriesBucketingParametersChanged(
opCtx, true);
};
@ -992,8 +992,9 @@ Status _collModInternal(OperationContext* opCtx,
// (Generic FCV reference): This FCV check happens whenever we upgrade to the latest
// version.
// TODO SERVER-80490: remove this check when 8.0 becomes the next LTS release.
if (auto version = serverGlobalParams.featureCompatibility.getVersion();
cmrNew.numModifications == 0 &&
const auto version =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
if (cmrNew.numModifications == 0 &&
(version == multiversion::GenericFCV::kUpgradingFromLastContinuousToLatest ||
version == multiversion::GenericFCV::kUpgradingFromLastLTSToLatest)) {
auto writableCollection = coll.getWritableCollection(opCtx);
@ -1007,8 +1008,7 @@ Status _collModInternal(OperationContext* opCtx,
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
// TODO SERVER-80003 remove special version handling when LTS becomes 8.0.
if (cmrNew.numModifications == 0 && coll->timeseriesBucketingParametersHaveChanged() &&
serverGlobalParams.featureCompatibility.getVersion() ==
multiversion::GenericFCV::kDowngradingFromLatestToLastLTS) {
version == multiversion::GenericFCV::kDowngradingFromLatestToLastLTS) {
coll.getWritableCollection(opCtx)->setTimeseriesBucketingParametersChanged(opCtx,
boost::none);
}

View File

@ -113,7 +113,7 @@ TEST(CollectionOptions, ErrorBadMax) {
}
TEST(CollectionOptions, CappedSizeNotRoundUpForAlignment) {
serverGlobalParams.mutableFeatureCompatibility.setVersion(
serverGlobalParams.mutableFCV.setVersion(
multiversion::FeatureCompatibilityVersion::kVersion_6_2);
const long long kUnalignedCappedSize = 1000;
const long long kAlignedCappedSize = 1000;

View File

@ -948,8 +948,8 @@ Status DatabaseImpl::userCreateNS(OperationContext* opCtx,
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
multiversion::FeatureCompatibilityVersion fcv;
if (serverGlobalParams.validateFeaturesAsPrimary.load() &&
serverGlobalParams.featureCompatibility.isLessThan(multiversion::GenericFCV::kLatest,
&fcv)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isLessThan(
multiversion::GenericFCV::kLatest, &fcv)) {
expCtx->maxFeatureCompatibilityVersion = fcv;
}

View File

@ -355,7 +355,7 @@ void dropReadyIndexes(OperationContext* opCtx,
const auto& shardKey = collDescription.getShardKeyPattern();
const bool skipDropIndex = skipDroppingHashedShardKeyIndex ||
!(gFeatureFlagShardKeyIndexOptionalHashedSharding.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
shardKey.isHashedPattern());
if (isCompatibleWithShardKey(opCtx,
CollectionPtr(collection),

View File

@ -275,7 +275,7 @@ void IndexBuildBlock::success(OperationContext* opCtx, Collection* collection) {
// collection scan, which does not use an index.
if (spec.hasField(IndexDescriptor::kExpireAfterSecondsFieldName) &&
(feature_flags::gFeatureFlagTTLIndexesOnCappedCollections.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
!coll->isCapped())) {
auto validateStatus = index_key_validate::validateExpireAfterSeconds(
spec[IndexDescriptor::kExpireAfterSecondsFieldName],

View File

@ -275,7 +275,7 @@ void IndexCatalogImpl::init(OperationContext* opCtx,
// Note that TTL deletion is supported on capped clustered collections via bounded
// collection scan, which does not use an index.
if (feature_flags::gFeatureFlagTTLIndexesOnCappedCollections.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
!collection->isCapped()) {
if (opCtx->lockState()->inAWriteUnitOfWork()) {
opCtx->recoveryUnit()->onCommit(
@ -519,7 +519,7 @@ StatusWith<BSONObj> IndexCatalogImpl::prepareSpecForCreate(
if (collection && collection->isCapped() &&
validatedSpec.hasField(IndexDescriptor::kExpireAfterSecondsFieldName) &&
!feature_flags::gFeatureFlagTTLIndexesOnCappedCollections.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
MONGO_likely(!ignoreTTLIndexCappedCollectionCheck.shouldFail())) {
return {ErrorCodes::CannotCreateIndex, "Cannot create TTL index on a capped collection"};
}
@ -975,15 +975,15 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx,
return wildcardSpecStatus;
}
} else if (pluginName == IndexNames::COLUMN) {
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
uassert(ErrorCodes::NotImplemented,
str::stream() << pluginName
<< " indexes are under development and cannot be used without "
"enabling the feature flag",
// With our testing failpoint we may try to run this code before we've initialized
// the FCV.
!serverGlobalParams.featureCompatibility.isVersionInitialized() ||
feature_flags::gFeatureFlagColumnstoreIndexes.isEnabled(
serverGlobalParams.featureCompatibility));
!fcvSnapshot.isVersionInitialized() ||
feature_flags::gFeatureFlagColumnstoreIndexes.isEnabled(fcvSnapshot));
if (auto columnSpecStatus = validateColumnStoreSpec(collection, spec, indexVersion);
!columnSpecStatus.isOK()) {
return columnSpecStatus;
@ -1740,7 +1740,7 @@ Status IndexCatalogImpl::_updateRecord(OperationContext* const opCtx,
// index has incorrect keys. Replace this failpoint with a test command instead.
if (auto failpoint = skipUpdatingIndexDocument.scoped(); MONGO_unlikely(failpoint.isActive()) &&
repl::feature_flags::gSecondaryIndexChecksInDbCheck.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
auto indexName = failpoint.getData()["indexName"].valueStringDataSafe();
if (indexName == index->descriptor()->indexName()) {
LOGV2_DEBUG(

View File

@ -169,7 +169,7 @@ auto makeOnSuppressedErrorFn(const std::function<void()>& saveCursorBeforeWrite,
bool shouldRelaxConstraints(OperationContext* opCtx, const CollectionPtr& collection) {
if (!feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
// Always suppress.
return true;
}

View File

@ -136,7 +136,7 @@ ValidateState::ValidateState(OperationContext* opCtx,
if (additionalOptions.enforceTimeseriesBucketsAreAlwaysCompressed) {
if (TestingProctor::instance().isEnabled() &&
feature_flags::gTimeseriesAlwaysUseCompressedBuckets.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
_enforceTimeseriesBucketsAreAlwaysCompressed = true;
} else {
LOGV2_WARNING(7735102, "Not enforcing that time-series buckets are always compressed");

View File

@ -138,7 +138,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> getDeleteExpiredPreImagesEx
bool useUnreplicatedTruncates() {
bool res = feature_flags::gFeatureFlagUseUnreplicatedTruncatesForDeletions.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
return res;
}
} // namespace

View File

@ -68,7 +68,7 @@ namespace change_stream_serverless_helpers {
namespace {
bool isServerlessChangeStreamFeatureFlagEnabled() {
return feature_flags::gFeatureFlagServerlessChangeStreams.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
}
} // namespace

View File

@ -371,7 +371,7 @@ StatusWith<std::vector<BSONObj>> DefaultClonerImpl::_filterCollectionsForClone(
const auto nss = NamespaceStringUtil::deserialize(fromDBName, collectionName.c_str());
if (nss.isSystem()) {
if (!nss.isLegalClientSystemNS(serverGlobalParams.featureCompatibility)) {
if (!nss.isLegalClientSystemNS()) {
LOGV2_DEBUG(20419, 2, "\t\t not cloning because system collection");
continue;
}

View File

@ -165,7 +165,7 @@ public:
uassert(6660400,
"Analyze command requires common query framework feature flag to be enabled",
feature_flags::gFeatureFlagCommonQueryFramework.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
const auto& cmd = request();
const NamespaceString& nss = ns();

View File

@ -1262,10 +1262,10 @@ public:
const Command* command,
const OpMsgRequest& opMsgRequest)
: InvocationBaseGen(opCtx, command, opMsgRequest), _commandObj(opMsgRequest.body) {
uassert(
ErrorCodes::CommandNotSupported,
"BulkWrite may not be run without featureFlagBulkWriteCommand enabled",
gFeatureFlagBulkWriteCommand.isEnabled(serverGlobalParams.featureCompatibility));
uassert(ErrorCodes::CommandNotSupported,
"BulkWrite may not be run without featureFlagBulkWriteCommand enabled",
gFeatureFlagBulkWriteCommand.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
bulk_write_common::validateRequest(request(), /*isRouter=*/false);

View File

@ -562,7 +562,7 @@ CreateIndexesReply runCreateIndexesWithCoordinator(OperationContext* opCtx,
!opCtx->inMultiDocumentTransaction());
if (feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassertStatusOK(IndexBuildsCoordinator::checkDiskSpaceSufficientToStartIndexBuild(opCtx));
}

View File

@ -230,7 +230,7 @@ std::unique_ptr<DbCheckRun> singleCollectionRun(OperationContext* opCtx,
const DbCheckSingleInvocation& invocation) {
const auto gSecondaryIndexChecksInDbCheck =
repl::feature_flags::gSecondaryIndexChecksInDbCheck.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
if (!gSecondaryIndexChecksInDbCheck) {
uassert(ErrorCodes::InvalidOptions,
"When featureFlagSecondaryIndexChecksInDbCheck is not enabled, the validateMode "

View File

@ -354,7 +354,8 @@ void FeatureCompatibilityVersion::validateSetFeatureCompatibilityVersionRequest(
uassert(5563601,
"Cannot transition to fully upgraded or fully downgraded state if the shard is not "
"in kUpgrading or kDowngrading state",
serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
tassert(5563502,
"Shard received a request for phase 2 of the 'setFeatureCompatibilityVersion' "
@ -388,7 +389,8 @@ void FeatureCompatibilityVersion::updateFeatureCompatibilityVersionDocument(
// Only transition to fully upgraded or downgraded states when we have completed all required
// upgrade/downgrade behavior, unless it is the newly added downgrading to upgrading path.
auto transitioningVersion = setTargetVersion &&
serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading(fromVersion) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isUpgradingOrDowngrading(
fromVersion) &&
!(fromVersion == GenericFCV::kDowngradingFromLatestToLastLTS &&
newVersion == GenericFCV::kLatest)
? fromVersion
@ -521,7 +523,8 @@ bool FeatureCompatibilityVersion::hasNoReplicatedCollections(OperationContext* o
void FeatureCompatibilityVersion::updateMinWireVersion(OperationContext* opCtx) {
WireSpec& wireSpec = WireSpec::getWireSpec(opCtx->getServiceContext());
const auto currentFcv = serverGlobalParams.featureCompatibility.getVersion();
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
const auto currentFcv = fcvSnapshot.getVersion();
// The reason we set the minWireVersion to LATEST_WIRE_VERSION when downgrading from latest as
// well as on upgrading to latest is because we shouldnt decrease the minWireVersion until we
// have fully downgraded to the lower FCV in case we get any backwards compatibility breakages,
@ -530,7 +533,7 @@ void FeatureCompatibilityVersion::updateMinWireVersion(OperationContext* opCtx)
// communicate with downgraded binary nodes until the FCV is completely downgraded to
// `kVersion_Y`.
if (currentFcv == GenericFCV::kLatest ||
(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading() &&
(fcvSnapshot.isUpgradingOrDowngrading() &&
currentFcv != GenericFCV::kUpgradingFromLastLTSToLastContinuous)) {
// FCV == kLatest or FCV is upgrading/downgrading to or from kLatest.
WireSpec::Specification newSpec = *wireSpec.get();
@ -558,7 +561,8 @@ void FeatureCompatibilityVersion::initializeForStartup(OperationContext* opCtx)
invariant(opCtx->lockState()->isW());
auto featureCompatibilityVersion = findFeatureCompatibilityVersionDocument(opCtx);
if (!featureCompatibilityVersion) {
serverGlobalParams.featureCompatibility.logFCVWithContext("startup"_sd);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().logFCVWithContext(
"startup"_sd);
return;
}
@ -582,13 +586,14 @@ void FeatureCompatibilityVersion::initializeForStartup(OperationContext* opCtx)
}
auto version = swVersion.getValue();
serverGlobalParams.mutableFeatureCompatibility.setVersion(version);
serverGlobalParams.mutableFCV.setVersion(version);
FeatureCompatibilityVersion::updateMinWireVersion(opCtx);
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
serverGlobalParams.featureCompatibility.logFCVWithContext("startup"_sd);
fcvSnapshot.logFCVWithContext("startup"_sd);
// On startup, if the version is in an upgrading or downgrading state, print a warning.
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
if (fcvSnapshot.isUpgradingOrDowngrading()) {
LOGV2_WARNING_OPTIONS(
4978301,
{logv2::LogTag::kStartupWarnings},
@ -637,7 +642,8 @@ void FeatureCompatibilityVersion::fassertInitializedAfterStartup(OperationContex
// startup. In standalone mode, FCV is initialized during startup, even in read-only mode.
bool isWriteableStorageEngine = storageGlobalParams.engine != "devnull";
if (isWriteableStorageEngine && (!usingReplication || nonLocalDatabases)) {
invariant(serverGlobalParams.featureCompatibility.isVersionInitialized());
invariant(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isVersionInitialized());
}
}
@ -667,12 +673,13 @@ void FeatureCompatibilityVersionParameter::append(OperationContext* opCtx,
BSONObjBuilder* b,
StringData name,
const boost::optional<TenantId>&) {
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
uassert(ErrorCodes::UnknownFeatureCompatibilityVersion,
str::stream() << name << " is not yet known.",
serverGlobalParams.featureCompatibility.isVersionInitialized());
fcvSnapshot.isVersionInitialized());
BSONObjBuilder featureCompatibilityVersionBuilder(b->subobjStart(name));
auto version = serverGlobalParams.featureCompatibility.getVersion();
auto version = fcvSnapshot.getVersion();
FeatureCompatibilityVersionDocument fcvDoc = fcvTransitions.getFCVDocument(version);
featureCompatibilityVersionBuilder.appendElements(fcvDoc.toBSON().removeField("_id"));
if (!fcvDoc.getTargetVersion()) {
@ -718,16 +725,21 @@ FixedFCVRegion::FixedFCVRegion(OperationContext* opCtx)
FixedFCVRegion::~FixedFCVRegion() = default;
const ServerGlobalParams::FeatureCompatibility& FixedFCVRegion::operator*() const {
// Note that the FixedFCVRegion only prevents the on-disk FCV from changing, not
// the in-memory FCV. (which for example could be reset during initial sync). The operator* and
// operator-> functions return a MutableFCV, which could change at different points in time. If you
// wanted to get a consistent snapshot of the in-memory FCV, you should still use the
// ServerGlobalParams::MutableFCV's acquireFCVSnapshot() function to get a FCVSnapshot.
const ServerGlobalParams::MutableFCV& FixedFCVRegion::operator*() const {
return serverGlobalParams.featureCompatibility;
}
const ServerGlobalParams::FeatureCompatibility* FixedFCVRegion::operator->() const {
const ServerGlobalParams::MutableFCV* FixedFCVRegion::operator->() const {
return &serverGlobalParams.featureCompatibility;
}
bool FixedFCVRegion::operator==(const FCV& other) const {
return serverGlobalParams.featureCompatibility.getVersion() == other;
return serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion() == other;
}
bool FixedFCVRegion::operator!=(const FCV& other) const {

View File

@ -144,7 +144,13 @@ public:
};
/**
* Utility class to prevent the FCV from changing while the FixedFCVRegion is in scope.
* Utility class to prevent the on-disk FCV from changing while the FixedFCVRegion is in scope.
*
* Note that this does not prevent the in-memory FCV from changing (which for example could be reset
* during initial sync). The operator* and operator-> functions return a MutableFCV, which could
* change at different points in time, so if you wanted to get a consistent snapshot of the
* in-memory FCV, you should still use the ServerGlobalParams::MutableFCV's acquireFCVSnapshot()
* function.
*/
class FixedFCVRegion {
public:
@ -154,8 +160,8 @@ public:
bool operator==(const multiversion::FeatureCompatibilityVersion& other) const;
bool operator!=(const multiversion::FeatureCompatibilityVersion& other) const;
const ServerGlobalParams::FeatureCompatibility& operator*() const;
const ServerGlobalParams::FeatureCompatibility* operator->() const;
const ServerGlobalParams::MutableFCV& operator*() const;
const ServerGlobalParams::MutableFCV* operator->() const;
private:
Lock::SharedLock _lk;

View File

@ -202,7 +202,7 @@ query_settings::QuerySettings lookupQuerySettingsForFind(
const NamespaceString& nss) {
// No QuerySettings lookup for IDHACK queries.
if (!feature_flags::gFeatureFlagQuerySettings.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
(collection &&
isIdHackEligibleQuery(
collection, *parsedRequest.findCommandRequest, parsedRequest.collator.get()))) {

View File

@ -150,7 +150,8 @@ CleanupStats cleanupEncryptedCollection(OperationContext* opCtx,
uassert(7618803,
str::stream() << "Feature flag `FLE2CleanupCommand` must be enabled to run "
<< CleanupStructuredEncryptionData::kCommandName,
gFeatureFlagFLE2CleanupCommand.isEnabled(serverGlobalParams.featureCompatibility));
gFeatureFlagFLE2CleanupCommand.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
uassert(7618804,
str::stream() << CleanupStructuredEncryptionData::kCommandName

View File

@ -84,7 +84,7 @@ public:
Reply typedRun(OperationContext* opCtx) {
if (!feature_flags::gFeatureFlagAuditConfigClusterParameter.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
str::stream() << Request::kCommandName << " cannot be run on standalones",
repl::ReplicationCoordinator::get(opCtx)->getSettings().isReplSet());

View File

@ -259,7 +259,7 @@ public:
uassert(7746400,
"setQuerySettings command is unknown",
feature_flags::gFeatureFlagQuerySettings.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
auto response =
stdx::visit(OverloadedVisitor{
[&](const query_shape::QueryShapeHash& queryShapeHash) {
@ -323,7 +323,7 @@ public:
uassert(7746700,
"removeQuerySettings command is unknown",
feature_flags::gFeatureFlagQuerySettings.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
auto tenantId = request().getDbName().tenantId();
auto queryShapeHash =
stdx::visit(OverloadedVisitor{

View File

@ -87,7 +87,7 @@ void setClusterParameterImplShard(OperationContext* opCtx,
(serverGlobalParams.clusterRole.has(ClusterRole::None)));
if (!feature_flags::gFeatureFlagAuditConfigClusterParameter.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
str::stream() << SetClusterParameter::kCommandName
<< " cannot be run on standalones",

View File

@ -316,7 +316,8 @@ public:
Lock::ExclusiveLock setFCVCommandLock(opCtx, commandMutex);
const auto requestedVersion = request.getCommandParameter();
const auto actualVersion = serverGlobalParams.featureCompatibility.getVersion();
const auto actualVersion =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
auto isConfirmed = request.getConfirm().value_or(false);
const auto upgradeMsg =
@ -466,7 +467,8 @@ public:
}
}
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
invariant(serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
if (!request.getPhase() || request.getPhase() == SetFCVPhaseEnum::kPrepare) {
if (serverGlobalParams.clusterRole.has(ClusterRole::ConfigServer)) {
@ -512,7 +514,8 @@ public:
}
}
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
invariant(serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
invariant(!request.getPhase() || request.getPhase() == SetFCVPhaseEnum::kComplete);
// All feature-specific FCV upgrade or downgrade code should go into the respective
@ -538,7 +541,7 @@ public:
FeatureCompatibilityVersion::updateFeatureCompatibilityVersionDocument(
opCtx,
serverGlobalParams.featureCompatibility.getVersion(),
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion(),
requestedVersion,
isFromConfigServer,
changeTimestamp,
@ -579,9 +582,9 @@ private:
// We do not expect any other feature-specific work to be done in the 'start' phase.
void _shardServerPhase1Tasks(OperationContext* opCtx,
multiversion::FeatureCompatibilityVersion requestedVersion) {
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
const auto& [originalVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
invariant(fcvSnapshot.isUpgradingOrDowngrading());
const auto& [originalVersion, _] = getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
const auto isDowngrading = originalVersion > requestedVersion;
const auto isUpgrading = originalVersion < requestedVersion;
@ -757,8 +760,8 @@ private:
void _maybeMigrateAuditConfig(OperationContext* opCtx,
const multiversion::FeatureCompatibilityVersion requestedVersion,
boost::optional<Timestamp> changeTimestamp) {
const auto& [fromVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto& [fromVersion, _] = getTransitionFCVFromAndTo(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion());
if (feature_flags::gFeatureFlagAuditConfigClusterParameter
.isEnabledOnTargetFCVButDisabledOnOriginalFCV(requestedVersion, fromVersion) &&
audit::migrateOldToNew) {
@ -833,8 +836,8 @@ private:
OperationContext* opCtx, const multiversion::FeatureCompatibilityVersion requestedVersion) {
// There is no need to re-create this index on upgrade, as the index is no longer
// needed to ensure resharding operations are unique.
const auto& [fromVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto& [fromVersion, _] = getTransitionFCVFromAndTo(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion());
if (resharding::gFeatureFlagReshardingImprovements
.isEnabledOnTargetFCVButDisabledOnOriginalFCV(requestedVersion, fromVersion)) {
LOGV2(7760401,
@ -866,7 +869,8 @@ private:
const multiversion::FeatureCompatibilityVersion requestedVersion,
const NamespaceString& indexCatalogNss) {
// TODO SERVER-67392: Remove once gGlobalIndexesShardingCatalog is enabled.
const auto actualVersion = serverGlobalParams.featureCompatibility.getVersion();
const auto actualVersion =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
if (feature_flags::gGlobalIndexesShardingCatalog
.isEnabledOnTargetFCVButDisabledOnOriginalFCV(requestedVersion, actualVersion)) {
uassertStatusOK(
@ -1003,9 +1007,9 @@ private:
// manually clean up some user data in order to retry the FCV downgrade.
void _userCollectionsUassertsForDowngrade(
OperationContext* opCtx, const multiversion::FeatureCompatibilityVersion requestedVersion) {
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
const auto& [originalVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
invariant(fcvSnapshot.isUpgradingOrDowngrading());
const auto& [originalVersion, _] = getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
if (feature_flags::gFeatureFlagAuditConfigClusterParameter
.isDisabledOnTargetFCVButEnabledOnOriginalFCV(requestedVersion, originalVersion)) {
@ -1066,9 +1070,9 @@ private:
// requestedVersion.
void _cleanUpClusterParameters(
OperationContext* opCtx, const multiversion::FeatureCompatibilityVersion requestedVersion) {
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
const auto& [fromVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
invariant(fcvSnapshot.isUpgradingOrDowngrading());
const auto& [fromVersion, _] = getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
auto* clusterParameters = ServerParameterSet::getClusterParameterSet();
std::vector<write_ops::DeleteOpEntry> deletes;
@ -1089,9 +1093,9 @@ private:
void _updateAuditConfigOnDowngrade(
OperationContext* opCtx, const multiversion::FeatureCompatibilityVersion requestedVersion) {
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
const auto& [fromVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
invariant(fcvSnapshot.isUpgradingOrDowngrading());
const auto& [fromVersion, _] = getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
if (feature_flags::gFeatureFlagAuditConfigClusterParameter
.isDisabledOnTargetFCVButEnabledOnOriginalFCV(requestedVersion, fromVersion)) {
@ -1121,9 +1125,9 @@ private:
// they would turn into a Support case.
void _internalServerCleanupForDowngrade(
OperationContext* opCtx, const multiversion::FeatureCompatibilityVersion requestedVersion) {
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
const auto& [originalVersion, _] =
getTransitionFCVFromAndTo(serverGlobalParams.featureCompatibility.getVersion());
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
invariant(fcvSnapshot.isUpgradingOrDowngrading());
const auto& [originalVersion, _] = getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
if (serverGlobalParams.clusterRole.has(ClusterRole::ShardServer) ||
serverGlobalParams.clusterRole.has(ClusterRole::None)) {
@ -1393,7 +1397,8 @@ private:
const SetFeatureCompatibilityVersion& request,
boost::optional<Timestamp> changeTimestamp) {
const auto requestedVersion = request.getCommandParameter();
const auto actualVersion = serverGlobalParams.featureCompatibility.getVersion();
const auto actualVersion =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
auto isFromConfigServer = request.getFromConfigServer().value_or(false);
hangDowngradingBeforeIsCleaningServerMetadata.pauseWhileSet(opCtx);
@ -1452,7 +1457,8 @@ private:
*/
void _cancelServerlessMigrations(OperationContext* opCtx) {
invariant(repl::ReplicationCoordinator::get(opCtx)->getSettings().isServerless());
invariant(serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
invariant(serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
auto donorService = checked_cast<TenantMigrationDonorService*>(
repl::PrimaryOnlyServiceRegistry::get(opCtx->getServiceContext())
->lookupServiceByName(TenantMigrationDonorService::kServiceName));

View File

@ -104,7 +104,8 @@ public:
uassert(
5356100,
"donorStartMigration not available while upgrading or downgrading the donor FCV",
!serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
!serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
uassert(ErrorCodes::IllegalOperation,
"tenant migrations are only available if --serverless is enabled",

View File

@ -107,7 +107,8 @@ public:
uassert(
5356101,
"recipientSyncData not available while upgrading or downgrading the recipient FCV",
!serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
!serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading());
const auto& cmd = request();
const auto migrationProtocol = cmd.getProtocol().value_or(kDefaultMigrationProtocol);

View File

@ -373,7 +373,7 @@ BSONObj CollectionScan::getPostBatchResumeToken() const {
BSONObjBuilder builder;
_lastSeenId.serializeToken("$recordId", &builder);
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
auto initialSyncId =
repl::ReplicationCoordinator::get(opCtx())->getInitialSyncId(opCtx());
if (initialSyncId) {

View File

@ -300,7 +300,7 @@ void TimeseriesModifyStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// retryable write or in a transaction.
if (_params.allowShardKeyUpdatesWithoutFullShardKeyInQuery &&
feature_flags::gFeatureFlagUpdateOneWithoutShardKey.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
bool isInternalThreadOrClient = !cc().session() || cc().isInternalClient();
uassert(ErrorCodes::InvalidOptions,
"$_allowShardKeyUpdatesWithoutFullShardKeyInQuery is an internal parameter",
@ -313,7 +313,7 @@ void TimeseriesModifyStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// wouldChangeOwningShard error thrown below. If this node is a replica set secondary node,
// we can skip validation.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"Must run update to shard key field in a multi-statement transaction or with "
"retryWrites: true.",
@ -338,7 +338,7 @@ void TimeseriesModifyStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// wouldChangeOwningShard error thrown below. If this node is a replica set secondary node,
// we can skip validation.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"Must run update to shard key field in a multi-statement transaction or with "
"retryWrites: true.",

View File

@ -169,7 +169,7 @@ void TimeseriesUpsertStage::_performInsert(BSONObj newMeasurement) {
// mongos will be able to start an internal transaction to handle the
// wouldChangeOwningShard error thrown below.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"The upsert document could not be inserted onto the shard targeted "
"by the query, since its shard key belongs on a different shard. "

View File

@ -698,7 +698,7 @@ void UpdateStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// retryable write or in a transaction.
if (_params.request->getAllowShardKeyUpdatesWithoutFullShardKeyInQuery().has_value() &&
feature_flags::gFeatureFlagUpdateOneWithoutShardKey.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
bool isInternalThreadOrClient = !cc().session() || cc().isInternalClient();
uassert(ErrorCodes::InvalidOptions,
"$_allowShardKeyUpdatesWithoutFullShardKeyInQuery is an internal parameter",
@ -711,7 +711,7 @@ void UpdateStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// wouldChangeOwningShard error thrown below. If this node is a replica set secondary node,
// we can skip validation.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"Must run update to shard key field in a multi-statement transaction or with "
"retryWrites: true.",
@ -734,7 +734,7 @@ void UpdateStage::_checkRestrictionsOnUpdatingShardKeyAreNotViolated(
// wouldChangeOwningShard error thrown below. If this node is a replica set secondary node,
// we can skip validation.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"Must run update to shard key field in a multi-statement transaction or with "
"retryWrites: true.",

View File

@ -179,7 +179,7 @@ void UpsertStage::_performInsert(BSONObj newDocument) {
// will be able to start an internal transaction to handle the
// wouldChangeOwningShard error thrown below.
if (!feature_flags::gFeatureFlagUpdateDocumentShardKeyUsingTransactionApi.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(
ErrorCodes::IllegalOperation,
"The upsert document could not be inserted onto the shard targeted by the "

View File

@ -54,20 +54,18 @@ public:
BSONObj generateSection(OperationContext* opCtx,
const BSONElement& configElement) const override {
BSONObjBuilder bob;
if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
bob.append(
"major",
multiversion::majorVersion(serverGlobalParams.featureCompatibility.getVersion()));
bob.append(
"minor",
multiversion::minorVersion(serverGlobalParams.featureCompatibility.getVersion()));
const ServerGlobalParams::FCVSnapshot fcvSnapshot =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
if (fcvSnapshot.isVersionInitialized()) {
bob.append("major", multiversion::majorVersion(fcvSnapshot.getVersion()));
bob.append("minor", multiversion::minorVersion(fcvSnapshot.getVersion()));
int currentlyTransitioning = 0;
// (Generic FCV reference): append information to serverStatus on if we are in a state
// of transitioning to a new FCV (upgrading or downgrading).
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
const auto& [fromVersion, toVersion] = multiversion::getTransitionFCVFromAndTo(
serverGlobalParams.featureCompatibility.getVersion());
if (fcvSnapshot.isUpgradingOrDowngrading()) {
const auto& [fromVersion, toVersion] =
multiversion::getTransitionFCVFromAndTo(fcvSnapshot.getVersion());
currentlyTransitioning = 1;
// from is greater, we are downgrading
if (fromVersion > toVersion) {

View File

@ -67,7 +67,7 @@ FeatureFlag::FeatureFlag(bool enabled, StringData versionString, bool shouldBeFC
// If the functionality of this function changes, make sure that the isEnabled/isPresentAndEnabled
// functions in feature_flag_util.js also incorporate the change.
bool FeatureFlag::isEnabled(const ServerGlobalParams::FeatureCompatibility& fcv) const {
bool FeatureFlag::isEnabled(const ServerGlobalParams::FCVSnapshot fcv) const {
// If the feature flag is not FCV gated, return whether it is enabled.
if (!_shouldBeFCVGated) {
return _enabled;
@ -93,8 +93,8 @@ bool FeatureFlag::isEnabled(const ServerGlobalParams::FeatureCompatibility& fcv)
}
bool FeatureFlag::isEnabledUseLastLTSFCVWhenUninitialized(
const ServerGlobalParams::FeatureCompatibility& fcv) const {
if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
const ServerGlobalParams::FCVSnapshot fcv) const {
if (fcv.isVersionInitialized()) {
return isEnabled(fcv);
} else {
// (Generic FCV reference): This reference is needed for the feature flag check API.
@ -103,8 +103,8 @@ bool FeatureFlag::isEnabledUseLastLTSFCVWhenUninitialized(
}
bool FeatureFlag::isEnabledUseLatestFCVWhenUninitialized(
const ServerGlobalParams::FeatureCompatibility& fcv) const {
if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
const ServerGlobalParams::FCVSnapshot fcv) const {
if (fcv.isVersionInitialized()) {
return isEnabled(fcv);
} else {
// (Generic FCV reference): This reference is needed for the feature flag check API.

View File

@ -66,22 +66,20 @@ public:
* If the functionality of this function changes, make sure that the
* isEnabled/isPresentAndEnabled functions in feature_flag_util.js also incorporate the change.
*/
bool isEnabled(const ServerGlobalParams::FeatureCompatibility& fcv) const;
bool isEnabled(const ServerGlobalParams::FCVSnapshot fcv) const;
/**
* Returns true if the flag is set to true and enabled for this FCV version. If the FCV version
* is unset, instead checks against the default last LTS FCV version.
*/
bool isEnabledUseLastLTSFCVWhenUninitialized(
const ServerGlobalParams::FeatureCompatibility& fcv) const;
bool isEnabledUseLastLTSFCVWhenUninitialized(const ServerGlobalParams::FCVSnapshot fcv) const;
/**
* Returns true if the flag is set to true and enabled for this FCV version. If the FCV version
* is unset, instead checks against the latest FCV version.
*/
bool isEnabledUseLatestFCVWhenUninitialized(
const ServerGlobalParams::FeatureCompatibility& fcv) const;
bool isEnabledUseLatestFCVWhenUninitialized(const ServerGlobalParams::FCVSnapshot fcv) const;
/**
* Returns true if this flag is enabled regardless of the current FCV version. When using this

View File

@ -593,7 +593,7 @@ IndexBuildsCoordinator::makeKillIndexBuildOnLowDiskSpaceAction() {
void act(OperationContext* opCtx, int64_t availableBytes) noexcept final {
if (!feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
LOGV2(6826200,
"Index build: disk space monitor detected we're low on storage space but "
"'featureFlagIndexBuildGracefulErrorHandling' is disabled. Ignoring it");
@ -2804,7 +2804,7 @@ void IndexBuildsCoordinator::_cleanUpTwoPhaseAfterNonShutdownFailure(
// (Ignore FCV check): This feature flag doesn't have any upgrade/downgrade concerns.
if (feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
replState->canVoteForAbort()) {
// Always request an abort to the primary node, even if we are primary. If
// primary, the signal will loop back and cause an asynchronous external
@ -2945,7 +2945,7 @@ void IndexBuildsCoordinator::_runIndexBuildInner(
// to the primary node. Single-phase builds can also abort immediately, as the primary or
// standalone is the only node aware of the build.
if (!feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
// Index builds only check index constraints when committing. If an error occurs at that
// point, then the build is cleaned up while still holding the appropriate locks. The only
// errors that we cannot anticipate are user interrupts and shutdown errors.

View File

@ -108,7 +108,8 @@ void logProcessDetailsForLogRotate(ServiceContext* serviceContext) {
}
}
serverGlobalParams.featureCompatibility.logFCVWithContext("log rotation"_sd);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().logFCVWithContext(
"log rotation"_sd);
logProcessDetails(nullptr);
}

View File

@ -64,8 +64,7 @@ bool NamespaceString::isCollectionlessAggregateNS() const {
return coll() == collectionlessAggregateCursorCol;
}
bool NamespaceString::isLegalClientSystemNS(
const ServerGlobalParams::FeatureCompatibility& currentFCV) const {
bool NamespaceString::isLegalClientSystemNS() const {
auto collectionName = coll();
if (isAdminDB()) {
if (collectionName == "system.roles")

View File

@ -668,7 +668,7 @@ public:
* Returns true if a client can modify this namespace even though it is under ".system."
* For example <dbname>.system.users is ok for regular clients to update.
*/
bool isLegalClientSystemNS(const ServerGlobalParams::FeatureCompatibility& currentFCV) const;
bool isLegalClientSystemNS() const;
/**
* Returns true if this namespace refers to a drop-pending collection.

View File

@ -162,17 +162,15 @@ TEST_F(NamespaceStringTest, IsCollectionlessCursorNamespace) {
}
TEST_F(NamespaceStringTest, IsLegalClientSystemNamespace) {
const auto& currentFCV = serverGlobalParams.featureCompatibility;
ASSERT_TRUE(makeNamespaceString(boost::none, "test.system.buckets.1234")
.isLegalClientSystemNS(currentFCV));
ASSERT_TRUE(makeNamespaceString(boost::none, "test.system.buckets.abcde")
.isLegalClientSystemNS(currentFCV));
ASSERT_FALSE(makeNamespaceString(boost::none, "test.system.buckets..1234")
.isLegalClientSystemNS(currentFCV));
ASSERT_FALSE(makeNamespaceString(boost::none, "test.system.buckets.a234$")
.isLegalClientSystemNS(currentFCV));
ASSERT_TRUE(
makeNamespaceString(boost::none, "test.system.buckets.1234").isLegalClientSystemNS());
ASSERT_TRUE(
makeNamespaceString(boost::none, "test.system.buckets.abcde").isLegalClientSystemNS());
ASSERT_FALSE(
makeNamespaceString(boost::none, "test.system.buckets.").isLegalClientSystemNS(currentFCV));
makeNamespaceString(boost::none, "test.system.buckets..1234").isLegalClientSystemNS());
ASSERT_FALSE(
makeNamespaceString(boost::none, "test.system.buckets.a234$").isLegalClientSystemNS());
ASSERT_FALSE(makeNamespaceString(boost::none, "test.system.buckets.").isLegalClientSystemNS());
}
TEST_F(NamespaceStringTest, IsDropPendingNamespace) {

View File

@ -119,7 +119,7 @@ OpMsgFuzzerFixture::OpMsgFuzzerFixture(bool skipGlobalInitializers)
storageGlobalParams.repair = false;
serverGlobalParams.enableMajorityReadConcern = false;
// (Generic FCV reference): Initialize FCV.
serverGlobalParams.mutableFeatureCompatibility.setVersion(multiversion::GenericFCV::kLatest);
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
initializeStorageEngine(opCtx.get(),
StorageEngineInitFlags::kAllowNoLockFile |

View File

@ -85,17 +85,19 @@ void FcvOpObserver::_setVersion(OperationContext* opCtx,
FeatureCompatibilityVersion::advanceLastFCVUpdateTimestamp(*commitTs);
boost::optional<multiversion::FeatureCompatibilityVersion> prevVersion;
if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
prevVersion = serverGlobalParams.featureCompatibility.getVersion();
const auto prevFcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
if (prevFcvSnapshot.isVersionInitialized()) {
prevVersion = prevFcvSnapshot.getVersion();
}
serverGlobalParams.mutableFeatureCompatibility.setVersion(newVersion);
serverGlobalParams.featureCompatibility.logFCVWithContext("setFCV"_sd);
serverGlobalParams.mutableFCV.setVersion(newVersion);
const auto newFcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
newFcvSnapshot.logFCVWithContext("setFCV"_sd);
FeatureCompatibilityVersion::updateMinWireVersion(opCtx);
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
if (serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo(
multiversion::GenericFCV::kLatest) ||
serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
if (newFcvSnapshot.isGreaterThanOrEqualTo(multiversion::GenericFCV::kLatest) ||
newFcvSnapshot.isUpgradingOrDowngrading()) {
// minWireVersion == maxWireVersion on kLatest FCV or upgrading/downgrading FCV.
// Close all incoming connections from internal clients with binary versions lower than
// ours.
@ -121,7 +123,7 @@ void FcvOpObserver::_setVersion(OperationContext* opCtx,
// in the upgrading/downgrading state.
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
try {
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
if (newFcvSnapshot.isUpgradingOrDowngrading()) {
SessionKiller::Matcher matcherAllSessions(
KillAllSessionsByPatternSet{makeKillAllSessionsByPattern(opCtx)});
killSessionsAbortUnpreparedTransactions(opCtx, matcherAllSessions);
@ -177,8 +179,9 @@ void FcvOpObserver::_onInsertOrUpdate(OperationContext* opCtx, const BSONObj& do
// version changes.
logv2::DynamicAttributes attrs;
bool isDifferent = true;
if (serverGlobalParams.featureCompatibility.isVersionInitialized()) {
const auto currentVersion = serverGlobalParams.featureCompatibility.getVersion();
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
if (fcvSnapshot.isVersionInitialized()) {
const auto currentVersion = fcvSnapshot.getVersion();
attrs.add("currentVersion", multiversion::toString(currentVersion));
isDifferent = currentVersion != newVersion;
}
@ -247,7 +250,8 @@ void FcvOpObserver::onReplicationRollback(OperationContext* opCtx,
if (swFcv.isOK()) {
const auto featureCompatibilityVersion = swFcv.getValue();
auto swVersion = FeatureCompatibilityVersionParser::parse(featureCompatibilityVersion);
const auto memoryFcv = serverGlobalParams.featureCompatibility.getVersion();
const auto memoryFcv =
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
if (swVersion.isOK() && (swVersion.getValue() != memoryFcv)) {
auto diskFcv = swVersion.getValue();
LOGV2(4675801,

View File

@ -1689,7 +1689,8 @@ void OpObserverImpl::onBatchedWriteCommit(OperationContext* opCtx) {
getMaxSizeOfBatchedOperationsInSingleOplogEntryBytes(),
/*prepare=*/false);
if (!gFeatureFlagLargeBatchedOperations.isEnabled(serverGlobalParams.featureCompatibility)) {
if (!gFeatureFlagLargeBatchedOperations.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
// Before SERVER-70765, we relied on packTransactionStatementsForApplyOps() to check if the
// batch of operations could fit in a single applyOps entry. Now, we pass the size limit to
// TransactionOperations::getApplyOpsInfo() and are now able to return an error earlier.

View File

@ -225,7 +225,7 @@ Status userAllowedCreateNS(OperationContext* opCtx, const NamespaceString& ns) {
return Status::OK();
}
if (ns.isSystem() && !ns.isLegalClientSystemNS(serverGlobalParams.featureCompatibility)) {
if (ns.isSystem() && !ns.isLegalClientSystemNS()) {
return Status(ErrorCodes::InvalidNamespace,
str::stream() << "Invalid system namespace: " << ns.toStringForErrorMsg());
}
@ -248,7 +248,7 @@ Status userAllowedCreateNS(OperationContext* opCtx, const NamespaceString& ns) {
return Status::OK();
}
if (ns.isConfigDB() && ns.isLegalClientSystemNS(serverGlobalParams.featureCompatibility)) {
if (ns.isConfigDB() && ns.isLegalClientSystemNS()) {
return Status::OK();
}

View File

@ -62,12 +62,13 @@ ParsedDelete::ParsedDelete(OperationContext* opCtx,
: _opCtx(opCtx),
_request(request),
_collection(collection),
_timeseriesDeleteQueryExprs(isTimeseriesDelete
? createTimeseriesWritesQueryExprsIfNecessary(
feature_flags::gTimeseriesDeletesSupport.isEnabled(
serverGlobalParams.featureCompatibility),
collection)
: nullptr),
_timeseriesDeleteQueryExprs(
isTimeseriesDelete
? createTimeseriesWritesQueryExprsIfNecessary(
feature_flags::gTimeseriesDeletesSupport.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()),
collection)
: nullptr),
_isRequestToTimeseries(isTimeseriesDelete) {}
Status ParsedDelete::parseRequest() {

View File

@ -102,12 +102,13 @@ ParsedUpdateBase::ParsedUpdateBase(OperationContext* opCtx,
_canonicalQuery(),
_extensionsCallback(std::move(extensionsCallback)),
_collection(collection),
_timeseriesUpdateQueryExprs(isRequestToTimeseries
? createTimeseriesWritesQueryExprsIfNecessary(
feature_flags::gTimeseriesUpdatesSupport.isEnabled(
serverGlobalParams.featureCompatibility),
collection)
: nullptr),
_timeseriesUpdateQueryExprs(
isRequestToTimeseries
? createTimeseriesWritesQueryExprsIfNecessary(
feature_flags::gTimeseriesUpdatesSupport.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()),
collection)
: nullptr),
_isRequestToTimeseries(isRequestToTimeseries) {
if (forgoOpCounterIncrements) {
_expCtx->enabledCounters = false;

View File

@ -2263,7 +2263,7 @@ void tryPerformTimeseriesBucketCompression(
const write_ops::InsertCommandRequest& request) {
// When enabled, we skip constructing ClosedBuckets which results in skipping compression.
invariant(!feature_flags::gTimeseriesAlwaysUseCompressedBuckets.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
// Buckets with just a single measurement is not worth compressing.
if (closedBucket.numMeasurements.has_value() && closedBucket.numMeasurements.value() <= 1) {

View File

@ -229,7 +229,7 @@ void validate(OperationContext* opCtx,
"$_requestResumeToken is not supported without Resharding Improvements",
!requestResumeTokenElem ||
resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
uassert(ErrorCodes::FailedToParse,
str::stream() << AggregateCommandRequest::kRequestResumeTokenFieldName
<< " must be a boolean type",

View File

@ -331,7 +331,7 @@ DocumentSourceChangeStreamUnwindTransaction::TransactionOpIterator::TransactionO
// We need endOfTransaction only for unprepared transactions: so this must be an applyOps with
// set lsid and txnNumber.
_needEndOfTransaction = feature_flags::gFeatureFlagEndOfTransactionChangeEvent.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
!applyOps.missing() && _lsid.has_value() && _txnNumber.has_value();
if (BSONType::Object ==

View File

@ -127,7 +127,7 @@ intrusive_ptr<DocumentSource> DocumentSourceListCatalog::createFromBson(
uassert(ErrorCodes::QueryFeatureNotAllowed,
fmt::format("The {} aggregation stage is not enabled", kStageName),
feature_flags::gDocumentSourceListCatalog.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
return new DocumentSourceListCatalog(pExpCtx);
}

View File

@ -190,7 +190,7 @@ void DocumentSourceOut::initialize() {
uassert(7406100,
"$out to time-series collections is only supported on FCV greater than or equal to 7.1",
feature_flags::gFeatureFlagAggOutTimeseries.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
!_timeseries);
const NamespaceString& outputNs = makeBucketNsIfTimeseries(getOutputNs());
@ -270,7 +270,7 @@ void DocumentSourceOut::finalize() {
uassert(7406101,
"$out to time-series collections is only supported on FCV greater than or equal to 7.1",
feature_flags::gFeatureFlagAggOutTimeseries.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
!_timeseries);
// If the collection is time-series, we must rename to the "real" buckets collection.

View File

@ -519,7 +519,8 @@ std::vector<std::unique_ptr<InnerPipelineStageInterface>> findSbeCompatibleStage
// TODO (SERVER-80243): Remove 'featureFlagTimeSeriesInSbe' check.
.unpackBucket = feature_flags::gFeatureFlagTimeSeriesInSbe.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
!queryKnob.getSbeDisableTimeSeriesForOp() &&
cq->getExpCtx()->sbePipelineCompatibility == SbeCompatibility::fullyCompatible,
};

View File

@ -89,7 +89,7 @@ AggregateCommandRequest asAggregateCommandRequest(const FindCommandRequest& find
// Some options are disallowed when resharding improvements are disabled.
if (!resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::InvalidPipelineOperator,
str::stream() << "Option " << FindCommandRequest::kRequestResumeTokenFieldName
<< " not supported in aggregation.",
@ -158,7 +158,7 @@ AggregateCommandRequest asAggregateCommandRequest(const FindCommandRequest& find
result.setLet(findCommand.getLet()->getOwned());
}
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
result.setRequestResumeToken(findCommand.getRequestResumeToken());
if (!findCommand.getResumeAfter().isEmpty()) {

View File

@ -265,7 +265,7 @@ extern MatchTypeToRewriteMap matchPredicateRewriteMap;
*/
#define REGISTER_ENCRYPTED_AGG_PREDICATE_REWRITE_WITH_FLAG(matchType, rewriteClass, featureFlag) \
REGISTER_ENCRYPTED_AGG_PREDICATE_REWRITE_GUARDED( \
matchType, rewriteClass, featureFlag.isEnabled(serverGlobalParams.featureCompatibility))
matchType, rewriteClass, featureFlag.isEnabled(serverGlobalParams.featureCompatibility.acquireFCVSnapshot())
/**
* Register a MatchExpression rewrite if a condition is true at startup time.
@ -298,6 +298,6 @@ extern MatchTypeToRewriteMap matchPredicateRewriteMap;
*/
#define REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(matchType, rewriteClass, featureFlag) \
REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_GUARDED( \
matchType, rewriteClass, featureFlag.isEnabled(serverGlobalParams.featureCompatibility))
matchType, rewriteClass, featureFlag.isEnabled(serverGlobalParams.featureCompatibility.acquireFCVSnapshot())
} // namespace fle
} // namespace mongo

View File

@ -72,7 +72,7 @@ Status QueryFrameworkControl::setFromString(StringData value, const boost::optio
break;
case QueryFrameworkControlEnum::kTryBonsai:
if (feature_flags::gFeatureFlagCommonQueryFramework.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
break;
}
return {ErrorCodes::IllegalOperation,

View File

@ -460,7 +460,7 @@ BSONObj PlanExecutorSBE::getPostBatchResumeToken() const {
BSONObjBuilder builder;
sbe::value::getRecordIdView(val)->serializeToken("$recordId", &builder);
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
auto initialSyncId =
repl::ReplicationCoordinator::get(_opCtx)->getInitialSyncId(_opCtx);
if (initialSyncId) {

View File

@ -114,7 +114,7 @@ Status validateResumeAfter(OperationContext* opCtx,
BSONType recordIdType = resumeAfter["$recordId"].type();
if (mongo::resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
if (resumeAfter.nFields() > 2 ||
(recordIdType != BSONType::NumberLong && recordIdType != BSONType::BinData &&
recordIdType != BSONType::jstNULL) ||

View File

@ -65,7 +65,7 @@ public:
bool includeByDefault() const override {
// Only include if Query Settings are enabled.
return feature_flags::gFeatureFlagQuerySettings.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
}
BSONObj generateSection(OperationContext* opCtx,

View File

@ -219,10 +219,10 @@ void updateStatistics(const QueryStatsStore::Partition& proofOfLock,
*/
bool isQueryStatsFeatureEnabled(bool requiresFullQueryStatsFeatureFlag) {
return feature_flags::gFeatureFlagQueryStats.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
(!requiresFullQueryStatsFeatureFlag &&
feature_flags::gFeatureFlagQueryStatsFindCommand.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
}
void registerRequest(OperationContext* opCtx,

View File

@ -110,9 +110,10 @@ bool isQuerySbeCompatible(const CollectionPtr* collection, const CanonicalQuery*
const auto& nss = cq->nss();
auto& queryKnob = QueryKnobConfiguration::decoration(cq->getExpCtxRaw()->opCtx);
if ((!feature_flags::gFeatureFlagTimeSeriesInSbe.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
queryKnob.getSbeDisableTimeSeriesForOp()) &&
nss.isTimeseriesBucketsCollection()) {
return false;

View File

@ -51,6 +51,25 @@ the sync source.
A node that starts with `--replSet` will also have an FCV value of `kUnsetDefaultLastLTSBehavior`
if it has not yet received the `replSetInitiate` command.
## Checking the in memory FCV
The in-memory FCV can be accessed through `serverGlobalParams.featureCompatibility.acquireFCVSnapshot()`. This
gets an immutable *copy* of the current FCV, so that we can use multiple functions like `getVersion` or `isVersionInitialized` to check a snapshot of the FCV value, without that value changing or getting reset (such as during initial sync) in-between the function calls. This
means that if we want to check multiple properties of what the FCV is at a particular point in time, we should do it all on the same snapshot.
For example: checking `isVersionInitialized() && isLessThan()` with the same `FCVSnapshot` value
would have the guarantee that if the FCV value is initialized during `isVersionInitialized()`,
it will still be during `isLessThan()`.
Conversely, if we do set the in-memory FCV to another value through `serverGlobalParams.mutableFCV.setVersion`,
and we want to now check something on the new FCV, we need to make sure to re-call `acquireFCVSnapshot` to get
a new copy of the FCV.
In general, if you want to check multiple properties of the FCV at a specific point in time, you should use one snapshot. For example, if you want to check both that
the FCV is initialized, and if it's less than some version, and that featureFlagXX is enabled
on this FCV, this should all be using the same `FCVSnapshot`. But if you're doing a multiple completely separate FCV
checks at different points in time, such as over multiple functions,or multiple distinct feature flag enablement checks (i.e. `featureFlagXX.isEnabled && featureFlagYY.isEnabled`), you should acquire a new FCV snapshot since the old one
may be stale.
# setFeatureCompatibilityVersion Command Overview
The FCV can be set using the `setFeatureCompatibilityVersion` admin command to one of the following:
@ -598,7 +617,7 @@ For example, a new index build feature that is being flag-guarded may be declare
To check if a feature flag is enabled, we should do the following:
```
if(feature_flags::gFeatureFlagToaster.isEnabled(serverGlobalParams.featureCompatibility)) {
if(feature_flags::gFeatureFlagToaster.isEnabled(serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
// The feature flag is enabled and we are guaranteed to be only communicating to
// nodes with binary versions greater than or equal to 4.9.0. Perform the new
// feature behavior.
@ -609,6 +628,18 @@ if(feature_flags::gFeatureFlagToaster.isEnabled(serverGlobalParams.featureCompat
}
```
A common pattern is to check if the FCV is initialized AND if the feature flag is enabled on the FCV.
In this case, we must make sure to do these checks on the SAME `FCVSnapshot`:
```
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
if(fcvSnapshot.isVersionInitialized() && feature_flags::gFeatureFlagToaster.isEnabled(fcvSnapshot)){
}
```
This is because otherwise, if you use two different snapshots, the in-memory FCV may be uninitialized in between calling `isVersionInitialized` on the first snapshot, and checking `isEnabled` on the second snapshot, resulting in a race.
This same principle applies in general. If you want to check multiple properties of the FCV/feature flag at a specific point in time (i.e. you are expecting the FCV value to be the same in all of your function calls), you must do the checks on the SAME `FCVSnapshot`.
See the [section about checking the in-memory FCV for more information](#checking-the-in-memory-FCV)
If the feature flag has `shouldBeFCVGated` set to false, then `isEnabled` will simply return
whether the feature flag is enabled.
@ -621,12 +652,12 @@ whether the feature flag is enabled.
the server's current FCV `serverGlobalParams.featureCompatibility`. However, during initial sync, we temporarily reset the FCV to be uninintialized.
Currently, if the FCV has not been initialized yet, it will check if the feature flag is enabled on the lastLTS FCV. After SERVER-82246,
this function will instead throw an invariant if the FCV is uninitialized.
this function will instead invariant if the FCV is uninitialized.
Each feature team should think about whether the feature could be run during initial sync, for example:
* if the feature is part of initial sync itself
* if the feature is in a background thread that runs during initial sync
* if the feature is run in a command that is allowed during initial sync, such as `hello`, etc
* if the feature is run in a command that is allowed during initial sync, such as `hello`, `serverStatus`,etc, or any command that returns `secondaryAllowed() == kAlways` or `kOptIn`, and returns `maintenanceOk() == true`
If the feature will never run during initial sync, it's fine to continue using `isEnabled`. However, if the feature could be run during initial sync, the feature team
should use one of these options instead:
@ -636,6 +667,8 @@ latest FCV version if the FCV version is unset, but note that this could result
even though the FCV has not been upgraded yet and will be set to lastLTS once initial sync is complete.
* Write your own special logic to avoid the invariant. If there is a request for creating additional server-wide helper functions in this area, please reach out to the Replication team.
### Additional feature flag gating guidelines
There are some cases outside of startup where we also want to check if the feature flag is turned on,
regardless of which FCV we are on. In these cases we can use the `isEnabledAndIgnoreFCVUnsafe`
helper, but it should only be used when we are sure that we don't care what the FCV is. We should

View File

@ -1700,24 +1700,28 @@ Before the data clone phase begins, the node will do the following:
node restarts while this flag is set, it will restart initial sync even though it may already
have data because it means that initial sync didn't complete. We also check this flag to prevent
reading from the oplog while initial sync is in progress.
2. Find a sync source.
3. Drop all of its data except for the local database and recreate the oplog.
4. Get the Rollback ID (RBID) from the sync source to ensure at the end that no rollbacks occurred
2. [Reset the in-memory FCV to `kUnsetDefaultLastLTSBehavior`.](https://github.com/10gen/mongo/blob/b718dc1aa3ffb3e6df4f61a30d54cda578cf2830/src/mongo/db/repl/initial_syncer.cpp#L689). This is to ensure compatibility between the sync source and sync
target. If the sync source is actually in a different feature compatibility version, we will find
out when we clone from the sync source.
3. Find a sync source.
4. Drop all of its data except for the local database and recreate the oplog.
5. Get the Rollback ID (RBID) from the sync source to ensure at the end that no rollbacks occurred
during initial sync.
5. Query its sync source's oplog for its latest OpTime and save it as the
6. Query its sync source's oplog for its latest OpTime and save it as the
`defaultBeginFetchingOpTime`. If there are no open transactions on the sync source, this will be
used as the `beginFetchingTimestamp` or the timestamp that it begins fetching oplog entries from.
6. Query its sync source's transactions table for the oldest starting OpTime of all active
7. Query its sync source's transactions table for the oldest starting OpTime of all active
transactions. If this timestamp exists (meaning there is an open transaction on the sync source)
this will be used as the `beginFetchingTimestamp`. If this timestamp doesn't exist, the node will
use the `defaultBeginFetchingOpTime` instead. This will ensure that even if a transaction was
started on the sync source after it was queried for the oldest active transaction timestamp, the
syncing node will have all the oplog entries associated with an active transaction in its oplog.
7. Query its sync source's oplog for its lastest OpTime. This will be the `beginApplyingTimestamp`,
8. Query its sync source's oplog for its lastest OpTime. This will be the `beginApplyingTimestamp`,
or the timestamp that it begins applying oplog entries at once it has completed the data clone
phase. If there was no active transaction on the sync source, the `beginFetchingTimestamp` will
be the same as the `beginApplyingTimestamp`.
8. Create an `OplogFetcher` and start fetching and buffering oplog entries from the sync source
9. [Set the in-memory FCV to the sync source's FCV.](https://github.com/10gen/mongo/blob/b718dc1aa3ffb3e6df4f61a30d54cda578cf2830/src/mongo/db/repl/initial_syncer.cpp#L1153). This is because during the cloning phase, we do expect to clone the sync source's "admin.system.version" collection eventually (which contains the FCV document), but we can't guarantee that we will clone "admin.system.version" first. Setting the in-memory FCV value to the sync source's FCV first will ensure that we clone collections using the same FCV as the sync source. However, we won't persist the FCV to disk nor will we update our minWireVersion until we clone the actual document.
10. Create an `OplogFetcher` and start fetching and buffering oplog entries from the sync source
to be applied later. Operations are buffered to a collection so that they are not limited by the
amount of memory available.

View File

@ -169,9 +169,9 @@ BaseCloner::AfterStageBehavior AllDatabaseCloner::getInitialSyncIdStage() {
BaseCloner::AfterStageBehavior AllDatabaseCloner::listDatabasesStage() {
std::vector<mongo::BSONObj> databasesArray;
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
const bool multiTenancyAndRequireTenantIdEnabled = gMultitenancySupport &&
serverGlobalParams.featureCompatibility.isVersionInitialized() &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility);
fcvSnapshot.isVersionInitialized() && gFeatureFlagRequireTenantID.isEnabled(fcvSnapshot);
databasesArray = getClient()->getDatabaseInfos(
BSONObj(),
@ -248,7 +248,8 @@ void AllDatabaseCloner::postStage() {
BSONObj cmdObj = BSON("dbStats" << 1);
BSONObjBuilder b(cmdObj);
if (gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility) &&
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
dbName.tenantId()) {
dbName.tenantId()->serializeToBSON("$tenant", &b);
}

View File

@ -162,7 +162,8 @@ void CollectionCloner::preStage() {
BSONObjBuilder b(BSON("collStats" << _sourceNss.coll().toString()));
if (gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility) &&
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
_sourceNss.tenantId()) {
_sourceNss.tenantId()->serializeToBSON("$tenant", &b);
}

View File

@ -686,7 +686,7 @@ void InitialSyncer::_startInitialSyncAttemptCallback(
"Resetting feature compatibility version to last-lts. If the sync source is in "
"latest feature compatibility version, we will find out when we clone the "
"server configuration collection (admin.system.version)");
serverGlobalParams.mutableFeatureCompatibility.reset();
serverGlobalParams.mutableFCV.reset();
// Clear the oplog buffer.
_oplogBuffer->clear(makeOpCtx().get());
@ -1138,7 +1138,8 @@ void InitialSyncer::_fcvFetcherCallback(const StatusWith<Fetcher::QueryResponse>
// Changing the featureCompatibilityVersion during initial sync is unsafe.
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading(version)) {
if (serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isUpgradingOrDowngrading(
version)) {
onCompletionGuard->setResultAndCancelRemainingWork_inlock(
lock,
Status(ErrorCodes::IncompatibleServerVersion,
@ -1150,7 +1151,7 @@ void InitialSyncer::_fcvFetcherCallback(const StatusWith<Fetcher::QueryResponse>
// and collection/index creation can depend on FCV, we set the in-memory FCV value to match
// the version on the sync source. We won't persist the FCV on disk nor will we update our
// minWireVersion until we clone the actual document.
serverGlobalParams.mutableFeatureCompatibility.setVersion(version);
serverGlobalParams.mutableFCV.setVersion(version);
}
if (MONGO_unlikely(initialSyncHangBeforeSplittingControlFlow.shouldFail())) {

View File

@ -4258,7 +4258,7 @@ OplogEntry InitialSyncerTest::doInitialSyncWithOneBatch() {
void InitialSyncerTest::doSuccessfulInitialSyncWithOneBatch() {
auto lastOp = doInitialSyncWithOneBatch();
serverGlobalParams.mutableFeatureCompatibility.reset();
serverGlobalParams.mutableFCV.reset();
ASSERT_OK(_lastApplied.getStatus());
ASSERT_EQUALS(lastOp.getOpTime(), _lastApplied.getValue().opTime);
ASSERT_EQUALS(lastOp.getWallClockTime(), _lastApplied.getValue().wallTime);

View File

@ -132,8 +132,7 @@ public:
// (Generic FCV reference): Test latest FCV behavior. This FCV reference should exist across
// LTS binary versions.
serverGlobalParams.mutableFeatureCompatibility.setVersion(
multiversion::GenericFCV::kLatest);
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
if (haveClient()) {
Client::releaseCurrent();

View File

@ -224,7 +224,7 @@ void OplogApplierImplTest::setUp() {
// test fixture does not create a featureCompatibilityVersion document from which to initialize
// the server parameter.
// (Generic FCV reference): This FCV reference should exist across LTS binary versions.
serverGlobalParams.mutableFeatureCompatibility.setVersion(multiversion::GenericFCV::kLatest);
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
// This is necessary to generate ghost timestamps for index builds that are not 0, since 0 is an
// invalid timestamp.

View File

@ -438,8 +438,9 @@ Status OplogApplierUtils::applyOplogEntryOrGroupedInsertsCommon(
const NamespaceString nss(op->getNss());
auto opType = op->getOpType();
if ((gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))) {
if (gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
invariant(op->getTid() == nss.tenantId());
} else {
invariant(op->getTid() == boost::none);

View File

@ -96,7 +96,8 @@ BSONObj makeOplogEntryDoc(OpTime opTime,
builder.append(OplogEntryBase::kVersionFieldName, version);
builder.append(OplogEntryBase::kOpTypeFieldName, OpType_serializer(opType));
if (nss.tenantId() && gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility)) {
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
nss.tenantId()->serializeToBSON(OplogEntryBase::kTidFieldName, &builder);
}
builder.append(OplogEntryBase::kNssFieldName,
@ -231,7 +232,8 @@ void ReplOperation::extractPrePostImageForTransaction(boost::optional<ImageBundl
void ReplOperation::setTid(boost::optional<mongo::TenantId> value) & {
if (gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()))
DurableReplOperation::setTid(value);
}
@ -376,7 +378,8 @@ ReplOperation MutableOplogEntry::toReplOperation() const noexcept {
void MutableOplogEntry::setTid(boost::optional<mongo::TenantId> value) & {
if (gMultitenancySupport &&
gFeatureFlagRequireTenantID.isEnabled(serverGlobalParams.featureCompatibility))
gFeatureFlagRequireTenantID.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()))
getDurableReplOperation().setTid(std::move(value));
}

View File

@ -4741,9 +4741,9 @@ ReplicationCoordinatorImpl::_updateMemberStateFromTopologyCoordinator(WithLock l
// receive the replicated version. This is to avoid bugs like SERVER-32639.
if (newState.arbiter()) {
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
serverGlobalParams.mutableFeatureCompatibility.setVersion(
multiversion::GenericFCV::kLatest);
serverGlobalParams.featureCompatibility.logFCVWithContext("arbiter"_sd);
serverGlobalParams.mutableFCV.setVersion(multiversion::GenericFCV::kLatest);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().logFCVWithContext(
"arbiter"_sd);
}
_memberState = newState;

View File

@ -2117,9 +2117,10 @@ void ShardMergeRecipientService::Instance::_updateStateDoc(
}
void ShardMergeRecipientService::Instance::_assertIfMigrationIsSafeToRunWithCurrentFcv() {
auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
//(Generic FCV reference): This FCV check should exist across LTS binary versions.
auto recipientFCV = serverGlobalParams.featureCompatibility.getVersion();
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading(recipientFCV)) {
auto recipientFCV = fcvSnapshot.getVersion();
if (fcvSnapshot.isUpgradingOrDowngrading(recipientFCV)) {
LOGV2(7339711, "Must abort shard merge as recipient is upgrading or downgrading");
uasserted(ErrorCodes::TenantMigrationAborted,
"Can't run shard merge when FCV is downgrading or upgrading");

View File

@ -2799,7 +2799,7 @@ TEST_F(StorageInterfaceImplTest,
// namespaces.
NamespaceString nss =
NamespaceString::createNamespaceString_forTest("local.system.rollback.docs");
ASSERT_FALSE(nss.isLegalClientSystemNS(serverGlobalParams.featureCompatibility));
ASSERT_FALSE(nss.isLegalClientSystemNS());
auto opCtx = getOperationContext();
auto options = generateOptionsWithUuid();
@ -3092,7 +3092,7 @@ TEST_F(StorageInterfaceImplTest, DeleteByFilterRemovesDocumentsInIllegalClientSy
// client system" namespaces.
NamespaceString nss =
NamespaceString::createNamespaceString_forTest("local.system.rollback.docs");
ASSERT_FALSE(nss.isLegalClientSystemNS(serverGlobalParams.featureCompatibility));
ASSERT_FALSE(nss.isLegalClientSystemNS());
auto opCtx = getOperationContext();
StorageInterfaceImpl storage;

View File

@ -958,7 +958,8 @@ SemiFuture<void> TenantMigrationDonorService::Instance::run(
auto isFCVUpgradingOrDowngrading = [&]() -> bool {
// We must abort the migration if we try to start or resume while upgrading or downgrading.
// (Generic FCV reference): This FCV check should exist across LTS binary versions.
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
if (serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading()) {
LOGV2(5356302, "Must abort tenant migration as donor is upgrading or downgrading");
return true;
}

View File

@ -2119,7 +2119,7 @@ TenantMigrationRecipientService::Instance::_checkIfFcvHasChangedSinceLastAttempt
// subsequent attempt. Fail if there is any mismatch in FCV or
// upgrade/downgrade state. (Generic FCV reference): This FCV check should
// exist across LTS binary versions.
auto currentFCV = serverGlobalParams.featureCompatibility.getVersion();
auto currentFCV = serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
auto startingFCV = _stateDoc.getRecipientPrimaryStartingFCV();
if (!startingFCV) {
@ -2361,7 +2361,8 @@ SemiFuture<void> TenantMigrationRecipientService::Instance::run(
// We defer this until after the state doc is persisted in a started so as to make sure it
// it safe to abort and forget the migration. (Generic FCV reference): This FCV check should
// exist across LTS binary versions.
if (serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading()) {
if (serverGlobalParams.featureCompatibility.acquireFCVSnapshot()
.isUpgradingOrDowngrading()) {
LOGV2(5356304, "Must abort tenant migration as recipient is upgrading or downgrading");
return true;
}

View File

@ -3157,7 +3157,7 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientServiceRecor
auto doc = getStateDoc(instance.get());
auto docFCV = doc.getRecipientPrimaryStartingFCV();
auto currentFCV = serverGlobalParams.featureCompatibility.getVersion();
auto currentFCV = serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
LOGV2(5356202, "FCV in doc vs current", "docFCV"_attr = docFCV, "currentFCV"_attr = currentFCV);
ASSERT(currentFCV == docFCV);
checkStateDocPersisted(opCtx.get(), instance.get());
@ -3184,7 +3184,7 @@ TEST_F(TenantMigrationRecipientServiceTest,
initialStateDocument.setProtocol(MigrationProtocolEnum::kMultitenantMigrations);
// Add an FCV value as if it was from a previous attempt.
auto currentFCV = serverGlobalParams.featureCompatibility.getVersion();
auto currentFCV = serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
initialStateDocument.setRecipientPrimaryStartingFCV(currentFCV);
// Create and start the instance.

View File

@ -182,7 +182,8 @@ inline Status validateProtocolFCVCompatibility(
return Status::OK();
if (*protocol == MigrationProtocolEnum::kShardMerge &&
!repl::feature_flags::gShardMerge.isEnabled(serverGlobalParams.featureCompatibility)) {
!repl::feature_flags::gShardMerge.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
return Status(ErrorCodes::IllegalOperation,
str::stream() << "protocol '" << MigrationProtocol_serializer(*protocol)
<< "' not supported");

View File

@ -129,7 +129,7 @@ void IndexBuildState::setState(State state,
bool IndexBuildState::_checkIfValidTransition(IndexBuildState::State currentState,
IndexBuildState::State newState) const {
const auto graceful = feature_flags::gIndexBuildGracefulErrorHandling.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
switch (currentState) {
case IndexBuildState::State::kSetup:
return
@ -735,7 +735,7 @@ bool ReplIndexBuildState::_shouldSkipIndexBuildStateTransitionCheck(OperationCon
const auto replCoord = repl::ReplicationCoordinator::get(opCtx);
if (replCoord->getSettings().isReplSet() && protocol == IndexBuildProtocol::kTwoPhase) {
if (replCoord->getMemberState() == repl::MemberState::RS_STARTUP2 &&
!serverGlobalParams.featureCompatibility.isVersionInitialized()) {
!serverGlobalParams.featureCompatibility.acquireFCVSnapshot().isVersionInitialized()) {
// We're likely at the initial stages of a new logical initial sync attempt, and we
// haven't yet replicated the FCV from the sync source. Skip the index build state
// transition checks because they rely on the FCV.

View File

@ -35,9 +35,9 @@ namespace mongo {
namespace replica_set_endpoint {
bool isFeatureFlagEnabled() {
return serverGlobalParams.featureCompatibility.isVersionInitialized() &&
feature_flags::gFeatureFlagReplicaSetEndpoint.isEnabled(
serverGlobalParams.featureCompatibility);
const auto fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
return fcvSnapshot.isVersionInitialized() &&
feature_flags::gFeatureFlagReplicaSetEndpoint.isEnabled(fcvSnapshot);
}
} // namespace replica_set_endpoint

View File

@ -268,7 +268,7 @@ void WriteDistributionMetricsCalculator::_addUpdateQuery(
// shard key is not supported or when the query targets an exact id value.
if (isReplacementUpdate &&
(!feature_flags::gFeatureFlagUpdateOneWithoutShardKey.isEnabled(
serverGlobalParams.featureCompatibility) ||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
isExactIdQuery())) {
auto filter =
_getShardKeyPattern().extractShardKeyFromDoc(updateMod.getUpdateReplacement());

View File

@ -1176,7 +1176,7 @@ int Balancer::_moveChunks(OperationContext* opCtx,
if (status == ErrorCodes::IndexNotFound &&
gFeatureFlagShardKeyIndexOptionalHashedSharding.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
const auto [cm, _] = uassertStatusOK(
Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(

View File

@ -162,7 +162,8 @@ public:
{
FixedFCVRegion fcvRegion{opCtx};
forceSameUUIDAsSource =
feature_flags::gTrackUnshardedCollectionsOnShardingCatalog.isEnabled(*fcvRegion);
feature_flags::gTrackUnshardedCollectionsOnShardingCatalog.isEnabled(
(*fcvRegion).acquireFCVSnapshot());
}
Cloner cloner;

View File

@ -506,7 +506,7 @@ CollectionShardingRuntime::_getMetadataWithVersionCheckAt(
const auto& currentMetadata = optCurrentMetadata->get();
const auto indexFeatureFlag = feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
const auto wantedPlacementVersion = currentMetadata.getShardPlacementVersion();
const auto wantedCollectionIndexes =
indexFeatureFlag ? getCollectionIndexes(opCtx) : boost::none;
@ -517,6 +517,7 @@ CollectionShardingRuntime::_getMetadataWithVersionCheckAt(
ShardVersionFactory::make(currentMetadata, wantedCollectionIndexes);
const ChunkVersion receivedPlacementVersion = receivedShardVersion.placementVersion();
const bool isPlacementVersionIgnored =
ShardVersion::isPlacementVersionIgnored(receivedShardVersion);
const boost::optional<Timestamp> receivedIndexVersion = receivedShardVersion.indexVersion();

View File

@ -115,9 +115,10 @@ auto assertGetReshardingMachine(OperationContext* opCtx,
"Could not find in-progress resharding operation to abort",
machine);
if (resharding::gFeatureFlagMoveCollection.isEnabled(serverGlobalParams.featureCompatibility) ||
if (resharding::gFeatureFlagMoveCollection.isEnabled(
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) ||
resharding::gFeatureFlagUnshardCollection.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::IllegalOperation,
"Could not find in-progress resharding operation with matching provenance",
provenance && (*machine)->getMetadata().getProvenance() == provenance.get());

View File

@ -192,7 +192,7 @@ public:
uassert(ErrorCodes::CommandNotSupported,
format(FMT_STRING("{} command not enabled"), definition()->getName()),
feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
uassert(
ErrorCodes::IllegalOperation,
format(FMT_STRING("{} can only be run on config servers"), definition()->getName()),

View File

@ -182,7 +182,7 @@ public:
uassert(ErrorCodes::CommandNotSupported,
format(FMT_STRING("{} command not enabled"), definition()->getName()),
feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
uassert(
ErrorCodes::IllegalOperation,
format(FMT_STRING("{} can only be run on config servers"), definition()->getName()),

View File

@ -172,7 +172,7 @@ public:
}
if (!resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(
ErrorCodes::InvalidOptions,
"Resharding improvements is not enabled, reject shardDistribution parameter",
@ -188,9 +188,9 @@ public:
"Resharding improvements is not enabled, reject feature flag "
"moveCollection or unshardCollection",
!resharding::gFeatureFlagMoveCollection.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
!resharding::gFeatureFlagUnshardCollection.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
}
if (const auto& shardDistribution = request().getShardDistribution()) {
@ -203,22 +203,21 @@ public:
-> boost::optional<std::shared_ptr<const ReshardingCoordinator>> {
FixedFCVRegion fixedFcv(opCtx);
const auto fcvSnapshot = (*fixedFcv).acquireFCVSnapshot();
// (Generic FCV reference): To run this command and ensure the consistency of
// the metadata we need to make sure we are on a stable state.
uassert(ErrorCodes::CommandNotSupported,
"Resharding is not supported for this version, please update the FCV to "
"latest.",
!serverGlobalParams.featureCompatibility.isUpgradingOrDowngrading());
!fcvSnapshot.isUpgradingOrDowngrading());
// We only want to use provenance in resharding if FCV is latest but it's still
// possible for a mongos on a higher fcv to send a reshard collection request to a
// configsvr on a lower fcv. We ignore the reshardCollection provenance in this
// case.
bool setProvenance = true;
if (resharding::gFeatureFlagMoveCollection.isEnabled(
serverGlobalParams.featureCompatibility) ||
resharding::gFeatureFlagUnshardCollection.isEnabled(
serverGlobalParams.featureCompatibility)) {
if (resharding::gFeatureFlagMoveCollection.isEnabled(fcvSnapshot) ||
resharding::gFeatureFlagUnshardCollection.isEnabled(fcvSnapshot)) {
uassert(ErrorCodes::InvalidOptions,
"Expected provenance to be specified",
request().getProvenance().has_value());

View File

@ -81,7 +81,7 @@ Status allowedToEnable(const BSONObj& command) {
auto name = getParameterName(command);
if (name == "pauseMigrationsDuringMultiUpdates" &&
!migration_blocking_operation::gFeatureFlagPauseMigrationsDuringMultiUpdatesAvailable
.isEnabled(serverGlobalParams.featureCompatibility)) {
.isEnabled(serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
return Status{
ErrorCodes::IllegalOperation,
"Unable to enable pauseMigrationsDuringMultiUpdates cluster parameter because "

View File

@ -427,7 +427,7 @@ SplitPointsBasedSplitPolicy::SplitPointsBasedSplitPolicy(
size_t numInitialChunksPerShard = 1;
// TODO SERVER-81884: update once 8.0 becomes last LTS.
if (!feature_flags::gOneChunkPerShardEmptyCollectionWithHashedShardKey.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
numInitialChunksPerShard = 2;
}
@ -621,7 +621,7 @@ PresplitHashedZonesSplitPolicy::PresplitHashedZonesSplitPolicy(
size_t numInitialChunksPerShard = 1;
// TODO SERVER-81884: update once 8.0 becomes last LTS.
if (!feature_flags::gOneChunkPerShardEmptyCollectionWithHashedShardKey.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
numInitialChunksPerShard = 2;
}
// If 'numInitialChunks' was not specified, use default value.

View File

@ -800,7 +800,7 @@ Status ShardingCatalogManager::_initConfigIndexes(OperationContext* opCtx) {
}
if (feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
result = sharding_util::createShardingIndexCatalogIndexes(
opCtx, NamespaceString::kConfigsvrIndexCatalogNamespace);
if (!result.isOK()) {

View File

@ -928,8 +928,10 @@ StatusWith<std::string> ShardingCatalogManager::addShard(
// while blocking on the network).
FixedFCVRegion fcvRegion(opCtx);
const auto fcvSnapshot = (*fcvRegion).acquireFCVSnapshot();
std::vector<CollectionType> collList;
if (feature_flags::gTrackUnshardedCollectionsOnShardingCatalog.isEnabled(*fcvRegion)) {
if (feature_flags::gTrackUnshardedCollectionsOnShardingCatalog.isEnabled(fcvSnapshot)) {
// TODO SERVER-80532: the sharding catalog might lose some collections.
auto listStatus = _getCollListFromShard(opCtx, dbNamesStatus.getValue(), targeter);
if (!listStatus.isOK()) {
@ -939,17 +941,18 @@ StatusWith<std::string> ShardingCatalogManager::addShard(
collList = std::move(listStatus.getValue());
}
// (Generic FCV reference): These FCV checks should exist across LTS binary versions.
uassert(5563603,
"Cannot add shard while in upgrading/downgrading FCV state",
!fcvRegion->isUpgradingOrDowngrading());
!fcvSnapshot.isUpgradingOrDowngrading());
// (Generic FCV reference): These FCV checks should exist across LTS binary versions.
invariant(fcvRegion == multiversion::GenericFCV::kLatest ||
fcvRegion == multiversion::GenericFCV::kLastContinuous ||
fcvRegion == multiversion::GenericFCV::kLastLTS);
const auto currentFCV = fcvSnapshot.getVersion();
invariant(currentFCV == multiversion::GenericFCV::kLatest ||
currentFCV == multiversion::GenericFCV::kLastContinuous ||
currentFCV == multiversion::GenericFCV::kLastLTS);
if (!isConfigShard) {
SetFeatureCompatibilityVersion setFcvCmd(fcvRegion->getVersion());
SetFeatureCompatibilityVersion setFcvCmd(currentFCV);
setFcvCmd.setDbName(DatabaseName::kAdmin);
setFcvCmd.setFromConfigServer(true);

View File

@ -1369,7 +1369,7 @@ void MigrationDestinationManager::_migrateDriver(OperationContext* outerOpCtx,
// Get the global indexes and install them.
if (feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
replaceShardingIndexCatalogInShardIfNeeded(
altOpCtx.get(), _nss, donorCollectionOptionsAndIndexes.uuid);
}

View File

@ -435,8 +435,7 @@ std::vector<NamespaceString> MovePrimaryCoordinator::getCollectionsToClone(
uassertStatusOK(bsonExtractStringField(collInfo, "name", &collName));
const NamespaceString nss(NamespaceStringUtil::deserialize(_dbName, collName));
if (!nss.isSystem() ||
nss.isLegalClientSystemNS(serverGlobalParams.featureCompatibility)) {
if (!nss.isSystem() || nss.isLegalClientSystemNS()) {
colls.push_back(nss);
}
}

View File

@ -148,7 +148,7 @@ ExecutorFuture<void> ReshardCollectionCoordinator::_runImpl(
configsvrReshardCollection.setNumInitialChunks(_doc.getNumInitialChunks());
if (!resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(
ErrorCodes::InvalidOptions,
"Resharding improvements is not enabled, reject shardDistribution parameter",
@ -164,15 +164,15 @@ ExecutorFuture<void> ReshardCollectionCoordinator::_runImpl(
"Resharding improvements is not enabled, reject feature flag "
"moveCollection or unshardCollection",
!resharding::gFeatureFlagMoveCollection.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
!resharding::gFeatureFlagUnshardCollection.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
}
if (!resharding::gFeatureFlagMoveCollection.isEnabled(
serverGlobalParams.featureCompatibility) &&
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()) &&
!resharding::gFeatureFlagUnshardCollection.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassert(ErrorCodes::InvalidOptions,
"Feature flag move collection or unshard collection is not enabled, reject "
"provenance",

View File

@ -829,7 +829,7 @@ SemiFuture<void> ReshardingCollectionCloner::run(
auto chainCtx = std::make_shared<ChainContext>();
auto reshardingImprovementsEnabled = resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility);
serverGlobalParams.featureCompatibility.acquireFCVSnapshot());
return resharding::WithAutomaticRetry([this,
chainCtx,

View File

@ -175,7 +175,7 @@ protected:
uassertStatusOK(createCollection(
operationContext(), tempNss.dbName(), BSON("create" << tempNss.coll())));
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
uassertStatusOK(createCollection(
operationContext(),
NamespaceString::kRecipientReshardingResumeDataNamespace.dbName(),
@ -239,7 +239,7 @@ protected:
initializePipelineTest(shardKey, recipientShard, collectionData, configData);
auto opCtx = operationContext();
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility))
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()))
opCtx->setLogicalSessionId(makeLogicalSessionId(opCtx));
TxnNumber txnNum(0);
while (_cloner->doOneBatch(operationContext(), *_pipeline, txnNum)) {

View File

@ -647,7 +647,7 @@ void writeToConfigIndexesForTempNss(OperationContext* opCtx,
const ReshardingCoordinatorDocument& coordinatorDoc,
TxnNumber txnNumber) {
if (!feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
return;
}
auto nextState = coordinatorDoc.getState();
@ -1243,7 +1243,7 @@ ReshardingCoordinatorExternalStateImpl::calculateParticipantShardsAndChunks(
"Resharding improvements is not enabled, should not have "
"shardDistribution in coordinatorDoc",
resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility));
serverGlobalParams.featureCompatibility.acquireFCVSnapshot()));
uassert(ErrorCodes::InvalidOptions,
"ShardDistribution should not be empty if provided",
shardDistribution->size() > 0);
@ -1399,7 +1399,7 @@ ExecutorFuture<void> ReshardingCoordinatorService::_rebuildService(
// downgrade simpler, so we can remove all of this initialization when the flag is
// removed.
if (!resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
client.runCommand(
nss.dbName(),
BSON("createIndexes"
@ -1961,7 +1961,7 @@ ExecutorFuture<void> ReshardingCoordinator::_runReshardingOp(
.onCompletion([this, self = shared_from_this()](Status status) {
_metrics->onStateTransition(_coordinatorDoc.getState(), boost::none);
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
_logStatsOnCompletion(status.isOK());
}
@ -2133,7 +2133,7 @@ ExecutorFuture<bool> ReshardingCoordinator::_isReshardingOpRedundant(
// Ensure indexes are loaded in the catalog cache, along with the collection
// placement.
if (feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
auto cri = uassertStatusOK(
Grid::get(opCtx)->catalogCache()->getTrackedCollectionRoutingInfoWithRefresh(

View File

@ -270,7 +270,7 @@ std::unique_ptr<ReshardingDataReplicationInterface> ReshardingDataReplication::m
std::shared_ptr<executor::TaskExecutor> collectionClonerExecutor;
if (!cloningDone) {
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
resharding::data_copy::ensureCollectionExists(
opCtx,
NamespaceString::kRecipientReshardingResumeDataNamespace,

View File

@ -387,7 +387,7 @@ ExecutorFuture<void> ReshardingDonorService::DonorStateMachine::_notifyCoordinat
return resharding::WithAutomaticRetry([this, executor] {
auto opCtx = _cancelableOpCtxFactory->makeOperationContext(&cc());
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
_metrics->fillDonorCtxOnCompletion(_donorCtx);
}
return _updateCoordinator(opCtx.get(), executor);
@ -881,7 +881,7 @@ void ReshardingDonorService::DonorStateMachine::_dropOriginalCollectionThenTrans
WriteBlockBypass::get(opCtx.get()).set(true);
if (feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
dropCollectionShardingIndexCatalog(opCtx.get(), _metadata.getSourceNss());
}
resharding::data_copy::ensureCollectionDropped(

View File

@ -257,7 +257,7 @@ StringData ReshardingMetrics::getStateString() const noexcept {
BSONObj ReshardingMetrics::reportForCurrentOp() const noexcept {
BSONObjBuilder builder;
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
reportDurationsForAllPhases<Seconds>(
kTimedPhaseNamesMap, getClockSource(), &builder, Seconds{0});
switch (_role) {
@ -310,7 +310,7 @@ void ReshardingMetrics::restoreRecipientSpecificFields(
void ReshardingMetrics::restoreCoordinatorSpecificFields(
const ReshardingCoordinatorDocument& document) {
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
auto isSameKeyResharding =
document.getForceRedistribution() && *document.getForceRedistribution();
setIsSameKeyResharding(isSameKeyResharding);
@ -350,7 +350,7 @@ void ReshardingMetrics::restoreIndexBuildDurationFields(const ReshardingRecipien
void ReshardingMetrics::reportOnCompletion(BSONObjBuilder* builder) {
invariant(builder);
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
reportDurationsForAllPhases<Seconds>(
kTimedPhaseNamesMap, getClockSource(), builder, Seconds{0});
} else {

View File

@ -183,7 +183,7 @@ void buildStateDocumentApplyMetricsForUpdate(BSONObjBuilder& bob,
ReshardingMetrics* metrics,
Date_t timestamp) {
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
bob.append(
getIntervalEndFieldName<DocT>(ReshardingRecipientMetrics::kIndexBuildTimeFieldName),
timestamp);
@ -243,7 +243,7 @@ void setMeticsAfterWrite(ReshardingMetrics* metrics,
return;
case RecipientStateEnum::kApplying:
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
metrics->setEndFor(ReshardingMetrics::TimedPhase::kBuildingIndex, timestamp);
} else {
metrics->setEndFor(ReshardingMetrics::TimedPhase::kCloning, timestamp);
@ -414,7 +414,7 @@ ReshardingRecipientService::RecipientStateMachine::_notifyCoordinatorAndAwaitDec
->withAutomaticRetry([this, executor](const auto& factory) {
auto opCtx = factory.makeOperationContext(&cc());
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
{
AutoGetCollection coll(opCtx.get(), _metadata.getTempReshardingNss(), MODE_IS);
if (coll) {
@ -700,7 +700,7 @@ void ReshardingRecipientService::RecipientStateMachine::
opCtx.get(), _metadata, *_cloneTimestamp);
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
_externalState->withShardVersionRetry(
opCtx.get(),
_metadata.getSourceNss(),
@ -864,7 +864,7 @@ ReshardingRecipientService::RecipientStateMachine::_cloneThenTransitionToBuildin
.thenRunOn(**executor)
.then([this, &factory] {
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
_transitionToBuildingIndex(factory);
} else {
_transitionToApplying(factory);
@ -1070,10 +1070,11 @@ void ReshardingRecipientService::RecipientStateMachine::_cleanupReshardingCollec
if (aborted) {
if (feature_flags::gGlobalIndexesShardingCatalog.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
dropCollectionShardingIndexCatalog(opCtx.get(), _metadata.getTempReshardingNss());
}
{
// We need to do this even though the feature flag is not on because the resharding can
// be aborted by setFCV downgrade, when the FCV is already in downgrading and the
@ -1099,7 +1100,7 @@ void ReshardingRecipientService::RecipientStateMachine::_cleanupReshardingCollec
}
if (resharding::gFeatureFlagReshardingImprovements.isEnabled(
serverGlobalParams.featureCompatibility)) {
serverGlobalParams.featureCompatibility.acquireFCVSnapshot())) {
resharding::data_copy::deleteRecipientResumeData(opCtx.get(),
_metadata.getReshardingUUID());
}

Some files were not shown because too many files have changed in this diff Show More