diff options
author | Jordi Serra Torrens <jordi.serra-torrens@mongodb.com> | 2023-05-09 13:34:04 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-05-09 14:59:57 +0000 |
commit | ef9da916d39ac0ea7c6aa3426dfdfbabe3d2cd5f (patch) | |
tree | 7640854cde43fb42bc090563658fd285def9c8fc /src/mongo/db/shard_role_test.cpp | |
parent | 75825b6618a887a76301b770e68c82077a84cb68 (diff) | |
download | mongo-ef9da916d39ac0ea7c6aa3426dfdfbabe3d2cd5f.tar.gz |
SERVER-76538 Use acquisitons on internal update paths
Diffstat (limited to 'src/mongo/db/shard_role_test.cpp')
-rw-r--r-- | src/mongo/db/shard_role_test.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/mongo/db/shard_role_test.cpp b/src/mongo/db/shard_role_test.cpp index 167780ce139..57626db51d4 100644 --- a/src/mongo/db/shard_role_test.cpp +++ b/src/mongo/db/shard_role_test.cpp @@ -1423,6 +1423,64 @@ TEST_F(ShardRoleTest, RestoreForWriteFailsIfCollectionIsNowAView) { testRestoreFailsIfCollectionIsNowAView(AcquisitionPrerequisites::kWrite); } +TEST_F(ShardRoleTest, RestoreCollectionCreatedUnderScopedLocalCatalogWriteFence) { + const auto nss = NamespaceString::createNamespaceString_forTest(dbNameTestDb, "inexistent"); + auto acquisition = acquireCollection( + opCtx(), + {nss, PlacementConcern{{}, {}}, repl::ReadConcernArgs(), AcquisitionPrerequisites::kWrite}, + MODE_IX); + ASSERT_FALSE(acquisition.exists()); + + // Create the collection + { + WriteUnitOfWork wuow(opCtx()); + ScopedLocalCatalogWriteFence scopedLocalCatalogWriteFence(opCtx(), &acquisition); + createTestCollection(opCtx(), nss); + wuow.commit(); + } + ASSERT_TRUE(acquisition.exists()); + + // Yield + auto yieldedTransactionResources = yieldTransactionResourcesFromOperationContext(opCtx()); + ASSERT(yieldedTransactionResources); + + // Restore works + restoreTransactionResourcesToOperationContext(opCtx(), std::move(*yieldedTransactionResources)); +} + +TEST_F(ShardRoleTest, + RestoreCollectionCreatedUnderScopedLocalCatalogWriteFenceFailsIfNoLongerExists) { + const auto nss = NamespaceString::createNamespaceString_forTest(dbNameTestDb, "inexistent"); + auto acquisition = acquireCollection( + opCtx(), + {nss, PlacementConcern{{}, {}}, repl::ReadConcernArgs(), AcquisitionPrerequisites::kWrite}, + MODE_IX); + ASSERT_FALSE(acquisition.exists()); + + // Create the collection + { + WriteUnitOfWork wuow(opCtx()); + ScopedLocalCatalogWriteFence scopedLocalCatalogWriteFence(opCtx(), &acquisition); + createTestCollection(opCtx(), nss); + wuow.commit(); + } + ASSERT_TRUE(acquisition.exists()); + + // Yield + auto yieldedTransactionResources = yieldTransactionResourcesFromOperationContext(opCtx()); + ASSERT(yieldedTransactionResources); + + // Drop the collection + DBDirectClient client(opCtx()); + client.dropCollection(nss); + + // Restore should fail + ASSERT_THROWS_CODE(restoreTransactionResourcesToOperationContext( + opCtx(), std::move(*yieldedTransactionResources)), + DBException, + ErrorCodes::CollectionUUIDMismatch); +} + // --------------------------------------------------------------------------- // Storage snapshot @@ -1584,5 +1642,58 @@ TEST_F(ShardRoleTest, ScopedLocalCatalogWriteFenceOutsideWUOURollback) { ASSERT(!acquisition.getCollectionPtr()->isTemporary()); } +TEST_F(ShardRoleTest, ScopedLocalCatalogWriteFenceWUOWRollbackAfterAcquisitionOutOfScope) { + // Tests that nothing breaks if ScopedLocalCatalogWriteFence's onRollback handler is executed + // when the collection acquisition has already gone out of scope. + WriteUnitOfWork wuow1(opCtx()); + { + auto acquisition = acquireCollection(opCtx(), + {nssShardedCollection1, + PlacementConcern{{}, shardVersionShardedCollection1}, + repl::ReadConcernArgs(), + AcquisitionPrerequisites::kRead}, + MODE_IX); + ScopedLocalCatalogWriteFence(opCtx(), &acquisition); + } +} + +TEST_F(ShardRoleTest, ScopedLocalCatalogWriteFenceWUOWRollbackAfterANotherClientCreatedCollection) { + const NamespaceString nss = + NamespaceString::createNamespaceString_forTest(dbNameTestDb, "inexistent"); + + // Acquire a collection that does not exist. + auto acquisition = acquireCollection( + opCtx(), + {nss, PlacementConcern{{}, {}}, repl::ReadConcernArgs(), AcquisitionPrerequisites::kWrite}, + MODE_IX); + ASSERT_FALSE(acquisition.exists()); + + // Another client creates the collection + { + auto newClient = opCtx()->getServiceContext()->makeClient("MigrationCoordinator"); + auto newOpCtx = newClient->makeOperationContext(); + createTestCollection(newOpCtx.get(), nss); + } + + // Acquisition still reflects that the collection does not exist. + ASSERT_FALSE(acquisition.exists()); + + // Original client attempts to create the collection, which will result in a WriteConflict and + // rollback. + { + WriteUnitOfWork wuow(opCtx()); + ScopedLocalCatalogWriteFence localCatalogWriteFence(opCtx(), &acquisition); + auto db = DatabaseHolder::get(opCtx())->openDb(opCtx(), nss.dbName()); + ASSERT_THROWS_CODE(db->createCollection(opCtx(), nss, CollectionOptions()), + DBException, + ErrorCodes::WriteConflict); + wuow.commit(); + } + + // Check that after rollback the acquisition has been updated to reflect the latest state of the + // catalog (i.e. the collection exists). + ASSERT_TRUE(acquisition.exists()); +} + } // namespace } // namespace mongo |