diff options
author | Daniel Gottlieb <daniel.gottlieb@mongodb.com> | 2019-11-26 04:48:50 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-11-26 04:48:50 +0000 |
commit | d471957fc37ef6cafe9ffeda3e231cdc871c3ce3 (patch) | |
tree | 3435c9d9420243e350da0f3dfbeecb81afbcd264 /src/mongo/db/cloner.cpp | |
parent | 8b0f534a706005d366e200ee56af5c76217656b2 (diff) | |
download | mongo-d471957fc37ef6cafe9ffeda3e231cdc871c3ce3.tar.gz |
SERVER-43859: Take MODE_IX locks for collection creation.
Two concurrent storage transactions can now create collections with the same
collection name. These transactions will conflict at commit time; the first
committer will win and register their collection into the global catalog. The
losing transactions will bubble a WriteConflictException.
Top-level callers that should fail if the collection already existed must now
check and fail with a NamespaceExists error code. Previously, those callers
could rely on lower level code returning the NamespaceExists error.
Callers that were implicitly creating a collection may retry the operation,
using the now-registered collection.
These transaction-local collections (UncommittedCollections) are returned when
doing any CollectionCatalog::lookup* call.
Diffstat (limited to 'src/mongo/db/cloner.cpp')
-rw-r--r-- | src/mongo/db/cloner.cpp | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp index c6475cbe0e9..410def3bffa 100644 --- a/src/mongo/db/cloner.cpp +++ b/src/mongo/db/cloner.cpp @@ -117,7 +117,8 @@ struct Cloner::Fun { bool createdCollection = false; Collection* collection = nullptr; - collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(to_collection); + collection = + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, to_collection); if (!collection) { massert(17321, str::stream() << "collection dropped during clone [" << to_collection.ns() @@ -139,7 +140,7 @@ struct Cloner::Fun { << to_collection.ns() << "]"); wunit.commit(); collection = - CollectionCatalog::get(opCtx).lookupCollectionByNamespace(to_collection); + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, to_collection); invariant(collection, str::stream() << "Missing collection during clone [" << to_collection.ns() << "]"); @@ -181,7 +182,7 @@ struct Cloner::Fun { db != nullptr); collection = - CollectionCatalog::get(opCtx).lookupCollectionByNamespace(to_collection); + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, to_collection); uassert(28594, str::stream() << "Collection " << to_collection.ns() << " dropped while cloning", @@ -329,7 +330,7 @@ void Cloner::copyIndexes(OperationContext* opCtx, auto db = databaseHolder->openDb(opCtx, toDBName); Collection* collection = - CollectionCatalog::get(opCtx).lookupCollectionByNamespace(to_collection); + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, to_collection); if (!collection) { writeConflictRetry(opCtx, "createCollection", to_collection.ns(), [&] { opCtx->checkForInterrupt(); @@ -347,7 +348,8 @@ void Cloner::copyIndexes(OperationContext* opCtx, << "Collection creation failed while copying indexes from " << from_collection.ns() << " to " << to_collection.ns() << " (Cloner)"); wunit.commit(); - collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(to_collection); + collection = + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, to_collection); invariant(collection, str::stream() << "Missing collection " << to_collection.ns() << " (Cloner)"); }); @@ -586,7 +588,8 @@ Status Cloner::createCollectionsForDb( opCtx->checkForInterrupt(); WriteUnitOfWork wunit(opCtx); - Collection* collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss); + Collection* collection = + CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nss); if (collection) { if (!params.shardedColl) { // If the collection is unsharded then we want to fail when a collection |