summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/apply_ops.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/apply_ops.cpp')
-rw-r--r--src/mongo/db/repl/apply_ops.cpp41
1 files changed, 32 insertions, 9 deletions
diff --git a/src/mongo/db/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp
index 3d17a8c5291..f6651330cbe 100644
--- a/src/mongo/db/repl/apply_ops.cpp
+++ b/src/mongo/db/repl/apply_ops.cpp
@@ -58,6 +58,7 @@ namespace mongo {
namespace {
const auto kPreconditionFieldName = "preCondition"_sd;
+const auto kOplogApplicationModeFieldName = "oplogApplicationMode"_sd;
// If enabled, causes loop in _applyOps() to hang after applying current operation.
MONGO_FP_DECLARE(applyOpsPauseBetweenOperations);
@@ -115,6 +116,30 @@ Status _applyOps(OperationContext* opCtx,
applyOpCmd.hasField("alwaysUpsert") ? applyOpCmd["alwaysUpsert"].trueValue() : true;
const bool haveWrappingWUOW = opCtx->lockState()->inAWriteUnitOfWork();
+ // TODO (SERVER-31384): This code is run when applying 'applyOps' oplog entries. Pass through
+ // oplog application mode from applyCommand_inlock as default and consider proper behavior
+ // if default differs from oplog entry.
+ repl::OplogApplication::Mode oplogApplicationMode = repl::OplogApplication::Mode::kApplyOps;
+ std::string oplogApplicationModeString;
+ auto status = bsonExtractStringField(
+ applyOpCmd, kOplogApplicationModeFieldName, &oplogApplicationModeString);
+ if (status.isOK()) {
+ auto modeSW = repl::OplogApplication::parseMode(oplogApplicationModeString);
+ if (!modeSW.isOK()) {
+ return Status(modeSW.getStatus().code(),
+ str::stream() << "Could not parse " << kOplogApplicationModeFieldName
+ << ": "
+ << modeSW.getStatus().reason());
+ }
+ oplogApplicationMode = modeSW.getValue();
+ } else if (status != ErrorCodes::NoSuchKey) {
+ // NoSuchKey means the user did not supply a mode.
+ return Status(status.code(),
+ str::stream() << "Could not parse out " << kOplogApplicationModeFieldName
+ << ": "
+ << status.reason());
+ }
+
while (i.more()) {
BSONElement e = i.next();
const BSONObj& opObj = e.Obj();
@@ -172,17 +197,19 @@ Status _applyOps(OperationContext* opCtx,
OldClientContext ctx(opCtx, nss.ns());
status = repl::applyOperation_inlock(
- opCtx, ctx.db(), opObj, alwaysUpsert, repl::OplogApplication::Mode::kApplyOps);
+ opCtx, ctx.db(), opObj, alwaysUpsert, oplogApplicationMode);
if (!status.isOK())
return status;
} else {
try {
status = writeConflictRetry(
- opCtx, "applyOps", nss.ns(), [opCtx, nss, opObj, opType, alwaysUpsert] {
+ opCtx,
+ "applyOps",
+ nss.ns(),
+ [opCtx, nss, opObj, opType, alwaysUpsert, oplogApplicationMode] {
if (*opType == 'c') {
invariant(opCtx->lockState()->isW());
- return repl::applyCommand_inlock(
- opCtx, opObj, repl::OplogApplication::Mode::kApplyOps);
+ return repl::applyCommand_inlock(opCtx, opObj, oplogApplicationMode);
}
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
@@ -204,11 +231,7 @@ Status _applyOps(OperationContext* opCtx,
if (!nss.isSystemDotIndexes()) {
return repl::applyOperation_inlock(
- opCtx,
- ctx.db(),
- opObj,
- alwaysUpsert,
- repl::OplogApplication::Mode::kApplyOps);
+ opCtx, ctx.db(), opObj, alwaysUpsert, oplogApplicationMode);
}
auto fieldO = opObj["o"];