diff options
Diffstat (limited to 'src/mongo/db/service_entry_point_common.cpp')
-rw-r--r-- | src/mongo/db/service_entry_point_common.cpp | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index a7fb9c60ce3..b5c8bfd4d83 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -69,6 +69,7 @@ #include "mongo/db/repl/optime.h" #include "mongo/db/repl/read_concern_args.h" #include "mongo/db/repl/repl_client_info.h" +#include "mongo/db/repl/repl_server_parameters_gen.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/repl/speculative_majority_read_info.h" #include "mongo/db/repl/storage_interface.h" @@ -358,12 +359,28 @@ StatusWith<repl::ReadConcernArgs> _extractReadConcern(OperationContext* opCtx, bool clientSuppliedReadConcern = readConcernArgs.isSpecified(); bool customDefaultWasApplied = false; - auto readConcernSupport = invocation->supportsReadConcern(readConcernArgs.getLevel()); - if (readConcernSupport.defaultReadConcernPermit.isOK() && - (startTransaction || !opCtx->inMultiDocumentTransaction()) && + auto readConcernSupport = invocation->supportsReadConcern(readConcernArgs.getLevel(), + readConcernArgs.isImplicitDefault()); + + auto applyDefaultReadConcern = [&](const repl::ReadConcernArgs rcDefault) -> void { + LOGV2_DEBUG(21955, + 2, + "Applying default readConcern on {command} of {readConcernDefault} " + "on {command}", + "Applying default readConcern on command", + "readConcernDefault"_attr = rcDefault, + "command"_attr = invocation->definition()->getName()); + readConcernArgs = std::move(rcDefault); + // Update the readConcernSupport, since the default RC was applied. + readConcernSupport = + invocation->supportsReadConcern(readConcernArgs.getLevel(), !customDefaultWasApplied); + }; + + auto shouldApplyDefaults = (startTransaction || !opCtx->inMultiDocumentTransaction()) && repl::ReplicationCoordinator::get(opCtx)->isReplEnabled() && - !opCtx->getClient()->isInDirectClient()) { + !opCtx->getClient()->isInDirectClient(); + if (readConcernSupport.defaultReadConcernPermit.isOK() && shouldApplyDefaults) { if (isInternalClient) { // ReadConcern should always be explicitly specified by operations received from // internal clients (ie. from a mongos or mongod), even if it is empty (ie. @@ -386,26 +403,35 @@ StatusWith<repl::ReadConcernArgs> _extractReadConcern(OperationContext* opCtx, // which is to apply the CWRWC defaults if present. This means we just test isEmpty(), // since this covers both isSpecified() && !isSpecified() if (readConcernArgs.isEmpty()) { - const auto rcDefault = ReadWriteConcernDefaults::get(opCtx->getServiceContext()) - .getDefaultReadConcern(opCtx); + const auto rwcDefaults = + ReadWriteConcernDefaults::get(opCtx->getServiceContext()).getDefault(opCtx); + const auto rcDefault = rwcDefaults.getDefaultReadConcern(); if (rcDefault) { - customDefaultWasApplied = true; - readConcernArgs = std::move(*rcDefault); - LOGV2_DEBUG(21955, - 2, - "Applying default readConcern on {command} of {readConcernDefault} " - "on {command}", - "Applying default readConcern on command", - "readConcernDefault"_attr = *rcDefault, - "command"_attr = invocation->definition()->getName()); - // Update the readConcernSupport, since the default RC was applied. - readConcernSupport = - invocation->supportsReadConcern(readConcernArgs.getLevel()); + const bool isDefaultRCLocalFeatureFlagEnabled = + serverGlobalParams.featureCompatibility.isVersionInitialized() && + repl::feature_flags::gDefaultRCLocal.isEnabled( + serverGlobalParams.featureCompatibility); + const auto readConcernSource = rwcDefaults.getDefaultReadConcernSource(); + customDefaultWasApplied = !isDefaultRCLocalFeatureFlagEnabled || + (readConcernSource && + readConcernSource.get() == DefaultReadConcernSourceEnum::kGlobal); + + applyDefaultReadConcern(*rcDefault); } } } } + // Apply the implicit default read concern even if the command does not support a cluster wide + // read concern. + if (!readConcernSupport.defaultReadConcernPermit.isOK() && + readConcernSupport.implicitDefaultReadConcernPermit.isOK() && shouldApplyDefaults && + !isInternalClient && readConcernArgs.isEmpty()) { + auto rcDefault = ReadWriteConcernDefaults::get(opCtx->getServiceContext()) + .getImplicitDefaultReadConcern(); + applyDefaultReadConcern(rcDefault); + } + // It's fine for clients to provide any provenance value to mongod. But if they haven't, then an // appropriate provenance needs to be determined. auto& provenance = readConcernArgs.getProvenance(); @@ -987,7 +1013,8 @@ void CheckoutSessionAndInvokeCommand::_checkOutSession() { // `createIndexes` do not support readConcern inside transactions. // TODO(SERVER-46971): Consider how to extend this check to other commands. auto cmdName = command->getName(); - auto readConcernSupport = invocation->supportsReadConcern(readConcernArgs.getLevel()); + auto readConcernSupport = invocation->supportsReadConcern( + readConcernArgs.getLevel(), readConcernArgs.isImplicitDefault()); if (readConcernArgs.hasLevel() && (cmdName == "create"_sd || cmdName == "createIndexes"_sd)) { if (!readConcernSupport.readConcernSupport.isOK()) { |