diff options
author | Jordi Serra Torrens <jordi.serra-torrens@mongodb.com> | 2022-09-28 10:11:50 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-11-04 18:50:12 +0000 |
commit | 53973727e253d8b797bc0b2a734326d4e3fdad6d (patch) | |
tree | d4cf0a1effcc98ab265b44317194658c975775b7 /src/mongo | |
parent | 05cf56be4fdfa33c88d47dfb48f95a60c9cc7e09 (diff) | |
download | mongo-53973727e253d8b797bc0b2a734326d4e3fdad6d.tar.gz |
SERVER-70043 Thread-through CollectionPtr into the onDelete OpObserver
Co-authored-by: Daniel Gómez Ferro <daniel.gomezferro@mongodb.com>
Diffstat (limited to 'src/mongo')
68 files changed, 443 insertions, 578 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 2b1b866efae..09f7d8e3cc9 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -551,6 +551,7 @@ env.CppUnitTest( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/client/sasl_client', '$BUILD_DIR/mongo/db/common', + '$BUILD_DIR/mongo/db/concurrency/exception_util', '$BUILD_DIR/mongo/db/pipeline/pipeline', '$BUILD_DIR/mongo/db/repl/oplog', '$BUILD_DIR/mongo/db/repl/oplog_interface_local', diff --git a/src/mongo/db/auth/auth_op_observer.cpp b/src/mongo/db/auth/auth_op_observer.cpp index a2ddfa79949..72a86220328 100644 --- a/src/mongo/db/auth/auth_op_observer.cpp +++ b/src/mongo/db/auth/auth_op_observer.cpp @@ -74,10 +74,9 @@ void AuthOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArg } void AuthOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - audit::logRemoveOperation(opCtx->getClient(), nss, doc); + audit::logRemoveOperation(opCtx->getClient(), coll->ns(), doc); // Extract the _id field from the document. If it does not have an _id, use the // document itself as the _id. @@ -85,14 +84,13 @@ void AuthOpObserver::aboutToDelete(OperationContext* opCtx, } void AuthOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { auto& documentId = documentIdDecoration(opCtx); invariant(!documentId.isEmpty()); AuthorizationManager::get(opCtx->getServiceContext()) - ->logOp(opCtx, "d", nss, documentId, nullptr); + ->logOp(opCtx, "d", coll->ns(), documentId, nullptr); } void AuthOpObserver::onCreateCollection(OperationContext* opCtx, diff --git a/src/mongo/db/auth/auth_op_observer.h b/src/mongo/db/auth/auth_op_observer.h index 51d0e7c5af8..83dc89521d2 100644 --- a/src/mongo/db/auth/auth_op_observer.h +++ b/src/mongo/db/auth/auth_op_observer.h @@ -112,13 +112,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/auth/auth_op_observer_test.cpp b/src/mongo/db/auth/auth_op_observer_test.cpp index 831d9b6fb05..56d9e80c82e 100644 --- a/src/mongo/db/auth/auth_op_observer_test.cpp +++ b/src/mongo/db/auth/auth_op_observer_test.cpp @@ -32,6 +32,7 @@ #include "mongo/db/auth/auth_op_observer.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/client.h" +#include "mongo/db/concurrency/exception_util.h" #include "mongo/db/concurrency/locker_noop.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" @@ -74,8 +75,23 @@ public: // Ensure that we are primary. auto replCoord = repl::ReplicationCoordinator::get(opCtx.get()); ASSERT_OK(replCoord->setFollowerMode(repl::MemberState::RS_PRIMARY)); + + // Create test collection + writeConflictRetry(opCtx.get(), "createColl", _nss.ns(), [&] { + opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoTimestamp); + opCtx->recoveryUnit()->abandonSnapshot(); + + WriteUnitOfWork wunit(opCtx.get()); + AutoGetCollection collRaii(opCtx.get(), _nss, MODE_X); + + auto db = collRaii.ensureDbExists(opCtx.get()); + invariant(db->createCollection(opCtx.get(), _nss, {})); + wunit.commit(); + }); } + NamespaceString _nss = {"test", "coll"}; + private: // Creates a reasonable set of ReplSettings for most tests. We need to be able to // override this to create a larger oplog. @@ -127,16 +143,15 @@ TEST_F(AuthOpObserverTest, OnRollbackDoesntInvalidateAuthCacheWhenNoAuthNamespac } TEST_F(AuthOpObserverTest, MultipleAboutToDeleteAndOnDelete) { - auto uuid = UUID::gen(); AuthOpObserver opObserver; auto opCtx = cc().makeOperationContext(); NamespaceString nss = {"test", "coll"}; - AutoGetDb autoDb(opCtx.get(), nss.dbName(), MODE_X); WriteUnitOfWork wunit(opCtx.get()); - opObserver.aboutToDelete(opCtx.get(), nss, uuid, BSON("_id" << 1)); - opObserver.onDelete(opCtx.get(), nss, uuid, {}, {}); - opObserver.aboutToDelete(opCtx.get(), nss, uuid, BSON("_id" << 1)); - opObserver.onDelete(opCtx.get(), nss, uuid, {}, {}); + AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX); + opObserver.aboutToDelete(opCtx.get(), *autoColl, BSON("_id" << 1)); + opObserver.onDelete(opCtx.get(), *autoColl, {}, {}); + opObserver.aboutToDelete(opCtx.get(), *autoColl, BSON("_id" << 1)); + opObserver.onDelete(opCtx.get(), *autoColl, {}, {}); } DEATH_TEST_F(AuthOpObserverTest, AboutToDeleteMustPreceedOnDelete, "invariant") { @@ -144,18 +159,18 @@ DEATH_TEST_F(AuthOpObserverTest, AboutToDeleteMustPreceedOnDelete, "invariant") auto opCtx = cc().makeOperationContext(); cc().swapLockState(std::make_unique<LockerNoop>()); NamespaceString nss = {"test", "coll"}; - opObserver.onDelete(opCtx.get(), nss, UUID::gen(), {}, {}); + AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX); + opObserver.onDelete(opCtx.get(), *autoColl, {}, {}); } DEATH_TEST_F(AuthOpObserverTest, EachOnDeleteRequiresAboutToDelete, "invariant") { - auto uuid = UUID::gen(); AuthOpObserver opObserver; auto opCtx = cc().makeOperationContext(); cc().swapLockState(std::make_unique<LockerNoop>()); - NamespaceString nss = {"test", "coll"}; - opObserver.aboutToDelete(opCtx.get(), nss, uuid, {}); - opObserver.onDelete(opCtx.get(), nss, uuid, {}, {}); - opObserver.onDelete(opCtx.get(), nss, uuid, {}, {}); + AutoGetCollection autoColl(opCtx.get(), _nss, MODE_IX); + opObserver.aboutToDelete(opCtx.get(), *autoColl, {}); + opObserver.onDelete(opCtx.get(), *autoColl, {}, {}); + opObserver.onDelete(opCtx.get(), *autoColl, {}, {}); } } // namespace diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript index 302d3782c72..d2ed66fe1b9 100644 --- a/src/mongo/db/catalog/SConscript +++ b/src/mongo/db/catalog/SConscript @@ -224,6 +224,7 @@ env.Library( '$BUILD_DIR/mongo/db/record_id_helpers', '$BUILD_DIR/mongo/db/repl/repl_coordinator_interface', '$BUILD_DIR/mongo/db/storage/record_store_base', + '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/db/storage/write_unit_of_work', '$BUILD_DIR/mongo/util/fail_point', 'collection', diff --git a/src/mongo/db/catalog/capped_collection_maintenance.cpp b/src/mongo/db/catalog/capped_collection_maintenance.cpp index 99095748188..1c79fad50ef 100644 --- a/src/mongo/db/catalog/capped_collection_maintenance.cpp +++ b/src/mongo/db/catalog/capped_collection_maintenance.cpp @@ -83,7 +83,6 @@ void cappedDeleteUntilBelowConfiguredMaximum(OperationContext* opCtx, return; const auto& nss = collection->ns(); - const auto& uuid = collection->uuid(); auto& ccs = cappedCollectionState(*collection->getSharedDecorations()); stdx::unique_lock<Latch> cappedFirstRecordMutex(ccs.cappedFirstRecordMutex, stdx::defer_lock); @@ -157,7 +156,7 @@ void cappedDeleteUntilBelowConfiguredMaximum(OperationContext* opCtx, BSONObj doc = record->data.toBson(); if (nss.isReplicated()) { OpObserver* opObserver = opCtx->getServiceContext()->getOpObserver(); - opObserver->aboutToDelete(opCtx, nss, uuid, doc); + opObserver->aboutToDelete(opCtx, collection, doc); OplogDeleteEntryArgs args; // Explicitly setting values despite them being the defaults. @@ -172,7 +171,7 @@ void cappedDeleteUntilBelowConfiguredMaximum(OperationContext* opCtx, } // Reserves an optime for the deletion and sets the timestamp for future writes. - opObserver->onDelete(opCtx, nss, uuid, kUninitializedStmtId, args); + opObserver->onDelete(opCtx, collection, kUninitializedStmtId, args); } int64_t unusedKeysDeleted = 0; diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index 76905a8fe6f..23b0170d01d 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -110,8 +110,6 @@ public: class Collection : public Decorable<Collection> { public: - enum class StoreDeletedDoc { Off, On }; - /** * Direction of collection scan plan executor returned by makePlanExecutor(). */ @@ -314,44 +312,6 @@ public: virtual std::unique_ptr<SeekableRecordCursor> getCursor(OperationContext* opCtx, bool forward = true) const = 0; - /** - * Deletes the document with the given RecordId from the collection. For a description of the - * parameters, see the overloaded function below. - */ - virtual void deleteDocument(OperationContext* opCtx, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - StoreDeletedDoc storeDeletedDoc = StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const = 0; - - /** - * Deletes the document from the collection. - * - * 'doc' the document to be deleted. - * 'fromMigrate' indicates whether the delete was induced by a chunk migration, and - * so should be ignored by the user as an internal maintenance operation and not a - * real delete. - * 'loc' key to uniquely identify a record in a collection. - * 'opDebug' Optional argument. When not null, will be used to record operation statistics. - * 'noWarn' if unindexing the record causes an error, if noWarn is true the error - * will not be logged. - * 'storeDeletedDoc' whether to store the document deleted in the oplog. - * 'checkRecordId' whether to confirm the recordId matches the record we are removing when - * unindexing. - */ - virtual void deleteDocument(OperationContext* opCtx, - Snapshotted<BSONObj> doc, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - StoreDeletedDoc storeDeletedDoc = StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const = 0; - virtual bool updateWithDamagesSupported() const = 0; diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index 59697e3073f..76b3c1a0119 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -59,7 +59,6 @@ #include "mongo/db/repl/oplog.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/durable_catalog.h" -#include "mongo/db/storage/storage_parameters_gen.h" #include "mongo/db/timeseries/timeseries_constants.h" #include "mongo/db/timeseries/timeseries_extended_range.h" #include "mongo/db/timeseries/timeseries_index_schema_conversion_functions.h" @@ -173,25 +172,6 @@ bool isRetryableWrite(OperationContext* opCtx) { (!opCtx->inMultiDocumentTransaction() || txnParticipant.transactionIsOpen()); } -// TODO(SERVER-70043) remove after that ticket is fixed -std::vector<OplogSlot> reserveOplogSlotsForRetryableFindAndModify(OperationContext* opCtx) { - invariant(isRetryableWrite(opCtx)); - - // For retryable findAndModify running in a multi-document transaction, we will reserve the - // oplog entries when the transaction prepares or commits without prepare. - if (opCtx->inMultiDocumentTransaction()) { - return {}; - } - - // We reserve oplog slots here, expecting the slot with the greatest timestmap (say TS) to be - // used as the oplog timestamp. Tenant migrations and resharding will forge no-op image oplog - // entries and set the timestamp for these synthetic entries to be TS - 1. - auto oplogInfo = LocalOplogInfo::get(opCtx); - auto slots = oplogInfo->getNextOpTimes(opCtx, 2); - uassertStatusOK(opCtx->recoveryUnit()->setTimestamp(slots.back().getTimestamp())); - return slots; -} - bool indexTypeSupportsPathLevelMultikeyTracking(StringData accessMethod) { return accessMethod == IndexNames::BTREE || accessMethod == IndexNames::GEO_2DSPHERE; } @@ -795,84 +775,6 @@ void CollectionImpl::setMinimumValidSnapshot(Timestamp newMinimumValidSnapshot) } } -void CollectionImpl::deleteDocument(OperationContext* opCtx, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate, - bool noWarn, - Collection::StoreDeletedDoc storeDeletedDoc, - CheckRecordId checkRecordId) const { - Snapshotted<BSONObj> doc = docFor(opCtx, loc); - deleteDocument( - opCtx, doc, stmtId, loc, opDebug, fromMigrate, noWarn, storeDeletedDoc, checkRecordId); -} - -void CollectionImpl::deleteDocument(OperationContext* opCtx, - Snapshotted<BSONObj> doc, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate, - bool noWarn, - Collection::StoreDeletedDoc storeDeletedDoc, - CheckRecordId checkRecordId) const { - if (isCapped() && opCtx->inMultiDocumentTransaction()) { - uasserted(ErrorCodes::IllegalOperation, - "Cannot remove from a capped collection in a multi-document transaction"); - } - - if (needsCappedLock()) { - Lock::ResourceLock heldUntilEndOfWUOW{opCtx, ResourceId(RESOURCE_METADATA, _ns), MODE_X}; - } - - std::vector<OplogSlot> oplogSlots; - auto retryableFindAndModifyLocation = RetryableFindAndModifyLocation::kNone; - if (storeDeletedDoc == Collection::StoreDeletedDoc::On && isRetryableWrite(opCtx)) { - retryableFindAndModifyLocation = RetryableFindAndModifyLocation::kSideCollection; - oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx); - } - OplogDeleteEntryArgs deleteArgs{nullptr /* deletedDoc */, - fromMigrate, - isChangeStreamPreAndPostImagesEnabled(), - retryableFindAndModifyLocation, - oplogSlots}; - - opCtx->getServiceContext()->getOpObserver()->aboutToDelete(opCtx, ns(), uuid(), doc.value()); - - boost::optional<BSONObj> deletedDoc; - const bool isRecordingPreImageForRetryableWrite = - retryableFindAndModifyLocation != RetryableFindAndModifyLocation::kNone; - - if (isRecordingPreImageForRetryableWrite || isChangeStreamPreAndPostImagesEnabled()) { - deletedDoc.emplace(doc.value().getOwned()); - } - int64_t keysDeleted = 0; - _indexCatalog->unindexRecord(opCtx, - CollectionPtr(this, CollectionPtr::NoYieldTag{}), - doc.value(), - loc, - noWarn, - &keysDeleted, - checkRecordId); - _shared->_recordStore->deleteRecord(opCtx, loc); - if (deletedDoc) { - deleteArgs.deletedDoc = &(deletedDoc.value()); - } - - opCtx->getServiceContext()->getOpObserver()->onDelete(opCtx, ns(), uuid(), stmtId, deleteArgs); - - if (opDebug) { - opDebug->additiveMetrics.incrementKeysDeleted(keysDeleted); - // 'opDebug' may be deleted at rollback time in case of multi-document transaction. - if (!opCtx->inMultiDocumentTransaction()) { - opCtx->recoveryUnit()->onRollback([opDebug, keysDeleted]() { - opDebug->additiveMetrics.incrementKeysDeleted(-keysDeleted); - }); - } - } -} - bool CollectionImpl::updateWithDamagesSupported() const { if (!_validator.isOK() || _validator.filter.getValue() != nullptr) return false; diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h index 46c2a3bb6be..c588d4f8614 100644 --- a/src/mongo/db/catalog/collection_impl.h +++ b/src/mongo/db/catalog/collection_impl.h @@ -149,48 +149,6 @@ public: std::unique_ptr<SeekableRecordCursor> getCursor(OperationContext* opCtx, bool forward = true) const final; - /** - * Deletes the document with the given RecordId from the collection. For a description of - * the parameters, see the overloaded function below. - */ - void deleteDocument( - OperationContext* opCtx, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - Collection::StoreDeletedDoc storeDeletedDoc = Collection::StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const final; - - /** - * Deletes the document from the collection. - - * 'doc' the document to be deleted. - * 'stmtId' the statement id for this delete operation. Pass in kUninitializedStmtId if not - * applicable. - * 'fromMigrate' indicates whether the delete was induced by a chunk migration, and - * so should be ignored by the user as an internal maintenance operation and not a - * real delete. - * 'loc' key to uniquely identify a record in a collection. - * 'opDebug' Optional argument. When not null, will be used to record operation statistics. - * 'noWarn' if unindexing the record causes an error, if noWarn is true the error - * will not be logged. - * 'storeDeletedDoc' whether to store the document deleted in the oplog. - * 'checkRecordId' whether to confirm the recordId matches the record we are removing when - * unindexing. - */ - void deleteDocument( - OperationContext* opCtx, - Snapshotted<BSONObj> doc, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - Collection::StoreDeletedDoc storeDeletedDoc = Collection::StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const final; - bool updateWithDamagesSupported() const final; // ----------- diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h index 7ff9e7d00d8..340e49b98f9 100644 --- a/src/mongo/db/catalog/collection_mock.h +++ b/src/mongo/db/catalog/collection_mock.h @@ -136,30 +136,6 @@ public: MONGO_UNREACHABLE; } - void deleteDocument(OperationContext* opCtx, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate, - bool noWarn, - Collection::StoreDeletedDoc storeDeletedDoc, - CheckRecordId checkRecordId) const { - MONGO_UNREACHABLE; - } - - void deleteDocument( - OperationContext* opCtx, - Snapshotted<BSONObj> doc, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - Collection::StoreDeletedDoc storeDeletedDoc = Collection::StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const { - MONGO_UNREACHABLE; - } - bool updateWithDamagesSupported() const { MONGO_UNREACHABLE; } diff --git a/src/mongo/db/catalog/collection_write_path.cpp b/src/mongo/db/catalog/collection_write_path.cpp index 38db9f4f22e..9a11ba7ce2a 100644 --- a/src/mongo/db/catalog/collection_write_path.cpp +++ b/src/mongo/db/catalog/collection_write_path.cpp @@ -36,6 +36,8 @@ #include "mongo/db/catalog/local_oplog_info.h" #include "mongo/db/concurrency/exception_util.h" #include "mongo/db/op_observer/op_observer.h" +#include "mongo/db/storage/storage_parameters_gen.h" +#include "mongo/db/transaction/transaction_participant.h" #include "mongo/logv2/log.h" #include "mongo/util/fail_point.h" @@ -80,8 +82,7 @@ bool compareSafeContentElem(const BSONObj& oldDoc, const BSONObj& newDoc) { return newDoc.getField(kSafeContent).binaryEqual(oldDoc.getField(kSafeContent)); } -std::vector<OplogSlot> reserveOplogSlotsForRetryableFindAndModify(OperationContext* opCtx, - const CollectionPtr& collection) { +std::vector<OplogSlot> reserveOplogSlotsForRetryableFindAndModify(OperationContext* opCtx) { // For retryable findAndModify running in a multi-document transaction, we will reserve the // oplog entries when the transaction prepares or commits without prepare. if (opCtx->inMultiDocumentTransaction()) { @@ -467,7 +468,7 @@ RecordId updateDocument(OperationContext* opCtx, // TS - 1: Tenant migrations and resharding will forge no-op image oplog entries and set // the entry timestamps to TS - 1. // TS: The timestamp given to the update oplog entry. - args->oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx, collection); + args->oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx); } else { // Retryable findAndModify commands should not reserve oplog slots before entering this // function since tenant migrations and resharding rely on always being able to set @@ -543,7 +544,7 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, // TS - 1: Tenant migrations and resharding will forge no-op image oplog entries and set // the entry timestamps to TS - 1. // TS: The timestamp given to the update oplog entry. - args->oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx, collection); + args->oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx); } else { // Retryable findAndModify commands should not reserve oplog slots before entering this // function since tenant migrations and resharding rely on always being able to set @@ -586,5 +587,98 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, return newDoc; } +void deleteDocument(OperationContext* opCtx, + const CollectionPtr& collection, + StmtId stmtId, + const RecordId& loc, + OpDebug* opDebug, + bool fromMigrate, + bool noWarn, + StoreDeletedDoc storeDeletedDoc, + CheckRecordId checkRecordId, + RetryableWrite retryableWrite) { + Snapshotted<BSONObj> doc = collection->docFor(opCtx, loc); + deleteDocument(opCtx, + collection, + doc, + stmtId, + loc, + opDebug, + fromMigrate, + noWarn, + storeDeletedDoc, + checkRecordId); +} + +void deleteDocument(OperationContext* opCtx, + const CollectionPtr& collection, + Snapshotted<BSONObj> doc, + StmtId stmtId, + const RecordId& loc, + OpDebug* opDebug, + bool fromMigrate, + bool noWarn, + StoreDeletedDoc storeDeletedDoc, + CheckRecordId checkRecordId, + RetryableWrite retryableWrite) { + const auto& nss = collection->ns(); + + if (collection->isCapped() && opCtx->inMultiDocumentTransaction()) { + uasserted(ErrorCodes::IllegalOperation, + "Cannot remove from a capped collection in a multi-document transaction"); + } + + if (collection->needsCappedLock()) { + Lock::ResourceLock heldUntilEndOfWUOW{opCtx, ResourceId(RESOURCE_METADATA, nss), MODE_X}; + } + + std::vector<OplogSlot> oplogSlots; + auto retryableFindAndModifyLocation = RetryableFindAndModifyLocation::kNone; + if (storeDeletedDoc == StoreDeletedDoc::On && retryableWrite == RetryableWrite::kYes) { + retryableFindAndModifyLocation = RetryableFindAndModifyLocation::kSideCollection; + oplogSlots = reserveOplogSlotsForRetryableFindAndModify(opCtx); + } + OplogDeleteEntryArgs deleteArgs{nullptr /* deletedDoc */, + fromMigrate, + collection->isChangeStreamPreAndPostImagesEnabled(), + retryableFindAndModifyLocation, + oplogSlots}; + + opCtx->getServiceContext()->getOpObserver()->aboutToDelete(opCtx, collection, doc.value()); + + boost::optional<BSONObj> deletedDoc; + const bool isRecordingPreImageForRetryableWrite = + retryableFindAndModifyLocation != RetryableFindAndModifyLocation::kNone; + const bool isTimeseriesCollection = + collection->getTimeseriesOptions() || nss.isTimeseriesBucketsCollection(); + + if (isRecordingPreImageForRetryableWrite || + collection->isChangeStreamPreAndPostImagesEnabled() || + (isTimeseriesCollection && + feature_flags::gTimeseriesScalabilityImprovements.isEnabled( + serverGlobalParams.featureCompatibility))) { + deletedDoc.emplace(doc.value().getOwned()); + } + int64_t keysDeleted = 0; + collection->getIndexCatalog()->unindexRecord( + opCtx, collection, doc.value(), loc, noWarn, &keysDeleted, checkRecordId); + collection->getRecordStore()->deleteRecord(opCtx, loc); + if (deletedDoc) { + deleteArgs.deletedDoc = &(deletedDoc.value()); + } + + opCtx->getServiceContext()->getOpObserver()->onDelete(opCtx, collection, stmtId, deleteArgs); + + if (opDebug) { + opDebug->additiveMetrics.incrementKeysDeleted(keysDeleted); + // 'opDebug' may be deleted at rollback time in case of multi-document transaction. + if (!opCtx->inMultiDocumentTransaction()) { + opCtx->recoveryUnit()->onRollback([opDebug, keysDeleted]() { + opDebug->additiveMetrics.incrementKeysDeleted(-keysDeleted); + }); + } + } +} + } // namespace collection_internal } // namespace mongo diff --git a/src/mongo/db/catalog/collection_write_path.h b/src/mongo/db/catalog/collection_write_path.h index 9e0af1f0273..e492aef05ca 100644 --- a/src/mongo/db/catalog/collection_write_path.h +++ b/src/mongo/db/catalog/collection_write_path.h @@ -40,6 +40,10 @@ namespace collection_internal { using OnRecordInsertedFn = std::function<Status(const RecordId& loc)>; +enum class StoreDeletedDoc { Off, On }; + +enum class RetryableWrite { kYes, kNo }; + /** * Inserts a document into the record store for a bulk loader that manages the index building. The * bulk loader is notified with the RecordId of the document inserted into the RecordStore through @@ -89,8 +93,7 @@ Status checkFailCollectionInsertsFailPoint(const NamespaceString& ns, const BSON * Updates the document @ oldLocation with newDoc. * * If the document fits in the old space, it is put there; if not, it is moved. - * Sets 'args.updatedDoc' to the updated version of the document with damages applied, on - * success. + * Sets 'args.updatedDoc' to the updated version of the document with damages applied, on success. * 'opDebug' Optional argument. When not null, will be used to record operation statistics. * @return the post update location of the doc (may or may not be the same as oldLocation) */ @@ -105,8 +108,7 @@ RecordId updateDocument(OperationContext* opCtx, /** * Illegal to call if collection->updateWithDamagesSupported() returns false. - * Sets 'args.updatedDoc' to the updated version of the document with damages applied, on - * success. + * Sets 'args.updatedDoc' to the updated version of the document with damages applied, on success. * Returns the contents of the updated document. */ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, @@ -119,5 +121,47 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, OpDebug* opDebug, CollectionUpdateArgs* args); +/** + * Deletes the document with the given RecordId from the collection. For a description of the + * parameters, see the overloaded function below. + */ +void deleteDocument(OperationContext* opCtx, + const CollectionPtr& collection, + StmtId stmtId, + const RecordId& loc, + OpDebug* opDebug, + bool fromMigrate = false, + bool noWarn = false, + StoreDeletedDoc storeDeletedDoc = StoreDeletedDoc::Off, + CheckRecordId checkRecordId = CheckRecordId::Off, + RetryableWrite retryableWrite = RetryableWrite::kNo); + +/** + * Deletes the document from the collection. + * + * @param doc: the document to be deleted. + * @param fromMigrate: indicates whether the delete was induced by a chunk migration, and so should + * be ignored by the user as an internal maintenance operation and not a real delete. + * @param loc: key to uniquely identify a record in a collection. + * @param opDebug: Optional argument. When not null, will be used to record operation statistics. + * @param noWarn: if unindexing the record causes an error, if noWarn is true the error will not be + * logged. + * @param storeDeletedDoc: whether to store the document deleted in the oplog. + * @param checkRecordId: whether to confirm the recordId matches the record we are removing when + * unindexing. + * @param retryableWrite: whether it's a retryable write, @see write_stage_common::isRetryableWrite + */ +void deleteDocument(OperationContext* opCtx, + const CollectionPtr& collection, + Snapshotted<BSONObj> doc, + StmtId stmtId, + const RecordId& loc, + OpDebug* opDebug, + bool fromMigrate = false, + bool noWarn = false, + StoreDeletedDoc storeDeletedDoc = StoreDeletedDoc::Off, + CheckRecordId checkRecordId = CheckRecordId::Off, + RetryableWrite retryableWrite = RetryableWrite::kNo); + } // namespace collection_internal } // namespace mongo diff --git a/src/mongo/db/catalog/index_repair.cpp b/src/mongo/db/catalog/index_repair.cpp index 8b36157188b..3f49f3a4563 100644 --- a/src/mongo/db/catalog/index_repair.cpp +++ b/src/mongo/db/catalog/index_repair.cpp @@ -98,14 +98,15 @@ StatusWith<int> moveRecordToLostAndFound(OperationContext* opCtx, // CheckRecordId set to 'On' because we need _unindexKeys to confirm the record id of // this document matches the record id of the element it tries to unindex. This avoids // wrongly unindexing a document with the same _id. - originalCollection->deleteDocument(opCtx, - kUninitializedStmtId, - dupRecord, - nullptr /* opDebug */, - false /* fromMigrate */, - false /* noWarn */, - Collection::StoreDeletedDoc::Off, - CheckRecordId::On); + collection_internal::deleteDocument(opCtx, + originalCollection, + kUninitializedStmtId, + dupRecord, + nullptr /* opDebug */, + false /* fromMigrate */, + false /* noWarn */, + collection_internal::StoreDeletedDoc::Off, + CheckRecordId::On); wuow.commit(); return docSize; diff --git a/src/mongo/db/catalog/views_for_database.cpp b/src/mongo/db/catalog/views_for_database.cpp index 23ea8df9c23..2d9ab5ad9da 100644 --- a/src/mongo/db/catalog/views_for_database.cpp +++ b/src/mongo/db/catalog/views_for_database.cpp @@ -362,7 +362,8 @@ void ViewsForDatabase::remove(OperationContext* opCtx, "view"_attr = ns, "viewCatalog"_attr = systemViews->ns()); - systemViews->deleteDocument(opCtx, kUninitializedStmtId, id, &CurOp::get(opCtx)->debug()); + collection_internal::deleteDocument( + opCtx, systemViews, kUninitializedStmtId, id, &CurOp::get(opCtx)->debug()); } void ViewsForDatabase::clear(OperationContext* opCtx) { diff --git a/src/mongo/db/catalog/virtual_collection_impl.h b/src/mongo/db/catalog/virtual_collection_impl.h index 499e6add895..8c8dbbc961c 100644 --- a/src/mongo/db/catalog/virtual_collection_impl.h +++ b/src/mongo/db/catalog/virtual_collection_impl.h @@ -155,31 +155,6 @@ public: return _shared->_recordStore->getCursor(opCtx, forward); } - void deleteDocument( - OperationContext* opCtx, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - Collection::StoreDeletedDoc storeDeletedDoc = Collection::StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const final { - unimplementedTasserted(); - } - - void deleteDocument( - OperationContext* opCtx, - Snapshotted<BSONObj> doc, - StmtId stmtId, - const RecordId& loc, - OpDebug* opDebug, - bool fromMigrate = false, - bool noWarn = false, - Collection::StoreDeletedDoc storeDeletedDoc = Collection::StoreDeletedDoc::Off, - CheckRecordId checkRecordId = CheckRecordId::Off) const final { - unimplementedTasserted(); - } - bool updateWithDamagesSupported() const final { unimplementedTasserted(); return false; diff --git a/src/mongo/db/exec/batched_delete_stage.cpp b/src/mongo/db/exec/batched_delete_stage.cpp index 7c1141e0f99..3c78b7ccab9 100644 --- a/src/mongo/db/exec/batched_delete_stage.cpp +++ b/src/mongo/db/exec/batched_delete_stage.cpp @@ -33,6 +33,7 @@ #include "mongo/db/exec/batched_delete_stage.h" #include "mongo/db/catalog/collection.h" +#include "mongo/db/catalog/collection_write_path.h" #include "mongo/db/commands/server_status.h" #include "mongo/db/curop.h" #include "mongo/db/exec/scoped_timer.h" @@ -348,6 +349,7 @@ long long BatchedDeleteStage::_commitBatch(WorkingSetID* out, const auto action = docStillMatches ? _preWriteFilter.computeAction(member->doc.value()) : write_stage_common::PreWriteFilter::Action::kSkip; bool writeToOrphan = false; + auto retryableWrite = write_stage_common::isRetryableWrite(opCtx()); switch (action) { case write_stage_common::PreWriteFilter::Action::kSkip: LOGV2_DEBUG( @@ -388,16 +390,20 @@ long long BatchedDeleteStage::_commitBatch(WorkingSetID* out, return batchTimer.millis(); } - collection()->deleteDocument(opCtx(), - Snapshotted(memberDoc.snapshotId(), bsonObjDoc), - _params->stmtId, - member->recordId, - _params->opDebug, - _params->fromMigrate || writeToOrphan, - false, - _params->returnDeleted - ? Collection::StoreDeletedDoc::On - : Collection::StoreDeletedDoc::Off); + collection_internal::deleteDocument( + opCtx(), + collection(), + Snapshotted(memberDoc.snapshotId(), bsonObjDoc), + _params->stmtId, + member->recordId, + _params->opDebug, + _params->fromMigrate || writeToOrphan, + false, + _params->returnDeleted ? collection_internal::StoreDeletedDoc::On + : collection_internal::StoreDeletedDoc::Off, + CheckRecordId::Off, + retryableWrite ? collection_internal::RetryableWrite::kYes + : collection_internal::RetryableWrite::kNo); (*docsDeleted)++; (*bytesDeleted) += bsonObjDoc.objsize(); diff --git a/src/mongo/db/exec/delete_stage.cpp b/src/mongo/db/exec/delete_stage.cpp index 8b85e082fd0..c8e35041287 100644 --- a/src/mongo/db/exec/delete_stage.cpp +++ b/src/mongo/db/exec/delete_stage.cpp @@ -33,6 +33,8 @@ #include "mongo/db/exec/delete_stage.h" #include "mongo/db/catalog/collection.h" +#include "mongo/db/catalog/collection_write_path.h" +#include "mongo/db/catalog/index_catalog.h" #include "mongo/db/curop.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" @@ -232,9 +234,11 @@ PlanStage::StageState DeleteStage::doWork(WorkingSetID* out) { } } + auto retryableWrite = write_stage_common::isRetryableWrite(opCtx()); + // Ensure that the BSONObj underlying the WSM is owned because saveState() is // allowed to free the memory the BSONObj points to. The BSONObj will be needed - // later when it is passed to Collection::deleteDocument(). Note that the call to + // later when it is passed to collection_internal::deleteDocument(). Note that the call to // makeObjOwnedIfNeeded() will leave the WSM in the RID_AND_OBJ state in case we need to retry // deleting it. member->makeObjOwnedIfNeeded(); @@ -267,16 +271,20 @@ PlanStage::StageState DeleteStage::doWork(WorkingSetID* out) { collection()->ns().ns(), [&] { WriteUnitOfWork wunit(opCtx()); - collection()->deleteDocument(opCtx(), - Snapshotted(memberDoc.snapshotId(), bsonObjDoc), - _params->stmtId, - recordId, - _params->opDebug, - writeToOrphan || _params->fromMigrate, - false, - _params->returnDeleted - ? Collection::StoreDeletedDoc::On - : Collection::StoreDeletedDoc::Off); + collection_internal::deleteDocument( + opCtx(), + collection(), + Snapshotted(memberDoc.snapshotId(), bsonObjDoc), + _params->stmtId, + recordId, + _params->opDebug, + writeToOrphan || _params->fromMigrate, + false, + _params->returnDeleted ? collection_internal::StoreDeletedDoc::On + : collection_internal::StoreDeletedDoc::Off, + CheckRecordId::Off, + retryableWrite ? collection_internal::RetryableWrite::kYes + : collection_internal::RetryableWrite::kNo); wunit.commit(); return PlanStage::NEED_TIME; }, diff --git a/src/mongo/db/free_mon/free_mon_op_observer.cpp b/src/mongo/db/free_mon/free_mon_op_observer.cpp index 0729e33b84a..5426c3b20ef 100644 --- a/src/mongo/db/free_mon/free_mon_op_observer.cpp +++ b/src/mongo/db/free_mon/free_mon_op_observer.cpp @@ -118,11 +118,10 @@ void FreeMonOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEntry } void FreeMonOpObserver::aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) { - bool isFreeMonDoc = (nss == NamespaceString::kServerConfigurationNamespace) && + bool isFreeMonDoc = (coll->ns() == NamespaceString::kServerConfigurationNamespace) && (doc["_id"].str() == FreeMonStorage::kFreeMonDocIdKey); // Set a flag that indicates whether the document to be delete is the free monitoring state @@ -131,11 +130,10 @@ void FreeMonOpObserver::aboutToDelete(OperationContext* opCtx, } void FreeMonOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss != NamespaceString::kServerConfigurationNamespace) { + if (coll->ns() != NamespaceString::kServerConfigurationNamespace) { return; } diff --git a/src/mongo/db/free_mon/free_mon_op_observer.h b/src/mongo/db/free_mon/free_mon_op_observer.h index edff328eab7..9d2bd0fbd24 100644 --- a/src/mongo/db/free_mon/free_mon_op_observer.h +++ b/src/mongo/db/free_mon/free_mon_op_observer.h @@ -112,13 +112,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/index_build_entry_helpers.cpp b/src/mongo/db/index_build_entry_helpers.cpp index 351f660191b..a0da462cfbc 100644 --- a/src/mongo/db/index_build_entry_helpers.cpp +++ b/src/mongo/db/index_build_entry_helpers.cpp @@ -270,7 +270,8 @@ Status removeIndexBuildEntry(OperationContext* opCtx, WriteUnitOfWork wuow(opCtx); OpDebug opDebug; - collection->deleteDocument(opCtx, kUninitializedStmtId, rid, &opDebug); + collection_internal::deleteDocument( + opCtx, collection, kUninitializedStmtId, rid, &opDebug); wuow.commit(); return Status::OK(); }); diff --git a/src/mongo/db/op_observer/fcv_op_observer.cpp b/src/mongo/db/op_observer/fcv_op_observer.cpp index 763b8dcdd92..b0b9d277535 100644 --- a/src/mongo/db/op_observer/fcv_op_observer.cpp +++ b/src/mongo/db/op_observer/fcv_op_observer.cpp @@ -169,10 +169,10 @@ void FcvOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs } void FcvOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { + const auto& nss = coll->ns(); // documentKeyDecoration is set in OpObserverImpl::aboutToDelete. So the FcvOpObserver // relies on the OpObserverImpl also being in the opObserverRegistry. auto optDocKey = repl::documentKeyDecoration(opCtx); diff --git a/src/mongo/db/op_observer/fcv_op_observer.h b/src/mongo/db/op_observer/fcv_op_observer.h index bae90557db4..2d9c6da2425 100644 --- a/src/mongo/db/op_observer/fcv_op_observer.h +++ b/src/mongo/db/op_observer/fcv_op_observer.h @@ -70,8 +70,7 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; @@ -122,8 +121,7 @@ public: bool fromMigrate) final {} void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final {} void onInternalOpMessage(OperationContext* opCtx, const NamespaceString& nss, diff --git a/src/mongo/db/op_observer/op_observer.h b/src/mongo/db/op_observer/op_observer.h index 8f57e825ea5..24d4becbc49 100644 --- a/src/mongo/db/op_observer/op_observer.h +++ b/src/mongo/db/op_observer/op_observer.h @@ -195,9 +195,9 @@ public: const BSONObj& docKey) = 0; virtual void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) = 0; + virtual void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) = 0; /** @@ -210,8 +210,7 @@ public: * opObserver must store the `deletedDoc` in addition to the documentKey. */ virtual void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) = 0; diff --git a/src/mongo/db/op_observer/op_observer_impl.cpp b/src/mongo/db/op_observer/op_observer_impl.cpp index 95c42ecb4cb..b2e9a15c67c 100644 --- a/src/mongo/db/op_observer/op_observer_impl.cpp +++ b/src/mongo/db/op_observer/op_observer_impl.cpp @@ -953,20 +953,19 @@ void OpObserverImpl::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArg } void OpObserverImpl::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - repl::documentKeyDecoration(opCtx).emplace(repl::getDocumentKey(opCtx, nss, doc)); + repl::documentKeyDecoration(opCtx).emplace(repl::getDocumentKey(opCtx, coll->ns(), doc)); - ShardingWriteRouter shardingWriteRouter(opCtx, nss, Grid::get(opCtx)->catalogCache()); + ShardingWriteRouter shardingWriteRouter(opCtx, coll->ns(), Grid::get(opCtx)->catalogCache()); repl::DurableReplOperation op; op.setDestinedRecipient(shardingWriteRouter.getReshardingDestinedRecipient(doc)); destinedRecipientDecoration(opCtx) = op.getDestinedRecipient(); - shardObserveAboutToDelete(opCtx, nss, doc); + shardObserveAboutToDelete(opCtx, coll->ns(), doc); - if (nss.isTimeseriesBucketsCollection()) { + if (coll->ns().isTimeseriesBucketsCollection()) { if (feature_flags::gTimeseriesScalabilityImprovements.isEnabled( serverGlobalParams.featureCompatibility)) { auto& deletedBuckets = timeseries::DeletedBuckets::get(opCtx); @@ -979,10 +978,11 @@ void OpObserverImpl::aboutToDelete(OperationContext* opCtx, } void OpObserverImpl::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { + const auto& nss = coll->ns(); + const auto uuid = coll->uuid(); auto optDocKey = repl::documentKeyDecoration(opCtx); invariant(optDocKey, nss.ns()); auto& documentKey = optDocKey.value(); diff --git a/src/mongo/db/op_observer/op_observer_impl.h b/src/mongo/db/op_observer/op_observer_impl.h index 58ab37979f6..146c37ec763 100644 --- a/src/mongo/db/op_observer/op_observer_impl.h +++ b/src/mongo/db/op_observer/op_observer_impl.h @@ -117,12 +117,10 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; void onInternalOpMessage(OperationContext* opCtx, diff --git a/src/mongo/db/op_observer/op_observer_impl_test.cpp b/src/mongo/db/op_observer/op_observer_impl_test.cpp index b451afe1c9c..ea3b022a39e 100644 --- a/src/mongo/db/op_observer/op_observer_impl_test.cpp +++ b/src/mongo/db/op_observer/op_observer_impl_test.cpp @@ -191,6 +191,7 @@ protected: reset(opCtx.get(), nss, uuid); reset(opCtx.get(), nss1, uuid1); reset(opCtx.get(), nss2, uuid2); + reset(opCtx.get(), nss3, uuid3); reset(opCtx.get(), kNssUnderTenantId, kNssUnderTenantIdUUID); reset(opCtx.get(), NamespaceString::kRsOplogNamespace); } @@ -339,6 +340,8 @@ protected: const UUID uuid1{UUID::gen()}; const NamespaceString nss2{TenantId(OID::gen()), "testDB2", "testColl2"}; const UUID uuid2{UUID::gen()}; + const NamespaceString nss3{boost::none, "testDB3", "testColl3"}; + const UUID uuid3{UUID::gen()}; const std::string kTenantId = "tenantId"; const NamespaceString kNssUnderTenantId{boost::none, "tenantId_db", "testColl"}; @@ -952,7 +955,7 @@ TEST_F(OpObserverTest, SingleStatementDeleteTestIncludesTenantId) { // `OpObserverImpl::onDelete` asserts its existence. repl::documentKeyDecoration(opCtx.get()).emplace(BSON("_id" << 0), boost::none); OplogDeleteEntryArgs deleteEntryArgs; - opObserver.onDelete(opCtx.get(), nss, uuid, kUninitializedStmtId, deleteEntryArgs); + opObserver.onDelete(opCtx.get(), *locks, kUninitializedStmtId, deleteEntryArgs); wuow.commit(); auto oplogEntryObj = getSingleOplogEntry(opCtx.get()); @@ -1046,24 +1049,23 @@ TEST_F(OpObserverSessionCatalogRollbackTest, } TEST_F(OpObserverTest, MultipleAboutToDeleteAndOnDelete) { - auto uuid = UUID::gen(); OpObserverImpl opObserver(std::make_unique<OplogWriterImpl>()); auto opCtx = cc().makeOperationContext(); - NamespaceString nss = {boost::none, "test", "coll"}; - AutoGetDb autoDb(opCtx.get(), nss.dbName(), MODE_X); + AutoGetCollection autoColl(opCtx.get(), nss3, MODE_X); WriteUnitOfWork wunit(opCtx.get()); - opObserver.aboutToDelete(opCtx.get(), nss, uuid, BSON("_id" << 1)); - opObserver.onDelete(opCtx.get(), nss, uuid, kUninitializedStmtId, {}); - opObserver.aboutToDelete(opCtx.get(), nss, uuid, BSON("_id" << 1)); - opObserver.onDelete(opCtx.get(), nss, uuid, kUninitializedStmtId, {}); + opObserver.aboutToDelete(opCtx.get(), *autoColl, BSON("_id" << 1)); + opObserver.onDelete(opCtx.get(), *autoColl, kUninitializedStmtId, {}); + opObserver.aboutToDelete(opCtx.get(), *autoColl, BSON("_id" << 1)); + opObserver.onDelete(opCtx.get(), *autoColl, kUninitializedStmtId, {}); } -DEATH_TEST_F(OpObserverTest, AboutToDeleteMustPreceedOnDelete, "invariant") { +DEATH_TEST_REGEX_F(OpObserverTest, + AboutToDeleteMustPreceedOnDelete, + "Invariant failure.*optDocKey") { OpObserverImpl opObserver(std::make_unique<OplogWriterImpl>()); auto opCtx = cc().makeOperationContext(); - cc().swapLockState(std::make_unique<LockerNoop>()); - NamespaceString nss = {boost::none, "test", "coll"}; - opObserver.onDelete(opCtx.get(), nss, UUID::gen(), kUninitializedStmtId, {}); + AutoGetCollection autoColl(opCtx.get(), nss3, MODE_IX); + opObserver.onDelete(opCtx.get(), *autoColl, kUninitializedStmtId, {}); } DEATH_TEST_REGEX_F(OpObserverTest, @@ -1071,10 +1073,8 @@ DEATH_TEST_REGEX_F(OpObserverTest, "Invariant failure.*!id.isEmpty()") { OpObserverImpl opObserver(std::make_unique<OplogWriterImpl>()); auto opCtx = cc().makeOperationContext(); - cc().swapLockState(std::make_unique<LockerNoop>()); - NamespaceString nss = {boost::none, "test", "coll"}; - UUID uuid = UUID::gen(); - opObserver.aboutToDelete(opCtx.get(), nss, uuid, {}); + AutoGetCollection autoColl(opCtx.get(), nss3, MODE_IX); + opObserver.aboutToDelete(opCtx.get(), *autoColl, {}); } DEATH_TEST_REGEX_F(OpObserverTest, @@ -1281,11 +1281,10 @@ TEST_F(OpObserverTransactionTest, TransactionalPrepareTest) { opObserver().onUpdate(opCtx(), update2); opObserver().aboutToDelete(opCtx(), - nss1, - uuid1, + *autoColl1, BSON("_id" << 0 << "data" << "x")); - opObserver().onDelete(opCtx(), nss1, uuid1, 0, {}); + opObserver().onDelete(opCtx(), *autoColl1, 0, {}); // One reserved slot for each statement, plus the prepare. auto reservedSlots = reserveOpTimesInSideTransaction(opCtx(), 5); @@ -1913,17 +1912,15 @@ TEST_F(OpObserverTransactionTest, TransactionalDeleteTest) { AutoGetCollection autoColl1(opCtx(), nss1, MODE_IX); AutoGetCollection autoColl2(opCtx(), nss2, MODE_IX); opObserver().aboutToDelete(opCtx(), - nss1, - uuid1, + *autoColl1, BSON("_id" << 0 << "data" << "x")); - opObserver().onDelete(opCtx(), nss1, uuid1, 0, {}); + opObserver().onDelete(opCtx(), *autoColl1, 0, {}); opObserver().aboutToDelete(opCtx(), - nss2, - uuid2, + *autoColl2, BSON("_id" << 1 << "data" << "y")); - opObserver().onDelete(opCtx(), nss2, uuid2, 0, {}); + opObserver().onDelete(opCtx(), *autoColl2, 0, {}); auto txnOps = txnParticipant.retrieveCompletedTransactionOperations(opCtx()); ASSERT_EQUALS(txnOps->getNumberOfPrePostImagesToWrite(), 0); opObserver().onUnpreparedTransactionCommit(opCtx(), txnOps); @@ -1954,17 +1951,15 @@ TEST_F(OpObserverTransactionTest, TransactionalDeleteTestIncludesTenantId) { AutoGetCollection autoColl1(opCtx(), nss1, MODE_IX); AutoGetCollection autoColl2(opCtx(), nss2, MODE_IX); opObserver().aboutToDelete(opCtx(), - nss1, - uuid1, + *autoColl1, BSON("_id" << 0 << "data" << "x")); - opObserver().onDelete(opCtx(), nss1, uuid1, 0, {}); + opObserver().onDelete(opCtx(), *autoColl1, 0, {}); opObserver().aboutToDelete(opCtx(), - nss2, - uuid2, + *autoColl2, BSON("_id" << 1 << "data" << "y")); - opObserver().onDelete(opCtx(), nss2, uuid2, 0, {}); + opObserver().onDelete(opCtx(), *autoColl2, 0, {}); auto txnOps = txnParticipant.retrieveCompletedTransactionOperations(opCtx()); ASSERT_EQUALS(txnOps->getNumberOfPrePostImagesToWrite(), 0); @@ -2100,14 +2095,14 @@ protected: void testRetryableFindAndModifyDeleteHasNeedsRetryImage() { - AutoGetDb autoDb(opCtx(), nss.dbName(), MODE_X); + AutoGetCollection autoColl(opCtx(), nss, MODE_IX); const auto deletedDoc = BSON("_id" << 0 << "data" << "x"); - opObserver().aboutToDelete(opCtx(), nss, uuid, deletedDoc); + opObserver().aboutToDelete(opCtx(), *autoColl, deletedDoc); OplogDeleteEntryArgs args; args.retryableFindAndModifyLocation = RetryableFindAndModifyLocation::kSideCollection; args.deletedDoc = &deletedDoc; - opObserver().onDelete(opCtx(), nss, uuid, 0, args); + opObserver().onDelete(opCtx(), *autoColl, 0, args); commit(); // Asserts that only a single oplog entry was created. In essence, we did not create any @@ -2774,7 +2769,7 @@ TEST_F(BatchedWriteOutputsTest, TestApplyOpsGrouping) { boost::none); const OplogDeleteEntryArgs args; opCtx->getServiceContext()->getOpObserver()->onDelete( - opCtx, autoColl->ns(), autoColl->uuid(), kUninitializedStmtId, args); + opCtx, *autoColl, kUninitializedStmtId, args); } wuow.commit(); @@ -2835,7 +2830,7 @@ TEST_F(BatchedWriteOutputsTest, TestApplyOpsInsertDeleteUpdate) { repl::documentKeyDecoration(opCtx).emplace(BSON("_id" << 1), boost::none); const OplogDeleteEntryArgs args; opCtx->getServiceContext()->getOpObserver()->onDelete( - opCtx, autoColl->ns(), autoColl->uuid(), kUninitializedStmtId, args); + opCtx, *autoColl, kUninitializedStmtId, args); } // (2) Update { @@ -2922,7 +2917,7 @@ TEST_F(BatchedWriteOutputsTest, TestApplyOpsInsertDeleteUpdateIncludesTenantId) repl::documentKeyDecoration(opCtx).emplace(BSON("_id" << 1), boost::none); const OplogDeleteEntryArgs args; opCtx->getServiceContext()->getOpObserver()->onDelete( - opCtx, autoColl->ns(), autoColl->uuid(), kUninitializedStmtId, args); + opCtx, *autoColl, kUninitializedStmtId, args); } // (2) Update { @@ -3026,7 +3021,7 @@ TEST_F(BatchedWriteOutputsTest, testWUOWLarge) { repl::documentKeyDecoration(opCtx).emplace(BSON("_id" << docId), boost::none); const OplogDeleteEntryArgs args; opCtx->getServiceContext()->getOpObserver()->onDelete( - opCtx, autoColl->ns(), autoColl->uuid(), kUninitializedStmtId, args); + opCtx, *autoColl, kUninitializedStmtId, args); } wuow.commit(); @@ -3076,7 +3071,7 @@ TEST_F(BatchedWriteOutputsTest, testWUOWTooLarge) { repl::documentKeyDecoration(opCtx).emplace(BSON("_id" << docId), boost::none); const OplogDeleteEntryArgs args; opCtx->getServiceContext()->getOpObserver()->onDelete( - opCtx, autoColl->ns(), autoColl->uuid(), kUninitializedStmtId, args); + opCtx, *autoColl, kUninitializedStmtId, args); } // This test used to rely on the BSONObjBuilder in packTransactionStatementsForApplyOps() @@ -3252,6 +3247,12 @@ TEST_F(AtomicApplyOpsOutputsTest, AtomicApplyOpsInsertWithoutUuidIntoCollectionW class OnDeleteOutputsTest : public OpObserverTest { protected: + void setUp() override { + OpObserverTest::setUp(); + auto opCtx = cc().makeOperationContext(); + reset(opCtx.get(), _nss, _uuid); + } + void logTestCase(const DeleteTestCase& testCase) { LOGV2(5739905, "DeleteTestCase", @@ -3376,7 +3377,7 @@ TEST_F(OnDeleteOutputsTest, TestNonTransactionFundamentalOnDeleteOutputs) { // `OpObserverImpl::onDelete` asserts its existence. repl::documentKeyDecoration(opCtx).emplace(_deletedDoc["_id"].wrap(), boost::none); opObserver.onDelete( - opCtx, _nss, _uuid, testCase.isRetryable() ? 1 : kUninitializedStmtId, deleteEntryArgs); + opCtx, *locks, testCase.isRetryable() ? 1 : kUninitializedStmtId, deleteEntryArgs); wuow.commit(); // Phase 3: Analyze the results: @@ -3425,7 +3426,7 @@ TEST_F(OnDeleteOutputsTest, TestTransactionFundamentalOnDeleteOutputs) { // of setting of `documentKey` on the delete for sharding purposes. // `OpObserverImpl::onDelete` asserts its existence. repl::documentKeyDecoration(opCtx).emplace(_deletedDoc["_id"].wrap(), boost::none); - opObserver.onDelete(opCtx, _nss, _uuid, stmtId, deleteEntryArgs); + opObserver.onDelete(opCtx, *locks, stmtId, deleteEntryArgs); commitUnpreparedTransaction<OpObserverRegistry>(opCtx, opObserver); wuow.commit(); @@ -3627,17 +3628,15 @@ TEST_F(OpObserverMultiEntryTransactionTest, TransactionalDeleteTest) { AutoGetCollection autoColl1(opCtx(), nss1, MODE_IX); AutoGetCollection autoColl2(opCtx(), nss2, MODE_IX); opObserver().aboutToDelete(opCtx(), - nss1, - uuid1, + *autoColl1, BSON("_id" << 0 << "data" << "x")); - opObserver().onDelete(opCtx(), nss1, uuid1, 0, {}); + opObserver().onDelete(opCtx(), *autoColl1, 0, {}); opObserver().aboutToDelete(opCtx(), - nss2, - uuid2, + *autoColl2, BSON("_id" << 1 << "data" << "y")); - opObserver().onDelete(opCtx(), nss2, uuid2, 0, {}); + opObserver().onDelete(opCtx(), *autoColl2, 0, {}); auto txnOps = txnParticipant.retrieveCompletedTransactionOperations(opCtx()); ASSERT_EQUALS(txnOps->getNumberOfPrePostImagesToWrite(), 0); opObserver().onUnpreparedTransactionCommit(opCtx(), txnOps); @@ -3828,17 +3827,15 @@ TEST_F(OpObserverMultiEntryTransactionTest, TransactionalDeletePrepareTest) { AutoGetCollection autoColl1(opCtx(), nss1, MODE_IX); AutoGetCollection autoColl2(opCtx(), nss2, MODE_IX); opObserver().aboutToDelete(opCtx(), - nss1, - uuid1, + *autoColl1, BSON("_id" << 0 << "data" << "x")); - opObserver().onDelete(opCtx(), nss1, uuid1, 0, {}); + opObserver().onDelete(opCtx(), *autoColl1, 0, {}); opObserver().aboutToDelete(opCtx(), - nss2, - uuid2, + *autoColl2, BSON("_id" << 1 << "data" << "y")); - opObserver().onDelete(opCtx(), nss2, uuid2, 0, {}); + opObserver().onDelete(opCtx(), *autoColl2, 0, {}); auto reservedSlots = reserveOpTimesInSideTransaction(opCtx(), 2); auto prepareOpTime = reservedSlots.back(); diff --git a/src/mongo/db/op_observer/op_observer_noop.h b/src/mongo/db/op_observer/op_observer_noop.h index 8263a6e6373..a3f284ad45e 100644 --- a/src/mongo/db/op_observer/op_observer_noop.h +++ b/src/mongo/db/op_observer/op_observer_noop.h @@ -100,12 +100,10 @@ public: const BSONObj& docKey) final {} void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) override{}; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override {} void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override {} void onInternalOpMessage(OperationContext* opCtx, diff --git a/src/mongo/db/op_observer/op_observer_registry.h b/src/mongo/db/op_observer/op_observer_registry.h index 8c98bfc7da0..f213be1d397 100644 --- a/src/mongo/db/op_observer/op_observer_registry.h +++ b/src/mongo/db/op_observer/op_observer_registry.h @@ -184,22 +184,20 @@ public: } void aboutToDelete(OperationContext* const opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override { ReservedTimes times{opCtx}; for (auto& o : _observers) - o->aboutToDelete(opCtx, nss, uuid, doc); + o->aboutToDelete(opCtx, coll, doc); } void onDelete(OperationContext* const opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override { ReservedTimes times{opCtx}; for (auto& o : _observers) - o->onDelete(opCtx, nss, uuid, stmtId, args); + o->onDelete(opCtx, coll, stmtId, args); } void onInternalOpMessage(OperationContext* const opCtx, diff --git a/src/mongo/db/op_observer/user_write_block_mode_op_observer.cpp b/src/mongo/db/op_observer/user_write_block_mode_op_observer.cpp index d1e90077f48..35b8f2e277c 100644 --- a/src/mongo/db/op_observer/user_write_block_mode_op_observer.cpp +++ b/src/mongo/db/op_observer/user_write_block_mode_op_observer.cpp @@ -125,19 +125,18 @@ void UserWriteBlockModeOpObserver::onUpdate(OperationContext* opCtx, } void UserWriteBlockModeOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss == NamespaceString::kUserWritesCriticalSectionsNamespace) { + if (coll->ns() == NamespaceString::kUserWritesCriticalSectionsNamespace) { documentIdDecoration(opCtx) = doc; } } void UserWriteBlockModeOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { + const auto& nss = coll->ns(); if (!args.fromMigrate) { _checkWriteAllowed(opCtx, nss); } diff --git a/src/mongo/db/op_observer/user_write_block_mode_op_observer.h b/src/mongo/db/op_observer/user_write_block_mode_op_observer.h index 540ee34d126..f797a02ef24 100644 --- a/src/mongo/db/op_observer/user_write_block_mode_op_observer.h +++ b/src/mongo/db/op_observer/user_write_block_mode_op_observer.h @@ -70,8 +70,7 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; @@ -154,8 +153,7 @@ public: // Note aboutToDelete is unchecked, but defined. void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; // Noop operations (don't perform any check). diff --git a/src/mongo/db/op_observer/user_write_block_mode_op_observer_test.cpp b/src/mongo/db/op_observer/user_write_block_mode_op_observer_test.cpp index baeadb8e394..6a551fe9d6e 100644 --- a/src/mongo/db/op_observer/user_write_block_mode_op_observer_test.cpp +++ b/src/mongo/db/op_observer/user_write_block_mode_op_observer_test.cpp @@ -88,7 +88,6 @@ protected: CollectionUpdateArgs collectionUpdateArgs; collectionUpdateArgs.source = fromMigrate ? OperationSource::kFromMigrate : OperationSource::kStandard; - auto uuid = UUID::gen(); OplogUpdateEntryArgs updateArgs(&collectionUpdateArgs, *autoColl); OplogDeleteEntryArgs deleteArgs; deleteArgs.fromMigrate = fromMigrate; @@ -96,7 +95,7 @@ protected: try { opObserver.onInserts(opCtx, *autoColl, inserts.begin(), inserts.end(), fromMigrate); opObserver.onUpdate(opCtx, updateArgs); - opObserver.onDelete(opCtx, nss, uuid, StmtId(), deleteArgs); + opObserver.onDelete(opCtx, *autoColl, StmtId(), deleteArgs); } catch (...) { // Make it easier to see that this is where we failed. ASSERT_OK(exceptionToStatus()); @@ -106,7 +105,7 @@ protected: opObserver.onInserts(opCtx, *autoColl, inserts.begin(), inserts.end(), fromMigrate), AssertionException); ASSERT_THROWS(opObserver.onUpdate(opCtx, updateArgs), AssertionException); - ASSERT_THROWS(opObserver.onDelete(opCtx, nss, uuid, StmtId(), deleteArgs), + ASSERT_THROWS(opObserver.onDelete(opCtx, *autoColl, StmtId(), deleteArgs), AssertionException); } } diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index 360fee1dbcf..2325df018e2 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -1643,9 +1643,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele } if (collection && collection->isCapped() && opCtx->inMultiDocumentTransaction()) { - // This check is duplicated from CollectionImpl::deleteDocument() for two reasons: + // This check is duplicated from collection_internal::deleteDocument() for two reasons: // - Performing a remove on an empty capped collection would not call - // CollectionImpl::deleteDocument(). + // collection_internal::deleteDocument(). // - We can avoid doing lookups on documents and erroring later when trying to delete them. return Status( ErrorCodes::IllegalOperation, diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp index 7c4a904b1a5..8d94ecb55c3 100644 --- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp +++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp @@ -70,14 +70,13 @@ void OplogApplierImplOpObserver::onInserts(OperationContext* opCtx, } void OplogApplierImplOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { if (!onDeleteFn) { return; } - onDeleteFn(opCtx, nss, uuid, stmtId, args); + onDeleteFn(opCtx, coll, stmtId, args); } void OplogApplierImplOpObserver::onUpdate(OperationContext* opCtx, @@ -247,13 +246,12 @@ void OplogApplierImplTest::_testApplyOplogEntryOrGroupedInsertsCrudOperation( }; _opObserver->onDeleteFn = [&](OperationContext* opCtx, - const NamespaceString& nss, - const boost::optional<UUID>& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { applyOpCalled = true; checkOpCtx(opCtx); - ASSERT_EQUALS(targetNss, nss); + ASSERT_EQUALS(targetNss, coll->ns()); ASSERT(args.deletedDoc); ASSERT_BSONOBJ_EQ(op.getObject(), *(args.deletedDoc)); return Status::OK(); diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h index c96ca3a881a..bce8a24e9ef 100644 --- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.h +++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.h @@ -83,8 +83,7 @@ public: * This function is called whenever OplogApplierImpl deletes a document from a collection. */ void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override; @@ -149,11 +148,8 @@ public: std::function<void(OperationContext*, const NamespaceString&, const std::vector<BSONObj>&)> onInsertsFn; - std::function<void(OperationContext*, - const NamespaceString&, - boost::optional<UUID>, - StmtId, - const OplogDeleteEntryArgs&)> + std::function<void( + OperationContext*, const CollectionPtr&, StmtId, const OplogDeleteEntryArgs&)> onDeleteFn; std::function<void(OperationContext*, const OplogUpdateEntryArgs&)> onUpdateFn; diff --git a/src/mongo/db/repl/primary_only_service_op_observer.cpp b/src/mongo/db/repl/primary_only_service_op_observer.cpp index 3ed52e7ec6b..4116af9d28d 100644 --- a/src/mongo/db/repl/primary_only_service_op_observer.cpp +++ b/src/mongo/db/repl/primary_only_service_op_observer.cpp @@ -50,8 +50,7 @@ PrimaryOnlyServiceOpObserver::~PrimaryOnlyServiceOpObserver() = default; void PrimaryOnlyServiceOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { // Extract the _id field from the document. If it does not have an _id, use the // document itself as the _id. @@ -59,10 +58,10 @@ void PrimaryOnlyServiceOpObserver::aboutToDelete(OperationContext* opCtx, } void PrimaryOnlyServiceOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { + const auto& nss = coll->ns(); auto& documentId = documentIdDecoration(opCtx); invariant(!documentId.isEmpty()); diff --git a/src/mongo/db/repl/primary_only_service_op_observer.h b/src/mongo/db/repl/primary_only_service_op_observer.h index 9c56950c19f..33874d2fab1 100644 --- a/src/mongo/db/repl/primary_only_service_op_observer.h +++ b/src/mongo/db/repl/primary_only_service_op_observer.h @@ -114,13 +114,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final {} void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/repl/storage_timestamp_test.cpp b/src/mongo/db/repl/storage_timestamp_test.cpp index 28c7b520aba..3d487c0ca64 100644 --- a/src/mongo/db/repl/storage_timestamp_test.cpp +++ b/src/mongo/db/repl/storage_timestamp_test.cpp @@ -2796,7 +2796,8 @@ TEST_F(StorageTimestampTest, IndexBuildsResolveErrorsDuringStateChangeToPrimary) { RecordId badRecord = Helpers::findOne(_opCtx, collection.get(), BSON("_id" << 1)); WriteUnitOfWork wuow(_opCtx); - collection->deleteDocument(_opCtx, kUninitializedStmtId, badRecord, nullptr); + collection_internal::deleteDocument( + _opCtx, *autoColl, kUninitializedStmtId, badRecord, nullptr); wuow.commit(); } @@ -3402,14 +3403,17 @@ TEST_F(RetryableFindAndModifyTest, RetryableFindAndModifyDelete) { auto record = cursor->next(); invariant(record); WriteUnitOfWork wuow(_opCtx); - collection->deleteDocument(_opCtx, - objSnapshot, - 1, - record->id, - nullptr, - false, - false, - Collection::StoreDeletedDoc::On); + collection_internal::deleteDocument(_opCtx, + *autoColl, + objSnapshot, + 1, + record->id, + nullptr, + false, + false, + collection_internal::StoreDeletedDoc::On, + CheckRecordId::Off, + collection_internal::RetryableWrite::kYes); wuow.commit(); } diff --git a/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp b/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp index 7fb4bf05a29..cdf47a03434 100644 --- a/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp +++ b/src/mongo/db/repl/tenant_migration_donor_op_observer.cpp @@ -298,10 +298,9 @@ void TenantMigrationDonorOpObserver::onUpdate(OperationContext* opCtx, } void TenantMigrationDonorOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss == NamespaceString::kTenantMigrationDonorsNamespace && + if (coll->ns() == NamespaceString::kTenantMigrationDonorsNamespace && !tenant_migration_access_blocker::inRecoveryMode(opCtx)) { auto donorStateDoc = tenant_migration_access_blocker::parseDonorStateDocument(doc); uassert(ErrorCodes::IllegalOperation, @@ -321,11 +320,10 @@ void TenantMigrationDonorOpObserver::aboutToDelete(OperationContext* opCtx, } void TenantMigrationDonorOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss == NamespaceString::kTenantMigrationDonorsNamespace && + if (coll->ns() == NamespaceString::kTenantMigrationDonorsNamespace && !tenant_migration_access_blocker::inRecoveryMode(opCtx)) { auto tmi = tenantMigrationInfo(opCtx); if (!tmi) { diff --git a/src/mongo/db/repl/tenant_migration_donor_op_observer.h b/src/mongo/db/repl/tenant_migration_donor_op_observer.h index 510ec3c56a1..6a50e2fba8d 100644 --- a/src/mongo/db/repl/tenant_migration_donor_op_observer.h +++ b/src/mongo/db/repl/tenant_migration_donor_op_observer.h @@ -112,13 +112,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp b/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp index b955988ab2d..1ec471f259f 100644 --- a/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp +++ b/src/mongo/db/repl/tenant_migration_recipient_op_observer.cpp @@ -269,10 +269,9 @@ void TenantMigrationRecipientOpObserver::onUpdate(OperationContext* opCtx, } void TenantMigrationRecipientOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss == NamespaceString::kTenantMigrationRecipientsNamespace && + if (coll->ns() == NamespaceString::kTenantMigrationRecipientsNamespace && !tenant_migration_access_blocker::inRecoveryMode(opCtx)) { auto recipientStateDoc = TenantMigrationRecipientDocument::parse(IDLParserContext("recipientStateDoc"), doc); @@ -293,11 +292,10 @@ void TenantMigrationRecipientOpObserver::aboutToDelete(OperationContext* opCtx, } void TenantMigrationRecipientOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss == NamespaceString::kTenantMigrationRecipientsNamespace && + if (coll->ns() == NamespaceString::kTenantMigrationRecipientsNamespace && !tenant_migration_access_blocker::inRecoveryMode(opCtx)) { auto tmi = tenantMigrationInfo(opCtx); if (!tmi) { diff --git a/src/mongo/db/repl/tenant_migration_recipient_op_observer.h b/src/mongo/db/repl/tenant_migration_recipient_op_observer.h index 7b1d51fe334..7309c9d6297 100644 --- a/src/mongo/db/repl/tenant_migration_recipient_op_observer.h +++ b/src/mongo/db/repl/tenant_migration_recipient_op_observer.h @@ -113,13 +113,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/repl/tenant_oplog_applier_test.cpp b/src/mongo/db/repl/tenant_oplog_applier_test.cpp index 319ef74c58f..bd668250a4f 100644 --- a/src/mongo/db/repl/tenant_oplog_applier_test.cpp +++ b/src/mongo/db/repl/tenant_oplog_applier_test.cpp @@ -742,11 +742,10 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_DatabaseMissing) { auto entry = makeOplogEntry( OpTypeEnum::kDelete, NamespaceString(_dbName.toStringWithTenantId(), "bar"), UUID::gen()); bool onDeleteCalled = false; - _opObserver->onDeleteFn = [&](OperationContext* opCtx, - const NamespaceString&, - boost::optional<UUID>, - StmtId, - const OplogDeleteEntryArgs&) { onDeleteCalled = true; }; + _opObserver->onDeleteFn = + [&](OperationContext* opCtx, const CollectionPtr&, StmtId, const OplogDeleteEntryArgs&) { + onDeleteCalled = true; + }; pushOps({entry}); auto writerPool = makeTenantMigrationWriterPool(); @@ -773,11 +772,10 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_CollectionMissing) { auto entry = makeOplogEntry( OpTypeEnum::kDelete, NamespaceString(_dbName.toStringWithTenantId(), "bar"), UUID::gen()); bool onDeleteCalled = false; - _opObserver->onDeleteFn = [&](OperationContext* opCtx, - const NamespaceString&, - boost::optional<UUID>, - StmtId, - const OplogDeleteEntryArgs&) { onDeleteCalled = true; }; + _opObserver->onDeleteFn = + [&](OperationContext* opCtx, const CollectionPtr&, StmtId, const OplogDeleteEntryArgs&) { + onDeleteCalled = true; + }; pushOps({entry}); auto writerPool = makeTenantMigrationWriterPool(); @@ -804,11 +802,10 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_DocumentMissing) { auto uuid = createCollectionWithUuid(_opCtx.get(), nss); auto entry = makeOplogEntry(OpTypeEnum::kDelete, nss, uuid, BSON("_id" << 0)); bool onDeleteCalled = false; - _opObserver->onDeleteFn = [&](OperationContext* opCtx, - const NamespaceString&, - boost::optional<UUID>, - StmtId, - const OplogDeleteEntryArgs&) { onDeleteCalled = true; }; + _opObserver->onDeleteFn = + [&](OperationContext* opCtx, const CollectionPtr&, StmtId, const OplogDeleteEntryArgs&) { + onDeleteCalled = true; + }; pushOps({entry}); auto writerPool = makeTenantMigrationWriterPool(); @@ -837,8 +834,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_Success) { auto entry = makeOplogEntry(OpTypeEnum::kDelete, nss, uuid, BSON("_id" << 0)); bool onDeleteCalled = false; _opObserver->onDeleteFn = [&](OperationContext* opCtx, - const NamespaceString& nss, - const boost::optional<UUID>& observer_uuid, + const CollectionPtr& coll, StmtId, const OplogDeleteEntryArgs& args) { onDeleteCalled = true; @@ -851,7 +847,7 @@ TEST_F(TenantOplogApplierTest, ApplyDelete_Success) { // passes "tid" to the NamespaceString constructor ASSERT_EQUALS(nss.dbName().db(), _dbName.toStringWithTenantId()); ASSERT_EQUALS(nss.coll(), "bar"); - ASSERT_EQUALS(uuid, observer_uuid); + ASSERT_EQUALS(uuid, coll->uuid()); }; pushOps({entry}); auto writerPool = makeTenantMigrationWriterPool(); diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 2876d1ee99c..98507bbd809 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -817,6 +817,7 @@ env.CppUnitTest( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', + '$BUILD_DIR/mongo/db/catalog/collection_crud', '$BUILD_DIR/mongo/db/commands/cluster_server_parameter_commands_invocation', '$BUILD_DIR/mongo/db/commands/set_feature_compatibility_version_idl', '$BUILD_DIR/mongo/db/multitenancy', diff --git a/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp index 3af87160948..7e2a87e9869 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp @@ -33,6 +33,7 @@ #include <vector> #include "mongo/bson/json.h" +#include "mongo/db/catalog/collection_write_path.h" #include "mongo/db/catalog_raii.h" #include "mongo/db/concurrency/exception_util.h" #include "mongo/db/curop.h" @@ -216,7 +217,8 @@ TEST_F(ConfigInitializationTest, ReRunsIfDocRolledBackThenReElected) { } mongo::WriteUnitOfWork wuow(opCtx); for (const auto& recordId : recordIds) { - coll->deleteDocument(opCtx, kUninitializedStmtId, recordId, nullptr); + collection_internal::deleteDocument( + opCtx, *coll, kUninitializedStmtId, recordId, nullptr); } wuow.commit(); ASSERT_EQUALS(0UL, coll->numRecords(opCtx)); diff --git a/src/mongo/db/s/config_server_op_observer.cpp b/src/mongo/db/s/config_server_op_observer.cpp index b947b0de536..f45b835489e 100644 --- a/src/mongo/db/s/config_server_op_observer.cpp +++ b/src/mongo/db/s/config_server_op_observer.cpp @@ -51,11 +51,10 @@ ConfigServerOpObserver::ConfigServerOpObserver() = default; ConfigServerOpObserver::~ConfigServerOpObserver() = default; void ConfigServerOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss == VersionType::ConfigNS) { + if (coll->ns() == VersionType::ConfigNS) { if (!repl::ReplicationCoordinator::get(opCtx)->getMemberState().rollback()) { uasserted(40302, "cannot delete config.version document while in --configsvr mode"); } else { diff --git a/src/mongo/db/s/config_server_op_observer.h b/src/mongo/db/s/config_server_op_observer.h index c93992dc155..d55ba8db2cd 100644 --- a/src/mongo/db/s/config_server_op_observer.h +++ b/src/mongo/db/s/config_server_op_observer.h @@ -115,13 +115,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) override; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override {} void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override; diff --git a/src/mongo/db/s/query_analysis_op_observer.cpp b/src/mongo/db/s/query_analysis_op_observer.cpp index 658c50c992d..64270b08f50 100644 --- a/src/mongo/db/s/query_analysis_op_observer.cpp +++ b/src/mongo/db/s/query_analysis_op_observer.cpp @@ -103,29 +103,28 @@ void QueryAnalysisOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdat } void QueryAnalysisOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { if (analyze_shard_key::supportsCoordinatingQueryAnalysis()) { - if (nss == NamespaceString::kConfigQueryAnalyzersNamespace || nss == MongosType::ConfigNS) { + if (coll->ns() == NamespaceString::kConfigQueryAnalyzersNamespace || + coll->ns() == MongosType::ConfigNS) { docToDeleteDecoration(opCtx) = doc; } } } void QueryAnalysisOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { if (analyze_shard_key::supportsCoordinatingQueryAnalysis()) { - if (nss == NamespaceString::kConfigQueryAnalyzersNamespace) { + if (coll->ns() == NamespaceString::kConfigQueryAnalyzersNamespace) { auto& doc = docToDeleteDecoration(opCtx); invariant(!doc.isEmpty()); opCtx->recoveryUnit()->onCommit([opCtx, doc](boost::optional<Timestamp>) { analyze_shard_key::QueryAnalysisCoordinator::get(opCtx)->onConfigurationDelete(doc); }); - } else if (nss == MongosType::ConfigNS) { + } else if (coll->ns() == MongosType::ConfigNS) { auto& doc = docToDeleteDecoration(opCtx); invariant(!doc.isEmpty()); opCtx->recoveryUnit()->onCommit([opCtx, doc](boost::optional<Timestamp>) { diff --git a/src/mongo/db/s/query_analysis_op_observer.h b/src/mongo/db/s/query_analysis_op_observer.h index b47d1fe5c19..caa21fce0e5 100644 --- a/src/mongo/db/s/query_analysis_op_observer.h +++ b/src/mongo/db/s/query_analysis_op_observer.h @@ -112,13 +112,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/s/range_deleter_service_op_observer.cpp b/src/mongo/db/s/range_deleter_service_op_observer.cpp index 10bbbb6a924..b463a802f76 100644 --- a/src/mongo/db/s/range_deleter_service_op_observer.cpp +++ b/src/mongo/db/s/range_deleter_service_op_observer.cpp @@ -115,20 +115,18 @@ void RangeDeleterServiceOpObserver::onUpdate(OperationContext* opCtx, } void RangeDeleterServiceOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss == NamespaceString::kRangeDeletionNamespace) { + if (coll->ns() == NamespaceString::kRangeDeletionNamespace) { deletedDocumentDecoration(opCtx) = doc; } } void RangeDeleterServiceOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss == NamespaceString::kRangeDeletionNamespace) { + if (coll->ns() == NamespaceString::kRangeDeletionNamespace) { const auto& deletedDoc = deletedDocumentDecoration(opCtx); auto deletionTask = diff --git a/src/mongo/db/s/range_deleter_service_op_observer.h b/src/mongo/db/s/range_deleter_service_op_observer.h index 264dec90134..a53393e8b73 100644 --- a/src/mongo/db/s/range_deleter_service_op_observer.h +++ b/src/mongo/db/s/range_deleter_service_op_observer.h @@ -66,13 +66,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) override; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override; diff --git a/src/mongo/db/s/resharding/resharding_destined_recipient_test.cpp b/src/mongo/db/s/resharding/resharding_destined_recipient_test.cpp index c41381c3a61..484a4a28bf0 100644 --- a/src/mongo/db/s/resharding/resharding_destined_recipient_test.cpp +++ b/src/mongo/db/s/resharding/resharding_destined_recipient_test.cpp @@ -283,7 +283,7 @@ protected: WriteUnitOfWork wuow(opCtx); OpDebug opDebug; - coll->deleteDocument(opCtx, kUninitializedStmtId, rid, &opDebug); + collection_internal::deleteDocument(opCtx, *coll, kUninitializedStmtId, rid, &opDebug); wuow.commit(); } diff --git a/src/mongo/db/s/resharding/resharding_op_observer.cpp b/src/mongo/db/s/resharding/resharding_op_observer.cpp index 840381f7942..882c7af07dd 100644 --- a/src/mongo/db/s/resharding/resharding_op_observer.cpp +++ b/src/mongo/db/s/resharding/resharding_op_observer.cpp @@ -249,11 +249,10 @@ void ReshardingOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEn } void ReshardingOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss == NamespaceString::kDonorReshardingOperationsNamespace) { + if (coll->ns() == NamespaceString::kDonorReshardingOperationsNamespace) { _doPin(opCtx); } } diff --git a/src/mongo/db/s/resharding/resharding_op_observer.h b/src/mongo/db/s/resharding/resharding_op_observer.h index 3cedd23dd6d..315afd4d9fd 100644 --- a/src/mongo/db/s/resharding/resharding_op_observer.h +++ b/src/mongo/db/s/resharding/resharding_op_observer.h @@ -130,13 +130,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) override; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override {} void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override; diff --git a/src/mongo/db/s/resharding/resharding_service_test_helpers.h b/src/mongo/db/s/resharding/resharding_service_test_helpers.h index 73e06640595..97714870963 100644 --- a/src/mongo/db/s/resharding/resharding_service_test_helpers.h +++ b/src/mongo/db/s/resharding/resharding_service_test_helpers.h @@ -176,11 +176,10 @@ public: } void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override { - if (nss != _stateDocumentNss) { + if (coll->ns() != _stateDocumentNss) { return; } diff --git a/src/mongo/db/s/shard_server_op_observer.cpp b/src/mongo/db/s/shard_server_op_observer.cpp index 352285de2ed..4253499fec9 100644 --- a/src/mongo/db/s/shard_server_op_observer.cpp +++ b/src/mongo/db/s/shard_server_op_observer.cpp @@ -507,12 +507,11 @@ void ShardServerOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateE } void ShardServerOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss == NamespaceString::kCollectionCriticalSectionsNamespace || - nss == NamespaceString::kRangeDeletionNamespace) { + if (coll->ns() == NamespaceString::kCollectionCriticalSectionsNamespace || + coll->ns() == NamespaceString::kRangeDeletionNamespace) { documentIdDecoration(opCtx) = doc; } else { // Extract the _id field from the document. If it does not have an _id, use the @@ -556,10 +555,10 @@ void ShardServerOpObserver::onModifyShardedCollectionGlobalIndexCatalogEntry( } void ShardServerOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { + const auto& nss = coll->ns(); auto& documentId = documentIdDecoration(opCtx); invariant(!documentId.isEmpty()); diff --git a/src/mongo/db/s/shard_server_op_observer.h b/src/mongo/db/s/shard_server_op_observer.h index 2d6388a5c98..a17a0666dca 100644 --- a/src/mongo/db/s/shard_server_op_observer.h +++ b/src/mongo/db/s/shard_server_op_observer.h @@ -112,13 +112,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) override; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) override; diff --git a/src/mongo/db/s/sharding_recovery_service_test.cpp b/src/mongo/db/s/sharding_recovery_service_test.cpp index 4825ce6ce9b..c39229e4c00 100644 --- a/src/mongo/db/s/sharding_recovery_service_test.cpp +++ b/src/mongo/db/s/sharding_recovery_service_test.cpp @@ -614,13 +614,8 @@ TEST_F(ShardingRecoveryServiceTestOnSecondary, BlockAndUnblockOperationsOnDataba { WriteUnitOfWork wuow(opCtx()); AutoGetDb db(opCtx(), dbName.dbName(), MODE_IS); - opObserver().aboutToDelete( - opCtx(), criticalSectionColl()->ns(), criticalSectionColl()->uuid(), doc.toBSON()); - opObserver().onDelete(opCtx(), - criticalSectionColl()->ns(), - criticalSectionColl()->uuid(), - kUninitializedStmtId, - {}); + opObserver().aboutToDelete(opCtx(), criticalSectionColl(), doc.toBSON()); + opObserver().onDelete(opCtx(), criticalSectionColl(), kUninitializedStmtId, {}); wuow.commit(); } @@ -684,13 +679,8 @@ TEST_F(ShardingRecoveryServiceTestOnSecondary, BlockAndUnblockOperationsOnCollec { WriteUnitOfWork wuow(opCtx()); AutoGetCollection coll(opCtx(), collNss, MODE_IS); - opObserver().aboutToDelete( - opCtx(), criticalSectionColl()->ns(), criticalSectionColl()->uuid(), doc.toBSON()); - opObserver().onDelete(opCtx(), - criticalSectionColl()->ns(), - criticalSectionColl()->uuid(), - kUninitializedStmtId, - {}); + opObserver().aboutToDelete(opCtx(), criticalSectionColl(), doc.toBSON()); + opObserver().onDelete(opCtx(), criticalSectionColl(), kUninitializedStmtId, {}); wuow.commit(); } diff --git a/src/mongo/db/serverless/shard_split_donor_op_observer.cpp b/src/mongo/db/serverless/shard_split_donor_op_observer.cpp index 54e33417d40..7f43900fa05 100644 --- a/src/mongo/db/serverless/shard_split_donor_op_observer.cpp +++ b/src/mongo/db/serverless/shard_split_donor_op_observer.cpp @@ -357,10 +357,9 @@ void ShardSplitDonorOpObserver::onUpdate(OperationContext* opCtx, } void ShardSplitDonorOpObserver::aboutToDelete(OperationContext* opCtx, - NamespaceString const& nss, - const UUID& uuid, + const CollectionPtr& coll, BSONObj const& doc) { - if (nss != NamespaceString::kShardSplitDonorsNamespace || + if (coll->ns() != NamespaceString::kShardSplitDonorsNamespace || tenant_migration_access_blocker::inRecoveryMode(opCtx)) { return; } @@ -390,11 +389,10 @@ void ShardSplitDonorOpObserver::aboutToDelete(OperationContext* opCtx, } void ShardSplitDonorOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { - if (nss != NamespaceString::kShardSplitDonorsNamespace || !splitCleanupDetails(opCtx) || + if (coll->ns() != NamespaceString::kShardSplitDonorsNamespace || !splitCleanupDetails(opCtx) || tenant_migration_access_blocker::inRecoveryMode(opCtx)) { return; } diff --git a/src/mongo/db/serverless/shard_split_donor_op_observer.h b/src/mongo/db/serverless/shard_split_donor_op_observer.h index efe1d43fc3b..092b9f1f1f7 100644 --- a/src/mongo/db/serverless/shard_split_donor_op_observer.h +++ b/src/mongo/db/serverless/shard_split_donor_op_observer.h @@ -111,13 +111,11 @@ public: void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; diff --git a/src/mongo/db/serverless/shard_split_donor_op_observer_test.cpp b/src/mongo/db/serverless/shard_split_donor_op_observer_test.cpp index b644356c301..cc679386b00 100644 --- a/src/mongo/db/serverless/shard_split_donor_op_observer_test.cpp +++ b/src/mongo/db/serverless/shard_split_donor_op_observer_test.cpp @@ -467,17 +467,13 @@ TEST_F(ShardSplitDonorOpObserverTest, DeleteAbortedDocumentDoesNotRemoveBlockers auto bsonDoc = stateDocument.toBSON(); WriteUnitOfWork wuow(_opCtx.get()); - _observer->aboutToDelete( - _opCtx.get(), NamespaceString::kShardSplitDonorsNamespace, UUID::gen(), bsonDoc); + AutoGetCollection autoColl(_opCtx.get(), NamespaceString::kShardSplitDonorsNamespace, MODE_IX); + _observer->aboutToDelete(_opCtx.get(), *autoColl, bsonDoc); OplogDeleteEntryArgs deleteArgs; deleteArgs.deletedDoc = &bsonDoc; - _observer->onDelete(_opCtx.get(), - NamespaceString::kShardSplitDonorsNamespace, - UUID::gen(), - 0 /* stmtId */, - deleteArgs); + _observer->onDelete(_opCtx.get(), *autoColl, 0 /* stmtId */, deleteArgs); wuow.commit(); // Verify blockers have not been removed @@ -509,17 +505,13 @@ TEST_F(ShardSplitDonorOpObserverTest, DeleteCommittedDocumentRemovesBlockers) { auto bsonDoc = stateDocument.toBSON(); WriteUnitOfWork wuow(_opCtx.get()); - _observer->aboutToDelete( - _opCtx.get(), NamespaceString::kShardSplitDonorsNamespace, UUID::gen(), bsonDoc); + AutoGetCollection autoColl(_opCtx.get(), NamespaceString::kShardSplitDonorsNamespace, MODE_IX); + _observer->aboutToDelete(_opCtx.get(), *autoColl, bsonDoc); OplogDeleteEntryArgs deleteArgs; deleteArgs.deletedDoc = &bsonDoc; - _observer->onDelete(_opCtx.get(), - NamespaceString::kShardSplitDonorsNamespace, - UUID::gen(), - 0 /* stmtId */, - deleteArgs); + _observer->onDelete(_opCtx.get(), *autoColl, 0 /* stmtId */, deleteArgs); wuow.commit(); // Verify blockers have been removed diff --git a/src/mongo/db/transaction/transaction_participant_test.cpp b/src/mongo/db/transaction/transaction_participant_test.cpp index 971b81d2a91..ec1ce45ec07 100644 --- a/src/mongo/db/transaction/transaction_participant_test.cpp +++ b/src/mongo/db/transaction/transaction_participant_test.cpp @@ -4516,7 +4516,8 @@ TEST_F(TxnParticipantTest, OldestActiveTransactionTimestamp) { } if (bson["startOpTime"]["ts"].timestamp() == ts) { - coll->deleteDocument(opCtx(), kUninitializedStmtId, record->id, nullptr); + collection_internal::deleteDocument( + opCtx(), coll, kUninitializedStmtId, record->id, nullptr); wuow.commit(); return; } diff --git a/src/mongo/dbtests/multikey_paths_test.cpp b/src/mongo/dbtests/multikey_paths_test.cpp index 69dc9294fba..220f9a1a792 100644 --- a/src/mongo/dbtests/multikey_paths_test.cpp +++ b/src/mongo/dbtests/multikey_paths_test.cpp @@ -354,7 +354,8 @@ TEST_F(MultikeyPathsTest, PathsNotUpdatedOnDocumentDelete) { { WriteUnitOfWork wuow(_opCtx.get()); OpDebug* const nullOpDebug = nullptr; - collection->deleteDocument(_opCtx.get(), kUninitializedStmtId, record->id, nullOpDebug); + collection_internal::deleteDocument( + _opCtx.get(), *collection, kUninitializedStmtId, record->id, nullOpDebug); wuow.commit(); } } diff --git a/src/mongo/dbtests/query_stage_batched_delete.cpp b/src/mongo/dbtests/query_stage_batched_delete.cpp index f036e5e3d14..95186d1fe0b 100644 --- a/src/mongo/dbtests/query_stage_batched_delete.cpp +++ b/src/mongo/dbtests/query_stage_batched_delete.cpp @@ -63,8 +63,7 @@ static const Milliseconds targetBatchTimeMS = Milliseconds(5); class ClockAdvancingOpObserver : public OpObserverNoop { public: void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) override { if (docDurationMap.find(doc) != docDurationMap.end()) { diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp index 6fe3479d4d9..29ff81184ca 100644 --- a/src/mongo/dbtests/query_stage_count.cpp +++ b/src/mongo/dbtests/query_stage_count.cpp @@ -116,7 +116,8 @@ public: void remove(const RecordId& recordId) { WriteUnitOfWork wunit(&_opCtx); OpDebug* const nullOpDebug = nullptr; - _coll->deleteDocument(&_opCtx, kUninitializedStmtId, recordId, nullOpDebug); + collection_internal::deleteDocument( + &_opCtx, _coll, kUninitializedStmtId, recordId, nullOpDebug); wunit.commit(); } diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp index 8afd2d9ff81..d90f336fe2d 100644 --- a/src/mongo/dbtests/query_stage_sort.cpp +++ b/src/mongo/dbtests/query_stage_sort.cpp @@ -506,7 +506,8 @@ public: set<RecordId>::iterator it = recordIds.begin(); { WriteUnitOfWork wuow(&_opCtx); - coll->deleteDocument(&_opCtx, kUninitializedStmtId, *it++, nullOpDebug); + collection_internal::deleteDocument( + &_opCtx, coll, kUninitializedStmtId, *it++, nullOpDebug); wuow.commit(); } exec->restoreState(&coll); @@ -522,7 +523,8 @@ public: while (it != recordIds.end()) { { WriteUnitOfWork wuow(&_opCtx); - coll->deleteDocument(&_opCtx, kUninitializedStmtId, *it++, nullOpDebug); + collection_internal::deleteDocument( + &_opCtx, coll, kUninitializedStmtId, *it++, nullOpDebug); wuow.commit(); } } diff --git a/src/mongo/idl/cluster_server_parameter_op_observer.cpp b/src/mongo/idl/cluster_server_parameter_op_observer.cpp index 4a7e7cc4c86..e4cb12faae9 100644 --- a/src/mongo/idl/cluster_server_parameter_op_observer.cpp +++ b/src/mongo/idl/cluster_server_parameter_op_observer.cpp @@ -82,14 +82,13 @@ void ClusterServerParameterOpObserver::onUpdate(OperationContext* opCtx, } void ClusterServerParameterOpObserver::aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) { std::string docBeingDeleted; - if (isConfigNamespace(nss)) { + if (isConfigNamespace(coll->ns())) { // Store the tenantId associated with the doc to be deleted. - tenantIdToDelete(opCtx) = nss.dbName().tenantId(); + tenantIdToDelete(opCtx) = coll->ns().dbName().tenantId(); auto elem = doc[kIdField]; if (elem.type() == String) { docBeingDeleted = elem.str(); @@ -111,8 +110,7 @@ void ClusterServerParameterOpObserver::aboutToDelete(OperationContext* opCtx, } void ClusterServerParameterOpObserver::onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) { const auto& docName = aboutToDeleteDoc(opCtx); diff --git a/src/mongo/idl/cluster_server_parameter_op_observer.h b/src/mongo/idl/cluster_server_parameter_op_observer.h index 2b378c98fe3..7c8b3657e1a 100644 --- a/src/mongo/idl/cluster_server_parameter_op_observer.h +++ b/src/mongo/idl/cluster_server_parameter_op_observer.h @@ -64,12 +64,10 @@ public: const BSONObj& docKey) final {} void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final; void aboutToDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, const BSONObj& doc) final; void onDelete(OperationContext* opCtx, - const NamespaceString& nss, - const UUID& uuid, + const CollectionPtr& coll, StmtId stmtId, const OplogDeleteEntryArgs& args) final; void onDropDatabase(OperationContext* opCtx, const DatabaseName& dbName) final; diff --git a/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp b/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp index 843c13e0cb6..e6edd93fd04 100644 --- a/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp +++ b/src/mongo/idl/cluster_server_parameter_op_observer_test.cpp @@ -87,11 +87,11 @@ public: void doDelete(const NamespaceString& nss, BSONObj deletedDoc, bool includeDeletedDoc = true) { auto opCtx = cc().makeOperationContext(); - auto uuid = UUID::gen(); - observer.aboutToDelete(opCtx.get(), nss, uuid, deletedDoc); + AutoGetCollection autoColl(opCtx.get(), nss, MODE_IX); + observer.aboutToDelete(opCtx.get(), *autoColl, deletedDoc); OplogDeleteEntryArgs args; args.deletedDoc = includeDeletedDoc ? &deletedDoc : nullptr; - observer.onDelete(opCtx.get(), nss, uuid, 1 /* StmtId */, args); + observer.onDelete(opCtx.get(), *autoColl, 1 /* StmtId */, args); } void doDropDatabase(const DatabaseName& dbname) { |