summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Shuvalov <andrew.shuvalov@mongodb.com>2021-05-24 23:12:15 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-24 23:32:10 +0000
commit8b9eaa903128dea6c70093bddd8d2a241473ac24 (patch)
tree8d5f1d8a7cb3b6cd2eab886432ba00a4c648fffd
parent5c6ba3aeb114334ab037dedfa39ee6e0aa540d4c (diff)
downloadmongo-8b9eaa903128dea6c70093bddd8d2a241473ac24.tar.gz
SERVER-56375: [RRFaM] BACKPORT-8905 Have delete path write to config.transactions
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/op_observer_impl.cpp50
-rw-r--r--src/mongo/db/ops/delete.cpp20
-rw-r--r--src/mongo/db/ops/delete.h11
-rw-r--r--src/mongo/db/repl/oplog.cpp20
5 files changed, 83 insertions, 19 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 0736608db0f..30058745a85 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -761,6 +761,7 @@ env.Library(
'session_catalog',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/repl/repl_server_parameters',
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/mongo/idl/server_parameter',
'$BUILD_DIR/mongo/util/concurrency/thread_pool',
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index e0df138b418..8d01ddd1583 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -171,22 +171,6 @@ struct OpTimeBundle {
Date_t wallClockTime;
};
-void writeToImagesCollection(OperationContext* opCtx,
- BSONObj image,
- repl::RetryImageEnum imageKind,
- Timestamp ts) {
- repl::ImageEntry imageEntry;
- invariant(opCtx->getLogicalSessionId());
- imageEntry.set_id(*opCtx->getLogicalSessionId());
- imageEntry.setTs(ts);
- imageEntry.setImage(std::move(image));
- imageEntry.setImageKind(imageKind);
- repl::UnreplicatedWritesBlock unreplicated(opCtx);
- AutoGetCollection imageCollectionRaii(
- opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX);
- Helpers::upsert(opCtx, NamespaceString::kConfigImagesNamespace.toString(), imageEntry.toBSON());
-}
-
/**
* Write oplog entry(ies) for the update operation.
*/
@@ -354,6 +338,25 @@ OpTimeBundle replLogApplyOps(OperationContext* opCtx,
return times;
}
+void writeToImageCollection(OperationContext* opCtx,
+ const LogicalSessionId& sessionId,
+ const Timestamp timestamp,
+ repl::RetryImageEnum imageKind,
+ const BSONObj& dataImage) {
+ repl::ImageEntry imageEntry;
+ invariant(opCtx->getLogicalSessionId());
+ imageEntry.set_id(sessionId);
+ imageEntry.setTxnNumber(opCtx->getTxnNumber().get());
+ imageEntry.setTs(timestamp);
+ imageEntry.setImageKind(imageKind);
+ imageEntry.setImage(dataImage);
+
+ repl::UnreplicatedWritesBlock unreplicated(opCtx);
+ AutoGetCollection imageCollectionRaii(
+ opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX);
+ Helpers::upsert(opCtx, NamespaceString::kConfigImagesNamespace.toString(), imageEntry.toBSON());
+}
+
} // namespace
BSONObj OpObserverImpl::getDocumentKey(OperationContext* opCtx,
@@ -621,7 +624,11 @@ void OpObserverImpl::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArg
imageDoc = args.updateArgs.updatedDoc;
imageKind = repl::RetryImageEnum::kPostImage;
}
- writeToImagesCollection(opCtx, imageDoc, imageKind, opTime.writeOpTime.getTimestamp());
+ writeToImageCollection(opCtx,
+ *opCtx->getLogicalSessionId(),
+ opTime.writeOpTime.getTimestamp(),
+ imageKind,
+ imageDoc);
}
SessionTxnRecord sessionTxnRecord;
sessionTxnRecord.setLastWriteOpTime(opTime.writeOpTime);
@@ -687,6 +694,15 @@ void OpObserverImpl::onDelete(OperationContext* opCtx,
args.deletedDoc ? boost::optional<BSONObj>(*(args.deletedDoc)) : boost::none;
opTime = replLogDelete(
opCtx, nss, uuid, stmtId, args.fromMigrate, deletedDoc, storeImagesInSideCollection);
+
+ if (storeImagesInSideCollection && deletedDoc && opCtx->getTxnNumber()) {
+ writeToImageCollection(opCtx,
+ *opCtx->getLogicalSessionId(),
+ opTime.writeOpTime.getTimestamp(),
+ repl::RetryImageEnum::kPreImage,
+ *deletedDoc);
+ }
+
SessionTxnRecord sessionTxnRecord;
sessionTxnRecord.setLastWriteOpTime(opTime.writeOpTime);
sessionTxnRecord.setLastWriteDate(opTime.wallClockTime);
diff --git a/src/mongo/db/ops/delete.cpp b/src/mongo/db/ops/delete.cpp
index 3a95b360a47..78ee9f8d924 100644
--- a/src/mongo/db/ops/delete.cpp
+++ b/src/mongo/db/ops/delete.cpp
@@ -64,4 +64,24 @@ long long deleteObjects(OperationContext* opCtx,
return DeleteStage::getNumDeleted(*exec);
}
+DeleteResult deleteObject(OperationContext* opCtx,
+ Collection* collection,
+ const DeleteRequest& request) {
+ ParsedDelete parsedDelete(opCtx, &request);
+ uassertStatusOK(parsedDelete.parseRequest());
+
+ // This method doesn't support multi-deletes.
+ invariant(!request.isMulti());
+
+ auto exec = uassertStatusOK(
+ getExecutorDelete(opCtx, &CurOp::get(opCtx)->debug(), collection, &parsedDelete));
+
+ BSONObj docImage;
+ if (exec->getNext(&docImage, nullptr) == PlanExecutor::IS_EOF) {
+ return {};
+ }
+
+ return {1, request.shouldReturnDeleted() ? docImage.getOwned() : BSONObj()};
+}
+
} // namespace mongo
diff --git a/src/mongo/db/ops/delete.h b/src/mongo/db/ops/delete.h
index b26f583d460..c73c353ff86 100644
--- a/src/mongo/db/ops/delete.h
+++ b/src/mongo/db/ops/delete.h
@@ -30,6 +30,7 @@
#pragma once
#include "mongo/db/jsobj.h"
+#include "mongo/db/ops/delete_request.h"
#include "mongo/db/query/plan_executor.h"
@@ -50,4 +51,14 @@ long long deleteObjects(OperationContext* opCtx,
bool justOne,
bool god = false,
bool fromMigrate = false);
+
+struct DeleteResult {
+ long long nDeleted;
+ boost::optional<BSONObj> requestedPreImage;
+};
+
+DeleteResult deleteObject(OperationContext* opCtx,
+ Collection* collection,
+ const DeleteRequest& request);
+
} // namespace mongo
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 8e842732f86..cebb59e3990 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -68,6 +68,7 @@
#include "mongo/db/namespace_string.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/delete.h"
+#include "mongo/db/ops/delete_request.h"
#include "mongo/db/ops/update.h"
#include "mongo/db/repl/apply_ops.h"
#include "mongo/db/repl/bgsync.h"
@@ -1791,6 +1792,7 @@ Status applyOperation_inlock(OperationContext* opCtx,
}
const StringData ns = fieldNs.valueStringDataSafe();
+ bool upsertConfigImage = true;
writeConflictRetry(opCtx, "applyOps_delete", ns, [&] {
WriteUnitOfWork wuow(opCtx);
if (timestamp != Timestamp::min()) {
@@ -1798,8 +1800,22 @@ Status applyOperation_inlock(OperationContext* opCtx,
}
if (opType[1] == 0) {
- const auto justOne = true;
- deleteObjects(opCtx, collection, requestNss, deleteCriteria, justOne);
+ const bool kNeedsRetryImage =
+ op.hasField(OplogEntryBase::kNeedsRetryImageFieldName);
+ DeleteRequest request(requestNss);
+ request.setQuery(deleteCriteria);
+ if (kNeedsRetryImage) {
+ request.setReturnDeleted(true);
+ }
+
+ DeleteResult result = deleteObject(opCtx, collection, request);
+ if (result.nDeleted == 1 && kNeedsRetryImage) {
+ writeToImageCollection(opCtx,
+ op,
+ result.requestedPreImage.get(),
+ repl::RetryImageEnum::kPreImage,
+ &upsertConfigImage);
+ }
} else
verify(opType[1] == 'b'); // "db" advertisement
wuow.commit();