SERVER-126889: Replace AutoGetCollection in shard catalog tests with collection acquisitions (#53839)

GitOrigin-RevId: 31abfd97abb032ccbe2b48f9c9a8fcc248480191
This commit is contained in:
Thomas Goyne 2026-05-18 15:03:10 -07:00 committed by MongoDB Bot
parent 011e6839e3
commit 7bab8bacb0
15 changed files with 534 additions and 254 deletions

View File

@ -51,6 +51,7 @@
#include "mongo/db/shard_role/shard_catalog/collection_options.h"
#include "mongo/db/shard_role/shard_catalog/create_collection.h"
#include "mongo/db/shard_role/shard_catalog/durable_catalog.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/mdb_catalog.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_collmod.h"
@ -258,8 +259,12 @@ TEST_F(CollModTest, TimeseriesBucketingParameterChanged) {
writeConflictRetry(opCtx.get(), "unitTestTimeseriesBucketingParameterChanged", tsNss, [&] {
WriteUnitOfWork wunit(opCtx.get());
AutoGetCollection collection(opCtx.get(), tsNss, MODE_X);
CollectionWriter writer{opCtx.get(), collection};
auto collection =
acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), tsNss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter writer{opCtx.get(), &collection};
auto writableColl = writer.getWritableCollection(opCtx.get());
writableColl->setTimeseriesBucketingParametersChanged(opCtx.get(), boost::none);

View File

@ -29,10 +29,6 @@
#include "mongo/db/shard_role/shard_catalog/collection_catalog.h"
#include <boost/move/utility_core.hpp>
#include <boost/none.hpp>
#include <boost/optional/optional.hpp>
// IWYU pragma: no_include "cxxabi.h"
#include "mongo/base/error_codes.h"
#include "mongo/base/status_with.h"
#include "mongo/base/string_data.h"
@ -60,10 +56,12 @@
#include "mongo/db/shard_role/shard_catalog/collection_options.h"
#include "mongo/db/shard_role/shard_catalog/collection_yield_restore.h"
#include "mongo/db/shard_role/shard_catalog/create_collection.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/durable_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_catalog/uncommitted_catalog_updates.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/shard_role/transaction_resources.h"
#include "mongo/db/storage/mdb_catalog.h"
#include "mongo/db/storage/record_store.h"
@ -81,6 +79,8 @@
#include <algorithm>
#include <map>
#include <boost/optional/optional.hpp>
namespace mongo {
namespace {
@ -866,8 +866,13 @@ TEST_F(ForEachCollectionFromDbTest, ModifyAllCollectionsMatchingHandlesConcurren
if (collection->ns() == originalNss) {
ASSERT_OK(storageInterface()->createCollection(opCtx, cloneNss, tempCollOptions));
}
auto acq =
acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, collection->ns(), AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx);
CollectionWriter writer(opCtx, collection->ns());
CollectionWriter writer(opCtx, &acq);
writer.getWritableCollection(opCtx)->setIsTemp(opCtx, false);
wuow.commit();
numModified++;
@ -1125,7 +1130,10 @@ public:
Timestamp timestamp) {
_setupDDLOperation(opCtx, timestamp);
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
ASSERT(coll);
CollectionPtr collPtr = CollectionPtr::CollectionPtr_UNSAFE(coll);
@ -1148,9 +1156,12 @@ public:
Timestamp createTimestamp) {
_setupDDLOperation(opCtx, createTimestamp);
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx);
CollectionWriter collection(opCtx, nss);
CollectionWriter collection(opCtx, &acq);
auto writableColl = collection.getWritableCollection(opCtx);
auto storageEngine = getServiceContext()->getStorageEngine();
@ -1186,9 +1197,12 @@ public:
Timestamp readyTimestamp) {
_setupDDLOperation(opCtx, readyTimestamp);
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx);
CollectionWriter collection(opCtx, nss);
CollectionWriter collection(opCtx, &acq);
indexBuildBlock->success(opCtx, collection.getWritableCollection(opCtx));
wuow.commit();
}
@ -1386,14 +1400,20 @@ public:
if (committed) {
return;
}
AutoGetCollection autoColl(opCtx, nss, MODE_X);
CollectionWriter collection(opCtx, nss);
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(opCtx, &acq);
multiIndexBlock.abortIndexBuild(opCtx, collection, MultiIndexBlock::kNoopOnCleanUpFn);
});
{
AutoGetCollection autoColl(opCtx, nss, MODE_X);
CollectionWriter collection(opCtx, nss);
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(opCtx, &acq);
auto storageEngine = getServiceContext()->getStorageEngine();
auto specs =
multiIndexBlock.init(opCtx,
@ -1407,7 +1427,10 @@ public:
ASSERT_OK(multiIndexBlock.insertAllDocumentsInCollection(opCtx, nss));
{
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
ASSERT_OK(multiIndexBlock.drainBackgroundWrites(
opCtx,
RecoveryUnit::ReadSource::kNoTimestamp,
@ -1419,8 +1442,12 @@ public:
lookupNssOrUUID,
commitBuildTs,
[&multiIndexBlock, &nss, &committed](OperationContext* threadOpCtx) {
AutoGetCollection autoColl(threadOpCtx, nss, MODE_X);
CollectionWriter collection(threadOpCtx, nss);
auto acq =
acquireCollection(threadOpCtx,
CollectionAcquisitionRequest::fromOpCtx(
threadOpCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(threadOpCtx, &acq);
uassertStatusOK(
multiIndexBlock.commit(threadOpCtx,
collection.getWritableCollection(threadOpCtx),
@ -1528,12 +1555,13 @@ private:
const NamespaceString& nss,
boost::optional<UUID> uuid = boost::none,
bool allowMixedModeWrites = false) {
AutoGetDb databaseWriteGuard(opCtx, nss.dbName(), MODE_IX);
auto db = databaseWriteGuard.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT(db);
Lock::CollectionLock lk(opCtx, nss, MODE_IX);
CollectionOptions options;
if (uuid) {
options.uuid.emplace(*uuid);
@ -1566,9 +1594,11 @@ private:
}
void _dropCollection(OperationContext* opCtx, const NamespaceString& nss, Timestamp timestamp) {
Lock::DBLock dbLk(opCtx, nss.dbName(), MODE_IX);
Lock::CollectionLock collLk(opCtx, nss, MODE_X);
CollectionWriter collection(opCtx, nss);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(opCtx, &acq);
Collection* writableCollection = collection.getWritableCollection(opCtx);
@ -1604,8 +1634,10 @@ private:
Timestamp timestamp) {
invariant(from != to);
Lock::DBLock dbLk(opCtx, from.dbName(), MODE_IX);
Lock::CollectionLock fromLk(opCtx, from, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, from, AcquisitionPrerequisites::kWrite),
MODE_X);
Lock::CollectionLock toLk(opCtx, to, MODE_X);
// Drop the collection if it exists. This triggers the same behavior as renaming with
@ -1614,7 +1646,7 @@ private:
_dropCollection(opCtx, to, timestamp);
}
CollectionWriter collection(opCtx, from);
CollectionWriter collection(opCtx, &acq);
ASSERT_OK(collection.getWritableCollection(opCtx)->rename(opCtx, to, false));
CollectionCatalog::get(opCtx)->onCollectionRename(
@ -1622,8 +1654,11 @@ private:
}
void _createIndex(OperationContext* opCtx, const NamespaceString& nss, BSONObj indexSpec) {
AutoGetCollection autoColl(opCtx, nss, MODE_X);
CollectionWriter collection(opCtx, nss);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(opCtx, &acq);
IndexBuildsCoordinator::createIndexesOnEmptyCollection(
opCtx, collection, {indexSpec}, /*fromMigrate=*/false);
}
@ -1631,9 +1666,12 @@ private:
void _dropIndex(OperationContext* opCtx,
const NamespaceString& nss,
const std::string& indexName) {
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter collection(opCtx, nss);
CollectionWriter collection(opCtx, &acq);
Collection* writableCollection = collection.getWritableCollection(opCtx);
@ -3681,9 +3719,12 @@ TEST_F(CollectionCatalogTimestampTest, IndexCatalogEntryCopying) {
IndexSpec spec;
spec.version(1).name("x_1").addKeys(BSON("x" << 1));
auto desc = IndexDescriptor(IndexNames::BTREE, spec.toBSON());
AutoGetCollection autoColl(opCtx.get(), nss, MODE_X);
auto acq = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx.get());
CollectionWriter writer{opCtx.get(), autoColl};
CollectionWriter writer{opCtx.get(), &acq};
auto writableColl = writer.getWritableCollection(opCtx.get());
ASSERT_OK(
writableColl->prepareForIndexBuild(opCtx.get(), &desc, "index-ident", boost::none));
@ -3706,9 +3747,12 @@ TEST_F(CollectionCatalogTimestampTest, IndexCatalogEntryCopying) {
{
// Now finish the index build on the original client.
AutoGetCollection autoColl(opCtx.get(), nss, MODE_X);
auto acq = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx.get());
CollectionWriter writer{opCtx.get(), autoColl};
CollectionWriter writer{opCtx.get(), &acq};
auto writableColl = writer.getWritableCollection(opCtx.get());
auto writableEntry = writableColl->getIndexCatalog()->getWritableEntryByName(
opCtx.get(), "x_1", IndexCatalog::InclusionPolicy::kUnfinished);
@ -4321,9 +4365,11 @@ TEST_F(CollectionCatalogTimestampTest, ConcurrentRecreateWithReapedIdentDoesNotC
// "reaped", establishConsistentCollection must throw SnapshotUnavailable.
{
ConcurrentDDL ddl(getServiceContext(), recreateTs, [&nss](OperationContext* opCtx) {
AutoGetDb databaseWriteGuard(opCtx, nss.dbName(), MODE_IX);
databaseWriteGuard.ensureDbExists(opCtx);
Lock::CollectionLock lk(opCtx, nss, MODE_IX);
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
CollectionOptions options;
options.uuid.emplace(UUID::gen());

View File

@ -43,13 +43,13 @@
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/collection_metadata.h"
#include "mongo/db/shard_role/shard_catalog/collection_sharding_runtime.h"
#include "mongo/db/shard_role/shard_catalog/collection_sharding_state.h"
#include "mongo/db/shard_role/shard_catalog/metadata_manager.h"
#include "mongo/db/shard_role/shard_catalog/operation_sharding_state.h"
#include "mongo/db/shard_role/shard_catalog/scoped_collection_metadata.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/sharding_environment/shard_id.h"
#include "mongo/db/sharding_environment/shard_server_test_fixture.h"
#include "mongo/db/versioning_protocol/chunk_version.h"
@ -184,7 +184,10 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsInTheFuture) {
auto&& readConcernArgs = repl::ReadConcernArgs::get(operationContext());
ASSERT_OK(readConcernArgs.initialize(readConcern["readConcern"]));
AutoGetCollection autoColl(operationContext(), kNss, MODE_IS);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kRead),
MODE_IS);
ScopedSetShardRole scopedSetShardRole{operationContext(),
kNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
@ -213,7 +216,10 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsInThePast) {
auto&& readConcernArgs = repl::ReadConcernArgs::get(operationContext());
ASSERT_OK(readConcernArgs.initialize(readConcern["readConcern"]));
AutoGetCollection autoColl(operationContext(), kNss, MODE_IS);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kRead),
MODE_IS);
ScopedSetShardRole scopedSetShardRole{operationContext(),
kNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
@ -250,7 +256,10 @@ TEST_F(CollectionMetadataFilteringTest, FilterDocumentsTooFarInThePastThrowsStal
auto&& readConcernArgs = repl::ReadConcernArgs::get(operationContext());
ASSERT_OK(readConcernArgs.initialize(readConcern["readConcern"]));
AutoGetCollection autoColl(operationContext(), kNss, MODE_IS);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kRead),
MODE_IS);
ScopedSetShardRole scopedSetShardRole{operationContext(),
kNss,
ShardVersionFactory::make(metadata) /* shardVersion */,

View File

@ -58,9 +58,9 @@
#include "mongo/db/session/session_catalog_mongod.h"
#include "mongo/db/shard_role/lock_manager/d_concurrency.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/collection.h"
#include "mongo/db/shard_role/shard_catalog/operation_sharding_state.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/sharding_environment/shard_id.h"
#include "mongo/db/sharding_environment/shard_server_op_observer.h"
#include "mongo/db/sharding_environment/shard_server_test_fixture.h"
@ -1095,8 +1095,12 @@ public:
createTestCollection(operationContext(), kTestNss);
AutoGetCollection autoColl(operationContext(), kTestNss, MODE_IX);
_uuid = autoColl->uuid();
auto acq =
acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kTestNss, AcquisitionPrerequisites::kWrite),
MODE_IX);
_uuid = acq.uuid();
auto opCtx = operationContext();
RangeDeleterService::get(opCtx)->onStartup(opCtx);

View File

@ -49,15 +49,16 @@
#include "mongo/db/service_context.h"
#include "mongo/db/shard_role/lock_manager/d_concurrency.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/catalog_test_fixture.h"
#include "mongo/db/shard_role/shard_catalog/clustered_collection_util.h"
#include "mongo/db/shard_role/shard_catalog/collection_mock.h"
#include "mongo/db/shard_role/shard_catalog/collection_options.h"
#include "mongo/db/shard_role/shard_catalog/database.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/shard_role/transaction_resources.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/storage/record_data.h"
@ -305,17 +306,23 @@ TEST_F(CollectionTest, AsynchronouslyNotifyCappedWaitersIfNeeded) {
void CollectionTest::makeCollectionForMultikey(NamespaceString nss, StringData indexName) {
auto opCtx = operationContext();
{
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
auto db = autoColl.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
WriteUnitOfWork wuow(opCtx);
ASSERT(db->createCollection(opCtx, nss));
wuow.commit();
}
{
AutoGetCollection autoColl(opCtx, nss, MODE_X);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(opCtx);
CollectionWriter writer{opCtx, autoColl};
CollectionWriter writer{opCtx, &acq};
auto writableColl = writer.getWritableCollection(opCtx);
ASSERT_OK(writableColl->getIndexCatalog()->createIndexOnEmptyCollection(
@ -330,8 +337,11 @@ TEST_F(CollectionTest, VerifyIndexIsUpdated) {
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
auto oldDoc = BSON("_id" << 1 << "a" << 1);
{
@ -385,8 +395,11 @@ TEST_F(CollectionTest, VerifyIndexIsUpdatedWithDamages) {
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
auto oldDoc = BSON("_id" << 1 << "a" << 1 << "b"
<< "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
@ -442,8 +455,11 @@ TEST_F(CollectionTest, SetIndexIsMultikey) {
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
ASSERT(coll);
MultikeyPaths paths = {{0}};
{
@ -464,8 +480,11 @@ TEST_F(CollectionTest, SetIndexIsMultikeyRemovesUncommittedChangesOnRollback) {
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
ASSERT(coll);
MultikeyPaths paths = {{0}};
@ -490,8 +509,11 @@ TEST_F(CollectionTest, ForceSetIndexIsMultikey) {
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
ASSERT(coll);
MultikeyPaths paths = {{0}};
{
@ -568,8 +590,11 @@ TEST_F(CollectionTest, ForceSetIndexIsMultikeyRemovesUncommittedChangesOnRollbac
makeCollectionForMultikey(nss, indexName);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
ASSERT(coll);
MultikeyPaths paths = {{0}};
@ -595,8 +620,11 @@ TEST_F(CollectionTest, CheckTimeseriesBucketDocsForMixedSchemaData) {
makeTimeseries(nss);
auto opCtx = operationContext();
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const auto& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const auto& coll = acq.getCollectionPtr();
ASSERT(coll);
ASSERT(coll->getTimeseriesOptions());
@ -796,8 +824,11 @@ TEST_F(CatalogTestFixture, CappedDeleteRecord) {
options.cappedSize = 512 * 1024 * 1024;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
ASSERT_EQUALS(0, coll->numRecords(operationContext()));
@ -846,8 +877,11 @@ TEST_F(CatalogTestFixture, CappedDeleteMultipleRecords) {
options.cappedSize = 512 * 1024 * 1024;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
ASSERT_EQUALS(0, coll->numRecords(operationContext()));
@ -894,8 +928,11 @@ TEST_F(CatalogTestFixture, CappedVisibilityEmptyInitialState) {
options.capped = true;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
RecordStore* rs = coll->getRecordStore();
auto doInsert = [&](OperationContext* opCtx) -> RecordId {
@ -1011,13 +1048,13 @@ TEST_F(CatalogTestFixture, CappedVisibilityNonEmptyInitialState) {
options.capped = true;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
RecordStore* rs = coll->getRecordStore();
auto doInsert = [&](OperationContext* opCtx) -> RecordId {
Lock::GlobalLock globalLock{opCtx, MODE_IX};
std::string data = "data";
auto coll = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto rs = coll.getCollectionPtr()->getRecordStore();
return uassertStatusOK(rs->insertRecord(opCtx,
*shard_role_details::getRecoveryUnit(opCtx),
data.c_str(),
@ -1035,6 +1072,12 @@ TEST_F(CatalogTestFixture, CappedVisibilityNonEmptyInitialState) {
wuow.commit();
}
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto rs = acq.getCollectionPtr()->getRecordStore();
WriteUnitOfWork longLivedWUOW(longLivedOpCtx.get());
// Can see initial doc.
@ -1188,8 +1231,11 @@ TEST_F(CollectionTest, CappedCursorRollover) {
options.cappedSize = 512 * 1024 * 1024;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
RecordStore* rs = coll->getRecordStore();
// First insert 3 documents.
@ -1232,8 +1278,11 @@ TEST_F(CollectionTest, BoundedSeek) {
NamespaceString nss = NamespaceString::createNamespaceString_forTest("test.t");
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, {}));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
RecordStore* rs = coll->getRecordStore();
auto doInsert = [&](OperationContext* opCtx) -> RecordId {
@ -1320,8 +1369,11 @@ TEST_F(CatalogTestFixture, CappedCursorYieldFirst) {
options.capped = true;
ASSERT_OK(storageInterface()->createCollection(operationContext(), nss, options));
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
RecordStore* rs = coll->getRecordStore();
RecordId recordId;
@ -1364,13 +1416,16 @@ TEST_F(CatalogTestFixture, TruncateRangeFailOnNonClusteredCollection) {
RecordId maxRecordId("b");
ASSERT_OK(storageInterface()->createCollection(opCtx, nss, options));
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
// Should fail since collection is not clustered.
ASSERT_THROWS_CODE(
collection_internal::truncateRange(opCtx, *autoColl, minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
ASSERT_THROWS_CODE(collection_internal::truncateRange(
opCtx, acq.getCollectionPtr(), minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
}
TEST_F(CatalogTestFixture, TruncateRangeOnClusteredCollection) {
@ -1383,8 +1438,11 @@ TEST_F(CatalogTestFixture, TruncateRangeOnClusteredCollection) {
ASSERT_OK(storageInterface()->createCollection(opCtx, nss, options));
// Acquire exclusive access for index creation later.
AutoGetCollection autoColl(opCtx, nss, MODE_X);
const CollectionPtr& coll = *autoColl;
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
const CollectionPtr& coll = acq.getCollectionPtr();
// Should not throw on a clustered collection with no indexes.
{
@ -1402,17 +1460,21 @@ TEST_F(CatalogTestFixture, TruncateRangeOnClusteredCollection) {
// Should fail if collection has indexes.
{
auto indexName = "myindex"_sd;
WriteUnitOfWork wuow(opCtx);
CollectionWriter writer{opCtx, autoColl};
auto writableColl = writer.getWritableCollection(opCtx);
ASSERT_OK(writableColl->getIndexCatalog()->createIndexOnEmptyCollection(
opCtx, writableColl, BSON("v" << 2 << "name" << indexName << "key" << BSON("a" << 1))));
wuow.commit();
{
CollectionWriter writer{opCtx, &acq};
WriteUnitOfWork wuow(opCtx);
auto writableColl = writer.getWritableCollection(opCtx);
ASSERT_OK(writableColl->getIndexCatalog()->createIndexOnEmptyCollection(
opCtx,
writableColl,
BSON("v" << 2 << "name" << indexName << "key" << BSON("a" << 1))));
wuow.commit();
}
ASSERT_THROWS_CODE(
collection_internal::truncateRange(opCtx, coll, minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
ASSERT_THROWS_CODE(collection_internal::truncateRange(
opCtx, acq.getCollectionPtr(), minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
}
}
@ -1426,13 +1488,16 @@ TEST_F(CatalogTestFixture, TruncateRangeOnPreimagesEnabledCollection) {
RecordId maxRecordId("b");
ASSERT_OK(storageInterface()->createCollection(opCtx, nss, options));
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
// Should fail since change stream preimages is enabled.
ASSERT_THROWS_CODE(
collection_internal::truncateRange(opCtx, *autoColl, minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
ASSERT_THROWS_CODE(collection_internal::truncateRange(
opCtx, acq.getCollectionPtr(), minRecordId, maxRecordId, 1, 1),
DBException,
ErrorCodes::IllegalOperation);
}
class TruncateRangeTest : public CollectionTest {
@ -1469,9 +1534,12 @@ protected:
options.clusteredIndex = clustered_util::makeDefaultClusteredIdIndex();
ASSERT_OK(storageInterface()->createCollection(opCtx, nss, options));
AutoGetCollection autoColl(opCtx, nss, MODE_IX);
const CollectionPtr& coll = *autoColl;
auto rs = autoColl->getRecordStore();
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
const CollectionPtr& coll = acq.getCollectionPtr();
auto rs = acq.getCollectionPtr()->getRecordStore();
std::vector<RecordId> recordIds = sortedRecordIds;
ASSERT_EQ(recordIds.size(), numToInsert);

View File

@ -39,6 +39,7 @@
#include "mongo/db/shard_role/shard_catalog/collection.h"
#include "mongo/db/shard_role/shard_catalog/collection_catalog.h"
#include "mongo/db/shard_role/shard_catalog/collection_mock.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/thread.h"
@ -121,8 +122,11 @@ protected:
};
TEST_F(CollectionWriterTest, Commit) {
AutoGetCollection lock(operationContext(), kNss, MODE_X);
CollectionWriter writer(operationContext(), kNss);
auto lock = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter writer(operationContext(), &lock);
const Collection* before = lookupCollectionFromCatalog().get();
@ -174,8 +178,11 @@ TEST_F(CollectionWriterTest, Commit) {
}
TEST_F(CollectionWriterTest, Rollback) {
AutoGetCollection lock(operationContext(), kNss, MODE_X);
CollectionWriter writer(operationContext(), kNss);
auto lock = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter writer(operationContext(), &lock);
const Collection* before = lookupCollectionFromCatalog().get();
@ -203,11 +210,15 @@ TEST_F(CollectionWriterTest, CommitAfterDestroy) {
const Collection* writable = nullptr;
{
AutoGetCollection lock(operationContext(), kNss, MODE_X);
auto lock =
acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kNss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(operationContext());
{
CollectionWriter writer(operationContext(), kNss);
CollectionWriter writer(operationContext(), &lock);
// Request a writable Collection and destroy CollectionWriter before WUOW commits
writable = writer.getWritableCollection(operationContext());
@ -269,8 +280,11 @@ TEST_F(CollectionWriterTest, OplogCOW) {
const auto& oplogInitial = lookupCollectionFromCatalogForRead(nss);
ASSERT(oplogInitial);
AutoGetCollection lock(operationContext(), nss, MODE_X);
CollectionWriter writer(operationContext(), nss);
auto lock = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter writer(operationContext(), &lock);
const auto& oplogDuringDDL = lookupCollectionFromCatalogForRead(nss);
ASSERT(oplogDuringDDL);
@ -318,11 +332,15 @@ void runAutoGetOplogFastPathObjectStabilityConcurrentDDL(ServiceContext* svcCtx,
writeConflictRetry(
opCtx.get(), "dummy oplog DDL", NamespaceString::kRsOplogNamespace, [&] {
AutoGetCollection autoColl(
opCtx.get(), NamespaceString::kRsOplogNamespace, MODE_X);
ASSERT(*autoColl);
auto acq = acquireCollection(
opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(opCtx.get(),
NamespaceString::kRsOplogNamespace,
AcquisitionPrerequisites::kWrite),
MODE_X);
ASSERT(acq.getCollectionPtr());
WriteUnitOfWork wunit(opCtx.get());
CollectionWriter writer{opCtx.get(), autoColl};
CollectionWriter writer{opCtx.get(), &acq};
auto oplogWrite = writer.getWritableCollection(opCtx.get());
ASSERT(oplogWrite);

View File

@ -53,12 +53,13 @@
#include "mongo/db/shard_role/lock_manager/d_concurrency.h"
#include "mongo/db/shard_role/lock_manager/exception_util.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/collection.h"
#include "mongo/db/shard_role/shard_catalog/collection_catalog.h"
#include "mongo/db/shard_role/shard_catalog/database.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/virtual_collection_impl.h"
#include "mongo/db/shard_role/shard_catalog/virtual_collection_options.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/kv/kv_engine.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_gen.h"
@ -148,8 +149,11 @@ void CreateCollectionTest::validateValidator(const std::string& validatorStr,
options.uuid = UUID::gen();
return writeConflictRetry(opCtx.get(), "create", newNss, [&] {
AutoGetCollection autoColl(opCtx.get(), newNss, MODE_IX);
auto db = autoColl.ensureDbExists(opCtx.get());
auto acq = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), newNss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(opCtx.get())->openDb(opCtx.get(), newNss.dbName());
ASSERT_TRUE(db) << "Cannot create collection " << newNss.toStringForErrorMsg()
<< " because database " << newNss.dbName().toStringForErrorMsg()
<< " does not exist.";

View File

@ -79,6 +79,7 @@
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_catalog/unique_collection_name.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/shard_role/transaction_resources.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_gen.h"
@ -217,10 +218,13 @@ void runCreateCollection(OperationContext* opCtx,
const BSONObj& idIndex = BSONObj(),
bool fromMigrate = false) {
writeConflictRetry(opCtx, "testCatalogIdentifiers", nss, [&] {
WriteUnitOfWork wuow(opCtx);
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(opCtx);
// Signals 'onCreateCollection()' to all OpObservers once complete.
ASSERT_TRUE(db->createCollection(
@ -278,10 +282,13 @@ TEST_F(DatabaseTest, CreateCollectionDoesNotReportCatalogIdentifierForVirtualCol
auto opCtx = _opCtx.get();
repl::UnreplicatedWritesBlock uwb(opCtx); // virtual collections are standalone-only
writeConflictRetry(opCtx, "testNoCatalogIdentifierForVirtualColl", _nss, [&] {
WriteUnitOfWork wuow(opCtx);
AutoGetDb autoDb(opCtx, _nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, _nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(opCtx);
// Signals 'onCreateCollection()' to the OpObserver once complete.
uassertStatusOK(
@ -298,8 +305,11 @@ TEST_F(DatabaseTest, CreateCollectionThrowsExceptionWhenDatabaseIsInADropPending
catalog.addDropPending(dbName);
});
AutoGetDb autoDb(_opCtx.get(), _nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(_opCtx.get());
auto acq = acquireCollection(_opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
_opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(_opCtx.get())->openDb(_opCtx.get(), _nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(_opCtx.get());
@ -321,18 +331,24 @@ void _testDropCollection(OperationContext* opCtx,
const CollectionOptions& collOpts = {}) {
if (createCollectionBeforeDrop) {
writeConflictRetry(opCtx, "testDropCollection", nss, [=] {
WriteUnitOfWork wuow(opCtx);
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(opCtx);
ASSERT_TRUE(db->createCollection(opCtx, nss, collOpts));
wuow.commit();
});
}
writeConflictRetry(opCtx, "testDropCollection", nss, [=] {
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(opCtx);
@ -372,8 +388,11 @@ TEST_F(DatabaseTest, DropCollectionRejectsProvidedDropOpTimeIfWritesAreReplicate
auto opCtx = _opCtx.get();
auto nss = _nss;
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
writeConflictRetry(opCtx, "testDropOpTimeWithReplicated", nss, [&] {
ASSERT_TRUE(db);
@ -390,8 +409,11 @@ TEST_F(DatabaseTest, DropCollectionRejectsProvidedDropOpTimeIfWritesAreReplicate
void _testDropCollectionThrowsExceptionIfThereAreIndexesInProgress(OperationContext* opCtx,
const NamespaceString& nss) {
writeConflictRetry(opCtx, "testDropCollectionWithIndexesInProgress", nss, [opCtx, nss] {
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db);
Collection* collection = nullptr;
@ -495,8 +517,11 @@ TEST_F(DatabaseTest, RenameCollectionPreservesUuidOfSourceCollectionAndUpdatesUu
TEST_F(DatabaseTest,
MakeUniqueCollectionNamespaceReturnsFailedToParseIfModelDoesNotContainPercentSign) {
writeConflictRetry(_opCtx.get(), "testMakeUniqueCollectionNamespace", _nss, [this] {
AutoGetDb autoDb(_opCtx.get(), _nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(_opCtx.get());
auto acq = acquireCollection(_opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
_opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(_opCtx.get())->openDb(_opCtx.get(), _nss.dbName());
ASSERT_TRUE(db);
ASSERT_EQUALS(ErrorCodes::FailedToParse,
makeUniqueCollectionName(
@ -570,7 +595,7 @@ TEST_F(
}
// makeUniqueCollectionName() returns NamespaceExists because it will not be able to
// generate a namespace that will not collide with an existings collection.
// generate a namespace that will not collide with an existing collection.
ASSERT_EQUALS(ErrorCodes::NamespaceExists,
makeUniqueCollectionName(_opCtx.get(), db->name(), model));
});
@ -578,7 +603,7 @@ TEST_F(
TEST_F(DatabaseTest, AutoGetDBSucceedsWithDeadlineNow) {
NamespaceString nss = NamespaceString::createNamespaceString_forTest("test", "coll");
Lock::DBLock lock(_opCtx.get(), nss.dbName(), MODE_X);
AutoGetDb autoDb(_opCtx.get(), nss.dbName(), MODE_X);
ASSERT(shard_role_details::getLocker(_opCtx.get())->isDbLockedForMode(nss.dbName(), MODE_X));
try {
AutoGetDb db(_opCtx.get(), nss.dbName(), MODE_X, Date_t::now());
@ -591,7 +616,7 @@ TEST_F(DatabaseTest, AutoGetDBSucceedsWithDeadlineNow) {
TEST_F(DatabaseTest, AutoGetDBSucceedsWithDeadlineMin) {
NamespaceString nss = NamespaceString::createNamespaceString_forTest("test", "coll");
Lock::DBLock lock(_opCtx.get(), nss.dbName(), MODE_X);
AutoGetDb autoDb(_opCtx.get(), nss.dbName(), MODE_X);
ASSERT(shard_role_details::getLocker(_opCtx.get())->isDbLockedForMode(nss.dbName(), MODE_X));
try {
AutoGetDb db(_opCtx.get(), nss.dbName(), MODE_X, Date_t());
@ -603,28 +628,30 @@ TEST_F(DatabaseTest, AutoGetDBSucceedsWithDeadlineMin) {
}
TEST_F(DatabaseTest, CreateCollectionProhibitsReplicatedCollectionsWithoutIdIndex) {
writeConflictRetry(_opCtx.get(),
"testÇreateCollectionProhibitsReplicatedCollectionsWithoutIdIndex",
_nss,
[this] {
AutoGetDb autoDb(_opCtx.get(), _nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(_opCtx.get());
ASSERT_TRUE(db);
writeConflictRetry(
_opCtx.get(),
"testÇreateCollectionProhibitsReplicatedCollectionsWithoutIdIndex",
_nss,
[this] {
auto acq = acquireCollection(_opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
_opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(_opCtx.get())->openDb(_opCtx.get(), _nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(_opCtx.get());
WriteUnitOfWork wuow(_opCtx.get());
CollectionOptions options;
options.setNoIdIndex();
CollectionOptions options;
options.setNoIdIndex();
ASSERT_THROWS_CODE_AND_WHAT(
db->createCollection(_opCtx.get(), _nss, options),
AssertionException,
50001,
(StringBuilder()
<< "autoIndexId:false is not allowed for collection "
<< _nss.toStringForErrorMsg() << " because it can be replicated")
.stringData());
});
ASSERT_THROWS_CODE_AND_WHAT(
db->createCollection(_opCtx.get(), _nss, options),
AssertionException,
50001,
(str::stream() << "autoIndexId:false is not allowed for collection "
<< _nss.toStringForErrorMsg() << " because it can be replicated"));
});
}
@ -740,9 +767,12 @@ TEST_F(DatabaseTest, OpenDbAllowsPreExistingNonAsciiCaseConflict) {
auto createAndClose = [&](const DatabaseName& dbName) {
NamespaceString nss = NamespaceString::createNamespaceString_forTest(dbName, "c");
writeConflictRetry(opCtx, "createAndClose", nss, [&] {
auto acq = acquireCollection(opCtx,
CollectionAcquisitionRequest::fromOpCtx(
opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, dbName);
WriteUnitOfWork wuow(opCtx);
AutoGetDb autoDb(opCtx, dbName, MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
ASSERT_TRUE(db->createCollection(opCtx, nss));
wuow.commit();
});
@ -845,9 +875,13 @@ protected:
}
bool areRecordIdsReplicated(OperationContext* opCtx, const NamespaceString& nss) {
AutoGetCollection autoColl(opCtx, nss, MODE_IS);
ASSERT_TRUE(*autoColl) << "Collection " << nss.toStringForErrorMsg() << " not found";
return (*autoColl)->areRecordIdsReplicated();
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kRead),
MODE_IS);
ASSERT_TRUE(acq.getCollectionPtr())
<< "Collection " << nss.toStringForErrorMsg() << " not found";
return (acq.getCollectionPtr())->areRecordIdsReplicated();
}
const NamespaceString _testNss =
@ -893,8 +927,11 @@ TEST_F(RecordIdsReplicatedDatabaseTest, NeitherProviderNorFlag_False) {
Status attemptUserCreateTimeseriesNS(OperationContext* opCtx,
const NamespaceString& nss,
bool fromMigrate = false) {
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto* db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto* db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
invariant(db);
CollectionOptions options{.clusteredIndex =
clustered_util::makeCanonicalClusteredInfoForLegacyFormat(),

View File

@ -199,8 +199,11 @@ void DropDatabaseTest::tearDown() {
*/
void _createCollection(OperationContext* opCtx, const NamespaceString& nss) {
writeConflictRetry(opCtx, "testDropCollection", nss, [=] {
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db);
WriteUnitOfWork wuow(opCtx);

View File

@ -30,25 +30,21 @@
#include "mongo/base/error_codes.h"
#include "mongo/base/string_data.h"
#include "mongo/crypto/encryption_fields_gen.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/clustered_collection_options_gen.h"
#include "mongo/db/shard_role/shard_catalog/collection_options.h"
#include "mongo/db/shard_role/shard_catalog/collection_sharding_runtime.h"
#include "mongo/db/shard_role/shard_catalog/database.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/operation_sharding_state.h"
#include "mongo/db/sharding_environment/shard_server_test_fixture.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_gen.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/uuid.h"
#include <memory>
#include <boost/move/utility_core.hpp>
#include <boost/optional/optional.hpp>
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
@ -62,8 +58,11 @@ class ImplicitCollectionCreationTest : public ShardServerTestFixture {};
TEST_F(ImplicitCollectionCreationTest, ImplicitCreateDisallowedByDefault) {
NamespaceString nss = NamespaceString::createNamespaceString_forTest(
"ImplicitCreateDisallowedByDefaultDB.TestColl");
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
auto db = autoColl.ensureDbExists(operationContext());
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(operationContext())->openDb(operationContext(), nss.dbName());
WriteUnitOfWork wuow(operationContext());
ASSERT_THROWS_CODE(
uassertStatusOK(db->userCreateNS(operationContext(), nss, CollectionOptions{})),
@ -77,8 +76,11 @@ TEST_F(ImplicitCollectionCreationTest, AllowImplicitCollectionCreate) {
NamespaceString::createNamespaceString_forTest("AllowImplicitCollectionCreateDB.TestColl");
OperationShardingState::ScopedAllowImplicitCollectionCreate_UNSAFE unsafeCreateCollection(
operationContext(), nss);
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
auto db = autoColl.ensureDbExists(operationContext());
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(operationContext())->openDb(operationContext(), nss.dbName());
WriteUnitOfWork wuow(operationContext());
ASSERT_OK(db->userCreateNS(operationContext(), nss, CollectionOptions{}));
wuow.commit();
@ -93,8 +95,11 @@ TEST_F(ImplicitCollectionCreationTest, AllowImplicitCollectionCreateWithSetCSRAs
NamespaceString::createNamespaceString_forTest("AllowImplicitCollectionCreateDB.TestColl");
OperationShardingState::ScopedAllowImplicitCollectionCreate_UNSAFE unsafeCreateCollection(
operationContext(), nss, /* forceCSRAsUnknownAfterCollectionCreation */ true);
AutoGetCollection autoColl(operationContext(), nss, MODE_IX);
auto db = autoColl.ensureDbExists(operationContext());
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_IX);
auto db = DatabaseHolder::get(operationContext())->openDb(operationContext(), nss.dbName());
WriteUnitOfWork wuow(operationContext());
ASSERT_OK(db->userCreateNS(operationContext(), nss, CollectionOptions{}));
wuow.commit();

View File

@ -33,6 +33,7 @@
#include "mongo/db/service_context.h"
#include "mongo/db/shard_role/ddl/list_indexes_allowed_fields.h"
#include "mongo/db/shard_role/shard_catalog/catalog_test_fixture.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/sorted_data_interface.h"
#include "mongo/unittest/barrier.h"
#include "mongo/util/time_support.h"
@ -62,9 +63,12 @@ TEST_F(IndexCatalogImplTest, WithInvalidIndexSpec) {
// Create an index which has an invalid on-disk format. This gets fixed whenever we return them
// with listIndexes.
{
AutoGetCollection autoColl(operationContext(), nss, MODE_X);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(operationContext());
CollectionWriter writer{operationContext(), autoColl};
CollectionWriter writer{operationContext(), &acq};
auto writableColl = writer.getWritableCollection(operationContext());
IndexDescriptor desc{IndexNames::BTREE, bson};
@ -78,17 +82,20 @@ TEST_F(IndexCatalogImplTest, WithInvalidIndexSpec) {
{
auto fixedSpec = index_key_validate::repairIndexSpec(nss, bson);
AutoGetCollection autoColl(operationContext(), nss, MODE_X);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), nss, AcquisitionPrerequisites::kWrite),
MODE_X);
// We have a spec that's fixed according to what listIndexes would output and the on-disk
// one. These two are different, so we expect them to cause a conflict and mismatch.
auto indexes = autoColl->getIndexCatalog()->removeExistingIndexesNoChecks(
operationContext(), *autoColl, {fixedSpec});
auto indexes = acq.getCollectionPtr()->getIndexCatalog()->removeExistingIndexesNoChecks(
operationContext(), acq.getCollectionPtr(), {fixedSpec});
ASSERT_FALSE(indexes.empty());
// However, if we specify to the index catalog that we must repair the spec before
// comparison with the given allowed fields then we should have no conflict.
indexes = autoColl->getIndexCatalog()->removeExistingIndexesNoChecks(
indexes = acq.getCollectionPtr()->getIndexCatalog()->removeExistingIndexesNoChecks(
operationContext(),
*autoColl,
acq.getCollectionPtr(),
{fixedSpec},
IndexCatalog::RemoveExistingIndexesFlags{true, &kAllowedListIndexesFieldNames});
ASSERT_TRUE(indexes.empty());

View File

@ -50,6 +50,7 @@
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_gen.h"
#include "mongo/idl/server_parameter_test_controller.h"
@ -72,20 +73,19 @@ public:
IndexSignatureTest() : CatalogTestFixture() {}
StatusWith<const IndexCatalogEntry*> createIndex(BSONObj spec) {
// Build the specified index on the collection.
WriteUnitOfWork wuow(opCtx());
CollectionWriter writer{opCtx(), _coll.get()};
// Get the index catalog associated with the test collection.
auto* indexCatalog = writer.getWritableCollection(opCtx())->getIndexCatalog();
auto status = indexCatalog->createIndexOnEmptyCollection(
opCtx(), writer.getWritableCollection(opCtx()), spec);
if (!status.isOK()) {
return status.getStatus();
CollectionWriter writer{opCtx(), &_coll.value()};
{
WriteUnitOfWork wuow(opCtx());
auto* indexCatalog = writer.getWritableCollection(opCtx())->getIndexCatalog();
auto status = indexCatalog->createIndexOnEmptyCollection(
opCtx(), writer.getWritableCollection(opCtx()), spec);
if (!status.isOK()) {
return status.getStatus();
}
wuow.commit();
}
wuow.commit();
// Find the index entry and return it.
return indexCatalog->findIndexByName(
return writer.get()->getIndexCatalog()->findIndexByName(
opCtx(), spec.getStringField(IndexDescriptor::kIndexNameFieldName));
}
@ -103,7 +103,7 @@ public:
}
const CollectionPtr& coll() const {
return *_coll.get();
return _coll->getCollectionPtr();
}
OperationContext* opCtx() {
@ -114,7 +114,10 @@ protected:
void setUp() override {
CatalogTestFixture::setUp();
ASSERT_OK(storageInterface()->createCollection(opCtx(), _nss, {}));
_coll.emplace(opCtx(), _nss, MODE_X);
_coll = acquireCollection(opCtx(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
}
void tearDown() override {
@ -123,7 +126,7 @@ protected:
}
private:
boost::optional<AutoGetCollection> _coll;
boost::optional<CollectionAcquisition> _coll;
NamespaceString _nss = NamespaceString::createNamespaceString_forTest("fooDB.barColl");
};

View File

@ -38,13 +38,14 @@
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/collection.h"
#include "mongo/db/shard_role/shard_catalog/collection_catalog.h"
#include "mongo/db/shard_role/shard_catalog/database.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/dbtests/dbtests.h" // IWYU pragma: keep
#include "mongo/unittest/unittest.h"
@ -78,20 +79,29 @@ public:
IndexIteratorTests() {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
AutoGetDb autodb(&opCtx, _nss.dbName(), MODE_X);
auto acq = acquireCollection(
&opCtx,
CollectionAcquisitionRequest::fromOpCtx(&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(&opCtx);
autodb.ensureDbExists(&opCtx)->createCollection(&opCtx, _nss);
DatabaseHolder::get(&opCtx)->openDb(&opCtx, _nss.dbName())->createCollection(&opCtx, _nss);
wuow.commit();
}
~IndexIteratorTests() {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
AutoGetDb autodb(&opCtx, _nss.dbName(), MODE_X);
auto acq = acquireCollection(
&opCtx,
CollectionAcquisitionRequest::fromOpCtx(&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(&opCtx);
autodb.ensureDbExists(&opCtx)->dropCollection(&opCtx, _nss).transitional_ignore();
DatabaseHolder::get(&opCtx)
->openDb(&opCtx, _nss.dbName())
->dropCollection(&opCtx, _nss)
.transitional_ignore();
wuow.commit();
}
@ -136,20 +146,29 @@ public:
RefreshEntry() {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
AutoGetDb autodb(&opCtx, _nss.dbName(), MODE_X);
auto acq = acquireCollection(
&opCtx,
CollectionAcquisitionRequest::fromOpCtx(&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(&opCtx);
autodb.ensureDbExists(&opCtx)->createCollection(&opCtx, _nss);
DatabaseHolder::get(&opCtx)->openDb(&opCtx, _nss.dbName())->createCollection(&opCtx, _nss);
wuow.commit();
}
~RefreshEntry() {
const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext();
OperationContext& opCtx = *opCtxPtr;
AutoGetDb autodb(&opCtx, _nss.dbName(), MODE_X);
auto acq = acquireCollection(
&opCtx,
CollectionAcquisitionRequest::fromOpCtx(&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow(&opCtx);
autodb.ensureDbExists(&opCtx)->dropCollection(&opCtx, _nss).transitional_ignore();
DatabaseHolder::get(&opCtx)
->openDb(&opCtx, _nss.dbName())
->dropCollection(&opCtx, _nss)
.transitional_ignore();
wuow.commit();
}
@ -172,8 +191,11 @@ public:
// Change value of "expireAfterSeconds" on disk. This will update the metadata for the
// Collection but not propagate the change to the IndexCatalog
{
AutoGetCollection autoColl(&opCtx, _nss, MODE_X);
CollectionWriter coll(&opCtx, autoColl);
auto acq = acquireCollection(&opCtx,
CollectionAcquisitionRequest::fromOpCtx(
&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter coll(&opCtx, &acq);
WriteUnitOfWork wuow(&opCtx);
coll.getWritableCollection(&opCtx)->updateTTLSetting(&opCtx, "x_1", 10);
@ -185,8 +207,11 @@ public:
ASSERT_EQUALS(5, entry->descriptor()->infoObj()["expireAfterSeconds"].numberLong());
{
AutoGetCollection autoColl(&opCtx, _nss, MODE_X);
CollectionWriter coll(&opCtx, autoColl);
auto acq = acquireCollection(&opCtx,
CollectionAcquisitionRequest::fromOpCtx(
&opCtx, _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
CollectionWriter coll(&opCtx, &acq);
// Notify the catalog of the change.
WriteUnitOfWork wuow(&opCtx);
@ -204,9 +229,14 @@ class PrepareUniqueIndexRecords : IndexCatalogTestBase {
public:
~PrepareUniqueIndexRecords() {
auto opCtx = cc().makeOperationContext();
AutoGetDb db{opCtx.get(), _nss.dbName(), LockMode::MODE_X};
auto acq = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_OK(db.getDb()->dropCollection(opCtx.get(), _nss));
ASSERT_OK(DatabaseHolder::get(opCtx.get())
->getDb(opCtx.get(), _nss.dbName())
->dropCollection(opCtx.get(), _nss));
wuow.commit();
}
@ -222,14 +252,19 @@ public:
<< IndexDescriptor::kKeyPatternFieldName << BSON("a" << 1)
<< IndexDescriptor::kPrepareUniqueFieldName << true)));
AutoGetCollection coll{opCtx.get(), _nss, LockMode::MODE_X};
auto coll = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto doc1 = BSON("_id" << 1 << "a" << 1);
auto doc2 = BSON("_id" << 2 << "a" << 1);
{
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_OK(indexCatalog(opCtx.get())
->indexRecords(opCtx.get(), *coll, {{RecordId{1}, {}, &doc1}}, nullptr));
ASSERT_OK(
indexCatalog(opCtx.get())
->indexRecords(
opCtx.get(), coll.getCollectionPtr(), {{RecordId{1}, {}, &doc1}}, nullptr));
wuow.commit();
}
@ -237,15 +272,18 @@ public:
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_NOT_OK(
indexCatalog(opCtx.get())
->indexRecords(opCtx.get(), *coll, {{RecordId{2}, {}, &doc2}}, nullptr));
->indexRecords(
opCtx.get(), coll.getCollectionPtr(), {{RecordId{2}, {}, &doc2}}, nullptr));
}
opCtx->setEnforceConstraints(false);
{
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_OK(indexCatalog(opCtx.get())
->indexRecords(opCtx.get(), *coll, {{RecordId{2}, {}, &doc2}}, nullptr));
ASSERT_OK(
indexCatalog(opCtx.get())
->indexRecords(
opCtx.get(), coll.getCollectionPtr(), {{RecordId{2}, {}, &doc2}}, nullptr));
wuow.commit();
}
}
@ -255,9 +293,14 @@ class PrepareUniqueUpdateRecord : IndexCatalogTestBase {
public:
~PrepareUniqueUpdateRecord() {
auto opCtx = cc().makeOperationContext();
AutoGetDb db{opCtx.get(), _nss.dbName(), LockMode::MODE_X};
auto acq = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_OK(db.getDb()->dropCollection(opCtx.get(), _nss));
ASSERT_OK(DatabaseHolder::get(opCtx.get())
->getDb(opCtx.get(), _nss.dbName())
->dropCollection(opCtx.get(), _nss));
wuow.commit();
}
@ -273,7 +316,10 @@ public:
<< IndexDescriptor::kKeyPatternFieldName << BSON("a" << 1)
<< IndexDescriptor::kPrepareUniqueFieldName << true)));
AutoGetCollection coll{opCtx.get(), _nss, LockMode::MODE_X};
auto coll = acquireCollection(opCtx.get(),
CollectionAcquisitionRequest::fromOpCtx(
opCtx.get(), _nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto doc1 = BSON("_id" << 1 << "a" << 1);
auto doc2 = BSON("_id" << 2 << "a" << 2);
auto updatedDoc2 = BSON("_id" << 2 << "a" << 1);
@ -282,7 +328,7 @@ public:
WriteUnitOfWork wuow{opCtx.get()};
ASSERT_OK(indexCatalog(opCtx.get())
->indexRecords(opCtx.get(),
*coll,
coll.getCollectionPtr(),
{{RecordId{1}, {}, &doc1}, {RecordId{2}, {}, &doc2}},
nullptr));
wuow.commit();
@ -293,7 +339,7 @@ public:
int64_t keysInsertedOut, keysDeletedOut;
ASSERT_NOT_OK(indexCatalog(opCtx.get())
->updateRecord(opCtx.get(),
*coll,
coll.getCollectionPtr(),
doc2,
updatedDoc2,
nullptr,
@ -311,7 +357,7 @@ public:
int64_t keysInsertedOut, keysDeletedOut;
ASSERT_OK(indexCatalog(opCtx.get())
->updateRecord(opCtx.get(),
*coll,
coll.getCollectionPtr(),
doc2,
updatedDoc2,
nullptr,

View File

@ -54,13 +54,13 @@
#include "mongo/db/session/logical_session_id.h"
#include "mongo/db/shard_role/lock_manager/d_concurrency.h"
#include "mongo/db/shard_role/lock_manager/lock_manager_defs.h"
#include "mongo/db/shard_role/shard_catalog/catalog_raii.h"
#include "mongo/db/shard_role/shard_catalog/collection.h"
#include "mongo/db/shard_role/shard_catalog/collection_metadata.h"
#include "mongo/db/shard_role/shard_catalog/collection_sharding_runtime.h"
#include "mongo/db/shard_role/shard_catalog/create_collection.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/operation_sharding_state.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/sharding_environment/shard_id.h"
#include "mongo/db/sharding_environment/shard_server_test_fixture.h"
#include "mongo/db/storage/write_unit_of_work.h"
@ -153,7 +153,10 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateUnsharded) {
kTestNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
boost::none /* databaseVersion */};
AutoGetCollection autoColl(operationContext(), kTestNss, MODE_IX);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kTestNss, AcquisitionPrerequisites::kRead),
MODE_IS);
auto doc = BSON("key3" << "abc"
<< "key" << 3 << "_id"
@ -161,7 +164,8 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateUnsharded) {
<< "key2" << true);
// Check that an order for deletion from an unsharded collection extracts just the "_id" field
ASSERT_BSONOBJ_EQ(getDocumentKey(*autoColl, doc).getShardKeyAndId(), BSON("_id" << "hello"));
ASSERT_BSONOBJ_EQ(getDocumentKey(acq.getCollectionPtr(), doc).getShardKeyAndId(),
BSON("_id" << "hello"));
}
TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithoutIdInShardKey) {
@ -173,7 +177,10 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithoutIdInShardKey) {
kTestNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
boost::none /* databaseVersion */};
AutoGetCollection autoColl(operationContext(), kTestNss, MODE_IX);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kTestNss, AcquisitionPrerequisites::kRead),
MODE_IS);
// The order of fields in `doc` deliberately does not match the shard key
auto doc = BSON("key3" << "abc"
@ -182,7 +189,7 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithoutIdInShardKey) {
<< "key2" << true);
// Verify the shard key is extracted, in correct order, followed by the "_id" field.
ASSERT_BSONOBJ_EQ(getDocumentKey(*autoColl, doc).getShardKeyAndId(),
ASSERT_BSONOBJ_EQ(getDocumentKey(acq.getCollectionPtr(), doc).getShardKeyAndId(),
BSON("key" << 100 << "key3"
<< "abc"
<< "_id"
@ -198,7 +205,10 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithIdInShardKey) {
kTestNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
boost::none /* databaseVersion */};
AutoGetCollection autoColl(operationContext(), kTestNss, MODE_IX);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kTestNss, AcquisitionPrerequisites::kRead),
MODE_IS);
// The order of fields in `doc` deliberately does not match the shard key
auto doc = BSON("key2" << true << "key3"
@ -208,7 +218,7 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithIdInShardKey) {
<< "key" << 100);
// Verify the shard key is extracted with "_id" in the right place.
ASSERT_BSONOBJ_EQ(getDocumentKey(*autoColl, doc).getShardKeyAndId(),
ASSERT_BSONOBJ_EQ(getDocumentKey(acq.getCollectionPtr(), doc).getShardKeyAndId(),
BSON("key" << 100 << "_id"
<< "hello"
<< "key2" << true));
@ -223,14 +233,18 @@ TEST_F(DocumentKeyStateTest, MakeDocumentKeyStateShardedWithIdHashInShardKey) {
kTestNss,
ShardVersionFactory::make(metadata) /* shardVersion */,
boost::none /* databaseVersion */};
AutoGetCollection autoColl(operationContext(), kTestNss, MODE_IX);
auto acq = acquireCollection(operationContext(),
CollectionAcquisitionRequest::fromOpCtx(
operationContext(), kTestNss, AcquisitionPrerequisites::kRead),
MODE_IS);
auto doc = BSON("key2" << true << "_id"
<< "hello"
<< "key" << 100);
// Verify the shard key is extracted with "_id" in the right place, not hashed.
ASSERT_BSONOBJ_EQ(getDocumentKey(*autoColl, doc).getShardKeyAndId(), BSON("_id" << "hello"));
ASSERT_BSONOBJ_EQ(getDocumentKey(acq.getCollectionPtr(), doc).getShardKeyAndId(),
BSON("_id" << "hello"));
}

View File

@ -63,8 +63,10 @@
#include "mongo/db/shard_role/shard_catalog/collection_catalog.h"
#include "mongo/db/shard_role/shard_catalog/collection_options.h"
#include "mongo/db/shard_role/shard_catalog/database.h"
#include "mongo/db/shard_role/shard_catalog/database_holder.h"
#include "mongo/db/shard_role/shard_catalog/index_catalog.h"
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/shard_role/shard_role.h"
#include "mongo/db/shard_role/transaction_resources.h"
#include "mongo/db/storage/write_unit_of_work.h"
#include "mongo/db/timeseries/timeseries_gen.h"
@ -475,8 +477,11 @@ void _createCollection(OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions options = {}) {
writeConflictRetry(opCtx, "_createCollection", nss, [=] {
AutoGetDb autoDb(opCtx, nss.dbName(), MODE_X);
auto db = autoDb.ensureDbExists(opCtx);
auto acq = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
auto db = DatabaseHolder::get(opCtx)->openDb(opCtx, nss.dbName());
ASSERT_TRUE(db) << "Cannot create collection " << nss.toStringForErrorMsg()
<< " because database " << nss.toStringForErrorMsg() << " does not exist.";
@ -561,16 +566,19 @@ void _createIndexOnEmptyCollection(OperationContext* opCtx,
const NamespaceString& nss,
const std::string& indexName) {
writeConflictRetry(opCtx, "_createIndexOnEmptyCollection", nss, [=] {
AutoGetCollection collection(opCtx, nss, MODE_X);
ASSERT_TRUE(collection) << "Cannot create index on empty collection "
<< nss.toStringForErrorMsg() << " because collection "
<< nss.toStringForErrorMsg() << " does not exist.";
auto collection = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
ASSERT_TRUE(collection.exists())
<< "Cannot create index on empty collection " << nss.toStringForErrorMsg()
<< " because collection " << nss.toStringForErrorMsg() << " does not exist.";
auto indexInfoObj = BSON("v" << int(IndexConfig::kLatestIndexVersion) << "key"
<< BSON("a" << 1) << "name" << indexName);
WriteUnitOfWork wuow(opCtx);
CollectionWriter writer{opCtx, collection};
CollectionWriter writer{opCtx, &collection};
auto indexCatalog = writer.getWritableCollection(opCtx)->getIndexCatalog();
ASSERT_OK(indexCatalog
@ -588,13 +596,16 @@ void _createIndexOnEmptyCollection(OperationContext* opCtx,
*/
void _insertDocument(OperationContext* opCtx, const NamespaceString& nss, const BSONObj& doc) {
writeConflictRetry(opCtx, "_insertDocument", nss, [=] {
AutoGetCollection collection(opCtx, nss, MODE_X);
ASSERT_TRUE(collection) << "Cannot insert document " << doc << " into collection "
<< nss.toStringForErrorMsg() << " because collection "
<< nss.toStringForErrorMsg() << " does not exist.";
auto collection = acquireCollection(
opCtx,
CollectionAcquisitionRequest::fromOpCtx(opCtx, nss, AcquisitionPrerequisites::kWrite),
MODE_X);
ASSERT_TRUE(collection.exists())
<< "Cannot insert document " << doc << " into collection " << nss.toStringForErrorMsg()
<< " because collection " << nss.toStringForErrorMsg() << " does not exist.";
WriteUnitOfWork wuow(opCtx);
ASSERT_OK(Helpers::insert(opCtx, *collection, doc));
ASSERT_OK(Helpers::insert(opCtx, collection.getCollectionPtr(), doc));
wuow.commit();
});
}