summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2022-05-20 11:47:42 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-31 14:41:36 +0000
commit0b5f72d6e251cb402aa3d8bb102cbba6b5734e8d (patch)
tree5045f9e06cd407506ecf4c8502583ad25168a4df
parente456ccda58bfc7cdae7803786d5527bcd2fb7187 (diff)
downloadmongo-0b5f72d6e251cb402aa3d8bb102cbba6b5734e8d.tar.gz
SERVER-63865 Handle missing index idents during standalone startup recovery
-rw-r--r--jstests/noPassthrough/libs/missing_index_ident.js93
-rw-r--r--jstests/noPassthrough/missing_index_ident_standalone_drop.js32
-rw-r--r--jstests/noPassthrough/restart_and_unclean_shutdown_recovery_before_index_build_commit_timestamp.js82
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp3
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp10
-rw-r--r--src/mongo/db/catalog/collection_validation.cpp8
-rw-r--r--src/mongo/db/catalog/drop_indexes.cpp23
-rw-r--r--src/mongo/db/catalog/index_build_block.cpp12
-rw-r--r--src/mongo/db/catalog/index_catalog.h40
-rw-r--r--src/mongo/db/catalog/index_catalog_entry.h4
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp5
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.h4
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp153
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.h18
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp5
-rw-r--r--src/mongo/db/catalog/validate_state.cpp3
-rw-r--r--src/mongo/db/commands/cqf/cqf_aggregate.cpp3
-rw-r--r--src/mongo/db/commands/validate_db_metadata_cmd.cpp6
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp2
-rw-r--r--src/mongo/db/index_builds_coordinator.cpp19
-rw-r--r--src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp6
-rw-r--r--src/mongo/db/query/collection_query_info.cpp18
-rw-r--r--src/mongo/db/query/get_executor.cpp7
-rw-r--r--src/mongo/db/query/plan_cache_key_factory.cpp4
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp7
-rw-r--r--src/mongo/db/repl/storage_interface_impl.cpp9
-rw-r--r--src/mongo/db/repl/storage_timestamp_test.cpp6
-rw-r--r--src/mongo/db/s/shard_key_index_util.cpp3
-rw-r--r--src/mongo/db/stats/storage_stats.cpp4
-rw-r--r--src/mongo/db/storage/storage_engine_impl.cpp38
-rw-r--r--src/mongo/db/storage/storage_engine_test_fixture.h5
-rw-r--r--src/mongo/db/system_index.cpp9
-rw-r--r--src/mongo/dbtests/indexcatalogtests.cpp4
-rw-r--r--src/mongo/dbtests/indexupdatetests.cpp6
-rw-r--r--src/mongo/dbtests/multikey_paths_test.cpp3
-rw-r--r--src/mongo/dbtests/query_plan_executor.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_and.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_count.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_count_scan.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_distinct.cpp8
-rw-r--r--src/mongo/dbtests/query_stage_ixscan.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp3
-rw-r--r--src/mongo/dbtests/rollbacktests.cpp11
-rw-r--r--src/mongo/dbtests/storage_debug_util.cpp2
46 files changed, 440 insertions, 261 deletions
diff --git a/jstests/noPassthrough/libs/missing_index_ident.js b/jstests/noPassthrough/libs/missing_index_ident.js
new file mode 100644
index 00000000000..1c7e7dc2782
--- /dev/null
+++ b/jstests/noPassthrough/libs/missing_index_ident.js
@@ -0,0 +1,93 @@
+load('jstests/libs/fail_point_util.js');
+load('jstests/noPassthrough/libs/index_build.js');
+
+const MissingIndexIdent = class {
+ /**
+ * Starts a one-node replica set and gets it into a state where the catalog entry for index
+ * 'a_1' references an ident which is missing. Returns with the node stopped.
+ */
+ static run() {
+ const replTest = new ReplSetTest({nodes: 1});
+ replTest.startSet();
+ replTest.initiate();
+
+ const primary = function() {
+ return replTest.getPrimary();
+ };
+ const testDB = function() {
+ return primary().getDB('test');
+ };
+ const coll = function() {
+ return testDB()[jsTestName()];
+ };
+
+ assert.commandWorked(coll().insert({a: 0}));
+
+ const fp = configureFailPoint(primary(), 'hangIndexBuildBeforeCommit');
+ const awaitCreateIndex =
+ IndexBuildTest.startIndexBuild(primary(), coll().getFullName(), {a: 1});
+ fp.wait();
+
+ // Get a timestamp before the commit timestamp of the index build.
+ const ts =
+ assert
+ .commandWorked(testDB().runCommand({insert: coll().getName(), documents: [{a: 1}]}))
+ .operationTime;
+
+ configureFailPoint(primary(), 'holdStableTimestampAtSpecificTimestamp', {timestamp: ts});
+ fp.off();
+ awaitCreateIndex();
+
+ const ident = assert.commandWorked(testDB().runCommand({collStats: coll().getName()}))
+ .indexDetails.a_1.uri.substring('statistics:table:'.length);
+
+ replTest.restart(primary(), {
+ setParameter: {
+ // Set minSnapshotHistoryWindowInSeconds to 0 so that the the oldest timestamp can
+ // move forward, despite the stable timestamp being held steady.
+ minSnapshotHistoryWindowInSeconds: 0,
+ 'failpoint.holdStableTimestampAtSpecificTimestamp':
+ tojson({mode: 'alwaysOn', data: {timestamp: ts}})
+ }
+ });
+
+ MissingIndexIdent.checkRecoveryLogs(primary(), coll(), ts, ident);
+
+ const dbpath = primary().dbpath;
+
+ // Shut down uncleanly so that a checkpoint is not taken. This will cause the index catalog
+ // entry referencing the now-dropped ident to still be present.
+ replTest.stop(0, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}, {forRestart: true});
+
+ return {replTest, dbpath, ts, ident};
+ }
+
+ /**
+ * Checks that the index was recovered.
+ */
+ static checkRecoveryLogs(conn, coll, ts, ident) {
+ // On startup, the node will recover from before the index commit timestamp.
+ checkLog.containsJson(conn, 23987, {
+ recoveryTimestamp: (recoveryTs) => {
+ return timestampCmp(
+ Timestamp(recoveryTs['$timestamp']['t'], recoveryTs['$timestamp']['i']),
+ ts) <= 0;
+ }
+ });
+
+ // Since the index build was not yet completed at the recovery timestamp, its ident will
+ // be dropped.
+ checkLog.containsJson(conn, 22206, {
+ index: 'a_1',
+ namespace: coll.getFullName(),
+ ident: ident,
+ commitTimestamp: {$timestamp: {t: 0, i: 0}},
+ });
+
+ // The oldest timestamp moving forward will cause the ident reaper to drop the ident.
+ checkLog.containsJson(conn, 22237, {
+ ident: ident,
+ dropTimestamp: {$timestamp: {t: 0, i: 0}},
+ });
+ }
+};
diff --git a/jstests/noPassthrough/missing_index_ident_standalone_drop.js b/jstests/noPassthrough/missing_index_ident_standalone_drop.js
new file mode 100644
index 00000000000..abb59d5bf64
--- /dev/null
+++ b/jstests/noPassthrough/missing_index_ident_standalone_drop.js
@@ -0,0 +1,32 @@
+/**
+ * Tests that if a node is in a state where the catalog entry for an index references a missing
+ * ident, the node can be started as a standalone and the index can be dropped.
+ *
+ * @tags: [
+ * requires_persistence,
+ * requires_replication,
+ * ]
+ */
+(function() {
+'use strict';
+
+load('jstests/noPassthrough/libs/missing_index_ident.js');
+
+const {replTest, dbpath} = MissingIndexIdent.run();
+
+const standalone = MongoRunner.runMongod({
+ dbpath: dbpath,
+ noCleanData: true,
+});
+const coll = standalone.getDB('test')[jsTestName()];
+
+IndexBuildTest.assertIndexes(coll, 2, ['_id_', 'a_1']);
+assert.commandWorked(standalone.getDB('test')[jsTestName()].dropIndex('a_1'));
+IndexBuildTest.assertIndexes(coll, 1, ['_id_']);
+
+MongoRunner.stopMongod(standalone);
+replTest.start(0, undefined, true /* restart */);
+IndexBuildTest.assertIndexes(replTest.getPrimary().getDB('test')[jsTestName()], 1, ['_id_']);
+
+replTest.stopSet();
+})();
diff --git a/jstests/noPassthrough/restart_and_unclean_shutdown_recovery_before_index_build_commit_timestamp.js b/jstests/noPassthrough/restart_and_unclean_shutdown_recovery_before_index_build_commit_timestamp.js
index d810f1cba84..cb3a5fae7f8 100644
--- a/jstests/noPassthrough/restart_and_unclean_shutdown_recovery_before_index_build_commit_timestamp.js
+++ b/jstests/noPassthrough/restart_and_unclean_shutdown_recovery_before_index_build_commit_timestamp.js
@@ -10,87 +10,15 @@
(function() {
'use strict';
-load('jstests/libs/fail_point_util.js');
-load('jstests/noPassthrough/libs/index_build.js');
+load('jstests/noPassthrough/libs/missing_index_ident.js');
-const replTest = new ReplSetTest({nodes: 1});
-replTest.startSet();
-replTest.initiate();
+const {replTest, ts, ident} = MissingIndexIdent.run();
-const primary = function() {
- return replTest.getPrimary();
-};
-const testDB = function() {
- return primary().getDB('test');
-};
-const coll = function() {
- return testDB()[jsTestName()];
-};
-
-assert.commandWorked(coll().insert({a: 0}));
-
-const fp = configureFailPoint(primary(), 'hangIndexBuildBeforeCommit');
-const awaitCreateIndex = IndexBuildTest.startIndexBuild(primary(), coll().getFullName(), {a: 1});
-fp.wait();
-
-// Get a timestamp before the commit timestamp of the index build.
-const ts =
- assert.commandWorked(testDB().runCommand({insert: coll().getName(), documents: [{a: 1}]}))
- .operationTime;
-
-configureFailPoint(primary(), 'holdStableTimestampAtSpecificTimestamp', {timestamp: ts});
-fp.off();
-awaitCreateIndex();
-
-const ident = assert.commandWorked(testDB().runCommand({collStats: coll().getName()}))
- .indexDetails.a_1.uri.substring('statistics:table:'.length);
-
-replTest.restart(primary(), {
- setParameter: {
- // Set minSnapshotHistoryWindowInSeconds to 0 so that the the oldest timestamp can move
- // forward, despite the stable timestamp being held steady.
- minSnapshotHistoryWindowInSeconds: 0,
- 'failpoint.holdStableTimestampAtSpecificTimestamp':
- tojson({mode: 'alwaysOn', data: {timestamp: ts}})
- }
-});
-
-const checkLogs = function() {
- // On startup, the node will recover from before the index commit timestamp.
- checkLog.containsJson(primary(), 23987, {
- recoveryTimestamp: (recoveryTs) => {
- return timestampCmp(
- Timestamp(recoveryTs['$timestamp']['t'], recoveryTs['$timestamp']['i']),
- ts) <= 0;
- }
- });
-
- // Since the index build was not yet completed at the recovery timestamp, its ident will be
- // dropped.
- checkLog.containsJson(primary(), 22206, {
- index: 'a_1',
- namespace: coll().getFullName(),
- ident: ident,
- commitTimestamp: {$timestamp: {t: 0, i: 0}},
- });
-
- // The oldest timestamp moving forward will cause the ident reaper to drop the ident.
- checkLog.containsJson(primary(), 22237, {
- ident: ident,
- dropTimestamp: {$timestamp: {t: 0, i: 0}},
- });
-};
-
-checkLogs();
-
-// Shut down uncleanly so that a checkpoint is not taken. This will cause the index catalog entry
-// referencing the now-dropped ident to still be present.
-replTest.stop(0, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}, {forRestart: true});
replTest.start(0, undefined, true /* restart */);
+const coll = replTest.getPrimary().getDB('test')[jsTestName()];
-checkLogs();
-
-IndexBuildTest.assertIndexes(coll(), 2, ['_id_', 'a_1']);
+MissingIndexIdent.checkRecoveryLogs(replTest.getPrimary(), coll, ts, ident);
+IndexBuildTest.assertIndexes(coll, 2, ['_id_', 'a_1']);
replTest.stopSet();
})();
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 0f88e0fc07a..0072c7a9f15 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -288,7 +288,8 @@ StatusWith<std::pair<ParsedCollModRequest, BSONObj>> parseCollModRequest(Operati
}
} else {
std::vector<const IndexDescriptor*> indexes;
- coll->getIndexCatalog()->findIndexesByKeyPattern(opCtx, keyPattern, false, &indexes);
+ coll->getIndexCatalog()->findIndexesByKeyPattern(
+ opCtx, keyPattern, IndexCatalog::InclusionPolicy::kReady, &indexes);
if (indexes.size() > 1) {
return {ErrorCodes::AmbiguousIndexKeyPattern,
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index ecb86d77238..e57cda3743a 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1726,7 +1726,8 @@ uint64_t CollectionImpl::getIndexSize(OperationContext* opCtx,
int scale) const {
const IndexCatalog* idxCatalog = getIndexCatalog();
- std::unique_ptr<IndexCatalog::IndexIterator> ii = idxCatalog->getIndexIterator(opCtx, true);
+ auto ii = idxCatalog->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
uint64_t totalSize = 0;
@@ -1748,8 +1749,8 @@ uint64_t CollectionImpl::getIndexSize(OperationContext* opCtx,
uint64_t CollectionImpl::getIndexFreeStorageBytes(OperationContext* const opCtx) const {
const auto idxCatalog = getIndexCatalog();
- const bool includeUnfinished = true;
- auto indexIt = idxCatalog->getIndexIterator(opCtx, includeUnfinished);
+ auto indexIt = idxCatalog->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
uint64_t totalSize = 0;
while (indexIt->more()) {
@@ -1773,8 +1774,7 @@ Status CollectionImpl::truncate(OperationContext* opCtx) {
// 1) store index specs
std::vector<BSONObj> indexSpecs;
{
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- _indexCatalog->getIndexIterator(opCtx, false);
+ auto ii = _indexCatalog->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (ii->more()) {
const IndexDescriptor* idx = ii->next()->descriptor();
indexSpecs.push_back(idx->infoObj().getOwned());
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp
index 610d7c39ca7..8fa78a9ba9f 100644
--- a/src/mongo/db/catalog/collection_validation.cpp
+++ b/src/mongo/db/catalog/collection_validation.cpp
@@ -80,8 +80,7 @@ void _validateIndexesInternalStructure(OperationContext* opCtx,
// Need to use the IndexCatalog here because the 'validateState->indexes' object hasn't been
// constructed yet. It must be initialized to ensure we're validating all indexes.
const IndexCatalog* indexCatalog = validateState->getCollection()->getIndexCatalog();
- const std::unique_ptr<IndexCatalog::IndexIterator> it =
- indexCatalog->getIndexIterator(opCtx, false);
+ const auto it = indexCatalog->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
// Validate Indexes Internal Structure, checking if index files have been compromised or
// corrupted.
@@ -412,7 +411,10 @@ void _validateCatalogEntry(OperationContext* opCtx,
}
const auto& indexCatalog = collection->getIndexCatalog();
- auto indexIt = indexCatalog->getIndexIterator(opCtx, /*includeUnfinishedIndexes=*/true);
+ auto indexIt = indexCatalog->getIndexIterator(opCtx,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
while (indexIt->more()) {
const IndexCatalogEntry* indexEntry = indexIt->next();
diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp
index e003e0e56ef..493c8326146 100644
--- a/src/mongo/db/catalog/drop_indexes.cpp
+++ b/src/mongo/db/catalog/drop_indexes.cpp
@@ -109,9 +109,13 @@ Status checkReplState(OperationContext* opCtx,
StatusWith<const IndexDescriptor*> getDescriptorByKeyPattern(OperationContext* opCtx,
const IndexCatalog* indexCatalog,
const BSONObj& keyPattern) {
- const bool includeUnfinished = true;
std::vector<const IndexDescriptor*> indexes;
- indexCatalog->findIndexesByKeyPattern(opCtx, keyPattern, includeUnfinished, &indexes);
+ indexCatalog->findIndexesByKeyPattern(opCtx,
+ keyPattern,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen,
+ &indexes);
if (indexes.empty()) {
return Status(ErrorCodes::IndexNotFound,
str::stream() << "can't find index with key: " << keyPattern);
@@ -340,7 +344,6 @@ void dropReadyIndexes(OperationContext* opCtx,
return;
}
- bool includeUnfinished = true;
for (const auto& indexName : indexNames) {
if (collDescription.isSharded()) {
uassert(
@@ -350,7 +353,11 @@ void dropReadyIndexes(OperationContext* opCtx,
opCtx, collection, indexCatalog, indexName, collDescription.getKeyPattern()));
}
- auto desc = indexCatalog->findIndexByName(opCtx, indexName, includeUnfinished);
+ auto desc = indexCatalog->findIndexByName(opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
if (!desc) {
uasserted(ErrorCodes::IndexNotFound,
str::stream() << "index not found with name [" << indexName << "]");
@@ -509,7 +516,6 @@ DropIndexesReply dropIndexes(OperationContext* opCtx,
// 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->getWritableCollection(opCtx)->getIndexCatalog();
- const bool includeUnfinished = false;
for (const auto& indexName : indexNames) {
auto collDescription =
CollectionShardingState::get(opCtx, nss)->getCollectionDescription(opCtx);
@@ -524,7 +530,12 @@ DropIndexesReply dropIndexes(OperationContext* opCtx,
collDescription.getKeyPattern()));
}
- auto desc = indexCatalog->findIndexByName(opCtx, indexName, includeUnfinished);
+ auto desc =
+ indexCatalog->findIndexByName(opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
if (!desc) {
// A similar index wasn't created while we yielded the locks during abort.
continue;
diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp
index fc5d39109d8..6c3c5df5ae3 100644
--- a/src/mongo/db/catalog/index_build_block.cpp
+++ b/src/mongo/db/catalog/index_build_block.cpp
@@ -94,7 +94,9 @@ Status IndexBuildBlock::initForResume(OperationContext* opCtx,
_indexName = _spec.getStringField("name").toString();
auto descriptor = collection->getIndexCatalog()->findIndexByName(
- opCtx, _indexName, true /* includeUnfinishedIndexes */);
+ opCtx,
+ _indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
auto indexCatalogEntry = descriptor->getEntry();
@@ -284,14 +286,18 @@ void IndexBuildBlock::success(OperationContext* opCtx, Collection* collection) {
const IndexCatalogEntry* IndexBuildBlock::getEntry(OperationContext* opCtx,
const CollectionPtr& collection) const {
auto descriptor = collection->getIndexCatalog()->findIndexByName(
- opCtx, _indexName, true /* includeUnfinishedIndexes */);
+ opCtx,
+ _indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
return descriptor->getEntry();
}
IndexCatalogEntry* IndexBuildBlock::getEntry(OperationContext* opCtx, Collection* collection) {
auto descriptor = collection->getIndexCatalog()->findIndexByName(
- opCtx, _indexName, true /* includeUnfinishedIndexes */);
+ opCtx,
+ _indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
return descriptor->getEntry();
}
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index 2754ac3e22f..58e48e08be5 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -197,6 +197,12 @@ public:
std::unique_ptr<std::vector<IndexCatalogEntry*>> _ownedContainer;
};
+ enum class InclusionPolicy {
+ kReady = 1 << 0,
+ kUnfinished = 1 << 1,
+ kFrozen = 1 << 2,
+ };
+
IndexCatalog() = default;
virtual ~IndexCatalog() = default;
@@ -237,9 +243,10 @@ public:
*
* @return null if cannot find
*/
- virtual const IndexDescriptor* findIndexByName(OperationContext* opCtx,
- StringData name,
- bool includeUnfinishedIndexes = false) const = 0;
+ virtual const IndexDescriptor* findIndexByName(
+ OperationContext* opCtx,
+ StringData name,
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const = 0;
/**
* Find index by matching key pattern and options. The key pattern, collation spec, and partial
@@ -251,7 +258,7 @@ public:
OperationContext* opCtx,
const BSONObj& key,
const BSONObj& indexSpec,
- bool includeUnfinishedIndexes = false) const = 0;
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const = 0;
/**
* Find indexes with a matching key pattern, putting them into the vector 'matches'. The key
@@ -261,12 +268,13 @@ public:
*/
virtual void findIndexesByKeyPattern(OperationContext* opCtx,
const BSONObj& key,
- bool includeUnfinishedIndexes,
+ InclusionPolicy inclusionPolicy,
std::vector<const IndexDescriptor*>* matches) const = 0;
- virtual void findIndexByType(OperationContext* opCtx,
- const std::string& type,
- std::vector<const IndexDescriptor*>& matches,
- bool includeUnfinishedIndexes = false) const = 0;
+ virtual void findIndexByType(
+ OperationContext* opCtx,
+ const std::string& type,
+ std::vector<const IndexDescriptor*>& matches,
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const = 0;
/**
* Reload the index definition for 'oldDesc' from the CollectionCatalogEntry. 'oldDesc'
@@ -308,7 +316,7 @@ public:
* Returns an iterator for the index descriptors in this IndexCatalog.
*/
virtual std::unique_ptr<IndexIterator> getIndexIterator(
- OperationContext* opCtx, bool includeUnfinishedIndexes) const = 0;
+ OperationContext* opCtx, InclusionPolicy inclusionPolicy) const = 0;
// ---- index set modifiers ------
@@ -521,4 +529,16 @@ public:
Collection* coll,
IndexCatalogEntry* index) = 0;
};
+
+inline IndexCatalog::InclusionPolicy operator|(IndexCatalog::InclusionPolicy lhs,
+ IndexCatalog::InclusionPolicy rhs) {
+ return static_cast<IndexCatalog::InclusionPolicy>(
+ static_cast<std::underlying_type_t<IndexCatalog::InclusionPolicy>>(lhs) |
+ static_cast<std::underlying_type_t<IndexCatalog::InclusionPolicy>>(rhs));
+}
+
+inline bool operator&(IndexCatalog::InclusionPolicy lhs, IndexCatalog::InclusionPolicy rhs) {
+ return static_cast<std::underlying_type_t<IndexCatalog::InclusionPolicy>>(lhs) &
+ static_cast<std::underlying_type_t<IndexCatalog::InclusionPolicy>>(rhs);
+}
} // namespace mongo
diff --git a/src/mongo/db/catalog/index_catalog_entry.h b/src/mongo/db/catalog/index_catalog_entry.h
index fa77370bb96..9761f590c9d 100644
--- a/src/mongo/db/catalog/index_catalog_entry.h
+++ b/src/mongo/db/catalog/index_catalog_entry.h
@@ -64,8 +64,6 @@ public:
inline IndexCatalogEntry(IndexCatalogEntry&&) = delete;
inline IndexCatalogEntry& operator=(IndexCatalogEntry&&) = delete;
- virtual void init(std::unique_ptr<IndexAccessMethod> accessMethod) = 0;
-
virtual const std::string& getIdent() const = 0;
virtual std::shared_ptr<Ident> getSharedIdent() const = 0;
@@ -75,6 +73,8 @@ public:
virtual IndexAccessMethod* accessMethod() const = 0;
+ virtual void setAccessMethod(std::unique_ptr<IndexAccessMethod> accessMethod) = 0;
+
virtual bool isHybridBuilding() const = 0;
virtual IndexBuildInterceptor* indexBuildInterceptor() const = 0;
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index b53aadbf696..cb47381ae39 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -124,7 +124,7 @@ IndexCatalogEntryImpl::IndexCatalogEntryImpl(OperationContext* const opCtx,
}
}
-void IndexCatalogEntryImpl::init(std::unique_ptr<IndexAccessMethod> accessMethod) {
+void IndexCatalogEntryImpl::setAccessMethod(std::unique_ptr<IndexAccessMethod> accessMethod) {
invariant(!_accessMethod);
_accessMethod = std::move(accessMethod);
}
@@ -372,7 +372,8 @@ Status IndexCatalogEntryImpl::_setMultikeyInMultiDocumentTransaction(
}
std::shared_ptr<Ident> IndexCatalogEntryImpl::getSharedIdent() const {
- return {shared_from_this(), _accessMethod->getIdentPtr()}; // aliasing constructor
+ return _accessMethod ? std::shared_ptr<Ident>{shared_from_this(), _accessMethod->getIdentPtr()}
+ : nullptr;
}
// ----
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.h b/src/mongo/db/catalog/index_catalog_entry_impl.h
index 821176164e1..30ef5a80921 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.h
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.h
@@ -61,8 +61,6 @@ public:
std::unique_ptr<IndexDescriptor> descriptor, // ownership passes to me
bool isFrozen);
- void init(std::unique_ptr<IndexAccessMethod> accessMethod) final;
-
const std::string& getIdent() const final {
return _ident;
}
@@ -80,6 +78,8 @@ public:
return _accessMethod.get();
}
+ void setAccessMethod(std::unique_ptr<IndexAccessMethod> accessMethod) final;
+
bool isHybridBuilding() const final {
return _indexBuildInterceptor != nullptr;
}
diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp
index 1c186a7e7ef..74049b34427 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -258,8 +258,8 @@ Status IndexCatalogImpl::init(OperationContext* opCtx, Collection* collection) {
}
std::unique_ptr<IndexCatalog::IndexIterator> IndexCatalogImpl::getIndexIterator(
- OperationContext* const opCtx, const bool includeUnfinishedIndexes) const {
- if (!includeUnfinishedIndexes) {
+ OperationContext* const opCtx, InclusionPolicy inclusionPolicy) const {
+ if (inclusionPolicy == InclusionPolicy::kReady) {
// If the caller only wants the ready indexes, we return an iterator over the catalog's
// ready indexes vector. When the user advances this iterator, it will filter out any
// indexes that were not ready at the OperationContext's read timestamp.
@@ -267,17 +267,28 @@ std::unique_ptr<IndexCatalog::IndexIterator> IndexCatalogImpl::getIndexIterator(
opCtx, _readyIndexes.begin(), _readyIndexes.end());
}
- // If the caller wants all indexes, for simplicity of implementation, we copy the pointers to
- // a new vector. The vector's ownership is passed to the iterator. The query code path from an
- // external client is not expected to hit this case so the cost isn't paid by the important
- // code path.
+ // If the caller doesn't only want the ready indexes, for simplicity of implementation, we copy
+ // the pointers to a new vector. The vector's ownership is passed to the iterator. The query
+ // code path from an external client is not expected to hit this case so the cost isn't paid by
+ // the important code path.
auto allIndexes = std::make_unique<std::vector<IndexCatalogEntry*>>();
- for (auto it = _readyIndexes.begin(); it != _readyIndexes.end(); ++it) {
- allIndexes->push_back(it->get());
+
+ if (inclusionPolicy & InclusionPolicy::kReady) {
+ for (auto it = _readyIndexes.begin(); it != _readyIndexes.end(); ++it) {
+ allIndexes->push_back(it->get());
+ }
+ }
+
+ if (inclusionPolicy & InclusionPolicy::kUnfinished) {
+ for (auto it = _buildingIndexes.begin(); it != _buildingIndexes.end(); ++it) {
+ allIndexes->push_back(it->get());
+ }
}
- for (auto it = _buildingIndexes.begin(); it != _buildingIndexes.end(); ++it) {
- allIndexes->push_back(it->get());
+ if (inclusionPolicy & InclusionPolicy::kFrozen) {
+ for (auto it = _frozenIndexes.begin(); it != _frozenIndexes.end(); ++it) {
+ allIndexes->push_back(it->get());
+ }
}
return std::make_unique<AllIndexesIterator>(opCtx, std::move(allIndexes));
@@ -351,6 +362,7 @@ void IndexCatalogImpl::_logInternalState(OperationContext* opCtx,
"numIndexesInCollectionCatalogEntry"_attr = numIndexesInCollectionCatalogEntry,
"numReadyIndexes"_attr = _readyIndexes.size(),
"numBuildingIndexes"_attr = _buildingIndexes.size(),
+ "numFrozenIndexes"_attr = _frozenIndexes.size(),
"indexNamesToDrop"_attr = indexNamesToDrop);
// Report the ready indexes.
@@ -426,7 +438,8 @@ StatusWith<BSONObj> IndexCatalogImpl::prepareSpecForCreate(
}
// First check against only the ready indexes for conflicts.
- status = _doesSpecConflictWithExisting(opCtx, collection, validatedSpec, false);
+ status =
+ _doesSpecConflictWithExisting(opCtx, collection, validatedSpec, InclusionPolicy::kReady);
if (!status.isOK()) {
return status;
}
@@ -442,7 +455,12 @@ StatusWith<BSONObj> IndexCatalogImpl::prepareSpecForCreate(
// The index catalog cannot currently iterate over only in-progress indexes. So by previously
// checking against only ready indexes without error, we know that any errors encountered
// checking against all indexes occurred due to an in-progress index.
- status = _doesSpecConflictWithExisting(opCtx, collection, validatedSpec, true);
+ status = _doesSpecConflictWithExisting(opCtx,
+ collection,
+ validatedSpec,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
if (!status.isOK()) {
if (ErrorCodes::IndexAlreadyExists == status.code()) {
// Callers need to be able to distinguish conflicts against ready indexes versus
@@ -471,8 +489,11 @@ std::vector<BSONObj> IndexCatalogImpl::removeExistingIndexesNoChecks(
// _doesSpecConflictWithExisting currently does more work than we require here: we are only
// interested in the index already exists error.
if (ErrorCodes::IndexAlreadyExists ==
- _doesSpecConflictWithExisting(
- opCtx, collection, spec, true /*includeUnfinishedIndexes*/)) {
+ _doesSpecConflictWithExisting(opCtx,
+ collection,
+ spec,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished)) {
continue;
}
@@ -535,14 +556,16 @@ IndexCatalogEntry* IndexCatalogImpl::createIndexEntry(OperationContext* opCtx,
engine->getEngine()->alterIdentMetadata(opCtx, ident, desc, isForceUpdateMetadata);
}
- std::unique_ptr<IndexAccessMethod> accessMethod = IndexAccessMethodFactory::get(opCtx)->make(
- opCtx, collection->ns(), collection->getCollectionOptions(), entry.get(), ident);
-
- entry->init(std::move(accessMethod));
+ if (!frozen) {
+ entry->setAccessMethod(IndexAccessMethodFactory::get(opCtx)->make(
+ opCtx, collection->ns(), collection->getCollectionOptions(), entry.get(), ident));
+ }
IndexCatalogEntry* save = entry.get();
if (isReadyIndex) {
_readyIndexes.add(std::move(entry));
+ } else if (frozen) {
+ _frozenIndexes.add(std::move(entry));
} else {
_buildingIndexes.add(std::move(entry));
}
@@ -1000,7 +1023,7 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx,
Status IndexCatalogImpl::_doesSpecConflictWithExisting(OperationContext* opCtx,
const CollectionPtr& collection,
const BSONObj& spec,
- const bool includeUnfinishedIndexes) const {
+ InclusionPolicy inclusionPolicy) const {
StringData name = spec.getStringField(IndexDescriptor::kIndexNameFieldName);
invariant(name[0]);
@@ -1014,7 +1037,7 @@ Status IndexCatalogImpl::_doesSpecConflictWithExisting(OperationContext* opCtx,
{
// Check whether an index with the specified candidate name already exists in the catalog.
- const IndexDescriptor* desc = findIndexByName(opCtx, name, includeUnfinishedIndexes);
+ const IndexDescriptor* desc = findIndexByName(opCtx, name, inclusionPolicy);
if (desc) {
// Index already exists with same name. Check whether the options are the same as well.
@@ -1067,7 +1090,7 @@ Status IndexCatalogImpl::_doesSpecConflictWithExisting(OperationContext* opCtx,
{
// No index with the candidate name exists. Check for an index with conflicting options.
const IndexDescriptor* desc =
- findIndexByKeyPatternAndOptions(opCtx, key, spec, includeUnfinishedIndexes);
+ findIndexByKeyPatternAndOptions(opCtx, key, spec, inclusionPolicy);
if (desc) {
LOGV2_DEBUG(20353,
@@ -1118,7 +1141,7 @@ Status IndexCatalogImpl::_doesSpecConflictWithExisting(OperationContext* opCtx,
string pluginName = IndexNames::findPluginName(key);
if (pluginName == IndexNames::TEXT) {
vector<const IndexDescriptor*> textIndexes;
- findIndexByType(opCtx, IndexNames::TEXT, textIndexes, includeUnfinishedIndexes);
+ findIndexByType(opCtx, IndexNames::TEXT, textIndexes, inclusionPolicy);
if (textIndexes.size() > 0) {
return Status(ErrorCodes::CannotCreateIndex,
str::stream() << "only one text index per collection allowed, "
@@ -1159,7 +1182,10 @@ void IndexCatalogImpl::dropIndexes(OperationContext* opCtx,
vector<string> indexNamesToDrop;
{
int seen = 0;
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, true);
+ auto ii = getIndexIterator(opCtx,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
while (ii->more()) {
seen++;
const IndexDescriptor* desc = ii->next()->descriptor();
@@ -1174,7 +1200,11 @@ void IndexCatalogImpl::dropIndexes(OperationContext* opCtx,
for (size_t i = 0; i < indexNamesToDrop.size(); i++) {
string indexName = indexNamesToDrop[i];
- const IndexDescriptor* desc = findIndexByName(opCtx, indexName, true);
+ const IndexDescriptor* desc = findIndexByName(
+ opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
invariant(desc);
LOGV2_DEBUG(20355, 1, "\t dropAllIndexes dropping: {desc}", "desc"_attr = *desc);
IndexCatalogEntry* entry = desc->getEntry();
@@ -1300,25 +1330,26 @@ Status IndexCatalogImpl::dropIndexEntry(OperationContext* opCtx,
audit::logDropIndex(opCtx->getClient(), indexName, collection->ns());
- auto released = _readyIndexes.release(entry->descriptor());
- if (released) {
- invariant(released.get() == entry);
- opCtx->recoveryUnit()->registerChange(
- std::make_unique<IndexRemoveChange>(opCtx,
- collection->ns(),
- collection->uuid(),
- std::move(released),
- collection->getSharedDecorations()));
- } else {
- released = _buildingIndexes.release(entry->descriptor());
- invariant(released.get() == entry);
- opCtx->recoveryUnit()->registerChange(
- std::make_unique<IndexRemoveChange>(opCtx,
- collection->ns(),
- collection->uuid(),
- std::move(released),
- collection->getSharedDecorations()));
- }
+ auto released = [&] {
+ if (auto released = _readyIndexes.release(entry->descriptor())) {
+ return released;
+ }
+ if (auto released = _buildingIndexes.release(entry->descriptor())) {
+ return released;
+ }
+ if (auto released = _frozenIndexes.release(entry->descriptor())) {
+ return released;
+ }
+ MONGO_UNREACHABLE;
+ }();
+
+ invariant(released.get() == entry);
+ opCtx->recoveryUnit()->registerChange(
+ std::make_unique<IndexRemoveChange>(opCtx,
+ collection->ns(),
+ collection->uuid(),
+ std::move(released),
+ collection->getSharedDecorations()));
CollectionQueryInfo::get(collection).rebuildIndexData(opCtx, collection);
CollectionIndexUsageTrackerDecoration::get(collection->getSharedDecorations())
@@ -1338,7 +1369,11 @@ void IndexCatalogImpl::_deleteIndexFromDisk(OperationContext* opCtx,
Collection* collection,
const string& indexName,
std::shared_ptr<Ident> ident) {
- invariant(!findIndexByName(opCtx, indexName, true /* includeUnfinishedIndexes*/));
+ invariant(!findIndexByName(opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen));
catalog::removeIndex(opCtx, indexName, collection, std::move(ident));
}
@@ -1368,7 +1403,7 @@ int IndexCatalogImpl::numIndexesTotal(OperationContext* opCtx) const {
int IndexCatalogImpl::numIndexesReady(OperationContext* opCtx) const {
std::vector<const IndexDescriptor*> itIndexes;
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, /*includeUnfinished*/ false);
+ auto ii = getIndexIterator(opCtx, InclusionPolicy::kReady);
while (ii->more()) {
itIndexes.push_back(ii->next()->descriptor());
}
@@ -1380,7 +1415,7 @@ bool IndexCatalogImpl::haveIdIndex(OperationContext* opCtx) const {
}
const IndexDescriptor* IndexCatalogImpl::findIdIndex(OperationContext* opCtx) const {
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, false);
+ auto ii = getIndexIterator(opCtx, InclusionPolicy::kReady);
while (ii->more()) {
const IndexDescriptor* desc = ii->next()->descriptor();
if (desc->isIdIndex())
@@ -1391,8 +1426,8 @@ const IndexDescriptor* IndexCatalogImpl::findIdIndex(OperationContext* opCtx) co
const IndexDescriptor* IndexCatalogImpl::findIndexByName(OperationContext* opCtx,
StringData name,
- bool includeUnfinishedIndexes) const {
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, includeUnfinishedIndexes);
+ InclusionPolicy inclusionPolicy) const {
+ auto ii = getIndexIterator(opCtx, inclusionPolicy);
while (ii->more()) {
const IndexDescriptor* desc = ii->next()->descriptor();
if (desc->indexName() == name)
@@ -1405,8 +1440,8 @@ const IndexDescriptor* IndexCatalogImpl::findIndexByKeyPatternAndOptions(
OperationContext* opCtx,
const BSONObj& key,
const BSONObj& indexSpec,
- bool includeUnfinishedIndexes) const {
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, includeUnfinishedIndexes);
+ InclusionPolicy inclusionPolicy) const {
+ auto ii = getIndexIterator(opCtx, inclusionPolicy);
IndexDescriptor needle(_getAccessMethodName(key), indexSpec);
while (ii->more()) {
const auto* entry = ii->next();
@@ -1420,10 +1455,10 @@ const IndexDescriptor* IndexCatalogImpl::findIndexByKeyPatternAndOptions(
void IndexCatalogImpl::findIndexesByKeyPattern(OperationContext* opCtx,
const BSONObj& key,
- bool includeUnfinishedIndexes,
+ InclusionPolicy inclusionPolicy,
std::vector<const IndexDescriptor*>* matches) const {
invariant(matches);
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, includeUnfinishedIndexes);
+ auto ii = getIndexIterator(opCtx, inclusionPolicy);
while (ii->more()) {
const IndexDescriptor* desc = ii->next()->descriptor();
if (SimpleBSONObjComparator::kInstance.evaluate(desc->keyPattern() == key)) {
@@ -1435,8 +1470,8 @@ void IndexCatalogImpl::findIndexesByKeyPattern(OperationContext* opCtx,
void IndexCatalogImpl::findIndexByType(OperationContext* opCtx,
const string& type,
vector<const IndexDescriptor*>& matches,
- bool includeUnfinishedIndexes) const {
- std::unique_ptr<IndexIterator> ii = getIndexIterator(opCtx, includeUnfinishedIndexes);
+ InclusionPolicy inclusionPolicy) const {
+ auto ii = getIndexIterator(opCtx, inclusionPolicy);
while (ii->more()) {
const IndexDescriptor* desc = ii->next()->descriptor();
if (IndexNames::findPluginName(desc->keyPattern()) == type) {
@@ -1677,7 +1712,10 @@ Status IndexCatalogImpl::indexRecords(OperationContext* opCtx,
for (const MultikeyPathInfo& newPath : newPaths) {
invariant(newPath.nss == coll->ns());
- auto idx = findIndexByName(opCtx, newPath.indexName, /*includeUnfinishedIndexes=*/true);
+ auto idx = findIndexByName(opCtx,
+ newPath.indexName,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished);
if (!idx) {
return Status(ErrorCodes::IndexNotFound,
str::stream()
@@ -1780,7 +1818,10 @@ Status IndexCatalogImpl::compactIndexes(OperationContext* opCtx) const {
}
std::string::size_type IndexCatalogImpl::getLongestIndexNameLength(OperationContext* opCtx) const {
- std::unique_ptr<IndexIterator> it = getIndexIterator(opCtx, true);
+ auto it = getIndexIterator(opCtx,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
std::string::size_type longestIndexNameLength = 0;
while (it->more()) {
auto thisLength = it->next()->descriptor()->indexName().length();
diff --git a/src/mongo/db/catalog/index_catalog_impl.h b/src/mongo/db/catalog/index_catalog_impl.h
index 259732da61c..f9baf272f11 100644
--- a/src/mongo/db/catalog/index_catalog_impl.h
+++ b/src/mongo/db/catalog/index_catalog_impl.h
@@ -96,9 +96,10 @@ public:
*
* @return null if cannot find
*/
- const IndexDescriptor* findIndexByName(OperationContext* opCtx,
- StringData name,
- bool includeUnfinishedIndexes = false) const override;
+ const IndexDescriptor* findIndexByName(
+ OperationContext* opCtx,
+ StringData name,
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const override;
/**
* Find index by matching key pattern and options. The key pattern, collation spec, and partial
@@ -110,7 +111,7 @@ public:
OperationContext* opCtx,
const BSONObj& key,
const BSONObj& indexSpec,
- bool includeUnfinishedIndexes = false) const override;
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const override;
/**
* Find indexes with a matching key pattern, putting them into the vector 'matches'. The key
@@ -120,12 +121,12 @@ public:
*/
void findIndexesByKeyPattern(OperationContext* opCtx,
const BSONObj& key,
- bool includeUnfinishedIndexes,
+ InclusionPolicy inclusionPolicy,
std::vector<const IndexDescriptor*>* matches) const override;
void findIndexByType(OperationContext* opCtx,
const std::string& type,
std::vector<const IndexDescriptor*>& matches,
- bool includeUnfinishedIndexes = false) const override;
+ InclusionPolicy inclusionPolicy = InclusionPolicy::kReady) const override;
/**
@@ -153,7 +154,7 @@ public:
using IndexIterator = IndexCatalog::IndexIterator;
std::unique_ptr<IndexIterator> getIndexIterator(OperationContext* opCtx,
- bool includeUnfinishedIndexes) const override;
+ InclusionPolicy inclusionPolicy) const override;
// ---- index set modifiers ------
@@ -377,7 +378,7 @@ private:
Status _doesSpecConflictWithExisting(OperationContext* opCtx,
const CollectionPtr& collection,
const BSONObj& spec,
- bool includeUnfinishedIndexes) const;
+ InclusionPolicy inclusionPolicy) const;
/**
* Returns true if the replica set member's config has {buildIndexes:false} set, which means
@@ -393,5 +394,6 @@ private:
IndexCatalogEntryContainer _readyIndexes;
IndexCatalogEntryContainer _buildingIndexes;
+ IndexCatalogEntryContainer _frozenIndexes;
};
} // namespace mongo
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp
index e3de3e5ddd5..1cc630d7458 100644
--- a/src/mongo/db/catalog/rename_collection.cpp
+++ b/src/mongo/db/catalog/rename_collection.cpp
@@ -617,7 +617,10 @@ Status renameBetweenDBs(OperationContext* opCtx,
// Copy the index descriptions from the source collection.
std::vector<BSONObj> indexesToCopy;
- for (auto sourceIndIt = sourceColl->getIndexCatalog()->getIndexIterator(opCtx, true);
+ for (auto sourceIndIt = sourceColl->getIndexCatalog()->getIndexIterator(
+ opCtx,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
sourceIndIt->more();) {
auto descriptor = sourceIndIt->next()->descriptor();
if (descriptor->isIdIndex()) {
diff --git a/src/mongo/db/catalog/validate_state.cpp b/src/mongo/db/catalog/validate_state.cpp
index 09b597752cf..09c8ec34ba3 100644
--- a/src/mongo/db/catalog/validate_state.cpp
+++ b/src/mongo/db/catalog/validate_state.cpp
@@ -242,8 +242,7 @@ void ValidateState::initializeCursors(OperationContext* opCtx) {
const IndexCatalog* indexCatalog = _collection->getIndexCatalog();
// The index iterator for ready indexes is timestamp-aware and will only return indexes that
// are visible at our read time.
- const std::unique_ptr<IndexCatalog::IndexIterator> it =
- indexCatalog->getIndexIterator(opCtx, /*includeUnfinished*/ false);
+ const auto it = indexCatalog->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (it->more()) {
const IndexCatalogEntry* entry = it->next();
const IndexDescriptor* desc = entry->descriptor();
diff --git a/src/mongo/db/commands/cqf/cqf_aggregate.cpp b/src/mongo/db/commands/cqf/cqf_aggregate.cpp
index 89d2045fec9..aabfc99c3a5 100644
--- a/src/mongo/db/commands/cqf/cqf_aggregate.cpp
+++ b/src/mongo/db/commands/cqf/cqf_aggregate.cpp
@@ -81,7 +81,8 @@ static opt::unordered_map<std::string, optimizer::IndexDefinition> buildIndexSpe
const IndexCatalog& indexCatalog = *collection->getIndexCatalog();
opt::unordered_map<std::string, IndexDefinition> result;
- auto indexIterator = indexCatalog.getIndexIterator(opCtx, false /*includeUnfinished*/);
+ auto indexIterator =
+ indexCatalog.getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (indexIterator->more()) {
const IndexCatalogEntry& catalogEntry = *indexIterator->next();
diff --git a/src/mongo/db/commands/validate_db_metadata_cmd.cpp b/src/mongo/db/commands/validate_db_metadata_cmd.cpp
index 0d057e498f5..6b0a494c3f6 100644
--- a/src/mongo/db/commands/validate_db_metadata_cmd.cpp
+++ b/src/mongo/db/commands/validate_db_metadata_cmd.cpp
@@ -217,8 +217,10 @@ public:
// Ensure there are no unstable indexes.
const auto* indexCatalog = collection->getIndexCatalog();
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- indexCatalog->getIndexIterator(opCtx, true /* includeUnfinishedIndexes */);
+ auto ii = indexCatalog->getIndexIterator(
+ opCtx,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
while (ii->more()) {
// Check if the index is allowed in API version 1.
const IndexDescriptor* desc = ii->next()->descriptor();
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index d83af04df07..a4548ce4a4c 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -261,7 +261,7 @@ public:
BSONObj keyPatternObj = keyPatternElement.Obj();
std::vector<const IndexDescriptor*> indexes;
collection->getIndexCatalog()->findIndexesByKeyPattern(
- opCtx, keyPatternObj, false, &indexes);
+ opCtx, keyPatternObj, IndexCatalog::InclusionPolicy::kReady, &indexes);
uassert(16890,
str::stream() << "Can't find index: " << keyPatternObj,
!indexes.empty());
diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp
index 6f0adb10684..6149ecd913a 100644
--- a/src/mongo/db/index_builds_coordinator.cpp
+++ b/src/mongo/db/index_builds_coordinator.cpp
@@ -554,9 +554,8 @@ Status IndexBuildsCoordinator::_startIndexBuildForRecovery(OperationContext* opC
for (size_t i = 0; i < indexNames.size(); i++) {
- bool includeUnfinished = false;
- auto descriptor =
- indexCatalog->findIndexByName(opCtx, indexNames[i], includeUnfinished);
+ auto descriptor = indexCatalog->findIndexByName(
+ opCtx, indexNames[i], IndexCatalog::InclusionPolicy::kReady);
if (descriptor) {
Status s =
indexCatalog->dropIndex(opCtx, collection.getWritableCollection(), descriptor);
@@ -592,8 +591,11 @@ Status IndexBuildsCoordinator::_startIndexBuildForRecovery(OperationContext* opC
// If the unfinished index is in the IndexCatalog, drop it through there, otherwise drop
// it from the DurableCatalog. Rollback-via-refetch does not clear any in-memory state,
// so we should do it manually here.
- includeUnfinished = true;
- descriptor = indexCatalog->findIndexByName(opCtx, indexNames[i], includeUnfinished);
+ descriptor = indexCatalog->findIndexByName(
+ opCtx,
+ indexNames[i],
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
if (descriptor) {
Status s = indexCatalog->dropUnfinishedIndex(
opCtx, collection.getWritableCollection(), descriptor);
@@ -924,7 +926,6 @@ void IndexBuildsCoordinator::applyStartIndexBuild(OperationContext* opCtx,
IndexCatalog* indexCatalog = coll.getWritableCollection(opCtx)->getIndexCatalog();
- const bool includeUnfinished = false;
for (const auto& spec : oplogEntry.indexSpecs) {
std::string name =
spec.getStringField(IndexDescriptor::kIndexNameFieldName).toString();
@@ -932,7 +933,8 @@ void IndexBuildsCoordinator::applyStartIndexBuild(OperationContext* opCtx,
str::stream() << "Index spec is missing the 'name' field " << spec,
!name.empty());
- if (auto desc = indexCatalog->findIndexByName(opCtx, name, includeUnfinished)) {
+ if (auto desc = indexCatalog->findIndexByName(
+ opCtx, name, IndexCatalog::InclusionPolicy::kReady)) {
uassertStatusOK(
indexCatalog->dropIndex(opCtx, coll.getWritableCollection(opCtx), desc));
}
@@ -1119,7 +1121,8 @@ void IndexBuildsCoordinator::applyAbortIndexBuild(OperationContext* opCtx,
const IndexDescriptor* desc = indexCatalog->findIndexByName(
opCtx,
indexSpec.getStringField(IndexDescriptor::kIndexNameFieldName),
- /*includeUnfinishedIndexes=*/true);
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
LOGV2(6455400,
"Dropping unfinished index during oplog recovery as standalone",
diff --git a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
index 43c97f7e7d2..b1d0090aa56 100644
--- a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
+++ b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
@@ -202,7 +202,8 @@ std::vector<Document> CommonMongodProcessInterface::getIndexStats(OperationConte
auto idxCatalog = collection->getIndexCatalog();
auto idx = idxCatalog->findIndexByName(opCtx,
indexName,
- /* includeUnfinishedIndexes */ true);
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished);
uassert(ErrorCodes::IndexNotFound,
"Could not find entry in IndexCatalog for index " + indexName,
idx);
@@ -605,7 +606,8 @@ bool CommonMongodProcessInterface::fieldsHaveSupportingUniqueIndex(
return fieldPaths == std::set<FieldPath>{"_id"};
}
- auto indexIterator = collection->getIndexCatalog()->getIndexIterator(opCtx, false);
+ auto indexIterator = collection->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady);
while (indexIterator->more()) {
const IndexCatalogEntry* entry = indexIterator->next();
if (supportsUniqueKey(expCtx, entry, fieldPaths)) {
diff --git a/src/mongo/db/query/collection_query_info.cpp b/src/mongo/db/query/collection_query_info.cpp
index d346265ff86..a0b4fe3cd36 100644
--- a/src/mongo/db/query/collection_query_info.cpp
+++ b/src/mongo/db/query/collection_query_info.cpp
@@ -92,12 +92,13 @@ CollectionQueryInfo::PlanCacheState::PlanCacheState(OperationContext* opCtx,
// TODO We shouldn't need to include unfinished indexes, but we must here because the index
// catalog may be in an inconsistent state. SERVER-18346.
- const bool includeUnfinishedIndexes = true;
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- collection->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes);
+ auto ii = collection->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
- indexCores.emplace_back(indexInfoFromIndexCatalogEntry(*ice));
+ if (ice->accessMethod()) {
+ indexCores.emplace_back(indexInfoFromIndexCatalogEntry(*ice));
+ }
}
planCacheIndexabilityState.updateDiscriminators(indexCores);
@@ -119,8 +120,8 @@ const UpdateIndexData& CollectionQueryInfo::getIndexKeys(OperationContext* opCtx
void CollectionQueryInfo::computeIndexKeys(OperationContext* opCtx, const CollectionPtr& coll) {
_indexedPaths.clear();
- std::unique_ptr<IndexCatalog::IndexIterator> it =
- coll->getIndexCatalog()->getIndexIterator(opCtx, true);
+ auto it = coll->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
while (it->more()) {
const IndexCatalogEntry* entry = it->next();
const IndexDescriptor* descriptor = entry->descriptor();
@@ -242,9 +243,8 @@ void CollectionQueryInfo::updatePlanCacheIndexEntries(OperationContext* opCtx,
}
void CollectionQueryInfo::init(OperationContext* opCtx, const CollectionPtr& coll) {
- const bool includeUnfinishedIndexes = false;
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- coll->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes);
+ auto ii =
+ coll->getIndexCatalog()->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (ii->more()) {
const IndexDescriptor* desc = ii->next()->descriptor();
CollectionIndexUsageTrackerDecoration::get(coll->getSharedDecorations())
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 6f6db41882c..35c83e8c5a5 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -284,7 +284,8 @@ void fillOutIndexEntries(OperationContext* opCtx,
const CollectionPtr& collection,
std::vector<IndexEntry>& entries,
std::vector<ColumnIndexEntry>& columnEntries) {
- auto ii = collection->getIndexCatalog()->getIndexIterator(opCtx, false);
+ auto ii = collection->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady);
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
@@ -2393,8 +2394,8 @@ QueryPlannerParams fillOutPlannerParamsForDistinct(OperationContext* opCtx,
// If the caller did not request a "strict" distinct scan then we may choose a plan which
// unwinds arrays and treats each element in an array as its own key.
const bool mayUnwindArrays = !(plannerOptions & QueryPlannerParams::STRICT_DISTINCT_ONLY);
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- collection->getIndexCatalog()->getIndexIterator(opCtx, false);
+ auto ii = collection->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady);
auto query = parsedDistinct.getQuery()->getFindCommandRequest().getFilter();
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
diff --git a/src/mongo/db/query/plan_cache_key_factory.cpp b/src/mongo/db/query/plan_cache_key_factory.cpp
index d47f1768858..6b154b29105 100644
--- a/src/mongo/db/query/plan_cache_key_factory.cpp
+++ b/src/mongo/db/query/plan_cache_key_factory.cpp
@@ -111,8 +111,8 @@ boost::optional<Timestamp> computeNewestVisibleIndexTimestamp(OperationContext*
Timestamp currentNewestVisible = Timestamp::min();
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- collection->getIndexCatalog()->getIndexIterator(opCtx, /*includeUnfinishedIndexes*/ true);
+ auto ii = collection->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
auto minVisibleSnapshot = ice->getMinimumVisibleSnapshot();
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 7d254bc723d..e527aa204eb 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -862,9 +862,10 @@ void dropIndex(OperationContext* opCtx,
const string& indexName,
NamespaceString& nss) {
IndexCatalog* indexCatalog = collection->getIndexCatalog();
- bool includeUnfinishedIndexes = true;
- auto indexDescriptor =
- indexCatalog->findIndexByName(opCtx, indexName, includeUnfinishedIndexes);
+ auto indexDescriptor = indexCatalog->findIndexByName(
+ opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
if (!indexDescriptor) {
LOGV2_WARNING(21725,
"Rollback failed to drop index {indexName} in {namespace}: index not found.",
diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp
index ca84c39b6f5..1a90e3a57c8 100644
--- a/src/mongo/db/repl/storage_interface_impl.cpp
+++ b/src/mongo/db/repl/storage_interface_impl.cpp
@@ -640,7 +640,9 @@ Status StorageInterfaceImpl::setIndexIsMultikey(OperationContext* opCtx,
}
auto idx = collection->getIndexCatalog()->findIndexByName(
- opCtx, indexName, true /* includeUnfinishedIndexes */);
+ opCtx,
+ indexName,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
if (!idx) {
return Status(ErrorCodes::IndexNotFound,
str::stream()
@@ -788,9 +790,8 @@ StatusWith<std::vector<BSONObj>> _findOrDeleteDocuments(
// Use index scan.
auto indexCatalog = collection->getIndexCatalog();
invariant(indexCatalog);
- bool includeUnfinishedIndexes = false;
- const IndexDescriptor* indexDescriptor =
- indexCatalog->findIndexByName(opCtx, *indexName, includeUnfinishedIndexes);
+ const IndexDescriptor* indexDescriptor = indexCatalog->findIndexByName(
+ opCtx, *indexName, IndexCatalog::InclusionPolicy::kReady);
if (!indexDescriptor) {
return Result(ErrorCodes::IndexNotFound,
str::stream() << "Index not found, ns:" << nsOrUUID.toString()
diff --git a/src/mongo/db/repl/storage_timestamp_test.cpp b/src/mongo/db/repl/storage_timestamp_test.cpp
index fbaa81a4251..467fa99b314 100644
--- a/src/mongo/db/repl/storage_timestamp_test.cpp
+++ b/src/mongo/db/repl/storage_timestamp_test.cpp
@@ -2708,8 +2708,10 @@ TEST_F(StorageTimestampTest, IndexBuildsResolveErrorsDuringStateChangeToPrimary)
}
auto indexCatalog = collection->getIndexCatalog();
- buildingIndex = indexCatalog->getEntry(
- indexCatalog->findIndexByName(_opCtx, "a_1_b_1", /* includeUnfinished */ true));
+ buildingIndex = indexCatalog->getEntry(indexCatalog->findIndexByName(
+ _opCtx,
+ "a_1_b_1",
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished));
ASSERT(buildingIndex);
ASSERT_OK(indexer.insertAllDocumentsInCollection(_opCtx, collection.get()));
diff --git a/src/mongo/db/s/shard_key_index_util.cpp b/src/mongo/db/s/shard_key_index_util.cpp
index 4097c9f236f..9b3b6371a4a 100644
--- a/src/mongo/db/s/shard_key_index_util.cpp
+++ b/src/mongo/db/s/shard_key_index_util.cpp
@@ -57,7 +57,8 @@ boost::optional<ShardKeyIndex> _findShardKeyPrefixedIndex(
const IndexDescriptor* best = nullptr;
- auto indexIterator = indexCatalog->getIndexIterator(opCtx, false);
+ auto indexIterator =
+ indexCatalog->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (indexIterator->more()) {
auto indexEntry = indexIterator->next();
auto indexDescriptor = indexEntry->descriptor();
diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp
index 8e3252e61b8..48668dd07a1 100644
--- a/src/mongo/db/stats/storage_stats.cpp
+++ b/src/mongo/db/stats/storage_stats.cpp
@@ -148,8 +148,8 @@ Status appendCollectionStorageStats(OperationContext* opCtx,
BSONObjBuilder indexDetails;
std::vector<std::string> indexBuilds;
- std::unique_ptr<IndexCatalog::IndexIterator> it =
- indexCatalog->getIndexIterator(opCtx, /*includeUnfinishedIndexes=*/true);
+ auto it = indexCatalog->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
while (it->more()) {
const IndexCatalogEntry* entry = it->next();
const IndexDescriptor* descriptor = entry->descriptor();
diff --git a/src/mongo/db/storage/storage_engine_impl.cpp b/src/mongo/db/storage/storage_engine_impl.cpp
index f866314229b..3465e9addf4 100644
--- a/src/mongo/db/storage/storage_engine_impl.cpp
+++ b/src/mongo/db/storage/storage_engine_impl.cpp
@@ -667,21 +667,19 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn
logAttrs(nss));
}
- // Two-phase index drop ensures that the underlying data table for an index in the
- // catalog is not dropped until the index removal from the catalog has been majority
- // committed and become part of the latest checkpoint. Therefore, there should almost
- // never be a case where the index catalog entry remains but the index table (identified
- // by ident) has been removed.
- //
- // There is an exception to this due to the fact that we drop the index ident without a
- // timestamp when restarting an index build for startup recovery. Then, if we experience
- // an unclean shutdown before a checkpoint is taken, the subsequent startup recovery can
- // see the now-dropped ident referenced by the old index catalog entry.
- invariant(engineIdents.find(indexIdent) != engineIdents.end() ||
- lastShutdownState == LastShutdownState::kUnclean,
- str::stream() << "Failed to find an index data table matching " << indexIdent
- << " for durable index catalog entry " << indexMetaData.spec
- << " in collection " << nss.ns());
+ if (!engineIdents.count(indexIdent)) {
+ // There are cetain cases where the catalog entry may reference an index ident which
+ // is no longer present. One example of this is when an unclean shutdown occurs
+ // before a checkpoint is taken during startup recovery. Since we drop the index
+ // ident without a timestamp when restarting the index build for startup recovery,
+ // the subsequent startup recovery can see the now-dropped ident referenced by the
+ // old index catalog entry.
+ LOGV2(6386500,
+ "Index catalog entry ident not found",
+ "ident"_attr = indexIdent,
+ "entry"_attr = indexMetaData.spec,
+ logAttrs(nss));
+ }
// Any index build with a UUID is an unfinished two-phase build and must be restarted.
// There are no special cases to handle on primaries or secondaries. An index build may
@@ -879,8 +877,10 @@ Status StorageEngineImpl::_dropCollectionsNoTimestamp(OperationContext* opCtx,
// No need to remove the indexes from the IndexCatalog because eliminating the Collection
// will have the same effect.
- auto ii =
- coll->getIndexCatalog()->getIndexIterator(opCtx, true /* includeUnfinishedIndexes */);
+ auto ii = coll->getIndexCatalog()->getIndexIterator(
+ opCtx,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished |
+ IndexCatalog::InclusionPolicy::kFrozen);
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
@@ -1306,7 +1306,9 @@ int64_t StorageEngineImpl::sizeOnDiskForDb(OperationContext* opCtx, const Databa
auto perCollectionWork = [&](const CollectionPtr& collection) {
size += collection->getRecordStore()->storageSize(opCtx);
- auto it = collection->getIndexCatalog()->getIndexIterator(opCtx, true);
+ auto it = collection->getIndexCatalog()->getIndexIterator(
+ opCtx,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
while (it->more()) {
size += _engine->getIdentSize(opCtx, it->next()->getIdent());
}
diff --git a/src/mongo/db/storage/storage_engine_test_fixture.h b/src/mongo/db/storage/storage_engine_test_fixture.h
index 96d3c7d0af8..eaedd287615 100644
--- a/src/mongo/db/storage/storage_engine_test_fixture.h
+++ b/src/mongo/db/storage/storage_engine_test_fixture.h
@@ -183,7 +183,10 @@ public:
Collection* collection =
CollectionCatalog::get(opCtx)->lookupCollectionByNamespaceForMetadataWrite(opCtx,
collNs);
- auto descriptor = collection->getIndexCatalog()->findIndexByName(opCtx, key, true);
+ auto descriptor = collection->getIndexCatalog()->findIndexByName(
+ opCtx,
+ key,
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
collection->indexBuildSuccess(opCtx, descriptor->getEntry());
}
diff --git a/src/mongo/db/system_index.cpp b/src/mongo/db/system_index.cpp
index d9daf28b194..02084801dda 100644
--- a/src/mongo/db/system_index.cpp
+++ b/src/mongo/db/system_index.cpp
@@ -143,7 +143,8 @@ Status verifySystemIndexes(OperationContext* opCtx) {
// Make sure the old unique index from v2.4 on system.users doesn't exist.
std::vector<const IndexDescriptor*> indexes;
- indexCatalog->findIndexesByKeyPattern(opCtx, v1SystemUsersKeyPattern, false, &indexes);
+ indexCatalog->findIndexesByKeyPattern(
+ opCtx, v1SystemUsersKeyPattern, IndexCatalog::InclusionPolicy::kReady, &indexes);
if (!indexes.empty()) {
fassert(ErrorCodes::AmbiguousIndexKeyPattern, indexes.size() == 1);
@@ -154,7 +155,8 @@ Status verifySystemIndexes(OperationContext* opCtx) {
}
// Ensure that system indexes exist for the user collection.
- indexCatalog->findIndexesByKeyPattern(opCtx, v3SystemUsersKeyPattern, false, &indexes);
+ indexCatalog->findIndexesByKeyPattern(
+ opCtx, v3SystemUsersKeyPattern, IndexCatalog::InclusionPolicy::kReady, &indexes);
if (indexes.empty()) {
try {
generateSystemIndexForExistingCollection(
@@ -176,7 +178,8 @@ Status verifySystemIndexes(OperationContext* opCtx) {
invariant(indexCatalog);
std::vector<const IndexDescriptor*> indexes;
- indexCatalog->findIndexesByKeyPattern(opCtx, v3SystemRolesKeyPattern, false, &indexes);
+ indexCatalog->findIndexesByKeyPattern(
+ opCtx, v3SystemRolesKeyPattern, IndexCatalog::InclusionPolicy::kReady, &indexes);
if (indexes.empty()) {
try {
generateSystemIndexForExistingCollection(
diff --git a/src/mongo/dbtests/indexcatalogtests.cpp b/src/mongo/dbtests/indexcatalogtests.cpp
index 6e6da7e8c7a..7a648f654f0 100644
--- a/src/mongo/dbtests/indexcatalogtests.cpp
+++ b/src/mongo/dbtests/indexcatalogtests.cpp
@@ -90,8 +90,8 @@ public:
ASSERT_TRUE(indexCatalog(&opCtx)->numIndexesReady(&opCtx) == numFinishedIndexesStart + 2);
- std::unique_ptr<IndexCatalog::IndexIterator> ii =
- indexCatalog(&opCtx)->getIndexIterator(&opCtx, false);
+ auto ii =
+ indexCatalog(&opCtx)->getIndexIterator(&opCtx, IndexCatalog::InclusionPolicy::kReady);
int indexesIterated = 0;
bool foundIndex = false;
while (ii->more()) {
diff --git a/src/mongo/dbtests/indexupdatetests.cpp b/src/mongo/dbtests/indexupdatetests.cpp
index e38d3663bc2..2988f9f658a 100644
--- a/src/mongo/dbtests/indexupdatetests.cpp
+++ b/src/mongo/dbtests/indexupdatetests.cpp
@@ -222,8 +222,10 @@ public:
.getStatus());
auto& coll = collection();
- auto desc =
- coll->getIndexCatalog()->findIndexByName(_opCtx, "a", true /* includeUnfinished */);
+ auto desc = coll->getIndexCatalog()->findIndexByName(
+ _opCtx,
+ "a",
+ IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
ASSERT(desc);
// Hybrid index builds check duplicates explicitly.
diff --git a/src/mongo/dbtests/multikey_paths_test.cpp b/src/mongo/dbtests/multikey_paths_test.cpp
index c7d8e1acb28..34afd00fa0e 100644
--- a/src/mongo/dbtests/multikey_paths_test.cpp
+++ b/src/mongo/dbtests/multikey_paths_test.cpp
@@ -95,7 +95,8 @@ public:
const MultikeyPaths& expectedMultikeyPaths) {
const IndexCatalog* indexCatalog = collection->getIndexCatalog();
std::vector<const IndexDescriptor*> indexes;
- indexCatalog->findIndexesByKeyPattern(_opCtx.get(), keyPattern, false, &indexes);
+ indexCatalog->findIndexesByKeyPattern(
+ _opCtx.get(), keyPattern, IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
auto desc = indexes[0];
const IndexCatalogEntry* ice = indexCatalog->getEntry(desc);
diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp
index b97dae14aa5..7b3249b313d 100644
--- a/src/mongo/dbtests/query_plan_executor.cpp
+++ b/src/mongo/dbtests/query_plan_executor.cpp
@@ -188,7 +188,8 @@ private:
CollectionPtr collection =
CollectionCatalog::get(&_opCtx)->lookupCollectionByNamespace(&_opCtx, nss);
std::vector<const IndexDescriptor*> indexes;
- collection->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, obj, false, &indexes);
+ collection->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, obj, IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_LTE(indexes.size(), 1U);
return indexes.size() == 0 ? nullptr : indexes[0];
}
diff --git a/src/mongo/dbtests/query_stage_and.cpp b/src/mongo/dbtests/query_stage_and.cpp
index 269682199c2..8773f170ca3 100644
--- a/src/mongo/dbtests/query_stage_and.cpp
+++ b/src/mongo/dbtests/query_stage_and.cpp
@@ -75,7 +75,8 @@ public:
const IndexDescriptor* getIndex(const BSONObj& obj, const CollectionPtr& coll) {
std::vector<const IndexDescriptor*> indexes;
- coll->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, obj, false, &indexes);
+ coll->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, obj, IndexCatalog::InclusionPolicy::kReady, &indexes);
if (indexes.empty()) {
FAIL(str::stream() << "Unable to find index with key pattern " << obj);
}
diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp
index 956c1f463b7..275d9939a50 100644
--- a/src/mongo/dbtests/query_stage_count.cpp
+++ b/src/mongo/dbtests/query_stage_count.cpp
@@ -203,7 +203,8 @@ public:
IndexScan* createIndexScan(MatchExpression* expr, WorkingSet* ws) {
const IndexCatalog* catalog = _coll->getIndexCatalog();
std::vector<const IndexDescriptor*> indexes;
- catalog->findIndexesByKeyPattern(&_opCtx, BSON("x" << 1), false, &indexes);
+ catalog->findIndexesByKeyPattern(
+ &_opCtx, BSON("x" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
auto descriptor = indexes[0];
diff --git a/src/mongo/dbtests/query_stage_count_scan.cpp b/src/mongo/dbtests/query_stage_count_scan.cpp
index 7485a938c01..b03ed4a49a9 100644
--- a/src/mongo/dbtests/query_stage_count_scan.cpp
+++ b/src/mongo/dbtests/query_stage_count_scan.cpp
@@ -95,7 +95,8 @@ public:
const IndexDescriptor* getIndex(Database* db, const BSONObj& obj) {
std::vector<const IndexDescriptor*> indexes;
- getCollection()->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, obj, false, &indexes);
+ getCollection()->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, obj, IndexCatalog::InclusionPolicy::kReady, &indexes);
return indexes.empty() ? nullptr : indexes[0];
}
diff --git a/src/mongo/dbtests/query_stage_distinct.cpp b/src/mongo/dbtests/query_stage_distinct.cpp
index 57552d1f18e..bea39ab55f1 100644
--- a/src/mongo/dbtests/query_stage_distinct.cpp
+++ b/src/mongo/dbtests/query_stage_distinct.cpp
@@ -130,7 +130,8 @@ public:
// Set up the distinct stage.
std::vector<const IndexDescriptor*> indexes;
- coll->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, BSON("a" << 1), false, &indexes);
+ coll->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, BSON("a" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
DistinctParams params{&_opCtx, coll, indexes[0]};
@@ -196,7 +197,8 @@ public:
// Set up the distinct stage.
std::vector<const IndexDescriptor*> indexes;
- coll->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, BSON("a" << 1), false, &indexes);
+ coll->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, BSON("a" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
verify(indexes.size() == 1);
DistinctParams params{&_opCtx, coll, indexes[0]};
@@ -263,7 +265,7 @@ public:
std::vector<const IndexDescriptor*> indices;
coll->getIndexCatalog()->findIndexesByKeyPattern(
- &_opCtx, BSON("a" << 1 << "b" << 1), false, &indices);
+ &_opCtx, BSON("a" << 1 << "b" << 1), IndexCatalog::InclusionPolicy::kReady, &indices);
ASSERT_EQ(1U, indices.size());
DistinctParams params{&_opCtx, coll, indices[0]};
diff --git a/src/mongo/dbtests/query_stage_ixscan.cpp b/src/mongo/dbtests/query_stage_ixscan.cpp
index 30ebc65e983..d8a2454b259 100644
--- a/src/mongo/dbtests/query_stage_ixscan.cpp
+++ b/src/mongo/dbtests/query_stage_ixscan.cpp
@@ -97,7 +97,8 @@ public:
IndexScan* createIndexScanSimpleRange(BSONObj startKey, BSONObj endKey) {
IndexCatalog* catalog = _coll->getIndexCatalog();
std::vector<const IndexDescriptor*> indexes;
- catalog->findIndexesByKeyPattern(&_opCtx, BSON("x" << 1), false, &indexes);
+ catalog->findIndexesByKeyPattern(
+ &_opCtx, BSON("x" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
// We are not testing indexing here so use maximal bounds
@@ -120,7 +121,8 @@ public:
int direction = 1) {
IndexCatalog* catalog = _coll->getIndexCatalog();
std::vector<const IndexDescriptor*> indexes;
- catalog->findIndexesByKeyPattern(&_opCtx, BSON("x" << 1), false, &indexes);
+ catalog->findIndexesByKeyPattern(
+ &_opCtx, BSON("x" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
IndexScanParams params(&_opCtx, _collPtr, indexes[0]);
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index f3f9f48139d..4b25e270647 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -75,7 +75,8 @@ public:
const IndexDescriptor* getIndex(const BSONObj& obj, const CollectionPtr& coll) {
std::vector<const IndexDescriptor*> indexes;
- coll->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, obj, false, &indexes);
+ coll->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, obj, IndexCatalog::InclusionPolicy::kReady, &indexes);
return indexes.empty() ? nullptr : indexes[0];
}
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index 3552cf095fd..984ecb861a8 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -146,7 +146,7 @@ unique_ptr<PlanStage> getIxScanPlan(ExpressionContext* expCtx,
int desiredFooValue) {
std::vector<const IndexDescriptor*> indexes;
coll->getIndexCatalog()->findIndexesByKeyPattern(
- expCtx->opCtx, BSON("foo" << 1), false, &indexes);
+ expCtx->opCtx, BSON("foo" << 1), IndexCatalog::InclusionPolicy::kReady, &indexes);
ASSERT_EQ(indexes.size(), 1U);
IndexScanParams ixparams(expCtx->opCtx, coll, indexes[0]);
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index e5aa014b78c..a3a46a047cd 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -127,7 +127,8 @@ public:
const IndexDescriptor* getIndex(const BSONObj& obj) {
AutoGetCollectionForReadCommand collection(&_opCtx, NamespaceString(ns()));
std::vector<const IndexDescriptor*> indexes;
- collection->getIndexCatalog()->findIndexesByKeyPattern(&_opCtx, obj, false, &indexes);
+ collection->getIndexCatalog()->findIndexesByKeyPattern(
+ &_opCtx, obj, IndexCatalog::InclusionPolicy::kReady, &indexes);
return indexes.empty() ? nullptr : indexes[0];
}
diff --git a/src/mongo/dbtests/rollbacktests.cpp b/src/mongo/dbtests/rollbacktests.cpp
index dedc02f08ff..ad52aa873bb 100644
--- a/src/mongo/dbtests/rollbacktests.cpp
+++ b/src/mongo/dbtests/rollbacktests.cpp
@@ -110,11 +110,16 @@ void assertEmpty(OperationContext* opCtx, const NamespaceString& nss) {
}
bool indexExists(OperationContext* opCtx, const NamespaceString& nss, const string& idxName) {
auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
- return coll->getIndexCatalog()->findIndexByName(opCtx, idxName, true) != nullptr;
+ return coll->getIndexCatalog()->findIndexByName(
+ opCtx,
+ idxName,
+ IndexCatalog::InclusionPolicy::kReady |
+ IndexCatalog::InclusionPolicy::kUnfinished) != nullptr;
}
bool indexReady(OperationContext* opCtx, const NamespaceString& nss, const string& idxName) {
auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
- return coll->getIndexCatalog()->findIndexByName(opCtx, idxName, false) != nullptr;
+ return coll->getIndexCatalog()->findIndexByName(
+ opCtx, idxName, IndexCatalog::InclusionPolicy::kReady) != nullptr;
}
size_t getNumIndexEntries(OperationContext* opCtx,
const NamespaceString& nss,
@@ -123,7 +128,7 @@ size_t getNumIndexEntries(OperationContext* opCtx,
auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
const IndexCatalog* catalog = coll->getIndexCatalog();
- auto desc = catalog->findIndexByName(opCtx, idxName, false);
+ auto desc = catalog->findIndexByName(opCtx, idxName, IndexCatalog::InclusionPolicy::kReady);
if (desc) {
auto iam = catalog->getEntry(desc)->accessMethod()->asSortedData();
diff --git a/src/mongo/dbtests/storage_debug_util.cpp b/src/mongo/dbtests/storage_debug_util.cpp
index 2bc12341a16..9cf0b3c640a 100644
--- a/src/mongo/dbtests/storage_debug_util.cpp
+++ b/src/mongo/dbtests/storage_debug_util.cpp
@@ -66,7 +66,7 @@ void printCollectionAndIndexTableEntries(OperationContext* opCtx, const Namespac
// Iterate and print each index's table of documents.
const auto indexCatalog = coll->getIndexCatalog();
- const auto it = indexCatalog->getIndexIterator(opCtx, /*includeUnfinished*/ false);
+ const auto it = indexCatalog->getIndexIterator(opCtx, IndexCatalog::InclusionPolicy::kReady);
while (it->more()) {
const auto indexCatalogEntry = it->next();
const auto indexDescriptor = indexCatalogEntry->descriptor();