summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuganthi Mani <suganthi.mani@mongodb.com>2019-08-26 15:03:15 +0000
committerevergreen <evergreen@mongodb.com>2019-08-26 15:03:15 +0000
commit4197e3c394abea7d01084e035a6ce8af32dc1161 (patch)
treeee85e3dd0724a1d4384b893d082a35d28c236ee7
parentaaa9874e04dbc2a4a33aeb7bfad9bee60f7145e0 (diff)
downloadmongo-4197e3c394abea7d01084e035a6ce8af32dc1161.tar.gz
SERVER-39996 Moved setting ignorePrepared behavior outside of waitForReadConcern.
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp5
-rw-r--r--src/mongo/db/read_concern.cpp1
-rw-r--r--src/mongo/db/read_concern.h21
-rw-r--r--src/mongo/db/read_concern_mongod.cpp50
-rw-r--r--src/mongo/db/s/migration_source_manager.cpp5
-rw-r--r--src/mongo/db/service_entry_point_common.cpp1
-rw-r--r--src/mongo/db/service_entry_point_common.h2
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp17
-rw-r--r--src/mongo/embedded/read_concern_embedded.cpp9
-rw-r--r--src/mongo/embedded/service_entry_point_embedded.cpp15
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);
}