summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2020-04-07 17:18:01 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-07 21:48:45 +0000
commit257b35c81481ec49590202080e7ad354f0890761 (patch)
tree99fb01d3c286275207e9e654b3753eb137e65a36 /src/mongo
parent242d86b0e9a4091466682bbb97d2298839a91569 (diff)
downloadmongo-257b35c81481ec49590202080e7ad354f0890761.tar.gz
SERVER-47176 Make update.cpp not take database MODE_X lock
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/ops/update.cpp49
1 files changed, 22 insertions, 27 deletions
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 81683541275..74e8756c29a 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -38,7 +38,6 @@
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/client.h"
#include "mongo/db/clientcursor.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/exec/update_stage.h"
#include "mongo/db/matcher/extensions_callback_real.h"
@@ -61,35 +60,31 @@ UpdateResult update(OperationContext* opCtx, Database* db, const UpdateRequest&
invariant(!request.isExplain());
const NamespaceString& nsString = request.getNamespaceString();
- Collection* collection =
- CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nsString);
+ invariant(opCtx->lockState()->isCollectionLockedForMode(nsString, MODE_IX));
+
+ Collection* collection;
// The update stage does not create its own collection. As such, if the update is
// an upsert, create the collection that the update stage inserts into beforehand.
- if (!collection && request.isUpsert()) {
- // We have to have an exclusive lock on the db to be allowed to create the collection.
- // Callers should either get an X or create the collection.
- const Locker* locker = opCtx->lockState();
- invariant(locker->isW() ||
- locker->isLockHeldForMode(ResourceId(RESOURCE_DATABASE, nsString.db()), MODE_IX));
-
- writeConflictRetry(opCtx, "createCollection", nsString.ns(), [&] {
- Lock::DBLock lk(opCtx, nsString.db(), MODE_X);
-
- const bool userInitiatedWritesAndNotPrimary = opCtx->writesAreReplicated() &&
- !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, nsString);
-
- if (userInitiatedWritesAndNotPrimary) {
- uassertStatusOK(Status(ErrorCodes::PrimarySteppedDown,
- str::stream() << "Not primary while creating collection "
- << nsString << " during upsert"));
- }
- WriteUnitOfWork wuow(opCtx);
- collection = db->createCollection(opCtx, nsString, CollectionOptions());
- invariant(collection);
- wuow.commit();
- });
- }
+ writeConflictRetry(opCtx, "createCollection", nsString.ns(), [&] {
+ collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(opCtx, nsString);
+ if (collection || !request.isUpsert()) {
+ return;
+ }
+
+ const bool userInitiatedWritesAndNotPrimary = opCtx->writesAreReplicated() &&
+ !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, nsString);
+
+ if (userInitiatedWritesAndNotPrimary) {
+ uassertStatusOK(Status(ErrorCodes::PrimarySteppedDown,
+ str::stream() << "Not primary while creating collection "
+ << nsString << " during upsert"));
+ }
+ WriteUnitOfWork wuow(opCtx);
+ collection = db->createCollection(opCtx, nsString, CollectionOptions());
+ invariant(collection);
+ wuow.commit();
+ });
// Parse the update, get an executor for it, run the executor, get stats out.
const ExtensionsCallbackReal extensionsCallback(opCtx, &request.getNamespaceString());