summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2019-03-22 17:17:21 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2019-03-28 14:15:11 -0400
commitb5f78884606ba87e5a1742e8dd19bbe2e03f709d (patch)
tree2678ce8730ccefb31ff756065bf79ade9cb6ecf7 /src/mongo
parent00afe420f0eccb4204c5a235049385a1189e9c78 (diff)
downloadmongo-b5f78884606ba87e5a1742e8dd19bbe2e03f709d.tar.gz
SERVER-39519 Create/drop view now only takes database IX lock
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/catalog/create_collection.cpp112
-rw-r--r--src/mongo/db/catalog/database.h4
-rw-r--r--src/mongo/db/catalog/database_impl.cpp43
-rw-r--r--src/mongo/db/catalog/database_impl.h4
-rw-r--r--src/mongo/db/catalog/drop_collection.cpp157
-rw-r--r--src/mongo/db/catalog/index_build_block.cpp16
-rw-r--r--src/mongo/db/storage/kv/kv_catalog.cpp8
-rw-r--r--src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp8
-rw-r--r--src/mongo/db/views/durable_view_catalog.cpp12
-rw-r--r--src/mongo/db/views/view_catalog.cpp18
10 files changed, 268 insertions, 114 deletions
diff --git a/src/mongo/db/catalog/create_collection.cpp b/src/mongo/db/catalog/create_collection.cpp
index 44605b2bea7..b2b7c8781db 100644
--- a/src/mongo/db/catalog/create_collection.cpp
+++ b/src/mongo/db/catalog/create_collection.cpp
@@ -51,6 +51,78 @@
namespace mongo {
namespace {
+Status _createView(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CollectionOptions& collectionOptions,
+ const BSONObj& idIndex) {
+ return writeConflictRetry(opCtx, "create", nss.ns(), [&] {
+ AutoGetOrCreateDb autoDb(opCtx, nss.db(), MODE_IX);
+ Lock::CollectionLock systemViewsLock(
+ opCtx->lockState(),
+ NamespaceString(nss.db(), NamespaceString::kSystemDotViewsCollectionName).toString(),
+ MODE_X);
+ Lock::CollectionLock collLock(opCtx->lockState(), nss.ns(), MODE_IX);
+
+ Database* db = autoDb.getDb();
+
+ AutoStatsTracker statsTracker(opCtx,
+ nss,
+ Top::LockType::NotLocked,
+ AutoStatsTracker::LogMode::kUpdateTopAndCurop,
+ db->getProfilingLevel());
+
+ if (opCtx->writesAreReplicated() &&
+ !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, nss)) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while creating collection " << nss);
+ }
+
+ // Create 'system.views' in a separate WUOW if it does not exist.
+ WriteUnitOfWork wuow(opCtx);
+ db->getOrCreateCollection(opCtx, NamespaceString(db->getSystemViewsName()));
+ wuow.commit();
+
+ WriteUnitOfWork wunit(opCtx);
+ Status status = db->userCreateNS(opCtx, nss, collectionOptions, true, idIndex);
+ if (!status.isOK()) {
+ return status;
+ }
+ wunit.commit();
+
+ return Status::OK();
+ });
+}
+
+Status _createCollection(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CollectionOptions& collectionOptions,
+ const BSONObj& idIndex) {
+ return writeConflictRetry(opCtx, "create", nss.ns(), [&] {
+ AutoGetOrCreateDb autoDb(opCtx, nss.db(), MODE_X);
+
+ AutoStatsTracker statsTracker(opCtx,
+ nss,
+ Top::LockType::NotLocked,
+ AutoStatsTracker::LogMode::kUpdateTopAndCurop,
+ autoDb.getDb()->getProfilingLevel());
+
+ if (opCtx->writesAreReplicated() &&
+ !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, nss)) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while creating collection " << nss);
+ }
+
+ WriteUnitOfWork wunit(opCtx);
+ Status status = autoDb.getDb()->userCreateNS(opCtx, nss, collectionOptions, true, idIndex);
+ if (!status.isOK()) {
+ return status;
+ }
+ wunit.commit();
+
+ return Status::OK();
+ });
+}
+
/**
* Shared part of the implementation of the createCollection versions for replicated and regular
* collection creation.
@@ -97,41 +169,13 @@ Status createCollection(OperationContext* opCtx,
}
}
- return writeConflictRetry(opCtx, "create", nss.ns(), [&] {
- Lock::DBLock dbXLock(opCtx, nss.db(), MODE_X);
-
- const bool shardVersionCheck = true;
- OldClientContext ctx(opCtx, nss.ns(), shardVersionCheck);
-
- if (opCtx->writesAreReplicated() &&
- !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, nss)) {
- return Status(ErrorCodes::NotMaster,
- str::stream() << "Not primary while creating collection " << nss);
- }
-
- if (collectionOptions.isView()) {
- // If the `system.views` collection does not exist, create it in a separate
- // WriteUnitOfWork.
- WriteUnitOfWork wuow(opCtx);
- ctx.db()->getOrCreateCollection(opCtx, NamespaceString(ctx.db()->getSystemViewsName()));
- wuow.commit();
- }
-
- WriteUnitOfWork wunit(opCtx);
-
- // Create collection.
- const bool createDefaultIndexes = true;
- Status status =
- ctx.db()->userCreateNS(opCtx, nss, collectionOptions, createDefaultIndexes, idIndex);
- if (!status.isOK()) {
- return status;
- }
-
- wunit.commit();
-
- return Status::OK();
- });
+ if (collectionOptions.isView()) {
+ return _createView(opCtx, nss, collectionOptions, idIndex);
+ } else {
+ return _createCollection(opCtx, nss, collectionOptions, idIndex);
+ }
}
+
} // namespace
Status createCollection(OperationContext* opCtx,
diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h
index a9c9c026714..69b9975bb67 100644
--- a/src/mongo/db/catalog/database.h
+++ b/src/mongo/db/catalog/database.h
@@ -139,7 +139,7 @@ public:
const NamespaceString& fullns,
repl::OpTime dropOpTime = {}) = 0;
- virtual Status dropView(OperationContext* const opCtx, const StringData fullns) = 0;
+ virtual Status dropView(OperationContext* const opCtx, const NamespaceString& viewName) = 0;
virtual Collection* createCollection(OperationContext* const opCtx,
StringData ns,
@@ -148,7 +148,7 @@ public:
const BSONObj& idIndex = BSONObj()) = 0;
virtual Status createView(OperationContext* const opCtx,
- const StringData viewName,
+ const NamespaceString& viewName,
const CollectionOptions& options) = 0;
/**
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 2a393d92f99..b15efab21aa 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -350,10 +350,14 @@ void DatabaseImpl::getStats(OperationContext* opCtx, BSONObjBuilder* output, dou
}
}
-Status DatabaseImpl::dropView(OperationContext* opCtx, StringData fullns) {
+Status DatabaseImpl::dropView(OperationContext* opCtx, const NamespaceString& viewName) {
+ dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(NamespaceString(_viewsName), MODE_X));
+
auto views = ViewCatalog::get(this);
- Status status = views->dropView(opCtx, NamespaceString(fullns));
- Top::get(opCtx->getServiceContext()).collectionDropped(fullns);
+ Status status = views->dropView(opCtx, viewName);
+ Top::get(opCtx->getServiceContext()).collectionDropped(viewName.toString());
return status;
}
@@ -639,22 +643,24 @@ void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx,
}
Status DatabaseImpl::createView(OperationContext* opCtx,
- StringData ns,
+ const NamespaceString& viewName,
const CollectionOptions& options) {
- invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(NamespaceString(_viewsName), MODE_X));
+
invariant(options.isView());
- NamespaceString nss(ns);
- NamespaceString viewOnNss(nss.db(), options.viewOn);
- _checkCanCreateCollection(opCtx, nss, options);
- audit::logCreateCollection(&cc(), ns);
+ NamespaceString viewOnNss(viewName.db(), options.viewOn);
+ _checkCanCreateCollection(opCtx, viewName, options);
+ audit::logCreateCollection(&cc(), viewName.toString());
- if (nss.isOplog())
+ if (viewName.isOplog())
return Status(ErrorCodes::InvalidNamespace,
- str::stream() << "invalid namespace name for a view: " + nss.toString());
+ str::stream() << "invalid namespace name for a view: " + viewName.toString());
- auto views = ViewCatalog::get(this);
- return views->createView(opCtx, nss, viewOnNss, BSONArray(options.pipeline), options.collation);
+ return ViewCatalog::get(this)->createView(
+ opCtx, viewName, viewOnNss, BSONArray(options.pipeline), options.collation);
}
Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
@@ -662,10 +668,17 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
const CollectionOptions& options,
bool createIdIndex,
const BSONObj& idIndex) {
- invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
invariant(!options.isView());
NamespaceString nss(ns);
+ // TODO(SERVER-39520): Once createCollection does not need database IX lock, 'system.views' will
+ // be no longer a special case.
+ if (nss.coll().startsWith("system.views")) {
+ invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX));
+ } else {
+ invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ }
+
uassert(CannotImplicitlyCreateCollectionInfo(nss),
"request doesn't allow collection to be created implicitly",
OperationShardingState::get(opCtx).allowImplicitCollectionCreation());
@@ -959,7 +972,7 @@ Status DatabaseImpl::userCreateNS(OperationContext* opCtx,
}
if (collectionOptions.isView()) {
- uassertStatusOK(createView(opCtx, fullns.ns(), collectionOptions));
+ uassertStatusOK(createView(opCtx, fullns, collectionOptions));
} else {
invariant(
createCollection(opCtx, fullns.ns(), collectionOptions, createDefaultIndexes, idIndex),
diff --git a/src/mongo/db/catalog/database_impl.h b/src/mongo/db/catalog/database_impl.h
index d2b5d228708..dfd66ebbb1c 100644
--- a/src/mongo/db/catalog/database_impl.h
+++ b/src/mongo/db/catalog/database_impl.h
@@ -91,7 +91,7 @@ public:
const NamespaceString& fullns,
repl::OpTime dropOpTime) final;
- Status dropView(OperationContext* opCtx, StringData fullns) final;
+ Status dropView(OperationContext* opCtx, const NamespaceString& viewName) final;
Status userCreateNS(OperationContext* opCtx,
const NamespaceString& fullns,
@@ -106,7 +106,7 @@ public:
const BSONObj& idIndex = BSONObj()) final;
Status createView(OperationContext* opCtx,
- StringData viewName,
+ const NamespaceString& viewName,
const CollectionOptions& options) final;
/**
diff --git a/src/mongo/db/catalog/drop_collection.cpp b/src/mongo/db/catalog/drop_collection.cpp
index 110016b1474..2bd54a0acd4 100644
--- a/src/mongo/db/catalog/drop_collection.cpp
+++ b/src/mongo/db/catalog/drop_collection.cpp
@@ -51,6 +51,99 @@ namespace mongo {
MONGO_FAIL_POINT_DEFINE(hangDuringDropCollection);
+Status _dropView(OperationContext* opCtx,
+ std::unique_ptr<AutoGetDb>& autoDb,
+ const NamespaceString& collectionName,
+ BSONObjBuilder& result) {
+ // TODO(SERVER-39520): No need to relock once createCollection doesn't need X lock.
+ autoDb.reset();
+ autoDb = std::make_unique<AutoGetDb>(opCtx, collectionName.db(), MODE_IX);
+ Database* db = autoDb->getDb();
+ if (!db) {
+ return Status(ErrorCodes::NamespaceNotFound, "ns not found");
+ }
+ auto view = ViewCatalog::get(db)->lookup(opCtx, collectionName.ns());
+ if (!view) {
+ return Status(ErrorCodes::NamespaceNotFound, "ns not found");
+ }
+ Lock::CollectionLock systemViewsLock(opCtx->lockState(), db->getSystemViewsName(), MODE_X);
+ Lock::CollectionLock collLock(opCtx->lockState(), collectionName.ns(), MODE_IX);
+
+ if (MONGO_FAIL_POINT(hangDuringDropCollection)) {
+ log() << "hangDuringDropCollection fail point enabled. Blocking until fail point is "
+ "disabled.";
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET(hangDuringDropCollection);
+ }
+
+ AutoStatsTracker statsTracker(opCtx,
+ collectionName,
+ Top::LockType::NotLocked,
+ AutoStatsTracker::LogMode::kUpdateTopAndCurop,
+ autoDb->getDb()->getProfilingLevel());
+
+ if (opCtx->writesAreReplicated() &&
+ !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, collectionName)) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while dropping collection " << collectionName);
+ }
+
+ WriteUnitOfWork wunit(opCtx);
+ Status status = db->dropView(opCtx, collectionName);
+ if (!status.isOK()) {
+ return status;
+ }
+ wunit.commit();
+
+ result.append("ns", collectionName.ns());
+ return Status::OK();
+}
+
+Status _dropCollection(OperationContext* opCtx,
+ Database* db,
+ Collection* coll,
+ const NamespaceString& collectionName,
+ const repl::OpTime& dropOpTime,
+ DropCollectionSystemCollectionMode systemCollectionMode,
+ BSONObjBuilder& result) {
+ if (MONGO_FAIL_POINT(hangDuringDropCollection)) {
+ log() << "hangDuringDropCollection fail point enabled. Blocking until fail point is "
+ "disabled.";
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET(hangDuringDropCollection);
+ }
+
+ AutoStatsTracker statsTracker(opCtx,
+ collectionName,
+ Top::LockType::NotLocked,
+ AutoStatsTracker::LogMode::kUpdateTopAndCurop,
+ db->getProfilingLevel());
+
+ if (opCtx->writesAreReplicated() &&
+ !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, collectionName)) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while dropping collection " << collectionName);
+ }
+
+ WriteUnitOfWork wunit(opCtx);
+
+ int numIndexes = coll->getIndexCatalog()->numIndexesTotal(opCtx);
+ BackgroundOperation::assertNoBgOpInProgForNs(collectionName.ns());
+ IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection(coll->uuid().get());
+ Status status =
+ systemCollectionMode == DropCollectionSystemCollectionMode::kDisallowSystemCollectionDrops
+ ? db->dropCollection(opCtx, collectionName.ns(), dropOpTime)
+ : db->dropCollectionEvenIfSystem(opCtx, collectionName, dropOpTime);
+
+ if (!status.isOK()) {
+ return status;
+ }
+ wunit.commit();
+
+ result.append("nIndexesWas", numIndexes);
+ result.append("ns", collectionName.ns());
+
+ return Status::OK();
+}
+
Status dropCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
BSONObjBuilder& result,
@@ -61,67 +154,21 @@ Status dropCollection(OperationContext* opCtx,
}
return writeConflictRetry(opCtx, "drop", collectionName.ns(), [&] {
- AutoGetDb autoDb(opCtx, collectionName.db(), MODE_X);
- Database* const db = autoDb.getDb();
- Collection* coll = db ? db->getCollection(opCtx, collectionName) : nullptr;
- auto view =
- db && !coll ? ViewCatalog::get(db)->lookup(opCtx, collectionName.ns()) : nullptr;
-
- if (MONGO_FAIL_POINT(hangDuringDropCollection)) {
- log() << "hangDuringDropCollection fail point enabled. Blocking until fail point is "
- "disabled.";
- MONGO_FAIL_POINT_PAUSE_WHILE_SET(hangDuringDropCollection);
- }
+ // TODO(SERVER-39520): Get rid of database MODE_X lock.
+ auto autoDb = std::make_unique<AutoGetDb>(opCtx, collectionName.db(), MODE_X);
- if (!db || (!coll && !view)) {
+ Database* db = autoDb->getDb();
+ if (!db) {
return Status(ErrorCodes::NamespaceNotFound, "ns not found");
}
- const bool shardVersionCheck = true;
- OldClientContext context(opCtx, collectionName.ns(), shardVersionCheck);
-
- bool userInitiatedWritesAndNotPrimary = opCtx->writesAreReplicated() &&
- !repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, collectionName);
-
- if (userInitiatedWritesAndNotPrimary) {
- return Status(ErrorCodes::NotMaster,
- str::stream() << "Not primary while dropping collection "
- << collectionName);
- }
-
- WriteUnitOfWork wunit(opCtx);
- if (!result.hasField("ns")) {
- result.append("ns", collectionName.ns());
- }
-
- if (coll) {
- invariant(!view);
- int numIndexes = coll->getIndexCatalog()->numIndexesTotal(opCtx);
-
- BackgroundOperation::assertNoBgOpInProgForNs(collectionName.ns());
- IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection(
- coll->uuid().get());
-
- Status s = systemCollectionMode ==
- DropCollectionSystemCollectionMode::kDisallowSystemCollectionDrops
- ? db->dropCollection(opCtx, collectionName.ns(), dropOpTime)
- : db->dropCollectionEvenIfSystem(opCtx, collectionName, dropOpTime);
-
- if (!s.isOK()) {
- return s;
- }
-
- result.append("nIndexesWas", numIndexes);
+ Collection* coll = db->getCollection(opCtx, collectionName);
+ if (!coll) {
+ return _dropView(opCtx, autoDb, collectionName, result);
} else {
- invariant(view);
- Status status = db->dropView(opCtx, collectionName.ns());
- if (!status.isOK()) {
- return status;
- }
+ return _dropCollection(
+ opCtx, db, coll, collectionName, dropOpTime, systemCollectionMode, result);
}
- wunit.commit();
-
- return Status::OK();
});
}
diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp
index 1715fbf1c50..af1bd77af68 100644
--- a/src/mongo/db/catalog/index_build_block.cpp
+++ b/src/mongo/db/catalog/index_build_block.cpp
@@ -138,7 +138,13 @@ void IndexCatalogImpl::IndexBuildBlock::fail(OperationContext* opCtx,
fassert(17204, collection->ok()); // defensive
NamespaceString ns(_indexNamespace);
- invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_X));
+ // TODO(SERVER-39520): Once createCollection does not need database IX lock, 'system.views' will
+ // be no longer a special case.
+ if (ns.coll().startsWith(NamespaceString::kSystemDotViewsCollectionName)) {
+ invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_IX));
+ } else {
+ invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_X));
+ }
if (_entry) {
invariant(_catalog->_dropIndex(opCtx, _entry).isOK());
@@ -156,7 +162,13 @@ void IndexCatalogImpl::IndexBuildBlock::success(OperationContext* opCtx, Collect
fassert(17207, collection->ok());
NamespaceString ns(_indexNamespace);
- invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_X));
+ // TODO(SERVER-39520): Once createCollection does not need database IX lock, 'system.views' will
+ // be no longer a special case.
+ if (ns.coll().startsWith(NamespaceString::kSystemDotViewsCollectionName)) {
+ invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_IX));
+ } else {
+ invariant(opCtx->lockState()->isDbLockedForMode(ns.db(), MODE_X));
+ }
if (_indexBuildInterceptor) {
// An index build should never be completed with writes remaining in the interceptor.
diff --git a/src/mongo/db/storage/kv/kv_catalog.cpp b/src/mongo/db/storage/kv/kv_catalog.cpp
index 8df05d06f0f..ced31ab93ac 100644
--- a/src/mongo/db/storage/kv/kv_catalog.cpp
+++ b/src/mongo/db/storage/kv/kv_catalog.cpp
@@ -410,7 +410,13 @@ Status KVCatalog::newCollection(OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options,
KVPrefix prefix) {
- invariant(opCtx->lockState()->isDbLockedForMode(nss.db(), MODE_X));
+ // TODO(SERVER-39520): Once createCollection does not need database IX lock, 'system.views' will
+ // be no longer a special case.
+ if (nss.coll().startsWith("system.views")) {
+ invariant(opCtx->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
+ } else {
+ invariant(opCtx->lockState()->isDbLockedForMode(nss.db(), MODE_X));
+ }
const string ident = _newUniqueIdent(nss.ns(), "collection");
diff --git a/src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp b/src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp
index aa3671c04e6..f01a25a73b0 100644
--- a/src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp
+++ b/src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp
@@ -128,7 +128,13 @@ Status KVDatabaseCatalogEntryBase::createCollection(OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options,
bool allocateDefaultSpace) {
- invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ // TODO(SERVER-39520): Once createCollection does not need database IX lock, 'system.views' will
+ // be no longer a special case.
+ if (nss.coll().startsWith("system.views")) {
+ dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX));
+ } else {
+ dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ }
invariant(nss.coll().size() > 0);
diff --git a/src/mongo/db/views/durable_view_catalog.cpp b/src/mongo/db/views/durable_view_catalog.cpp
index 24a23b928e9..f32283bad27 100644
--- a/src/mongo/db/views/durable_view_catalog.cpp
+++ b/src/mongo/db/views/durable_view_catalog.cpp
@@ -138,8 +138,12 @@ Status DurableViewCatalogImpl::iterate(OperationContext* opCtx, Callback callbac
void DurableViewCatalogImpl::upsert(OperationContext* opCtx,
const NamespaceString& name,
const BSONObj& view) {
- dassert(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_X));
+ dassert(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(name, MODE_IX));
+
NamespaceString systemViewsNs(_db->getSystemViewsName());
+ dassert(opCtx->lockState()->isCollectionLockedForMode(systemViewsNs, MODE_X));
+
Collection* systemViews = _db->getCollection(opCtx, systemViewsNs);
invariant(systemViews);
@@ -164,8 +168,12 @@ void DurableViewCatalogImpl::upsert(OperationContext* opCtx,
}
void DurableViewCatalogImpl::remove(OperationContext* opCtx, const NamespaceString& name) {
- dassert(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_X));
+ dassert(opCtx->lockState()->isDbLockedForMode(_db->name(), MODE_IX));
+ dassert(opCtx->lockState()->isCollectionLockedForMode(name, MODE_IX));
+
Collection* systemViews = _db->getCollection(opCtx, _db->getSystemViewsName());
+ dassert(opCtx->lockState()->isCollectionLockedForMode(systemViews->ns(), MODE_X));
+
if (!systemViews)
return;
const bool requireIndex = false;
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index 08dba9ada81..c932c365983 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -146,6 +146,11 @@ Status ViewCatalog::_createOrUpdateView(WithLock lk,
const NamespaceString& viewOn,
const BSONArray& pipeline,
std::unique_ptr<CollatorInterface> collator) {
+ invariant(opCtx->lockState()->isDbLockedForMode(viewName.db(), MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(
+ NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X));
+
_requireValidCatalog(lk, opCtx);
// Build the BSON definition for this view to be saved in the durable view catalog. If the
@@ -329,6 +334,12 @@ Status ViewCatalog::createView(OperationContext* opCtx,
const NamespaceString& viewOn,
const BSONArray& pipeline,
const BSONObj& collation) {
+
+ invariant(opCtx->lockState()->isDbLockedForMode(viewName.db(), MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(
+ NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X));
+
stdx::lock_guard<stdx::mutex> lk(_mutex);
if (viewName.db() != viewOn.db())
@@ -359,6 +370,8 @@ Status ViewCatalog::modifyView(OperationContext* opCtx,
const NamespaceString& viewName,
const NamespaceString& viewOn,
const BSONArray& pipeline) {
+ invariant(opCtx->lockState()->isDbLockedForMode(viewName.db(), MODE_X));
+
stdx::lock_guard<stdx::mutex> lk(_mutex);
if (viewName.db() != viewOn.db())
@@ -388,6 +401,11 @@ Status ViewCatalog::modifyView(OperationContext* opCtx,
}
Status ViewCatalog::dropView(OperationContext* opCtx, const NamespaceString& viewName) {
+ invariant(opCtx->lockState()->isDbLockedForMode(viewName.db(), MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(
+ NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X));
+
stdx::lock_guard<stdx::mutex> lk(_mutex);
_requireValidCatalog(lk, opCtx);