diff options
author | Suganthi Mani <suganthi.mani@mongodb.com> | 2019-08-26 15:03:15 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-08-26 15:03:15 +0000 |
commit | 4197e3c394abea7d01084e035a6ce8af32dc1161 (patch) | |
tree | ee85e3dd0724a1d4384b893d082a35d28c236ee7 /src/mongo | |
parent | aaa9874e04dbc2a4a33aeb7bfad9bee60f7145e0 (diff) | |
download | mongo-4197e3c394abea7d01084e035a6ce8af32dc1161.tar.gz |
SERVER-39996 Moved setting ignorePrepared behavior outside of waitForReadConcern.
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/run_aggregate.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/read_concern.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/read_concern.h | 21 | ||||
-rw-r--r-- | src/mongo/db/read_concern_mongod.cpp | 50 | ||||
-rw-r--r-- | src/mongo/db/s/migration_source_manager.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_common.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_common.h | 2 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_mongod.cpp | 17 | ||||
-rw-r--r-- | src/mongo/embedded/read_concern_embedded.cpp | 9 | ||||
-rw-r--r-- | src/mongo/embedded/service_entry_point_embedded.cpp | 15 |
10 files changed, 79 insertions, 47 deletions
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp index 6b915fc5329..bf6b65c13f4 100644 --- a/src/mongo/db/commands/run_aggregate.cpp +++ b/src/mongo/db/commands/run_aggregate.cpp @@ -402,8 +402,9 @@ void _adjustChangeStreamReadConcern(OperationContext* opCtx) { } // Wait for read concern again since we changed the original read concern. - uassertStatusOK(waitForReadConcern( - opCtx, readConcernArgs, true, PrepareConflictBehavior::kIgnoreConflicts)); + uassertStatusOK(waitForReadConcern(opCtx, readConcernArgs, true)); + setPrepareConflictBehaviorForReadConcern( + opCtx, readConcernArgs, PrepareConflictBehavior::kIgnoreConflicts); } /** diff --git a/src/mongo/db/read_concern.cpp b/src/mongo/db/read_concern.cpp index 4c6ce40747b..1ddbf1dcefc 100644 --- a/src/mongo/db/read_concern.cpp +++ b/src/mongo/db/read_concern.cpp @@ -31,6 +31,7 @@ namespace mongo { +MONGO_DEFINE_SHIM(setPrepareConflictBehaviorForReadConcern); MONGO_DEFINE_SHIM(waitForReadConcern); MONGO_DEFINE_SHIM(waitForLinearizableReadConcern); MONGO_DEFINE_SHIM(waitForSpeculativeMajorityReadConcern); diff --git a/src/mongo/db/read_concern.h b/src/mongo/db/read_concern.h index c9ac7f08e1c..cdb4a968682 100644 --- a/src/mongo/db/read_concern.h +++ b/src/mongo/db/read_concern.h @@ -45,16 +45,29 @@ class SpeculativeMajorityReadInfo; } // namespace repl /** + * Sets the prepare conflict behavior for a command. + * + * If the prepareConflictBehavior requested is to ignore prepare conflicts, then readConcernArgs + * are used to verify if the command is safe to ignore prepare conflicts, and if not, we + * enforce prepare conflicts. + */ +extern MONGO_DECLARE_SHIM((OperationContext * opCtx, + const repl::ReadConcernArgs& readConcernArgs, + PrepareConflictBehavior prepareConflictBehavior) + ->void) setPrepareConflictBehaviorForReadConcern; + +/** * Given the specified read concern arguments, performs checks that the read concern can actually be * satisfied given the current state of the server and if so calls into the replication subsystem to * perform the wait. If allowAfterClusterTime is false returns an error if afterClusterTime is - * set on the readConcernArgs. Both cmdName and readConcernArgs are used to determine whether or not - * prepare conflicts can be ignored. + * set on the readConcernArgs. + * + * Note: Callers should use setPrepareConflictBehaviorForReadConcern method to set the desired + * prepare conflict behavior for their command. */ extern MONGO_DECLARE_SHIM((OperationContext * opCtx, const repl::ReadConcernArgs& readConcernArgs, - bool allowAfterClusterTime, - PrepareConflictBehavior prepareConflictBehavior) + bool allowAfterClusterTime) ->Status) waitForReadConcern; /* diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp index b5ce3b2fdb9..60028d779f9 100644 --- a/src/mongo/db/read_concern_mongod.cpp +++ b/src/mongo/db/read_concern_mongod.cpp @@ -205,35 +205,50 @@ Status makeNoopWriteIfNeeded(OperationContext* opCtx, LogicalTime clusterTime) { } /** - * Returns the PrepareConflictBehavior that a command should use given the requested behavior and - * readConcern options. + * Evaluates if it's safe for the command to ignore prepare conflicts. */ -PrepareConflictBehavior getPrepareBehaviorForReadConcern( - PrepareConflictBehavior requestedBehavior, - repl::ReadConcernLevel readConcernLevel, - boost::optional<LogicalTime> afterClusterTime, - boost::optional<LogicalTime> atClusterTime) { - +bool canIgnorePrepareConflicts(const repl::ReadConcernArgs& readConcernArgs) { + auto readConcernLevel = readConcernArgs.getLevel(); // Only these read concern levels are eligible for ignoring prepare conflicts. if (readConcernLevel != repl::ReadConcernLevel::kLocalReadConcern && readConcernLevel != repl::ReadConcernLevel::kAvailableReadConcern && readConcernLevel != repl::ReadConcernLevel::kMajorityReadConcern) { - return PrepareConflictBehavior::kEnforce; + return false; } + auto afterClusterTime = readConcernArgs.getArgsAfterClusterTime(); + auto atClusterTime = readConcernArgs.getArgsAtClusterTime(); + if (afterClusterTime || atClusterTime) { - return PrepareConflictBehavior::kEnforce; + return false; } - return requestedBehavior; + return true; } + } // namespace -MONGO_REGISTER_SHIM(waitForReadConcern) +MONGO_REGISTER_SHIM(setPrepareConflictBehaviorForReadConcern) (OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs, - bool allowAfterClusterTime, PrepareConflictBehavior prepareConflictBehavior) + ->void { + // DBDirectClient should inherit whether or not to ignore prepare conflicts from its parent. + if (opCtx->getClient()->isInDirectClient()) { + return; + } + + // Enforce prepare conflict behavior if the command is not eligible to ignore prepare conflicts. + if (!(prepareConflictBehavior == PrepareConflictBehavior::kEnforce || + canIgnorePrepareConflicts(readConcernArgs))) { + prepareConflictBehavior = PrepareConflictBehavior::kEnforce; + } + + opCtx->recoveryUnit()->setPrepareConflictBehavior(prepareConflictBehavior); +} + +MONGO_REGISTER_SHIM(waitForReadConcern) +(OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs, bool allowAfterClusterTime) ->Status { // If we are in a direct client within a transaction, then we may be holding locks, so it is // illegal to wait for read concern. This is fine, since the outer operation should have handled @@ -363,15 +378,6 @@ MONGO_REGISTER_SHIM(waitForReadConcern) LOG(debugLevel) << "Using 'committed' snapshot: " << CurOp::get(opCtx)->opDescription() << " with readTs: " << opCtx->recoveryUnit()->getPointInTimeReadTimestamp(); } - - // DBDirectClient should inherit whether or not to ignore prepare conflicts from its parent. - if (!opCtx->getClient()->isInDirectClient()) { - // Set whether this command should ignore prepare conflicts or not. - const auto behavior = getPrepareBehaviorForReadConcern( - prepareConflictBehavior, readConcernArgs.getLevel(), afterClusterTime, atClusterTime); - opCtx->recoveryUnit()->setPrepareConflictBehavior(behavior); - } - return Status::OK(); } diff --git a/src/mongo/db/s/migration_source_manager.cpp b/src/mongo/db/s/migration_source_manager.cpp index 022df3b0745..725af2a1ea7 100644 --- a/src/mongo/db/s/migration_source_manager.cpp +++ b/src/mongo/db/s/migration_source_manager.cpp @@ -275,8 +275,9 @@ Status MigrationSourceManager::startClone(OperationContext* opCtx) { auto const readConcernArgs = repl::ReadConcernArgs( replCoord->getMyLastAppliedOpTime(), repl::ReadConcernLevel::kLocalReadConcern); - uassertStatusOK( - waitForReadConcern(opCtx, readConcernArgs, false, PrepareConflictBehavior::kEnforce)); + uassertStatusOK(waitForReadConcern(opCtx, readConcernArgs, false)); + setPrepareConflictBehaviorForReadConcern( + opCtx, readConcernArgs, PrepareConflictBehavior::kEnforce); } Status startCloneStatus = _cloneDriver->startClone(opCtx); diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index c233891ccf4..c43fdfd1206 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -892,6 +892,7 @@ void execCommandDatabase(OperationContext* opCtx, } behaviors.waitForReadConcern(opCtx, invocation.get(), request); + behaviors.setPrepareConflictBehaviorForReadConcern(opCtx, invocation.get()); try { if (!runCommandImpl(opCtx, diff --git a/src/mongo/db/service_entry_point_common.h b/src/mongo/db/service_entry_point_common.h index 60fb5f9e2cb..87a6c178588 100644 --- a/src/mongo/db/service_entry_point_common.h +++ b/src/mongo/db/service_entry_point_common.h @@ -60,6 +60,8 @@ struct ServiceEntryPointCommon { public: virtual ~Hooks(); virtual bool lockedForWriting() const = 0; + virtual void setPrepareConflictBehaviorForReadConcern( + OperationContext* opCtx, const CommandInvocation* invocation) const = 0; virtual void waitForReadConcern(OperationContext* opCtx, const CommandInvocation* invocation, const OpMsgRequest& request) const = 0; diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index 5435e14b49a..5f769f4d2b2 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -64,17 +64,20 @@ public: return mongo::lockedForWriting(); } - void waitForReadConcern(OperationContext* opCtx, - const CommandInvocation* invocation, - const OpMsgRequest& request) const override { + void setPrepareConflictBehaviorForReadConcern( + OperationContext* opCtx, const CommandInvocation* invocation) const override { const auto prepareConflictBehavior = invocation->canIgnorePrepareConflicts() ? PrepareConflictBehavior::kIgnoreConflicts : PrepareConflictBehavior::kEnforce; + mongo::setPrepareConflictBehaviorForReadConcern( + opCtx, repl::ReadConcernArgs::get(opCtx), prepareConflictBehavior); + } - Status rcStatus = mongo::waitForReadConcern(opCtx, - repl::ReadConcernArgs::get(opCtx), - invocation->allowsAfterClusterTime(), - prepareConflictBehavior); + void waitForReadConcern(OperationContext* opCtx, + const CommandInvocation* invocation, + const OpMsgRequest& request) const override { + Status rcStatus = mongo::waitForReadConcern( + opCtx, repl::ReadConcernArgs::get(opCtx), invocation->allowsAfterClusterTime()); if (!rcStatus.isOK()) { if (ErrorCodes::isExceededTimeLimitError(rcStatus.code())) { diff --git a/src/mongo/embedded/read_concern_embedded.cpp b/src/mongo/embedded/read_concern_embedded.cpp index f8e367d0b74..dde836dca47 100644 --- a/src/mongo/embedded/read_concern_embedded.cpp +++ b/src/mongo/embedded/read_concern_embedded.cpp @@ -33,11 +33,14 @@ namespace mongo { -MONGO_REGISTER_SHIM(waitForReadConcern) +MONGO_REGISTER_SHIM(setPrepareConflictBehaviorForReadConcern) (OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs, - bool allowAfterClusterTime, - PrepareConflictBehavior prepareConflictBehavior) + PrepareConflictBehavior requestedPrepareConflictBehavior) + ->void {} + +MONGO_REGISTER_SHIM(waitForReadConcern) +(OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs, bool allowAfterClusterTime) ->Status { if (readConcernArgs.getLevel() == repl::ReadConcernLevel::kLinearizableReadConcern) { return {ErrorCodes::NotImplemented, "linearizable read concern not supported on embedded"}; diff --git a/src/mongo/embedded/service_entry_point_embedded.cpp b/src/mongo/embedded/service_entry_point_embedded.cpp index d8d3f55c236..3ce0db7ef7d 100644 --- a/src/mongo/embedded/service_entry_point_embedded.cpp +++ b/src/mongo/embedded/service_entry_point_embedded.cpp @@ -47,16 +47,17 @@ public: return false; } + void setPrepareConflictBehaviorForReadConcern( + OperationContext* opCtx, const CommandInvocation* invocation) const override { + mongo::setPrepareConflictBehaviorForReadConcern( + opCtx, repl::ReadConcernArgs::get(opCtx), PrepareConflictBehavior::kEnforce); + } + void waitForReadConcern(OperationContext* opCtx, const CommandInvocation* invocation, const OpMsgRequest& request) const override { - const auto prepareConflictBehavior = invocation->canIgnorePrepareConflicts() - ? PrepareConflictBehavior::kIgnoreConflicts - : PrepareConflictBehavior::kEnforce; - auto rcStatus = mongo::waitForReadConcern(opCtx, - repl::ReadConcernArgs::get(opCtx), - invocation->allowsAfterClusterTime(), - prepareConflictBehavior); + auto rcStatus = mongo::waitForReadConcern( + opCtx, repl::ReadConcernArgs::get(opCtx), invocation->allowsAfterClusterTime()); uassertStatusOK(rcStatus); } |