diff options
author | Dianna Hohensee <dianna.hohensee@10gen.com> | 2019-01-22 11:47:50 -0500 |
---|---|---|
committer | Dianna Hohensee <dianna.hohensee@10gen.com> | 2019-03-11 17:38:03 -0400 |
commit | d02edd5290131978f901ffc657bee3470d03f8fd (patch) | |
tree | 3e53beb391466f36d073d0ce710dee3f88d90273 /src/mongo/db/catalog | |
parent | b69c97b4da596f1da8dea2b40cf32a7c5c657870 (diff) | |
download | mongo-d02edd5290131978f901ffc657bee3470d03f8fd.tar.gz |
SERVER-39079 Move BackgroundOperation checks out of the catalog layer; add parallel IndexBuildsCoordinator checks for all BackgroundOperation checks
Diffstat (limited to 'src/mongo/db/catalog')
22 files changed, 136 insertions, 16 deletions
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript index efc323713ce..e8bc9168d3c 100644 --- a/src/mongo/db/catalog/SConscript +++ b/src/mongo/db/catalog/SConscript @@ -355,6 +355,7 @@ env.Library( LIBDEPS_PRIVATE=[ 'collection', 'uuid_catalog', + '$BUILD_DIR/mongo/db/index_builds_coordinator_interface', '$BUILD_DIR/mongo/db/repair_database', '$BUILD_DIR/mongo/db/service_context', ], @@ -368,6 +369,7 @@ env.CppUnitTest( LIBDEPS=[ 'catalog_control', 'database_holder', + '$BUILD_DIR/mongo/db/index_builds_coordinator_mongod', '$BUILD_DIR/mongo/db/service_context', ], ) @@ -436,6 +438,7 @@ env.Library( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/background', '$BUILD_DIR/mongo/db/db_raii', + '$BUILD_DIR/mongo/db/index_builds_coordinator_interface', '$BUILD_DIR/mongo/db/query_exec', '$BUILD_DIR/mongo/db/server_options_core', '$BUILD_DIR/mongo/db/views/views', diff --git a/src/mongo/db/catalog/capped_utils.cpp b/src/mongo/db/catalog/capped_utils.cpp index 2ddae23aa80..0f9562d653c 100644 --- a/src/mongo/db/catalog/capped_utils.cpp +++ b/src/mongo/db/catalog/capped_utils.cpp @@ -45,6 +45,7 @@ #include "mongo/db/client.h" #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/op_observer.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/query/plan_yield_policy.h" @@ -95,6 +96,8 @@ Status emptyCapped(OperationContext* opCtx, const NamespaceString& collectionNam } BackgroundOperation::assertNoBgOpInProgForNs(collectionName.ns()); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + collection->uuid().get()); WriteUnitOfWork wuow(opCtx); @@ -258,6 +261,7 @@ void convertToCapped(OperationContext* opCtx, ErrorCodes::NamespaceNotFound, str::stream() << "database " << dbname << " not found", db); BackgroundOperation::assertNoBgOpInProgForDb(dbname); + IndexBuildsCoordinator::get(opCtx)->assertNoBgOpInProgForDb(dbname); // Generate a temporary collection name that will not collide with any existing collections. auto tmpNameResult = diff --git a/src/mongo/db/catalog/catalog_control.cpp b/src/mongo/db/catalog/catalog_control.cpp index e9199519632..f3e93ba6814 100644 --- a/src/mongo/db/catalog/catalog_control.cpp +++ b/src/mongo/db/catalog/catalog_control.cpp @@ -32,12 +32,14 @@ #include "mongo/db/catalog/catalog_control.h" +#include "mongo/db/background.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database.h" #include "mongo/db/catalog/database_catalog_entry.h" #include "mongo/db/catalog/database_holder.h" #include "mongo/db/catalog/uuid_catalog.h" #include "mongo/db/ftdc/ftdc_mongod.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/namespace_string.h" #include "mongo/db/repair_database.h" #include "mongo/util/log.h" @@ -47,6 +49,9 @@ namespace catalog { MinVisibleTimestampMap closeCatalog(OperationContext* opCtx) { invariant(opCtx->lockState()->isW()); + BackgroundOperation::assertNoBgOpInProg(); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgress(); + MinVisibleTimestampMap minVisibleTimestampMap; std::vector<std::string> allDbs; opCtx->getServiceContext()->getStorageEngine()->listDatabases(&allDbs); diff --git a/src/mongo/db/catalog/catalog_control_test.cpp b/src/mongo/db/catalog/catalog_control_test.cpp index b887b9ef5d7..39b4d74153b 100644 --- a/src/mongo/db/catalog/catalog_control_test.cpp +++ b/src/mongo/db/catalog/catalog_control_test.cpp @@ -31,6 +31,7 @@ #include "mongo/db/catalog/database_holder_mock.h" #include "mongo/db/client.h" +#include "mongo/db/index_builds_coordinator_mongod.h" #include "mongo/db/operation_context_noop.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/storage_engine.h" @@ -112,6 +113,10 @@ void CatalogControlTest::setUp() { auto storageEngine = std::make_unique<MockStorageEngine>(); serviceContext->setStorageEngine(std::move(storageEngine)); DatabaseHolder::set(serviceContext.get(), std::make_unique<DatabaseHolderMock>()); + // Only need the IndexBuildsCoordinator to call into and check whether there are any index + // builds in progress. + IndexBuildsCoordinator::set(serviceContext.get(), + std::make_unique<IndexBuildsCoordinatorMongod>()); setGlobalServiceContext(std::move(serviceContext)); } diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp index b28a7bbccdb..6e2ac01fb74 100644 --- a/src/mongo/db/catalog/coll_mod.cpp +++ b/src/mongo/db/catalog/coll_mod.cpp @@ -45,6 +45,7 @@ #include "mongo/db/command_generic_argument.h" #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/op_observer.h" #include "mongo/db/repl/repl_client_info.h" #include "mongo/db/repl/replication_coordinator.h" @@ -319,6 +320,10 @@ Status _collModInternal(OperationContext* opCtx, // This can kill all cursors so don't allow running it while a background operation is in // progress. BackgroundOperation::assertNoBgOpInProgForNs(nss); + if (coll) { + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + coll->uuid().get()); + } // If db/collection/view does not exist, short circuit and return. if (!db || (!coll && !view)) { diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index b32c0e449b8..85598d29f51 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -315,6 +315,9 @@ public: * removes all documents as fast as possible * indexes before and after will be the same * as will other characteristics. + * + * The caller should hold a collection X lock and ensure there are no index builds in progress + * on the collection. */ virtual Status truncate(OperationContext* const opCtx) = 0; @@ -343,6 +346,9 @@ public: * collection. The collection cannot be completely emptied using this * function. An assertion will be thrown if that is attempted. * @param inclusive - Truncate 'end' as well iff true + * + * The caller should hold a collection X lock and ensure there are no index builds in progress + * on the collection. */ virtual void cappedTruncateAfter(OperationContext* const opCtx, RecordId end, diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index a11d2461ba1..1d53ce43989 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -780,7 +780,6 @@ uint64_t CollectionImpl::getIndexSize(OperationContext* opCtx, BSONObjBuilder* d */ Status CollectionImpl::truncate(OperationContext* opCtx) { dassert(opCtx->lockState()->isCollectionLockedForMode(ns(), MODE_X)); - BackgroundOperation::assertNoBgOpInProgForNs(ns()); invariant(_indexCatalog->numIndexesInProgress(opCtx) == 0); // 1) store index specs @@ -815,7 +814,6 @@ Status CollectionImpl::truncate(OperationContext* opCtx) { void CollectionImpl::cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive) { dassert(opCtx->lockState()->isCollectionLockedForMode(ns(), MODE_X)); invariant(isCapped()); - BackgroundOperation::assertNoBgOpInProgForNs(ns()); invariant(_indexCatalog->numIndexesInProgress(opCtx) == 0); _recordStore->cappedTruncateAfter(opCtx, end, inclusive); diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h index 1260150ca49..73861c965de 100644 --- a/src/mongo/db/catalog/collection_impl.h +++ b/src/mongo/db/catalog/collection_impl.h @@ -224,6 +224,9 @@ public: * removes all documents as fast as possible * indexes before and after will be the same * as will other characteristics + * + * The caller should hold a collection X lock and ensure there are no index builds in progress + * on the collection. */ Status truncate(OperationContext* opCtx) final; @@ -252,6 +255,9 @@ public: * collection. The collection cannot be completely emptied using this * function. An assertion will be thrown if that is attempted. * @param inclusive - Truncate 'end' as well iff true + * + * The caller should hold a collection X lock and ensure there are no index builds in progress + * on the collection. */ void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive) final; diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h index 30648c41bd9..4e4245f4625 100644 --- a/src/mongo/db/catalog/database.h +++ b/src/mongo/db/catalog/database.h @@ -176,6 +176,9 @@ public: * * If we are applying a 'drop' oplog entry on a secondary, 'dropOpTime' will contain the optime * of the oplog entry. + * + * The caller should hold a DB X lock and ensure there are no index builds in progress on the + * collection. */ virtual Status dropCollection(OperationContext* const opCtx, const StringData fullns, diff --git a/src/mongo/db/catalog/database_holder.h b/src/mongo/db/catalog/database_holder.h index 0ddefd433f5..fdadd00bd0f 100644 --- a/src/mongo/db/catalog/database_holder.h +++ b/src/mongo/db/catalog/database_holder.h @@ -81,7 +81,8 @@ public: * doesn't notify the replication subsystem or do any other consistency checks, so it should * not be used directly from user commands. * - * Must be called with the specified database locked in X mode. + * Must be called with the specified database locked in X mode. The caller must ensure no index + * builds are in progress on the database. */ virtual void dropDb(OperationContext* opCtx, Database* db) = 0; @@ -94,6 +95,8 @@ public: /** * Closes all opened databases. Must be called with the global lock acquired in X-mode. * Will uassert if any background jobs are running when this function is called. + * + * The caller must hold the global X lock and ensure there are no index builds in progress. */ virtual void closeAll(OperationContext* opCtx) = 0; diff --git a/src/mongo/db/catalog/database_holder_impl.cpp b/src/mongo/db/catalog/database_holder_impl.cpp index f518c6c0f13..d333d8bfe0f 100644 --- a/src/mongo/db/catalog/database_holder_impl.cpp +++ b/src/mongo/db/catalog/database_holder_impl.cpp @@ -170,7 +170,12 @@ void DatabaseHolderImpl::dropDb(OperationContext* opCtx, Database* db) { invariant(opCtx->lockState()->isDbLockedForMode(name, MODE_X)); - BackgroundOperation::assertNoBgOpInProgForDb(name); + for (auto&& coll : *db) { + // It is the caller's responsibility to ensure that no index builds are active in the + // database. + invariant(!coll->getIndexCatalog()->haveAnyIndexesInProgress(), + str::stream() << "An index is building on collection '" << coll->ns() << "'."); + } audit::logDropDatabase(opCtx->getClient(), name); @@ -232,7 +237,13 @@ void DatabaseHolderImpl::closeAll(OperationContext* opCtx) { std::set<std::string> dbs; for (DBs::const_iterator i = _dbs.begin(); i != _dbs.end(); ++i) { - BackgroundOperation::assertNoBgOpInProgForDb(i->first); + for (auto&& coll : *(i->second)) { + // It is the caller's responsibility to ensure that no index builds are active in the + // database. + invariant(!coll->getIndexCatalog()->haveAnyIndexesInProgress(), + str::stream() << "An index is building on collection '" << coll->ns() + << "'."); + } dbs.insert(i->first); } diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index e8db845ce50..8833c4fea54 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -515,12 +515,10 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx, uassertNamespaceNotIndex(fullns.toString(), "dropCollection"); - BackgroundOperation::assertNoBgOpInProgForNs(fullns); - // Make sure no indexes builds are in progress. // Use massert() to be consistent with IndexCatalog::dropAllIndexes(). auto numIndexesInProgress = collection->getIndexCatalog()->numIndexesInProgress(opCtx); - massert(40461, + massert(ErrorCodes::BackgroundOperationInProgressForNamespace, str::stream() << "cannot drop collection " << fullns << " (" << uuidString << ") when " << numIndexesInProgress << " index builds in progress.", @@ -695,8 +693,6 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx, bool stayTemp) { audit::logRenameCollection(&cc(), fromNS, toNS); invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); - BackgroundOperation::assertNoBgOpInProgForNs(fromNS); - BackgroundOperation::assertNoBgOpInProgForNs(toNS); const NamespaceString fromNSS(fromNS); const NamespaceString toNSS(toNS); @@ -713,6 +709,20 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx, if (!collToRename) { return Status(ErrorCodes::NamespaceNotFound, "collection not found to rename"); } + invariant(!collToRename->getIndexCatalog()->haveAnyIndexesInProgress(), + mongoutils::str::stream() + << "cannot perform operation: an index build is currently running for " + "collection " + << fromNSS); + + Collection* toColl = getCollection(opCtx, toNSS); + if (toColl) { + invariant(!toColl->getIndexCatalog()->haveAnyIndexesInProgress(), + mongoutils::str::stream() + << "cannot perform operation: an index build is currently running for " + "collection " + << toNSS); + } log() << "renameCollection: renaming collection " << collToRename->uuid()->toString() << " from " << fromNS << " to " << toNS; diff --git a/src/mongo/db/catalog/database_impl.h b/src/mongo/db/catalog/database_impl.h index 31e04fb8476..09b5441c0bf 100644 --- a/src/mongo/db/catalog/database_impl.h +++ b/src/mongo/db/catalog/database_impl.h @@ -83,6 +83,9 @@ public: * * If we are applying a 'drop' oplog entry on a secondary, 'dropOpTime' will contain the optime * of the oplog entry. + * + * The caller should hold a DB X lock and ensure there are no index builds in progress on the + * collection. */ Status dropCollection(OperationContext* opCtx, StringData fullns, @@ -122,6 +125,9 @@ public: * Renames the fully qualified namespace 'fromNS' to the fully qualified namespace 'toNS'. * Illegal to call unless both 'fromNS' and 'toNS' are within this database. Returns an error if * 'toNS' already exists or 'fromNS' does not exist. + * + * The caller should hold a DB X lock and ensure there are no index builds in progress on either + * the 'fromNS' or the 'toNS'. */ Status renameCollection(OperationContext* opCtx, StringData fromNS, diff --git a/src/mongo/db/catalog/database_test.cpp b/src/mongo/db/catalog/database_test.cpp index e1743a76488..70af753caa0 100644 --- a/src/mongo/db/catalog/database_test.cpp +++ b/src/mongo/db/catalog/database_test.cpp @@ -324,7 +324,9 @@ void _testDropCollectionThrowsExceptionIfThereAreIndexesInProgress(OperationCont ASSERT_GREATER_THAN(indexCatalog->numIndexesInProgress(opCtx), 0); WriteUnitOfWork wuow(opCtx); - ASSERT_THROWS_CODE(db->dropCollection(opCtx, nss.ns()), AssertionException, 40461); + ASSERT_THROWS_CODE(db->dropCollection(opCtx, nss.ns()), + AssertionException, + ErrorCodes::BackgroundOperationInProgressForNamespace); }); } diff --git a/src/mongo/db/catalog/drop_collection.cpp b/src/mongo/db/catalog/drop_collection.cpp index 93b281930a1..110016b1474 100644 --- a/src/mongo/db/catalog/drop_collection.cpp +++ b/src/mongo/db/catalog/drop_collection.cpp @@ -39,6 +39,7 @@ #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context.h" @@ -98,6 +99,8 @@ Status dropCollection(OperationContext* opCtx, int numIndexes = coll->getIndexCatalog()->numIndexesTotal(opCtx); BackgroundOperation::assertNoBgOpInProgForNs(collectionName.ns()); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + coll->uuid().get()); Status s = systemCollectionMode == DropCollectionSystemCollectionMode::kDisallowSystemCollectionDrops diff --git a/src/mongo/db/catalog/drop_database.cpp b/src/mongo/db/catalog/drop_database.cpp index 13b8193f36c..2f2b9f79d29 100644 --- a/src/mongo/db/catalog/drop_database.cpp +++ b/src/mongo/db/catalog/drop_database.cpp @@ -41,6 +41,7 @@ #include "mongo/db/client.h" #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/op_observer.h" #include "mongo/db/repl/repl_client_info.h" #include "mongo/db/repl/replication_coordinator.h" @@ -65,6 +66,10 @@ Status _finishDropDatabase(OperationContext* opCtx, const std::string& dbName, Database* db, std::size_t numCollections) { + invariant(opCtx->lockState()->isDbLockedForMode(dbName, MODE_X)); + BackgroundOperation::assertNoBgOpInProgForDb(dbName); + IndexBuildsCoordinator::get(opCtx)->assertNoBgOpInProgForDb(dbName); + // If DatabaseHolder::dropDb() fails, we should reset the drop-pending state on Database. auto dropPendingGuard = makeGuard([db, opCtx] { db->setDropPending(opCtx, false); }); @@ -175,6 +180,10 @@ Status dropDatabase(OperationContext* opCtx, const std::string& dbName) { invariant(!nss.isReplicated() || nss.coll().startsWith("tmp.mr")); } + BackgroundOperation::assertNoBgOpInProgForNs(nss.ns()); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + db->getCollection(opCtx, nss)->uuid().get()); + WriteUnitOfWork wunit(opCtx); // A primary processing this will assign a timestamp when the operation is written to // the oplog. As stated above, a secondary processing must only observe non-replicated diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp index eb8049c3090..56143447308 100644 --- a/src/mongo/db/catalog/drop_indexes.cpp +++ b/src/mongo/db/catalog/drop_indexes.cpp @@ -40,6 +40,7 @@ #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/op_observer.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/service_context.h" @@ -225,9 +226,12 @@ Status dropIndexes(OperationContext* opCtx, return Status(ErrorCodes::NamespaceNotFound, "ns not found"); } + BackgroundOperation::assertNoBgOpInProgForNs(nss); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + collection->uuid().get()); + WriteUnitOfWork wunit(opCtx); OldClientContext ctx(opCtx, nss.ns()); - BackgroundOperation::assertNoBgOpInProgForNs(nss); Status status = wrappedRun(opCtx, collection, cmdObj, result); if (!status.isOK()) { diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h index 5ee4aed313c..5ba372df577 100644 --- a/src/mongo/db/catalog/index_catalog.h +++ b/src/mongo/db/catalog/index_catalog.h @@ -218,6 +218,8 @@ public: virtual bool haveAnyIndexes() const = 0; + virtual bool haveAnyIndexesInProgress() const = 0; + virtual int numIndexesTotal(OperationContext* const opCtx) const = 0; virtual int numIndexesReady(OperationContext* const opCtx) const = 0; @@ -301,6 +303,9 @@ public: * Use this method to notify the IndexCatalog that the spec for this index has changed. * * It is invalid to dereference 'oldDesc' after calling this method. + * + * The caller must hold the collection X lock and ensure no index builds are in progress + * on the collection. */ virtual const IndexDescriptor* refreshEntry(OperationContext* const opCtx, const IndexDescriptor* const oldDesc) = 0; @@ -372,6 +377,12 @@ public: stdx::function<void(const IndexDescriptor*)> onDropFn) = 0; virtual void dropAllIndexes(OperationContext* opCtx, bool includingIdIndex) = 0; + /** + * Drops the index. + * + * The caller must hold the collection X lock and ensure no index builds are in progress on the + * collection. + */ virtual Status dropIndex(OperationContext* const opCtx, const IndexDescriptor* const desc) = 0; /** diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index 7f7d98b17c5..902daebfa3c 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -740,7 +740,10 @@ void IndexCatalogImpl::dropAllIndexes(OperationContext* opCtx, stdx::function<void(const IndexDescriptor*)> onDropFn) { invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); - BackgroundOperation::assertNoBgOpInProgForNs(_collection->ns().ns()); + uassert(ErrorCodes::BackgroundOperationInProgressForNamespace, + mongoutils::str::stream() + << "cannot perform operation: an index build is currently running", + !haveAnyIndexesInProgress()); // make sure nothing in progress massert(17348, @@ -813,8 +816,7 @@ void IndexCatalogImpl::dropAllIndexes(OperationContext* opCtx, bool includingIdI Status IndexCatalogImpl::dropIndex(OperationContext* opCtx, const IndexDescriptor* desc) { invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); - BackgroundOperation::assertNoBgOpInProgForNs(_collection->ns().ns()); - invariant(_buildingIndexes.size() == 0); + invariant(!haveAnyIndexesInProgress()); IndexCatalogEntry* entry = _readyIndexes.find(desc); @@ -960,6 +962,10 @@ bool IndexCatalogImpl::haveAnyIndexes() const { return _readyIndexes.size() > 0 || _buildingIndexes.size() > 0; } +bool IndexCatalogImpl::haveAnyIndexesInProgress() const { + return _buildingIndexes.size() > 0; +} + int IndexCatalogImpl::numIndexesTotal(OperationContext* opCtx) const { int count = _readyIndexes.size() + _buildingIndexes.size() + _unfinishedIndexes.size(); dassert(_collection->getCatalogEntry()->getTotalIndexCount(opCtx) == count); @@ -1124,7 +1130,6 @@ std::vector<std::shared_ptr<const IndexCatalogEntry>> IndexCatalogImpl::getAllRe const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx, const IndexDescriptor* oldDesc) { invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); - invariant(!BackgroundOperation::inProgForNs(_collection->ns())); invariant(_buildingIndexes.size() == 0); const std::string indexName = oldDesc->indexName(); diff --git a/src/mongo/db/catalog/index_catalog_impl.h b/src/mongo/db/catalog/index_catalog_impl.h index 933bab58b62..d95f557102f 100644 --- a/src/mongo/db/catalog/index_catalog_impl.h +++ b/src/mongo/db/catalog/index_catalog_impl.h @@ -67,6 +67,7 @@ public: // ---- accessors ----- bool haveAnyIndexes() const override; + bool haveAnyIndexesInProgress() const override; int numIndexesTotal(OperationContext* opCtx) const override; int numIndexesReady(OperationContext* opCtx) const override; int numIndexesInProgress(OperationContext* opCtx) const { @@ -154,6 +155,9 @@ public: * Use this method to notify the IndexCatalog that the spec for this index has changed. * * It is invalid to dereference 'oldDesc' after calling this method. + * + * The caller must hold the collection X lock and ensure no index builds are in progress + * on the collection. */ const IndexDescriptor* refreshEntry(OperationContext* opCtx, const IndexDescriptor* oldDesc) override; @@ -201,6 +205,12 @@ public: stdx::function<void(const IndexDescriptor*)> onDropFn) override; void dropAllIndexes(OperationContext* opCtx, bool includingIdIndex) override; + /** + * Drops the index. + * + * The caller must hold the collection X lock and ensure no index builds are in progress on the + * collection. + */ Status dropIndex(OperationContext* opCtx, const IndexDescriptor* desc) override; /** diff --git a/src/mongo/db/catalog/index_catalog_noop.h b/src/mongo/db/catalog/index_catalog_noop.h index b1730c1fd05..445b26f384c 100644 --- a/src/mongo/db/catalog/index_catalog_noop.h +++ b/src/mongo/db/catalog/index_catalog_noop.h @@ -51,6 +51,10 @@ public: return false; } + bool haveAnyIndexesInProgress() const override { + return false; + } + int numIndexesTotal(OperationContext* const opCtx) const override { return 0; } diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp index fcf5d8065ce..89e99ac6cd4 100644 --- a/src/mongo/db/catalog/rename_collection.cpp +++ b/src/mongo/db/catalog/rename_collection.cpp @@ -45,6 +45,7 @@ #include "mongo/db/curop.h" #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/ops/insert.h" @@ -202,6 +203,8 @@ Status renameCollectionCommon(OperationContext* opCtx, } BackgroundOperation::assertNoBgOpInProgForNs(source.ns()); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + sourceColl->uuid().get()); auto targetDB = databaseHolder->openDb(opCtx, target.db()); @@ -353,6 +356,10 @@ Status renameCollectionCommon(OperationContext* opCtx, // No logOp necessary because the entire renameCollection command is one logOp. repl::UnreplicatedWritesBlock uwb(opCtx); + BackgroundOperation::assertNoBgOpInProgForNs(targetColl->ns().ns()); + IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection( + targetColl->uuid().get()); + status = targetDB->dropCollection(opCtx, targetColl->ns().ns(), renameOpTime); if (!status.isOK()) { return status; |