summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@10gen.com>2019-01-22 11:47:50 -0500
committerDianna Hohensee <dianna.hohensee@10gen.com>2019-03-11 17:38:03 -0400
commitd02edd5290131978f901ffc657bee3470d03f8fd (patch)
tree3e53beb391466f36d073d0ce710dee3f88d90273 /src/mongo/db/catalog
parentb69c97b4da596f1da8dea2b40cf32a7c5c657870 (diff)
downloadmongo-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')
-rw-r--r--src/mongo/db/catalog/SConscript3
-rw-r--r--src/mongo/db/catalog/capped_utils.cpp4
-rw-r--r--src/mongo/db/catalog/catalog_control.cpp5
-rw-r--r--src/mongo/db/catalog/catalog_control_test.cpp5
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp5
-rw-r--r--src/mongo/db/catalog/collection.h6
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp2
-rw-r--r--src/mongo/db/catalog/collection_impl.h6
-rw-r--r--src/mongo/db/catalog/database.h3
-rw-r--r--src/mongo/db/catalog/database_holder.h5
-rw-r--r--src/mongo/db/catalog/database_holder_impl.cpp15
-rw-r--r--src/mongo/db/catalog/database_impl.cpp20
-rw-r--r--src/mongo/db/catalog/database_impl.h6
-rw-r--r--src/mongo/db/catalog/database_test.cpp4
-rw-r--r--src/mongo/db/catalog/drop_collection.cpp3
-rw-r--r--src/mongo/db/catalog/drop_database.cpp9
-rw-r--r--src/mongo/db/catalog/drop_indexes.cpp6
-rw-r--r--src/mongo/db/catalog/index_catalog.h11
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp13
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.h10
-rw-r--r--src/mongo/db/catalog/index_catalog_noop.h4
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp7
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;