summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2020-05-05 13:42:17 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-05 21:22:38 +0000
commit1e525750c99b70e21af0b20d4c29159f8329c008 (patch)
tree782f9ab99642417f9e97f021eb76b48c4649e7ad /src
parent0684c1761e399146a3a1760162d017d747bc3d3e (diff)
downloadmongo-1e525750c99b70e21af0b20d4c29159f8329c008.tar.gz
SERVER-47319 dropIndexes should not invariant if a similar index was created while yielding locks to abort different indexes
(cherry picked from commit 60b2655e069a30dfa1656809b1ae25d77617292c)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/drop_indexes.cpp52
1 files changed, 35 insertions, 17 deletions
diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp
index b862c5549cd..3b947e81851 100644
--- a/src/mongo/db/catalog/drop_indexes.cpp
+++ b/src/mongo/db/catalog/drop_indexes.cpp
@@ -51,6 +51,8 @@
namespace mongo {
namespace {
+MONGO_FAIL_POINT_DEFINE(hangAfterAbortingIndexes);
+
// Field name in dropIndexes command for indexes to drop.
constexpr auto kIndexFieldName = "index"_sd;
@@ -345,6 +347,11 @@ Status dropIndexes(OperationContext* opCtx,
abortedIndexBuilders.insert(
abortedIndexBuilders.end(), justAborted.begin(), justAborted.end());
+ if (MONGO_unlikely(hangAfterAbortingIndexes.shouldFail())) {
+ LOGV2(4731900, "Hanging on hangAfterAbortingIndexes fail point");
+ hangAfterAbortingIndexes.pauseWhileSet();
+ }
+
// Take an exclusive lock on the collection now to be able to perform index catalog writes
// when removing ready indexes from disk.
autoColl.emplace(opCtx, dbAndUUID, MODE_X);
@@ -379,25 +386,36 @@ Status dropIndexes(OperationContext* opCtx,
}
}
- // If the "*" wildcard was not specified, verify that all the index names belonging to the
- // index builder were aborted.
+ // Drop any ready indexes that were created while we yielded our locks while aborting using
+ // similar index specs.
if (!isWildcard && !abortedIndexBuilders.empty()) {
- // This is necessary to check shard version.
- OldClientContext ctx(opCtx, collection->ns().ns());
-
- // Iterate through all aborted indexes and verify none of them are ready. This would
- // indicate a flaw with the abort logic that allows indexes to complete despite the
- // dropIndexes command reporting they were aborted.
- auto indexCatalog = collection->getIndexCatalog();
- const bool includeUnfinished = false;
- const bool noneReady = std::none_of(indexNames.begin(), indexNames.end(), [&](auto name) {
- return indexCatalog->findIndexByName(opCtx, name, includeUnfinished);
- });
+ return writeConflictRetry(opCtx, "dropIndexes", dbAndUUID.toString(), [&] {
+ WriteUnitOfWork wuow(opCtx);
- invariant(noneReady,
- str::stream() << "Found completed indexes despite aborting index build: "
- << abortedIndexBuilders.front());
- return Status::OK();
+ // This is necessary to check shard version.
+ OldClientContext ctx(opCtx, collection->ns().ns());
+
+ // Iterate through all the aborted indexes and drop any indexes that are ready in the
+ // index catalog. This would indicate that while we yielded our locks during the abort
+ // phase, a new identical index was created.
+ auto indexCatalog = collection->getIndexCatalog();
+ const bool includeUnfinished = false;
+ for (const auto& indexName : indexNames) {
+ auto desc = indexCatalog->findIndexByName(opCtx, indexName, includeUnfinished);
+ if (!desc) {
+ // A similar index wasn't created while we yielded the locks during abort.
+ continue;
+ }
+
+ Status status = dropIndexByDescriptor(opCtx, collection, indexCatalog, desc);
+ if (!status.isOK()) {
+ return status;
+ }
+ }
+
+ wuow.commit();
+ return Status::OK();
+ });
}
if (!abortedIndexBuilders.empty()) {