diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-03-22 17:17:21 -0400 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-03-28 14:15:11 -0400 |
commit | b5f78884606ba87e5a1742e8dd19bbe2e03f709d (patch) | |
tree | 2678ce8730ccefb31ff756065bf79ade9cb6ecf7 /src/mongo | |
parent | 00afe420f0eccb4204c5a235049385a1189e9c78 (diff) | |
download | mongo-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.cpp | 112 | ||||
-rw-r--r-- | src/mongo/db/catalog/database.h | 4 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.cpp | 43 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.h | 4 | ||||
-rw-r--r-- | src/mongo/db/catalog/drop_collection.cpp | 157 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_build_block.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_catalog.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_database_catalog_entry_base.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/views/durable_view_catalog.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog.cpp | 18 |
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); |