summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/durable_catalog_impl.cpp
diff options
context:
space:
mode:
authorDaniel Gottlieb <daniel.gottlieb@mongodb.com>2019-11-26 04:48:50 +0000
committerevergreen <evergreen@mongodb.com>2019-11-26 04:48:50 +0000
commitd471957fc37ef6cafe9ffeda3e231cdc871c3ce3 (patch)
tree3435c9d9420243e350da0f3dfbeecb81afbcd264 /src/mongo/db/storage/durable_catalog_impl.cpp
parent8b0f534a706005d366e200ee56af5c76217656b2 (diff)
downloadmongo-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/storage/durable_catalog_impl.cpp')
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.cpp16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp
index 42a1207672b..49e4c3fa52b 100644
--- a/src/mongo/db/storage/durable_catalog_impl.cpp
+++ b/src/mongo/db/storage/durable_catalog_impl.cpp
@@ -39,6 +39,7 @@
#include "mongo/bson/util/builder.h"
#include "mongo/db/catalog/index_timestamp_helper.h"
#include "mongo/db/concurrency/d_concurrency.h"
+#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
@@ -459,9 +460,13 @@ void DurableCatalogImpl::init(OperationContext* opCtx) {
}
if (!_featureTracker) {
- // If there wasn't a feature document, then just an initialize a feature tracker that
- // doesn't manage a feature document yet.
+ // If there wasn't a feature document, commit a default one to disk. All deployments will
+ // end up with `kPathLevelMultikeyTracking` as every `_id` index build sets this.
+ WriteUnitOfWork wuow(opCtx);
_featureTracker = DurableCatalogImpl::FeatureTracker::create(opCtx, this);
+ _featureTracker->markRepairableFeatureAsInUse(
+ opCtx, FeatureTracker::RepairableFeature::kPathLevelMultikeyTracking);
+ wuow.commit();
}
// In the unlikely event that we have used this _rand before generate a new one.
@@ -777,12 +782,11 @@ StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> DurableCatalogImpl
const NamespaceString& nss,
const CollectionOptions& options,
bool allocateDefaultSpace) {
- invariant(opCtx->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_IX));
invariant(nss.coll().size() > 0);
- if (CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss)) {
- return Status(ErrorCodes::NamespaceExists,
- str::stream() << "collection already exists " << nss);
+ if (CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nss)) {
+ throw WriteConflictException();
}
KVPrefix prefix = KVPrefix::getNextPrefix(nss);