diff options
author | Maria van Keulen <maria.vankeulen@mongodb.com> | 2020-01-07 15:15:10 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2020-01-07 15:15:10 +0000 |
commit | cb293d4de806e8089e4fb08926124ed18b2fa578 (patch) | |
tree | f073318c41619271ff050855b5b80fc1d6f957bb /src/mongo | |
parent | 47a810f853921657acb78db1110590c0c380091f (diff) | |
download | mongo-cb293d4de806e8089e4fb08926124ed18b2fa578.tar.gz |
SERVER-44139 Allow collection creation in multi-document transactions
This commit allows the feature for single-node replica sets only.
Diffstat (limited to 'src/mongo')
39 files changed, 206 insertions, 123 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 580367c9016..6ffcf7467ba 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -58,6 +58,7 @@ env.Library( '$BUILD_DIR/mongo/db/index/index_descriptor', '$BUILD_DIR/mongo/db/op_observer', '$BUILD_DIR/mongo/db/op_observer_util', + '$BUILD_DIR/mongo/db/repl/oplog_entry', '$BUILD_DIR/mongo/db/s/sharding_api_d', ] ) diff --git a/src/mongo/db/auth/auth_op_observer.cpp b/src/mongo/db/auth/auth_op_observer.cpp index df979414ba6..60db0b23f77 100644 --- a/src/mongo/db/auth/auth_op_observer.cpp +++ b/src/mongo/db/auth/auth_op_observer.cpp @@ -35,6 +35,7 @@ #include "mongo/db/catalog/collection_options.h" #include "mongo/db/op_observer_util.h" #include "mongo/db/operation_context.h" +#include "mongo/db/repl/oplog_entry.h" namespace mongo { @@ -101,7 +102,8 @@ void AuthOpObserver::onCreateCollection(OperationContext* opCtx, const OplogSlot& createOpTime) { const auto cmdNss = collectionName.getCommandNS(); - const auto cmdObj = makeCreateCollCmdObj(collectionName, options, idIndex); + const auto cmdObj = + repl::MutableOplogEntry::makeCreateCollCmdObj(collectionName, options, idIndex); AuthorizationManager::get(opCtx->getServiceContext()) ->logOp(opCtx, "c", cmdNss, cmdObj, nullptr); diff --git a/src/mongo/db/catalog/create_collection.cpp b/src/mongo/db/catalog/create_collection.cpp index dc841b95b2c..75754ad4da3 100644 --- a/src/mongo/db/catalog/create_collection.cpp +++ b/src/mongo/db/catalog/create_collection.cpp @@ -190,6 +190,10 @@ Status createCollection(OperationContext* opCtx, } if (collectionOptions.isView()) { + uassert(ErrorCodes::OperationNotSupportedInTransaction, + str::stream() << "Cannot create a view in a multi-document " + "transaction.", + !opCtx->inMultiDocumentTransaction()); return _createView(opCtx, nss, collectionOptions, idIndex); } else { return _createCollection(opCtx, nss, collectionOptions, idIndex); diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp index 85e184b7036..148ccf20cfb 100644 --- a/src/mongo/db/catalog/index_build_block.cpp +++ b/src/mongo/db/catalog/index_build_block.cpp @@ -171,8 +171,9 @@ void IndexBuildBlock::success(OperationContext* opCtx, Collection* collection) { log() << "index build: done building index " << _indexName << " on ns " << _nss; collection->indexBuildSuccess(opCtx, _indexCatalogEntry); + auto svcCtx = opCtx->getClient()->getServiceContext(); - opCtx->recoveryUnit()->onCommit([opCtx, entry = _indexCatalogEntry, coll = collection]( + opCtx->recoveryUnit()->onCommit([svcCtx, entry = _indexCatalogEntry, coll = collection]( boost::optional<Timestamp> commitTime) { // Note: this runs after the WUOW commits but before we release our X lock on the // collection. This means that any snapshot created after this must include the full @@ -182,7 +183,7 @@ void IndexBuildBlock::success(OperationContext* opCtx, Collection* collection) { // timestamp. We use the cluster time since it's guaranteed to be greater than the // time of the index build. It is possible the cluster time could be in the future, // and we will need to do another write to reach the minimum visible snapshot. - commitTime = LogicalClock::getClusterTimeForReplicaSet(opCtx).asTimestamp(); + commitTime = LogicalClock::getClusterTimeForReplicaSet(svcCtx).asTimestamp(); } entry->setMinimumVisibleSnapshot(commitTime.get()); // We must also set the minimum visible snapshot on the collection like during init(). diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index 8f50b465447..043161e9fb7 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -376,7 +376,8 @@ IndexCatalogEntry* IndexCatalogImpl::createIndexEntry(OperationContext* opCtx, _buildingIndexes.add(std::move(entry)); } - if (!initFromDisk) { + if (!initFromDisk && + UncommittedCollections::getForTxn(opCtx, descriptorPtr->parentNS()) == nullptr) { opCtx->recoveryUnit()->onRollback([this, opCtx, isReadyIndex, descriptor = descriptorPtr] { // Need to preserve indexName as descriptor no longer exists after remove(). const std::string indexName = descriptor->indexName(); @@ -1607,14 +1608,17 @@ void IndexCatalogImpl::indexBuildSuccess(OperationContext* opCtx, IndexCatalogEn index->setIndexBuildInterceptor(nullptr); index->setIsReady(true); - opCtx->recoveryUnit()->onRollback([this, index, interceptor]() { - auto releasedEntry = _readyIndexes.release(index->descriptor()); - invariant(releasedEntry.get() == index); - _buildingIndexes.add(std::move(releasedEntry)); + // Only roll back index changes that are part of pre-existing collections. + if (UncommittedCollections::getForTxn(opCtx, index->descriptor()->parentNS()) == nullptr) { + opCtx->recoveryUnit()->onRollback([this, index, interceptor]() { + auto releasedEntry = _readyIndexes.release(index->descriptor()); + invariant(releasedEntry.get() == index); + _buildingIndexes.add(std::move(releasedEntry)); - index->setIndexBuildInterceptor(interceptor); - index->setIsReady(false); - }); + index->setIndexBuildInterceptor(interceptor); + index->setIsReady(false); + }); + } } StatusWith<BSONObj> IndexCatalogImpl::_fixIndexSpec(OperationContext* opCtx, diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index e67e02b8c85..0df24b22613 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -110,11 +110,12 @@ bool checkAuthorizationImplPreParse(OperationContext* opCtx, } // The command names that are allowed in a multi-document transaction. +const StringMap<int> txnCmdWhitelistFCV44 = { + {"create", 1}, {"createIndexes", 1}, {"_configsvrCreateCollection", 1}}; const StringMap<int> txnCmdWhitelist = {{"abortTransaction", 1}, {"aggregate", 1}, {"commitTransaction", 1}, {"coordinateCommitTransaction", 1}, - {"createIndexes", 1}, {"delete", 1}, {"distinct", 1}, {"find", 1}, @@ -443,9 +444,21 @@ void CommandHelpers::canUseTransactions(const NamespaceString& nss, "http://dochub.mongodb.org/core/transaction-count for a recommended alternative.", cmdName != "count"_sd); + auto inTxnWhitelist = txnCmdWhitelist.find(cmdName) != txnCmdWhitelist.cend(); + auto inTxnWhitelistFCV44 = txnCmdWhitelistFCV44.find(cmdName) != txnCmdWhitelistFCV44.cend(); + auto isFullyUpgradedTo44 = + (serverGlobalParams.featureCompatibility.getVersion() == + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44); + + uassert(ErrorCodes::OperationNotSupportedInTransaction, + str::stream() << "Cannot run '" << cmdName + << "' in a multi-document transaction unless the " + "featureCompatibilityVersion is equal to 4.4.", + isFullyUpgradedTo44 || !inTxnWhitelistFCV44); + uassert(ErrorCodes::OperationNotSupportedInTransaction, str::stream() << "Cannot run '" << cmdName << "' in a multi-document transaction.", - txnCmdWhitelist.find(cmdName) != txnCmdWhitelist.cend()); + inTxnWhitelist || inTxnWhitelistFCV44); const auto dbName = nss.db(); diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp index 6b2b702d38b..55b4857c1d7 100644 --- a/src/mongo/db/commands/create_indexes.cpp +++ b/src/mongo/db/commands/create_indexes.cpp @@ -471,7 +471,7 @@ BSONObj runCreateIndexesOnNewCollection(OperationContext* opCtx, auto createStatus = createCollection(opCtx, ns.db().toString(), builder.obj().getOwned(), idIndexSpec); - if (!UncommittedCollections::get(opCtx).hasExclusiveAccessToCollection(opCtx, ns)) { + if (createStatus == ErrorCodes::NamespaceExists) { // We should retry the createIndexes command so we can perform the checks for index // and/or collection existence again. throw WriteConflictException(); diff --git a/src/mongo/db/logical_clock.cpp b/src/mongo/db/logical_clock.cpp index 5cc982465d9..6dea3e7acdc 100644 --- a/src/mongo/db/logical_clock.cpp +++ b/src/mongo/db/logical_clock.cpp @@ -52,14 +52,18 @@ bool lessThanOrEqualToMaxPossibleTime(LogicalTime time, uint64_t nTicks) { } } // namespace -LogicalTime LogicalClock::getClusterTimeForReplicaSet(OperationContext* opCtx) { +LogicalTime LogicalClock::getClusterTimeForReplicaSet(ServiceContext* svcCtx) { if (getGlobalReplSettings().usingReplSets()) { - return get(opCtx)->getClusterTime(); + return get(svcCtx)->getClusterTime(); } return {}; } +LogicalTime LogicalClock::getClusterTimeForReplicaSet(OperationContext* opCtx) { + return getClusterTimeForReplicaSet(opCtx->getClient()->getServiceContext()); +} + LogicalClock* LogicalClock::get(ServiceContext* service) { return getLogicalClock(service).get(); } diff --git a/src/mongo/db/logical_clock.h b/src/mongo/db/logical_clock.h index 28191be87f6..ec4bddc518a 100644 --- a/src/mongo/db/logical_clock.h +++ b/src/mongo/db/logical_clock.h @@ -53,6 +53,7 @@ public: * Returns the current cluster time if this is a replica set node, otherwise returns a null * logical time. */ + static LogicalTime getClusterTimeForReplicaSet(ServiceContext* svcCtx); static LogicalTime getClusterTimeForReplicaSet(OperationContext* opCtx); /** diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp index 1644ff3b582..4966ef4b333 100644 --- a/src/mongo/db/op_observer_impl.cpp +++ b/src/mongo/db/op_observer_impl.cpp @@ -608,13 +608,27 @@ void OpObserverImpl::onCreateCollection(OperationContext* opCtx, const CollectionOptions& options, const BSONObj& idIndex, const OplogSlot& createOpTime) { - if (!collectionName.isSystemDotProfile()) { - // do not replicate system.profile modifications + // do not replicate system.profile modifications + if (collectionName.isSystemDotProfile()) { + return; + } + + auto txnParticipant = TransactionParticipant::get(opCtx); + const bool inMultiDocumentTransaction = + txnParticipant && opCtx->writesAreReplicated() && txnParticipant.transactionIsOpen(); + + if (inMultiDocumentTransaction) { + invariant(serverGlobalParams.featureCompatibility.getVersion() == + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44); + auto operation = MutableOplogEntry::makeCreateCommand(collectionName, options, idIndex); + txnParticipant.addTransactionOperation(opCtx, operation); + } else { MutableOplogEntry oplogEntry; oplogEntry.setOpType(repl::OpTypeEnum::kCommand); oplogEntry.setNss(collectionName.getCommandNS()); oplogEntry.setUuid(options.uuid); - oplogEntry.setObject(makeCreateCollCmdObj(collectionName, options, idIndex)); + oplogEntry.setObject( + MutableOplogEntry::makeCreateCollCmdObj(collectionName, options, idIndex)); oplogEntry.setOpTime(createOpTime); logOperation(opCtx, &oplogEntry); } diff --git a/src/mongo/db/op_observer_util.cpp b/src/mongo/db/op_observer_util.cpp index b1bc7074915..9c03a37a3db 100644 --- a/src/mongo/db/op_observer_util.cpp +++ b/src/mongo/db/op_observer_util.cpp @@ -65,28 +65,4 @@ BSONObj makeCollModCmdObj(const BSONObj& collModCmd, return cmdObjBuilder.obj(); } -BSONObj makeCreateCollCmdObj(const NamespaceString& collectionName, - const CollectionOptions& options, - const BSONObj& idIndex) { - BSONObjBuilder b; - b.append("create", collectionName.coll().toString()); - { - // Don't store the UUID as part of the options, but instead only at the top level - CollectionOptions optionsToStore = options; - optionsToStore.uuid.reset(); - b.appendElements(optionsToStore.toBSON()); - } - - // Include the full _id index spec in the oplog for index versions >= 2. - if (!idIndex.isEmpty()) { - auto versionElem = idIndex[IndexDescriptor::kIndexVersionFieldName]; - invariant(versionElem.isNumber()); - if (IndexDescriptor::IndexVersion::kV2 <= - static_cast<IndexDescriptor::IndexVersion>(versionElem.numberInt())) { - b.append("idIndex", idIndex); - } - } - - return b.obj(); -} } // namespace mongo diff --git a/src/mongo/db/op_observer_util.h b/src/mongo/db/op_observer_util.h index 7e60c66cca8..800a1486d4d 100644 --- a/src/mongo/db/op_observer_util.h +++ b/src/mongo/db/op_observer_util.h @@ -34,11 +34,6 @@ #include "mongo/db/op_observer.h" namespace mongo { - -BSONObj makeCreateCollCmdObj(const NamespaceString& collectionName, - const CollectionOptions& options, - const BSONObj& idIndex); - BSONObj makeCollModCmdObj(const BSONObj& collModCmd, const CollectionOptions& oldCollOptions, boost::optional<TTLCollModInfo> ttlInfo); diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 4b672142624..391f09637df 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -179,11 +179,11 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/idl/idl_parser', - '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/catalog/health_log', '$BUILD_DIR/mongo/db/db_raii', ], LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/query_exec', '$BUILD_DIR/mongo/util/md5', ], @@ -488,6 +488,7 @@ env.Library( 'optime_and_wall_time_base', '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/logical_session_id', + '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/idl/idl_parser', ], ) diff --git a/src/mongo/db/repl/oplog_entry.cpp b/src/mongo/db/repl/oplog_entry.cpp index 4da5afdc4dc..787e54f0384 100644 --- a/src/mongo/db/repl/oplog_entry.cpp +++ b/src/mongo/db/repl/oplog_entry.cpp @@ -33,6 +33,7 @@ #include "mongo/db/repl/oplog_entry.h" +#include "mongo/db/index/index_descriptor.h" #include "mongo/db/namespace_string.h" #include "mongo/util/log.h" #include "mongo/util/time_support.h" @@ -164,6 +165,31 @@ ReplOperation MutableOplogEntry::makeInsertOperation(const NamespaceString& nss, return op; } +BSONObj MutableOplogEntry::makeCreateCollCmdObj(const NamespaceString& collectionName, + const CollectionOptions& options, + const BSONObj& idIndex) { + BSONObjBuilder b; + b.append("create", collectionName.coll().toString()); + { + // Don't store the UUID as part of the options, but instead only at the top level + CollectionOptions optionsToStore = options; + optionsToStore.uuid.reset(); + b.appendElements(optionsToStore.toBSON()); + } + + // Include the full _id index spec in the oplog for index versions >= 2. + if (!idIndex.isEmpty()) { + auto versionElem = idIndex[IndexDescriptor::kIndexVersionFieldName]; + invariant(versionElem.isNumber()); + if (IndexDescriptor::IndexVersion::kV2 <= + static_cast<IndexDescriptor::IndexVersion>(versionElem.numberInt())) { + b.append("idIndex", idIndex); + } + } + + return b.obj(); +} + ReplOperation MutableOplogEntry::makeUpdateOperation(const NamespaceString nss, boost::optional<UUID> uuid, const BSONObj& update, @@ -177,6 +203,18 @@ ReplOperation MutableOplogEntry::makeUpdateOperation(const NamespaceString nss, return op; } +ReplOperation MutableOplogEntry::makeCreateCommand(const NamespaceString nss, + const CollectionOptions& options, + const BSONObj& idIndex) { + + ReplOperation op; + op.setOpType(OpTypeEnum::kCommand); + op.setNss(nss.getCommandNS()); + op.setUuid(options.uuid); + op.setObject(makeCreateCollCmdObj(nss, options, idIndex)); + return op; +} + ReplOperation MutableOplogEntry::makeDeleteOperation(const NamespaceString& nss, boost::optional<UUID> uuid, const BSONObj& docToDelete) { diff --git a/src/mongo/db/repl/oplog_entry.h b/src/mongo/db/repl/oplog_entry.h index c01b2766d1b..b1678b37267 100644 --- a/src/mongo/db/repl/oplog_entry.h +++ b/src/mongo/db/repl/oplog_entry.h @@ -31,6 +31,7 @@ #include "mongo/bson/bsonobj.h" #include "mongo/bson/simple_bsonobj_comparator.h" +#include "mongo/db/catalog/collection_options.h" #include "mongo/db/logical_session_id.h" #include "mongo/db/repl/apply_ops_gen.h" #include "mongo/db/repl/oplog_entry_gen.h" @@ -90,6 +91,14 @@ public: boost::optional<UUID> uuid, const BSONObj& docToDelete); + static ReplOperation makeCreateCommand(const NamespaceString nss, + const mongo::CollectionOptions& options, + const BSONObj& idIndex); + + static BSONObj makeCreateCollCmdObj(const NamespaceString& collectionName, + const mongo::CollectionOptions& options, + const BSONObj& idIndex); + static StatusWith<MutableOplogEntry> parse(const BSONObj& object); MutableOplogEntry() : OplogEntryBase() {} @@ -213,6 +222,7 @@ public: // Make helper functions accessible. using MutableOplogEntry::getOpTime; + using MutableOplogEntry::makeCreateCommand; using MutableOplogEntry::makeDeleteOperation; using MutableOplogEntry::makeInsertOperation; using MutableOplogEntry::makeUpdateOperation; diff --git a/src/mongo/db/storage/biggie/biggie_kv_engine.cpp b/src/mongo/db/storage/biggie/biggie_kv_engine.cpp index 370ececd244..2a43de99a32 100644 --- a/src/mongo/db/storage/biggie/biggie_kv_engine.cpp +++ b/src/mongo/db/storage/biggie/biggie_kv_engine.cpp @@ -118,21 +118,20 @@ std::unique_ptr<mongo::SortedDataInterface> KVEngine::getSortedDataInterface( return std::make_unique<SortedDataInterface>(opCtx, ident, desc); } -Status KVEngine::dropIdent(OperationContext* opCtx, StringData ident) { +Status KVEngine::dropIdent(OperationContext* opCtx, mongo::RecoveryUnit* ru, StringData ident) { Status dropStatus = Status::OK(); if (_idents.count(ident.toString()) > 0) { // Check if the ident is a RecordStore or a SortedDataInterface then call the corresponding // truncate. A true value in the map means it is a RecordStore, false a SortedDataInterface. if (_idents[ident.toString()] == true) { // ident is RecordStore. CollectionOptions s; - auto rs = getRecordStore(opCtx, ""_sd, ident, s); - dropStatus = checked_cast<RecordStore*>(rs.get()) - ->truncateWithoutUpdatingCount(opCtx) - .getStatus(); + auto rs = getRecordStore(/*unused*/ opCtx, ""_sd, ident, s); + dropStatus = + checked_cast<RecordStore*>(rs.get())->truncateWithoutUpdatingCount(ru).getStatus(); } else { // ident is SortedDataInterface. auto sdi = std::make_unique<SortedDataInterface>(Ordering::make(BSONObj()), true, ident); - dropStatus = sdi->truncate(opCtx); + dropStatus = sdi->truncate(ru); } _idents.erase(ident.toString()); } diff --git a/src/mongo/db/storage/biggie/biggie_kv_engine.h b/src/mongo/db/storage/biggie/biggie_kv_engine.h index a9a3582cfdd..2ce35d07cbf 100644 --- a/src/mongo/db/storage/biggie/biggie_kv_engine.h +++ b/src/mongo/db/storage/biggie/biggie_kv_engine.h @@ -80,7 +80,7 @@ public: virtual void endBackup(OperationContext* opCtx) {} - virtual Status dropIdent(OperationContext* opCtx, StringData ident); + virtual Status dropIdent(OperationContext* opCtx, mongo::RecoveryUnit* ru, StringData ident); virtual bool supportsDocLocking() const { return true; diff --git a/src/mongo/db/storage/biggie/biggie_record_store.cpp b/src/mongo/db/storage/biggie/biggie_record_store.cpp index c4c0c698456..05d325f7bb2 100644 --- a/src/mongo/db/storage/biggie/biggie_record_store.cpp +++ b/src/mongo/db/storage/biggie/biggie_record_store.cpp @@ -226,16 +226,17 @@ std::unique_ptr<SeekableRecordCursor> RecordStore::getCursor(OperationContext* o Status RecordStore::truncate(OperationContext* opCtx) { SizeAdjuster adjuster(opCtx, this); - StatusWith<int64_t> s = truncateWithoutUpdatingCount(opCtx); + StatusWith<int64_t> s = + truncateWithoutUpdatingCount(checked_cast<biggie::RecoveryUnit*>(opCtx->recoveryUnit())); if (!s.isOK()) return s.getStatus(); return Status::OK(); } -StatusWith<int64_t> RecordStore::truncateWithoutUpdatingCount(OperationContext* opCtx) { - auto ru = RecoveryUnit::get(opCtx); - StringStore* workingCopy(ru->getHead()); +StatusWith<int64_t> RecordStore::truncateWithoutUpdatingCount(mongo::RecoveryUnit* ru) { + auto bRu = checked_cast<biggie::RecoveryUnit*>(ru); + StringStore* workingCopy(bRu->getHead()); StringStore::const_iterator end = workingCopy->upper_bound(_postfix); std::vector<std::string> toDelete; @@ -249,7 +250,7 @@ StatusWith<int64_t> RecordStore::truncateWithoutUpdatingCount(OperationContext* for (const auto& key : toDelete) workingCopy->erase(key); - ru->makeDirty(); + bRu->makeDirty(); return static_cast<int64_t>(toDelete.size()); } diff --git a/src/mongo/db/storage/biggie/biggie_record_store.h b/src/mongo/db/storage/biggie/biggie_record_store.h index d604ba51826..f4281ea528f 100644 --- a/src/mongo/db/storage/biggie/biggie_record_store.h +++ b/src/mongo/db/storage/biggie/biggie_record_store.h @@ -92,7 +92,7 @@ public: bool forward) const final; virtual Status truncate(OperationContext* opCtx); - StatusWith<int64_t> truncateWithoutUpdatingCount(OperationContext* opCtx); + StatusWith<int64_t> truncateWithoutUpdatingCount(RecoveryUnit* ru); virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive); diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp index d55ed2d1bf6..68bcb271f96 100644 --- a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp +++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp @@ -443,8 +443,9 @@ void SortedDataInterface::unindex(OperationContext* opCtx, // This function is, as of now, not in the interface, but there exists a server ticket to add // truncate to the list of commands able to be used. -Status SortedDataInterface::truncate(OperationContext* opCtx) { - StringStore* workingCopy(RecoveryUnit::get(opCtx)->getHead()); +Status SortedDataInterface::truncate(mongo::RecoveryUnit* ru) { + auto bRu = checked_cast<biggie::RecoveryUnit*>(ru); + StringStore* workingCopy(bRu->getHead()); std::vector<std::string> toDelete; auto end = workingCopy->upper_bound(_KSForIdentEnd); for (auto it = workingCopy->lower_bound(_KSForIdentStart); it != end; ++it) { @@ -453,7 +454,7 @@ Status SortedDataInterface::truncate(OperationContext* opCtx) { if (!toDelete.empty()) { for (const auto& key : toDelete) workingCopy->erase(key); - RecoveryUnit::get(opCtx)->makeDirty(); + bRu->makeDirty(); } return Status::OK(); diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.h b/src/mongo/db/storage/biggie/biggie_sorted_impl.h index acf8414b9eb..559789df44e 100644 --- a/src/mongo/db/storage/biggie/biggie_sorted_impl.h +++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.h @@ -75,7 +75,7 @@ class SortedDataInterface : public ::mongo::SortedDataInterface { public: // Truncate is not required at the time of writing but will be when the truncate command is // created - Status truncate(OperationContext* opCtx); + Status truncate(RecoveryUnit* ru); SortedDataInterface(OperationContext* opCtx, StringData ident, const IndexDescriptor* desc); SortedDataInterface(const Ordering& ordering, bool isUnique, StringData ident); virtual SortedDataBuilderInterface* getBulkBuilder(OperationContext* opCtx, diff --git a/src/mongo/db/storage/devnull/devnull_kv_engine.h b/src/mongo/db/storage/devnull/devnull_kv_engine.h index 34d39f79919..f32af0d4235 100644 --- a/src/mongo/db/storage/devnull/devnull_kv_engine.h +++ b/src/mongo/db/storage/devnull/devnull_kv_engine.h @@ -74,7 +74,7 @@ public: virtual std::unique_ptr<SortedDataInterface> getSortedDataInterface( OperationContext* opCtx, StringData ident, const IndexDescriptor* desc); - virtual Status dropIdent(OperationContext* opCtx, StringData ident) { + virtual Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) { return Status::OK(); } diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp index 38f9db61e58..e43f2013cd2 100644 --- a/src/mongo/db/storage/durable_catalog_impl.cpp +++ b/src/mongo/db/storage/durable_catalog_impl.cpp @@ -178,17 +178,22 @@ public: class DurableCatalogImpl::AddIndexChange : public RecoveryUnit::Change { public: - AddIndexChange(OperationContext* opCtx, StorageEngineInterface* engine, StringData ident) - : _opCtx(opCtx), _engine(engine), _ident(ident.toString()) {} + AddIndexChange(OperationContext* opCtx, + RecoveryUnit* ru, + StorageEngineInterface* engine, + StringData ident) + : _opCtx(opCtx), _recoveryUnit(ru), _engine(engine), _ident(ident.toString()) {} virtual void commit(boost::optional<Timestamp>) {} virtual void rollback() { // Intentionally ignoring failure. auto kvEngine = _engine->getEngine(); - MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); + MONGO_COMPILER_VARIABLE_UNUSED auto status = + kvEngine->dropIdent(_opCtx, _recoveryUnit, _ident); } OperationContext* const _opCtx; + RecoveryUnit* const _recoveryUnit; StorageEngineInterface* _engine; const std::string _ident; }; @@ -202,6 +207,7 @@ public: StringData indexName, StringData ident) : _opCtx(opCtx), + _recoveryUnit(opCtx->recoveryUnit()), _engine(engine), _uuid(uuid), _indexNss(indexNss), @@ -219,11 +225,13 @@ public: _engine->addDropPendingIdent(*commitTimestamp, _indexNss, _ident); } else { auto kvEngine = _engine->getEngine(); - MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); + MONGO_COMPILER_VARIABLE_UNUSED auto status = + kvEngine->dropIdent(_opCtx, _recoveryUnit, _ident); } } OperationContext* const _opCtx; + RecoveryUnit* const _recoveryUnit; StorageEngineInterface* _engine; OptionalCollectionUUID _uuid; const NamespaceString _indexNss; @@ -809,11 +817,13 @@ StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> DurableCatalogImpl } } + auto ru = opCtx->recoveryUnit(); CollectionUUID uuid = options.uuid.get(); - opCtx->recoveryUnit()->onRollback([opCtx, catalog = this, nss, ident = entry.ident, uuid]() { - // Intentionally ignoring failure - catalog->_engine->getEngine()->dropIdent(opCtx, ident).ignore(); - }); + opCtx->recoveryUnit()->onRollback( + [opCtx, ru, catalog = this, nss, ident = entry.ident, uuid]() { + // Intentionally ignoring failure + catalog->_engine->getEngine()->dropIdent(opCtx, ru, ident).ignore(); + }); auto rs = _engine->getEngine()->getGroupedRecordStore(opCtx, nss.ns(), entry.ident, options, prefix); @@ -854,9 +864,10 @@ Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, RecordId cata return status; } + auto ru = opCtx->recoveryUnit(); // This will notify the storageEngine to drop the collection only on WUOW::commit(). opCtx->recoveryUnit()->onCommit( - [opCtx, catalog = this, entry](boost::optional<Timestamp> commitTimestamp) { + [opCtx, ru, catalog = this, entry](boost::optional<Timestamp> commitTimestamp) { StorageEngineInterface* engine = catalog->_engine; auto storageEngine = engine->getStorageEngine(); if (storageEngine->supportsPendingDrops() && commitTimestamp) { @@ -867,7 +878,7 @@ Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, RecordId cata // Intentionally ignoring failure here. Since we've removed the metadata pointing to // the collection, we should never see it again anyway. auto kvEngine = engine->getEngine(); - kvEngine->dropIdent(opCtx, entry.ident).ignore(); + kvEngine->dropIdent(opCtx, ru, entry.ident).ignore(); } }); @@ -982,7 +993,7 @@ Status DurableCatalogImpl::prepareForIndexBuild(OperationContext* opCtx, opCtx, getCollectionOptions(opCtx, catalogId), ident, spec, prefix); if (status.isOK()) { opCtx->recoveryUnit()->registerChange( - std::make_unique<AddIndexChange>(opCtx, _engine, ident)); + std::make_unique<AddIndexChange>(opCtx, opCtx->recoveryUnit(), _engine, ident)); } return status; diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp index 597bc513d20..070d6cbf244 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp @@ -104,7 +104,9 @@ std::unique_ptr<SortedDataInterface> EphemeralForTestEngine::getSortedDataInterf &_dataMap[ident]); } -Status EphemeralForTestEngine::dropIdent(OperationContext* opCtx, StringData ident) { +Status EphemeralForTestEngine::dropIdent(OperationContext* opCtx, + RecoveryUnit* ru, + StringData ident) { stdx::lock_guard<Latch> lk(_mutex); _dataMap.erase(ident); return Status::OK(); diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h index 002d8468b80..a18079a860d 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h @@ -71,7 +71,7 @@ public: virtual void endBackup(OperationContext* opCtx) {} - virtual Status dropIdent(OperationContext* opCtx, StringData ident); + virtual Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident); virtual bool supportsDocLocking() const { return false; diff --git a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper.cpp b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper.cpp index 44337fffc49..a68cbfe58f1 100644 --- a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper.cpp +++ b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper.cpp @@ -112,7 +112,7 @@ void KVDropPendingIdentReaper::dropIdentsOlderThan(OperationContext* opCtx, cons log() << "Completing drop for ident " << ident << " (ns: " << nss << ") with drop timestamp " << dropTimestamp; WriteUnitOfWork wuow(opCtx); - auto status = _engine->dropIdent(opCtx, ident); + auto status = _engine->dropIdent(opCtx, opCtx->recoveryUnit(), ident); if (!status.isOK()) { severe() << "Failed to remove drop-pending ident " << ident << "(ns: " << nss << ") with drop timestamp " << dropTimestamp << ": " << status; diff --git a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp index f58c2abb0b4..7f187993d7a 100644 --- a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp +++ b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp @@ -59,7 +59,7 @@ public: */ class KVEngineMock : public KVEngine { public: - Status dropIdent(OperationContext* opCtx, StringData ident) override; + Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) override; // Unused KVEngine functions below. RecoveryUnit* newRecoveryUnit() override { @@ -132,12 +132,14 @@ public: std::vector<std::string> droppedIdents; // Override to modify dropIdent() behavior. - using DropIdentFn = std::function<Status(OperationContext*, StringData)>; - DropIdentFn dropIdentFn = [](OperationContext*, StringData) { return Status::OK(); }; + using DropIdentFn = std::function<Status(OperationContext*, RecoveryUnit*, StringData)>; + DropIdentFn dropIdentFn = [](OperationContext*, RecoveryUnit*, StringData) { + return Status::OK(); + }; }; -Status KVEngineMock::dropIdent(OperationContext* opCtx, StringData ident) { - auto status = dropIdentFn(opCtx, ident); +Status KVEngineMock::dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) { + auto status = dropIdentFn(opCtx, ru, ident); if (status.isOK()) { droppedIdents.push_back(ident.toString()); } @@ -320,11 +322,13 @@ DEATH_TEST_F(KVDropPendingIdentReaperTest, ASSERT_EQUALS(dropTimestamp, *reaper.getEarliestDropTimestamp()); // Make KVEngineMock::dropIndent() fail. - engine->dropIdentFn = [ident](OperationContext* opCtx, StringData identToDrop) { - ASSERT(opCtx); - ASSERT_EQUALS(ident, identToDrop); - return Status(ErrorCodes::OperationFailed, "Mock KV engine dropIndent() failed."); - }; + engine->dropIdentFn = + [ident](OperationContext* opCtx, RecoveryUnit* ru, StringData identToDrop) { + ASSERT(opCtx); + ASSERT(ru); + ASSERT_EQUALS(ident, identToDrop); + return Status(ErrorCodes::OperationFailed, "Mock KV engine dropIndent() failed."); + }; auto opCtx = makeOpCtx(); reaper.dropIdentsOlderThan(opCtx.get(), makeTimestampWithNextInc(dropTimestamp)); diff --git a/src/mongo/db/storage/kv/kv_engine.h b/src/mongo/db/storage/kv/kv_engine.h index 5b80e7a857d..fa7a095a6ac 100644 --- a/src/mongo/db/storage/kv/kv_engine.h +++ b/src/mongo/db/storage/kv/kv_engine.h @@ -182,7 +182,15 @@ public: */ virtual Status repairIdent(OperationContext* opCtx, StringData ident) = 0; - virtual Status dropIdent(OperationContext* opCtx, StringData ident) = 0; + /** + * Takes both an OperationContext and a RecoveryUnit, since most storage engines except for + * mobile only need the RecoveryUnit. Obtaining the RecoveryUnit from the OperationContext is + * not necessarily possible, since as of SERVER-44139 dropIdent can be called as part of + * multi-document transactions, which use the same RecoveryUnit throughout but not the same + * OperationContext. + * TODO(SERVER-45371) Remove OperationContext argument. + */ + virtual Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) = 0; /** * Attempts to locate and recover a file that is "orphaned" from the storage engine's metadata, diff --git a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp index e9c07d7fdbd..0bce1df682d 100644 --- a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp +++ b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp @@ -256,7 +256,7 @@ TEST(KVEngineTestHarness, TemporaryRecordStoreSimple) { ASSERT_EQUALS(ident, all[0]); WriteUnitOfWork wuow(&opCtx); - ASSERT_OK(engine->dropIdent(&opCtx, ident)); + ASSERT_OK(engine->dropIdent(&opCtx, opCtx.recoveryUnit(), ident)); wuow.commit(); } } diff --git a/src/mongo/db/storage/kv/storage_engine_test.cpp b/src/mongo/db/storage/kv/storage_engine_test.cpp index 5fb349a9a6b..1926a0f64ad 100644 --- a/src/mongo/db/storage/kv/storage_engine_test.cpp +++ b/src/mongo/db/storage/kv/storage_engine_test.cpp @@ -93,7 +93,7 @@ TEST_F(StorageEngineTest, ReconcileIdentsTest) { ASSERT_EQUALS("_id", toRebuild.indexName); // Now drop the `db.coll1` table, while leaving the DurableCatalog entry. - ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident)); + ASSERT_OK(dropIdent(opCtx.get(), opCtx.get()->recoveryUnit(), swCollInfo.getValue().ident)); ASSERT_EQUALS(static_cast<const unsigned long>(1), getAllKVEngineIdents(opCtx.get()).size()); // Reconciling this should result in an error. @@ -109,7 +109,7 @@ TEST_F(StorageEngineTest, LoadCatalogDropsOrphansAfterUncleanShutdown) { auto swCollInfo = createCollection(opCtx.get(), collNs); ASSERT_OK(swCollInfo.getStatus()); - ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident)); + ASSERT_OK(dropIdent(opCtx.get(), opCtx.get()->recoveryUnit(), swCollInfo.getValue().ident)); ASSERT(collectionExists(opCtx.get(), collNs)); // After the catalog is reloaded, we expect that the collection has been dropped because the @@ -292,7 +292,7 @@ TEST_F(StorageEngineRepairTest, LoadCatalogRecoversOrphans) { auto swCollInfo = createCollection(opCtx.get(), collNs); ASSERT_OK(swCollInfo.getStatus()); - ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident)); + ASSERT_OK(dropIdent(opCtx.get(), opCtx.get()->recoveryUnit(), swCollInfo.getValue().ident)); ASSERT(collectionExists(opCtx.get(), collNs)); // After the catalog is reloaded, we expect that the ident has been recovered because the @@ -316,7 +316,7 @@ TEST_F(StorageEngineRepairTest, ReconcileSucceeds) { auto swCollInfo = createCollection(opCtx.get(), collNs); ASSERT_OK(swCollInfo.getStatus()); - ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident)); + ASSERT_OK(dropIdent(opCtx.get(), opCtx.get()->recoveryUnit(), swCollInfo.getValue().ident)); ASSERT(collectionExists(opCtx.get(), collNs)); // Reconcile would normally return an error if a collection existed with a missing ident in the diff --git a/src/mongo/db/storage/kv/temporary_kv_record_store.cpp b/src/mongo/db/storage/kv/temporary_kv_record_store.cpp index 7625fe8630d..ee71e5d7091 100644 --- a/src/mongo/db/storage/kv/temporary_kv_record_store.cpp +++ b/src/mongo/db/storage/kv/temporary_kv_record_store.cpp @@ -49,7 +49,7 @@ void TemporaryKVRecordStore::deleteTemporaryTable(OperationContext* opCtx) { // destructed while we're using it. invariant(opCtx->lockState()->isReadLocked()); - auto status = _kvEngine->dropIdent(opCtx, _rs->getIdent()); + auto status = _kvEngine->dropIdent(opCtx, opCtx->recoveryUnit(), _rs->getIdent()); fassert( 51032, status.withContext(str::stream() << "failed to drop temporary ident: " << _rs->getIdent())); diff --git a/src/mongo/db/storage/mobile/mobile_kv_engine.cpp b/src/mongo/db/storage/mobile/mobile_kv_engine.cpp index 648ac3612ae..495dce80070 100644 --- a/src/mongo/db/storage/mobile/mobile_kv_engine.cpp +++ b/src/mongo/db/storage/mobile/mobile_kv_engine.cpp @@ -244,8 +244,9 @@ std::unique_ptr<SortedDataInterface> MobileKVEngine::getSortedDataInterface( return std::make_unique<MobileIndexStandard>(opCtx, desc, ident.toString()); } -Status MobileKVEngine::dropIdent(OperationContext* opCtx, StringData ident) { - MobileSession* session = MobileRecoveryUnit::get(opCtx)->getSessionNoTxn(opCtx); +Status MobileKVEngine::dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) { + auto mRu = checked_cast<MobileRecoveryUnit*>(ru); + MobileSession* session = mRu->getSessionNoTxn(opCtx); std::string dropQuery = "DROP TABLE IF EXISTS \"" + ident + "\";"; try { @@ -256,7 +257,7 @@ Status MobileKVEngine::dropIdent(OperationContext* opCtx, StringData ident) { LOG(MOBILE_LOG_LEVEL_LOW) << "MobileSE: Caught WriteConflictException while dropping table, " "queuing to retry later"; - MobileRecoveryUnit::get(opCtx)->enqueueFailedDrop(dropQuery); + mRu->enqueueFailedDrop(dropQuery); } return Status::OK(); } diff --git a/src/mongo/db/storage/mobile/mobile_kv_engine.h b/src/mongo/db/storage/mobile/mobile_kv_engine.h index 0e0b3ab17e3..662f2898b24 100644 --- a/src/mongo/db/storage/mobile/mobile_kv_engine.h +++ b/src/mongo/db/storage/mobile/mobile_kv_engine.h @@ -78,7 +78,7 @@ public: void endBackup(OperationContext* opCtx) override {} - Status dropIdent(OperationContext* opCtx, StringData ident) override; + Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) override; bool supportsDocLocking() const override { return false; diff --git a/src/mongo/db/storage/storage_engine_impl.cpp b/src/mongo/db/storage/storage_engine_impl.cpp index ff055222963..1cb0d8f7c9e 100644 --- a/src/mongo/db/storage/storage_engine_impl.cpp +++ b/src/mongo/db/storage/storage_engine_impl.cpp @@ -383,7 +383,7 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn const auto& toRemove = it; log() << "Dropping unknown ident: " << toRemove; WriteUnitOfWork wuow(opCtx); - fassert(40591, _engine->dropIdent(opCtx, toRemove)); + fassert(40591, _engine->dropIdent(opCtx, opCtx->recoveryUnit(), toRemove)); wuow.commit(); } @@ -479,7 +479,7 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn log() << "Dropping an unfinished index because --noIndexBuildRetry is set. " "Collection: " << coll << " Index: " << indexName; - fassert(51197, _engine->dropIdent(opCtx, indexIdent)); + fassert(51197, _engine->dropIdent(opCtx, opCtx->recoveryUnit(), indexIdent)); indexesToDrop.push_back(indexName); continue; } @@ -501,7 +501,7 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn log() << "Dropping unfinished index. Collection: " << coll << " Index: " << indexName; // Ensure the `ident` is dropped while we have the `indexIdent` value. - fassert(50713, _engine->dropIdent(opCtx, indexIdent)); + fassert(50713, _engine->dropIdent(opCtx, opCtx->recoveryUnit(), indexIdent)); indexesToDrop.push_back(indexName); continue; } @@ -522,7 +522,7 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn for (auto&& temp : internalIdentsToDrop) { log() << "Dropping internal ident: " << temp; WriteUnitOfWork wuow(opCtx); - fassert(51067, _engine->dropIdent(opCtx, temp)); + fassert(51067, _engine->dropIdent(opCtx, opCtx->recoveryUnit(), temp)); wuow.commit(); } diff --git a/src/mongo/db/storage/storage_engine_test_fixture.h b/src/mongo/db/storage/storage_engine_test_fixture.h index 3495fd893e8..35254e71eb9 100644 --- a/src/mongo/db/storage/storage_engine_test_fixture.h +++ b/src/mongo/db/storage/storage_engine_test_fixture.h @@ -82,11 +82,11 @@ public: CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nss)->getCatalogId(); std::string indexIdent = _storageEngine->getCatalog()->getIndexIdent(opCtx, catalogId, indexName); - return dropIdent(opCtx, indexIdent); + return dropIdent(opCtx, opCtx->recoveryUnit(), indexIdent); } - Status dropIdent(OperationContext* opCtx, StringData ident) { - return _storageEngine->getEngine()->dropIdent(opCtx, ident); + Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) { + return _storageEngine->getEngine()->dropIdent(opCtx, ru, ident); } StatusWith<StorageEngine::ReconcileResult> reconcile(OperationContext* opCtx) { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp index dd63aad920a..2d0cf8c6a16 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp @@ -1481,11 +1481,11 @@ std::unique_ptr<RecordStore> WiredTigerKVEngine::makeTemporaryRecordStore(Operat return std::move(rs); } -Status WiredTigerKVEngine::dropIdent(OperationContext* opCtx, StringData ident) { +Status WiredTigerKVEngine::dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) { string uri = _uri(ident); - WiredTigerRecoveryUnit* ru = WiredTigerRecoveryUnit::get(opCtx); - ru->getSessionNoTxn()->closeAllCursors(uri); + WiredTigerRecoveryUnit* wtRu = checked_cast<WiredTigerRecoveryUnit*>(ru); + wtRu->getSessionNoTxn()->closeAllCursors(uri); _sessionCache->closeAllCursors(uri); WiredTigerSession session(_conn); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h index ca4c51c1ccd..98ca038789a 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h @@ -165,7 +165,7 @@ public: const IndexDescriptor* desc, KVPrefix prefix) override; - Status dropIdent(OperationContext* opCtx, StringData ident) override; + Status dropIdent(OperationContext* opCtx, RecoveryUnit* ru, StringData ident) override; Status okToRename(OperationContext* opCtx, StringData fromNS, diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp index 76ab1239046..2f818dce98a 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine_test.cpp @@ -166,7 +166,7 @@ TEST_F(WiredTigerKVEngineRepairTest, OrphanedDataFilesCanBeRecovered) { boost::filesystem::rename(*dataFilePath, tmpFile, err); ASSERT(!err) << err.message(); - ASSERT_OK(_engine->dropIdent(opCtxPtr.get(), ident)); + ASSERT_OK(_engine->dropIdent(opCtxPtr.get(), opCtxPtr.get()->recoveryUnit(), ident)); // The data file is moved back in place so that it becomes an "orphan" of the storage // engine and the restoration process can be tested. @@ -209,7 +209,7 @@ TEST_F(WiredTigerKVEngineRepairTest, UnrecoverableOrphanedDataFilesAreRebuilt) { ASSERT(boost::filesystem::exists(*dataFilePath)); - ASSERT_OK(_engine->dropIdent(opCtxPtr.get(), ident)); + ASSERT_OK(_engine->dropIdent(opCtxPtr.get(), opCtxPtr.get()->recoveryUnit(), ident)); #ifdef _WIN32 auto status = diff --git a/src/mongo/dbtests/catalogtests.cpp b/src/mongo/dbtests/catalogtests.cpp index 56db54cc9f8..288ab67f19c 100644 --- a/src/mongo/dbtests/catalogtests.cpp +++ b/src/mongo/dbtests/catalogtests.cpp @@ -59,10 +59,6 @@ public: return; } - // TODO SERVER-44138: The commented out lines can be reinstated when committing new - // collections to the catalog are transactional (all succeed or fail). - - // NamespaceString op1UniqueNss("test.uniqueCollection"); NamespaceString competingNss("test.competingCollection"); auto client1 = serviceContext->makeClient("client1"); @@ -74,7 +70,6 @@ public: Lock::DBLock dbLk1(op1.get(), competingNss.db(), LockMode::MODE_IX); Lock::CollectionLock collLk1(op1.get(), competingNss, LockMode::MODE_IX); - // Lock::CollectionLock uniqueNssLk(op1.get(), op1UniqueNss, LockMode::MODE_IX); Lock::DBLock dbLk2(op2.get(), competingNss.db(), LockMode::MODE_IX); Lock::CollectionLock collLk2(op2.get(), competingNss, LockMode::MODE_IX); @@ -83,7 +78,6 @@ public: { WriteUnitOfWork wuow1(op1.get()); - // ASSERT_TRUE(db->createCollection(op1.get(), op1UniqueNss) != nullptr); ASSERT_TRUE(db->createCollection(op1.get(), competingNss) != nullptr); ASSERT_TRUE(collectionExists(op1.get(), competingNss)); ASSERT_FALSE(collectionExists(op2.get(), competingNss)); @@ -103,8 +97,6 @@ public: ASSERT_TRUE(collectionExists(op1.get(), competingNss)); ASSERT_TRUE(collectionExists(op2.get(), competingNss)); - // ASSERT_FALSE(collectionExists(op1.get(), op1UniqueNss)); - // ASSERT_FALSE(collectionExists(op2.get(), op1UniqueNss)); } }; |