summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/catalog/index_catalog.h10
-rw-r--r--src/mongo/db/catalog/index_catalog_entry.cpp15
-rw-r--r--src/mongo/db/catalog/index_catalog_entry.h22
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp56
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.h3
-rw-r--r--src/mongo/db/catalog/index_catalog_noop.h4
-rw-r--r--src/mongo/db/exec/cached_plan.h4
-rw-r--r--src/mongo/db/exec/collection_scan.cpp4
-rw-r--r--src/mongo/db/exec/collection_scan.h4
-rw-r--r--src/mongo/db/exec/delete.cpp2
-rw-r--r--src/mongo/db/exec/delete.h4
-rw-r--r--src/mongo/db/exec/fetch.cpp4
-rw-r--r--src/mongo/db/exec/fetch.h4
-rw-r--r--src/mongo/db/exec/geo_near.cpp8
-rw-r--r--src/mongo/db/exec/index_scan.cpp57
-rw-r--r--src/mongo/db/exec/index_scan.h70
-rw-r--r--src/mongo/db/exec/multi_iterator.cpp4
-rw-r--r--src/mongo/db/exec/multi_iterator.h4
-rw-r--r--src/mongo/db/exec/multi_plan.h4
-rw-r--r--src/mongo/db/exec/near.h4
-rw-r--r--src/mongo/db/exec/record_store_fast_count.h4
-rw-r--r--src/mongo/db/exec/requires_collection_stage.cpp6
-rw-r--r--src/mongo/db/exec/requires_collection_stage.h8
-rw-r--r--src/mongo/db/exec/requires_index_stage.cpp64
-rw-r--r--src/mongo/db/exec/requires_index_stage.h109
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp2
-rw-r--r--src/mongo/db/exec/subplan.h4
-rw-r--r--src/mongo/db/exec/text.cpp2
-rw-r--r--src/mongo/db/exec/update.cpp2
-rw-r--r--src/mongo/db/exec/update.h4
-rw-r--r--src/mongo/db/query/internal_plans.cpp2
-rw-r--r--src/mongo/db/query/stage_builder.cpp2
-rw-r--r--src/mongo/dbtests/query_plan_executor.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_and.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_count.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_ixscan.cpp20
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp2
40 files changed, 367 insertions, 162 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 2e5bd249acb..8a71699022b 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1064,6 +1064,7 @@ env.Library(
'exec/queued_data_stage.cpp',
'exec/record_store_fast_count.cpp',
'exec/requires_collection_stage.cpp',
+ 'exec/requires_index_stage.cpp',
'exec/shard_filter.cpp',
'exec/skip.cpp',
'exec/sort.cpp',
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index eadb7a56733..386a344d65c 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -280,10 +280,18 @@ public:
const IndexDescriptor* const oldDesc) = 0;
/**
- * Never returns nullptr.
+ * Returns a pointer to the index catalog entry associated with 'desc'. Throws if there is no
+ * such index. Never returns nullptr.
*/
virtual const IndexCatalogEntry* getEntry(const IndexDescriptor* const desc) const = 0;
+ /**
+ * Returns a pointer to the index catalog entry associated with 'desc', where the caller assumes
+ * shared ownership of the entry. Returns null if the entry does not exist.
+ */
+ virtual std::shared_ptr<const IndexCatalogEntry> getEntryShared(
+ const IndexDescriptor*) const = 0;
+
virtual IndexAccessMethod* getIndex(const IndexDescriptor* const desc) = 0;
virtual const IndexAccessMethod* getIndex(const IndexDescriptor* const desc) const = 0;
diff --git a/src/mongo/db/catalog/index_catalog_entry.cpp b/src/mongo/db/catalog/index_catalog_entry.cpp
index 0f5f8dda58d..997cb4a4ba8 100644
--- a/src/mongo/db/catalog/index_catalog_entry.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry.cpp
@@ -63,6 +63,16 @@ IndexCatalogEntry* IndexCatalogEntryContainer::find(const IndexDescriptor* desc)
return nullptr;
}
+std::shared_ptr<IndexCatalogEntry> IndexCatalogEntryContainer::findShared(
+ const IndexDescriptor* desc) const {
+ for (auto&& entry : _entries) {
+ if (entry->descriptor() == desc) {
+ return entry;
+ }
+ }
+ return {};
+}
+
IndexCatalogEntry* IndexCatalogEntryContainer::find(const std::string& name) {
for (iterator i = begin(); i != end(); ++i) {
IndexCatalogEntry* e = i->get();
@@ -72,11 +82,12 @@ IndexCatalogEntry* IndexCatalogEntryContainer::find(const std::string& name) {
return nullptr;
}
-IndexCatalogEntry* IndexCatalogEntryContainer::release(const IndexDescriptor* desc) {
+std::shared_ptr<IndexCatalogEntry> IndexCatalogEntryContainer::release(
+ const IndexDescriptor* desc) {
for (auto i = _entries.begin(); i != _entries.end(); ++i) {
if ((*i)->descriptor() != desc)
continue;
- IndexCatalogEntry* e = i->release();
+ auto e = std::move(*i);
_entries.erase(i);
return e;
}
diff --git a/src/mongo/db/catalog/index_catalog_entry.h b/src/mongo/db/catalog/index_catalog_entry.h
index eb54f065e7b..192788e3948 100644
--- a/src/mongo/db/catalog/index_catalog_entry.h
+++ b/src/mongo/db/catalog/index_catalog_entry.h
@@ -156,8 +156,8 @@ public:
class IndexCatalogEntryContainer {
public:
- typedef std::vector<std::unique_ptr<IndexCatalogEntry>>::const_iterator const_iterator;
- typedef std::vector<std::unique_ptr<IndexCatalogEntry>>::const_iterator iterator;
+ typedef std::vector<std::shared_ptr<IndexCatalogEntry>>::const_iterator const_iterator;
+ typedef std::vector<std::shared_ptr<IndexCatalogEntry>>::const_iterator iterator;
const_iterator begin() const {
return _entries.begin();
@@ -182,6 +182,11 @@ public:
IndexCatalogEntry* find(const std::string& name);
+ /**
+ * Returns a pointer to the IndexCatalogEntry corresponding to 'desc', where the caller assumes
+ * shared ownership of the catalog object. Returns null if the entry does not exist.
+ */
+ std::shared_ptr<IndexCatalogEntry> findShared(const IndexDescriptor* desc) const;
unsigned size() const {
return _entries.size();
@@ -192,20 +197,17 @@ public:
/**
* Removes from _entries and returns the matching entry or NULL if none matches.
*/
- IndexCatalogEntry* release(const IndexDescriptor* desc);
+ std::shared_ptr<IndexCatalogEntry> release(const IndexDescriptor* desc);
bool remove(const IndexDescriptor* desc) {
- IndexCatalogEntry* entry = release(desc);
- delete entry;
- return entry;
+ return static_cast<bool>(release(desc));
}
- // pass ownership to EntryContainer
- void add(IndexCatalogEntry* entry) {
- _entries.push_back(std::unique_ptr<IndexCatalogEntry>{entry});
+ void add(std::shared_ptr<IndexCatalogEntry>&& entry) {
+ _entries.push_back(std::move(entry));
}
private:
- std::vector<std::unique_ptr<IndexCatalogEntry>> _entries;
+ std::vector<std::shared_ptr<IndexCatalogEntry>> _entries;
};
} // namespace mongo
diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp
index 837ccfd7b4a..9a4aa990ab0 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -150,20 +150,20 @@ IndexCatalogEntry* IndexCatalogImpl::_setupInMemoryStructures(
}
auto* const descriptorPtr = descriptor.get();
- auto entry = stdx::make_unique<IndexCatalogEntryImpl>(opCtx,
- _collection->ns().ns(),
- _collection->getCatalogEntry(),
- std::move(descriptor),
- _collection->infoCache());
+ auto entry = std::make_shared<IndexCatalogEntryImpl>(opCtx,
+ _collection->ns().ns(),
+ _collection->getCatalogEntry(),
+ std::move(descriptor),
+ _collection->infoCache());
std::unique_ptr<IndexAccessMethod> accessMethod(
_collection->dbce()->getIndex(opCtx, _collection->getCatalogEntry(), entry.get()));
entry->init(std::move(accessMethod));
IndexCatalogEntry* save = entry.get();
if (isReadyIndex) {
- _readyIndexes.add(entry.release());
+ _readyIndexes.add(std::move(entry));
} else {
- _buildingIndexes.add(entry.release());
+ _buildingIndexes.add(std::move(entry));
}
if (!initFromDisk) {
@@ -821,8 +821,8 @@ public:
IndexRemoveChange(OperationContext* opCtx,
Collection* collection,
IndexCatalogEntryContainer* entries,
- IndexCatalogEntry* entry)
- : _opCtx(opCtx), _collection(collection), _entries(entries), _entry(entry) {}
+ std::shared_ptr<IndexCatalogEntry> entry)
+ : _opCtx(opCtx), _collection(collection), _entries(entries), _entry(std::move(entry)) {}
void commit(boost::optional<Timestamp> commitTime) final {
// Ban reading from this collection on committed reads on snapshots before now.
@@ -834,20 +834,18 @@ public:
commitTime = LogicalClock::getClusterTimeForReplicaSet(_opCtx).asTimestamp();
}
_collection->setMinimumVisibleSnapshot(commitTime.get());
-
- delete _entry;
}
void rollback() final {
- _entries->add(_entry);
_collection->infoCache()->addedIndex(_opCtx, _entry->descriptor());
+ _entries->add(std::move(_entry));
}
private:
OperationContext* _opCtx;
Collection* _collection;
IndexCatalogEntryContainer* _entries;
- IndexCatalogEntry* _entry;
+ std::shared_ptr<IndexCatalogEntry> _entry;
};
} // namespace
@@ -881,14 +879,16 @@ Status IndexCatalogImpl::_dropIndex(OperationContext* opCtx, IndexCatalogEntry*
auto released = _readyIndexes.release(entry->descriptor());
if (released) {
- invariant(released == entry);
+ invariant(released.get() == entry);
opCtx->recoveryUnit()->registerChange(
- new IndexRemoveChange(opCtx, _collection, &_readyIndexes, entry));
+ new IndexRemoveChange(opCtx, _collection, &_readyIndexes, std::move(released)));
} else {
- invariant(_buildingIndexes.release(entry->descriptor()) == entry);
+ released = _buildingIndexes.release(entry->descriptor());
+ invariant(released.get() == entry);
opCtx->recoveryUnit()->registerChange(
- new IndexRemoveChange(opCtx, _collection, &_buildingIndexes, entry));
+ new IndexRemoveChange(opCtx, _collection, &_buildingIndexes, std::move(released)));
}
+
_collection->infoCache()->droppedIndex(opCtx, indexName);
entry = nullptr;
_deleteIndexFromDisk(opCtx, indexName, indexNamespace);
@@ -1100,6 +1100,14 @@ const IndexCatalogEntry* IndexCatalogImpl::getEntry(const IndexDescriptor* desc)
return entry;
}
+std::shared_ptr<const IndexCatalogEntry> IndexCatalogImpl::getEntryShared(
+ const IndexDescriptor* indexDescriptor) const {
+ auto entry = _readyIndexes.findShared(indexDescriptor);
+ if (entry) {
+ return entry;
+ }
+ return _buildingIndexes.findShared(indexDescriptor);
+}
const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx,
const IndexDescriptor* oldDesc) {
@@ -1119,10 +1127,10 @@ const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx,
// Delete the IndexCatalogEntry that owns this descriptor. After deletion, 'oldDesc' is
// invalid and should not be dereferenced.
- IndexCatalogEntry* oldEntry = _readyIndexes.release(oldDesc);
+ auto oldEntry = _readyIndexes.release(oldDesc);
invariant(oldEntry);
opCtx->recoveryUnit()->registerChange(
- new IndexRemoveChange(opCtx, _collection, &_readyIndexes, oldEntry));
+ new IndexRemoveChange(opCtx, _collection, &_readyIndexes, std::move(oldEntry)));
// Ask the CollectionCatalogEntry for the new index spec.
BSONObj spec = _collection->getCatalogEntry()->getIndexSpec(opCtx, indexName).getOwned();
@@ -1348,11 +1356,13 @@ void IndexCatalogImpl::prepareInsertDeleteOptions(OperationContext* opCtx,
}
void IndexCatalogImpl::indexBuildSuccess(OperationContext* opCtx, IndexCatalogEntry* index) {
- invariant(_buildingIndexes.release(index->descriptor()));
- _readyIndexes.add(index);
+ auto releasedEntry = _buildingIndexes.release(index->descriptor());
+ invariant(releasedEntry.get() == index);
+ _readyIndexes.add(std::move(releasedEntry));
opCtx->recoveryUnit()->onRollback([this, index]() {
- invariant(_readyIndexes.release(index->descriptor()));
- _buildingIndexes.add(index);
+ auto releasedEntry = _readyIndexes.release(index->descriptor());
+ invariant(releasedEntry.get() == index);
+ _buildingIndexes.add(std::move(releasedEntry));
});
}
diff --git a/src/mongo/db/catalog/index_catalog_impl.h b/src/mongo/db/catalog/index_catalog_impl.h
index f37e145c5b9..7c6c415241f 100644
--- a/src/mongo/db/catalog/index_catalog_impl.h
+++ b/src/mongo/db/catalog/index_catalog_impl.h
@@ -162,9 +162,10 @@ public:
const IndexDescriptor* refreshEntry(OperationContext* opCtx,
const IndexDescriptor* oldDesc) override;
- // never returns NULL
const IndexCatalogEntry* getEntry(const IndexDescriptor* desc) const override;
+ std::shared_ptr<const IndexCatalogEntry> getEntryShared(const IndexDescriptor*) const override;
+
IndexAccessMethod* getIndex(const IndexDescriptor* desc) override;
const IndexAccessMethod* getIndex(const IndexDescriptor* desc) const override;
diff --git a/src/mongo/db/catalog/index_catalog_noop.h b/src/mongo/db/catalog/index_catalog_noop.h
index 29ad037e221..e645831063a 100644
--- a/src/mongo/db/catalog/index_catalog_noop.h
+++ b/src/mongo/db/catalog/index_catalog_noop.h
@@ -115,6 +115,10 @@ public:
return nullptr;
}
+ std::shared_ptr<const IndexCatalogEntry> getEntryShared(const IndexDescriptor*) const override {
+ return nullptr;
+ }
+
IndexAccessMethod* getIndex(const IndexDescriptor* const desc) override {
return nullptr;
}
diff --git a/src/mongo/db/exec/cached_plan.h b/src/mongo/db/exec/cached_plan.h
index ed6260c5f72..d1c6fcaaf8f 100644
--- a/src/mongo/db/exec/cached_plan.h
+++ b/src/mongo/db/exec/cached_plan.h
@@ -87,9 +87,9 @@ public:
Status pickBestPlan(PlanYieldPolicy* yieldPolicy);
protected:
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final {}
+ void doRestoreStateRequiresCollection() final {}
private:
/**
diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp
index 3f395d6fa21..f507a24dba4 100644
--- a/src/mongo/db/exec/collection_scan.cpp
+++ b/src/mongo/db/exec/collection_scan.cpp
@@ -211,13 +211,13 @@ bool CollectionScan::isEOF() {
return _commonStats.isEOF;
}
-void CollectionScan::saveState(RequiresCollTag) {
+void CollectionScan::doSaveStateRequiresCollection() {
if (_cursor) {
_cursor->save();
}
}
-void CollectionScan::restoreState(RequiresCollTag) {
+void CollectionScan::doRestoreStateRequiresCollection() {
if (_cursor) {
const bool couldRestore = _cursor->restore();
uassert(ErrorCodes::CappedPositionLost,
diff --git a/src/mongo/db/exec/collection_scan.h b/src/mongo/db/exec/collection_scan.h
index 1c7138256e0..3752df9db13 100644
--- a/src/mongo/db/exec/collection_scan.h
+++ b/src/mongo/db/exec/collection_scan.h
@@ -79,9 +79,9 @@ public:
const SpecificStats* getSpecificStats() const final;
protected:
- void saveState(RequiresCollTag) final;
+ void doSaveStateRequiresCollection() final;
- void restoreState(RequiresCollTag) final;
+ void doRestoreStateRequiresCollection() final;
private:
/**
diff --git a/src/mongo/db/exec/delete.cpp b/src/mongo/db/exec/delete.cpp
index a279cdd27f7..49bbef02748 100644
--- a/src/mongo/db/exec/delete.cpp
+++ b/src/mongo/db/exec/delete.cpp
@@ -258,7 +258,7 @@ PlanStage::StageState DeleteStage::doWork(WorkingSetID* out) {
return PlanStage::NEED_TIME;
}
-void DeleteStage::restoreState(RequiresCollTag) {
+void DeleteStage::doRestoreStateRequiresCollection() {
const NamespaceString& ns = collection()->ns();
uassert(ErrorCodes::PrimarySteppedDown,
str::stream() << "Demoted from primary while removing from " << ns.ns(),
diff --git a/src/mongo/db/exec/delete.h b/src/mongo/db/exec/delete.h
index c3fd5ee5cba..4fe3590745d 100644
--- a/src/mongo/db/exec/delete.h
+++ b/src/mongo/db/exec/delete.h
@@ -116,9 +116,9 @@ public:
static long long getNumDeleted(const PlanExecutor& exec);
protected:
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final;
+ void doRestoreStateRequiresCollection() final;
private:
/**
diff --git a/src/mongo/db/exec/fetch.cpp b/src/mongo/db/exec/fetch.cpp
index 90654b11d92..1a41badc768 100644
--- a/src/mongo/db/exec/fetch.cpp
+++ b/src/mongo/db/exec/fetch.cpp
@@ -132,13 +132,13 @@ PlanStage::StageState FetchStage::doWork(WorkingSetID* out) {
return status;
}
-void FetchStage::saveState(RequiresCollTag) {
+void FetchStage::doSaveStateRequiresCollection() {
if (_cursor) {
_cursor->saveUnpositioned();
}
}
-void FetchStage::restoreState(RequiresCollTag) {
+void FetchStage::doRestoreStateRequiresCollection() {
if (_cursor) {
const bool couldRestore = _cursor->restore();
uassert(50982, "could not restore cursor for FETCH stage", couldRestore);
diff --git a/src/mongo/db/exec/fetch.h b/src/mongo/db/exec/fetch.h
index ea55f13892f..52b3a71d083 100644
--- a/src/mongo/db/exec/fetch.h
+++ b/src/mongo/db/exec/fetch.h
@@ -76,9 +76,9 @@ public:
static const char* kStageType;
protected:
- void saveState(RequiresCollTag) final;
+ void doSaveStateRequiresCollection() final;
- void restoreState(RequiresCollTag) final;
+ void doRestoreStateRequiresCollection() final;
private:
/**
diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp
index 2a6524151cf..5725fc9d9f9 100644
--- a/src/mongo/db/exec/geo_near.cpp
+++ b/src/mongo/db/exec/geo_near.cpp
@@ -316,7 +316,7 @@ void GeoNear2DStage::DensityEstimator::buildIndexScan(OperationContext* opCtx,
WorkingSet* workingSet) {
// Scan bounds on 2D indexes are only over the 2D field - other bounds aren't applicable.
// This is handled in query planning.
- IndexScanParams scanParams(opCtx, *_twoDIndex);
+ IndexScanParams scanParams(opCtx, _twoDIndex);
scanParams.bounds = _nearParams->baseBounds;
// The "2d" field is always the first in the index
@@ -684,7 +684,7 @@ StatusWith<NearStage::CoveredInterval*> //
// Scan bounds on 2D indexes are only over the 2D field - other bounds aren't applicable.
// This is handled in query planning.
- IndexScanParams scanParams(opCtx, *_twoDIndex);
+ IndexScanParams scanParams(opCtx, _twoDIndex);
// This does force us to do our own deduping of results.
scanParams.bounds = _nearParams.baseBounds;
@@ -874,7 +874,7 @@ private:
// Setup the index scan stage for neighbors at this level.
void GeoNear2DSphereStage::DensityEstimator::buildIndexScan(OperationContext* opCtx,
WorkingSet* workingSet) {
- IndexScanParams scanParams(opCtx, *_s2Index);
+ IndexScanParams scanParams(opCtx, _s2Index);
scanParams.bounds = _nearParams->baseBounds;
// Because the planner doesn't yet set up 2D index bounds, do it ourselves here
@@ -1044,7 +1044,7 @@ StatusWith<NearStage::CoveredInterval*> //
// Setup the covering region and stages for this interval
//
- IndexScanParams scanParams(opCtx, *_s2Index);
+ IndexScanParams scanParams(opCtx, _s2Index);
// This does force us to do our own deduping of results.
scanParams.bounds = _nearParams.baseBounds;
diff --git a/src/mongo/db/exec/index_scan.cpp b/src/mongo/db/exec/index_scan.cpp
index 7594b5af011..11bf51dabb4 100644
--- a/src/mongo/db/exec/index_scan.cpp
+++ b/src/mongo/db/exec/index_scan.cpp
@@ -65,38 +65,41 @@ IndexScan::IndexScan(OperationContext* opCtx,
IndexScanParams params,
WorkingSet* workingSet,
const MatchExpression* filter)
- : PlanStage(kStageType, opCtx),
+ : RequiresIndexStage(kStageType, opCtx, params.indexDescriptor),
_workingSet(workingSet),
- _iam(params.accessMethod),
_keyPattern(params.keyPattern.getOwned()),
- _scanState(INITIALIZING),
+ _bounds(std::move(params.bounds)),
_filter(filter),
+ _direction(params.direction),
_forward(params.direction == 1),
- _params(std::move(params)),
- _startKeyInclusive(IndexBounds::isStartIncludedInBound(_params.bounds.boundInclusion)),
- _endKeyInclusive(IndexBounds::isEndIncludedInBound(_params.bounds.boundInclusion)) {
- _specificStats.indexName = _params.name;
+ _shouldDedup(params.shouldDedup),
+ _addKeyMetadata(params.addKeyMetadata),
+ _startKeyInclusive(IndexBounds::isStartIncludedInBound(params.bounds.boundInclusion)),
+ _endKeyInclusive(IndexBounds::isEndIncludedInBound(params.bounds.boundInclusion)) {
+ _specificStats.indexName = params.name;
_specificStats.keyPattern = _keyPattern;
- _specificStats.isMultiKey = _params.isMultiKey;
- _specificStats.multiKeyPaths = _params.multikeyPaths;
- _specificStats.isUnique = _params.isUnique;
- _specificStats.isSparse = _params.isSparse;
- _specificStats.isPartial = _params.isPartial;
- _specificStats.indexVersion = static_cast<int>(_params.version);
- _specificStats.collation = _params.collation.getOwned();
+ _specificStats.isMultiKey = params.isMultiKey;
+ _specificStats.multiKeyPaths = params.multikeyPaths;
+ _specificStats.isUnique = params.indexDescriptor->unique();
+ _specificStats.isSparse = params.indexDescriptor->isSparse();
+ _specificStats.isPartial = params.indexDescriptor->isPartial();
+ _specificStats.indexVersion = static_cast<int>(params.indexDescriptor->version());
+ _specificStats.collation = params.indexDescriptor->infoObj()
+ .getObjectField(IndexDescriptor::kCollationFieldName)
+ .getOwned();
}
boost::optional<IndexKeyEntry> IndexScan::initIndexScan() {
// Perform the possibly heavy-duty initialization of the underlying index cursor.
- _indexCursor = _iam->newCursor(getOpCtx(), _forward);
+ _indexCursor = indexAccessMethod()->newCursor(getOpCtx(), _forward);
// We always seek once to establish the cursor position.
++_specificStats.seeks;
- if (_params.bounds.isSimpleRange) {
+ if (_bounds.isSimpleRange) {
// Start at one key, end at another.
- _startKey = _params.bounds.startKey;
- _endKey = _params.bounds.endKey;
+ _startKey = _bounds.startKey;
+ _endKey = _bounds.endKey;
_indexCursor->setEndPosition(_endKey, _endKeyInclusive);
return _indexCursor->seek(_startKey, _startKeyInclusive);
} else {
@@ -104,11 +107,11 @@ boost::optional<IndexKeyEntry> IndexScan::initIndexScan() {
// of an end cursor. For all other index scans, we fall back on using
// IndexBoundsChecker to determine when we've finished the scan.
if (IndexBoundsBuilder::isSingleInterval(
- _params.bounds, &_startKey, &_startKeyInclusive, &_endKey, &_endKeyInclusive)) {
+ _bounds, &_startKey, &_startKeyInclusive, &_endKey, &_endKeyInclusive)) {
_indexCursor->setEndPosition(_endKey, _endKeyInclusive);
return _indexCursor->seek(_startKey, _startKeyInclusive);
} else {
- _checker.reset(new IndexBoundsChecker(&_params.bounds, _keyPattern, _params.direction));
+ _checker.reset(new IndexBoundsChecker(&_bounds, _keyPattern, _direction));
if (!_checker->getStartSeekPoint(&_seekPoint))
return boost::none;
@@ -188,7 +191,7 @@ PlanStage::StageState IndexScan::doWork(WorkingSetID* out) {
_scanState = GETTING_NEXT;
- if (_params.shouldDedup) {
+ if (_shouldDedup) {
++_specificStats.dupsTested;
if (!_returned.insert(kv->loc).second) {
// We've seen this RecordId before. Skip it this time.
@@ -210,10 +213,10 @@ PlanStage::StageState IndexScan::doWork(WorkingSetID* out) {
WorkingSetID id = _workingSet->allocate();
WorkingSetMember* member = _workingSet->get(id);
member->recordId = kv->loc;
- member->keyData.push_back(IndexKeyDatum(_keyPattern, kv->key, _iam));
+ member->keyData.push_back(IndexKeyDatum(_keyPattern, kv->key, indexAccessMethod()));
_workingSet->transitionToRecordIdAndIdx(id);
- if (_params.addKeyMetadata) {
+ if (_addKeyMetadata) {
member->addComputed(
new IndexKeyComputedData(IndexKeyComputedData::rehydrateKey(_keyPattern, kv->key)));
}
@@ -226,7 +229,7 @@ bool IndexScan::isEOF() {
return _commonStats.isEOF;
}
-void IndexScan::doSaveState() {
+void IndexScan::doSaveStateRequiresIndex() {
if (!_indexCursor)
return;
@@ -238,7 +241,7 @@ void IndexScan::doSaveState() {
_indexCursor->save();
}
-void IndexScan::doRestoreState() {
+void IndexScan::doRestoreStateRequiresIndex() {
if (_indexCursor)
_indexCursor->restore();
}
@@ -268,9 +271,9 @@ std::unique_ptr<PlanStageStats> IndexScan::getStats() {
if (_specificStats.indexType.empty()) {
_specificStats.indexType = "BtreeCursor"; // TODO amName;
- _specificStats.indexBounds = _params.bounds.toBSON();
+ _specificStats.indexBounds = _bounds.toBSON();
- _specificStats.direction = _params.direction;
+ _specificStats.direction = _direction;
}
std::unique_ptr<PlanStageStats> ret =
diff --git a/src/mongo/db/exec/index_scan.h b/src/mongo/db/exec/index_scan.h
index 40f790e6034..3719ade1055 100644
--- a/src/mongo/db/exec/index_scan.h
+++ b/src/mongo/db/exec/index_scan.h
@@ -30,7 +30,7 @@
#pragma once
-#include "mongo/db/exec/plan_stage.h"
+#include "mongo/db/exec/requires_index_stage.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/matcher/expression.h"
@@ -45,49 +45,35 @@ namespace mongo {
class WorkingSet;
struct IndexScanParams {
- IndexScanParams(const IndexDescriptor& descriptor,
+ IndexScanParams(const IndexDescriptor* descriptor,
std::string indexName,
BSONObj keyPattern,
MultikeyPaths multikeyPaths,
bool multikey)
- : accessMethod(descriptor.getIndexCatalog()->getIndex(&descriptor)),
+ : indexDescriptor(descriptor),
name(std::move(indexName)),
keyPattern(std::move(keyPattern)),
multikeyPaths(std::move(multikeyPaths)),
- isMultiKey(multikey),
- isSparse(descriptor.isSparse()),
- isUnique(descriptor.unique()),
- isPartial(descriptor.isPartial()),
- version(descriptor.version()),
- collation(descriptor.infoObj()
- .getObjectField(IndexDescriptor::kCollationFieldName)
- .getOwned()) {
- invariant(accessMethod);
- }
+ isMultiKey(multikey) {}
- IndexScanParams(OperationContext* opCtx, const IndexDescriptor& descriptor)
+ IndexScanParams(OperationContext* opCtx, const IndexDescriptor* descriptor)
: IndexScanParams(descriptor,
- descriptor.indexName(),
- descriptor.keyPattern(),
- descriptor.getMultikeyPaths(opCtx),
- descriptor.isMultikey(opCtx)) {}
+ descriptor->indexName(),
+ descriptor->keyPattern(),
+ descriptor->getMultikeyPaths(opCtx),
+ descriptor->isMultikey(opCtx)) {}
+
+ const IndexDescriptor* indexDescriptor;
- const IndexAccessMethod* accessMethod;
std::string name;
BSONObj keyPattern;
- IndexBounds bounds;
MultikeyPaths multikeyPaths;
- bool isMultiKey;
-
- bool isSparse;
- bool isUnique;
- bool isPartial;
- IndexDescriptor::IndexVersion version;
+ bool isMultiKey;
- BSONObj collation;
+ IndexBounds bounds;
int direction{1};
@@ -103,7 +89,7 @@ struct IndexScanParams {
*
* Sub-stage preconditions: None. Is a leaf and consumes no stage data.
*/
-class IndexScan final : public PlanStage {
+class IndexScan final : public RequiresIndexStage {
public:
/**
* Keeps track of what this index scan is currently doing so that it
@@ -130,8 +116,6 @@ public:
StageState doWork(WorkingSetID* out) final;
bool isEOF() final;
- void doSaveState() final;
- void doRestoreState() final;
void doDetachFromOperationContext() final;
void doReattachToOperationContext() final;
@@ -145,6 +129,11 @@ public:
static const char* kStageType;
+protected:
+ void doSaveStateRequiresIndex() final;
+
+ void doRestoreStateRequiresIndex() final;
+
private:
/**
* Initialize the underlying index Cursor, returning first result if any.
@@ -154,28 +143,33 @@ private:
// The WorkingSet we fill with results. Not owned by us.
WorkingSet* const _workingSet;
- // Index access.
- const IndexAccessMethod* const _iam; // owned by Collection -> IndexCatalog
std::unique_ptr<SortedDataInterface::Cursor> _indexCursor;
const BSONObj _keyPattern;
- // Keeps track of what work we need to do next.
- ScanState _scanState;
+ const IndexBounds _bounds;
// Contains expressions only over fields in the index key. We assume this is built
// correctly by whomever creates this class.
// The filter is not owned by us.
const MatchExpression* const _filter;
- // Could our index have duplicates? If so, we use _returned to dedup.
- stdx::unordered_set<RecordId, RecordId::Hasher> _returned;
-
+ const int _direction;
const bool _forward;
- const IndexScanParams _params;
+
+ const bool _shouldDedup;
+
+ // Do we want to add the key as metadata?
+ const bool _addKeyMetadata;
// Stats
IndexScanStats _specificStats;
+ // Keeps track of what work we need to do next.
+ ScanState _scanState = ScanState::INITIALIZING;
+
+ // Could our index have duplicates? If so, we use _returned to dedup.
+ stdx::unordered_set<RecordId, RecordId::Hasher> _returned;
+
//
// This class employs one of two different algorithms for determining when the index scan
// has reached the end:
diff --git a/src/mongo/db/exec/multi_iterator.cpp b/src/mongo/db/exec/multi_iterator.cpp
index f3222d3fbc5..707e463204f 100644
--- a/src/mongo/db/exec/multi_iterator.cpp
+++ b/src/mongo/db/exec/multi_iterator.cpp
@@ -84,13 +84,13 @@ bool MultiIteratorStage::isEOF() {
return _iterators.empty();
}
-void MultiIteratorStage::saveState(RequiresCollTag) {
+void MultiIteratorStage::doSaveStateRequiresCollection() {
for (auto&& iterator : _iterators) {
iterator->save();
}
}
-void MultiIteratorStage::restoreState(RequiresCollTag) {
+void MultiIteratorStage::doRestoreStateRequiresCollection() {
for (auto&& iterator : _iterators) {
const bool couldRestore = iterator->restore();
uassert(50991, "could not restore cursor for MULTI_ITERATOR stage", couldRestore);
diff --git a/src/mongo/db/exec/multi_iterator.h b/src/mongo/db/exec/multi_iterator.h
index 5b9b9aeef6c..6e84c8253fb 100644
--- a/src/mongo/db/exec/multi_iterator.h
+++ b/src/mongo/db/exec/multi_iterator.h
@@ -75,9 +75,9 @@ public:
static const char* kStageType;
protected:
- void saveState(RequiresCollTag) final;
+ void doSaveStateRequiresCollection() final;
- void restoreState(RequiresCollTag) final;
+ void doRestoreStateRequiresCollection() final;
private:
OperationContext* _opCtx;
diff --git a/src/mongo/db/exec/multi_plan.h b/src/mongo/db/exec/multi_plan.h
index c24390c24c7..9693082b529 100644
--- a/src/mongo/db/exec/multi_plan.h
+++ b/src/mongo/db/exec/multi_plan.h
@@ -154,9 +154,9 @@ public:
static const char* kStageType;
protected:
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final {}
+ void doRestoreStateRequiresCollection() final {}
private:
//
diff --git a/src/mongo/db/exec/near.h b/src/mongo/db/exec/near.h
index 36ec727de74..9052e5d7d26 100644
--- a/src/mongo/db/exec/near.h
+++ b/src/mongo/db/exec/near.h
@@ -145,9 +145,9 @@ protected:
WorkingSet* workingSet,
WorkingSetID* out) = 0;
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final {}
+ void doRestoreStateRequiresCollection() final {}
// Filled in by subclasses.
NearStats _specificStats;
diff --git a/src/mongo/db/exec/record_store_fast_count.h b/src/mongo/db/exec/record_store_fast_count.h
index b3578ae5f30..ab601569cd4 100644
--- a/src/mongo/db/exec/record_store_fast_count.h
+++ b/src/mongo/db/exec/record_store_fast_count.h
@@ -64,9 +64,9 @@ public:
}
protected:
- void saveState(RequiresCollTag) override {}
+ void doSaveStateRequiresCollection() override {}
- void restoreState(RequiresCollTag) override {}
+ void doRestoreStateRequiresCollection() override {}
private:
long long _skip = 0;
diff --git a/src/mongo/db/exec/requires_collection_stage.cpp b/src/mongo/db/exec/requires_collection_stage.cpp
index 9424f542839..5825485dea6 100644
--- a/src/mongo/db/exec/requires_collection_stage.cpp
+++ b/src/mongo/db/exec/requires_collection_stage.cpp
@@ -37,10 +37,10 @@ namespace mongo {
template <typename CollectionT>
void RequiresCollectionStageBase<CollectionT>::doSaveState() {
+ doSaveStateRequiresCollection();
+
// A stage may not access storage while in a saved state.
_collection = nullptr;
-
- saveState(RequiresCollTag{});
}
template <typename CollectionT>
@@ -53,7 +53,7 @@ void RequiresCollectionStageBase<CollectionT>::doRestoreState() {
str::stream() << "UUID " << _collectionUUID << " no longer exists.",
_collection);
- restoreState(RequiresCollTag{});
+ doRestoreStateRequiresCollection();
}
template class RequiresCollectionStageBase<const Collection*>;
diff --git a/src/mongo/db/exec/requires_collection_stage.h b/src/mongo/db/exec/requires_collection_stage.h
index 273a7185ae4..9ebd96f84f0 100644
--- a/src/mongo/db/exec/requires_collection_stage.h
+++ b/src/mongo/db/exec/requires_collection_stage.h
@@ -41,7 +41,7 @@ namespace mongo {
* for checking that the collection is still valid (e.g. has not been dropped) when recovering from
* yield.
*
- * Subclasses must implement the saveStage() and restoreState() variants tagged with RequiresCollTag
+ * Subclasses must implement doSaveStateRequiresCollection() and doRestoreStateRequiresCollection()
* in order to supply custom yield preparation or yield recovery logic.
*
* Templated on 'CollectionT', which may be instantiated using either Collection* or const
@@ -63,8 +63,6 @@ public:
virtual ~RequiresCollectionStageBase() = default;
protected:
- struct RequiresCollTag {};
-
void doSaveState() final;
void doRestoreState() final;
@@ -72,12 +70,12 @@ protected:
/**
* Performs yield preparation specific to a stage which subclasses from RequiresCollectionStage.
*/
- virtual void saveState(RequiresCollTag) = 0;
+ virtual void doSaveStateRequiresCollection() = 0;
/**
* Performs yield recovery specific to a stage which subclasses from RequiresCollectionStage.
*/
- virtual void restoreState(RequiresCollTag) = 0;
+ virtual void doRestoreStateRequiresCollection() = 0;
CollectionT collection() const {
return _collection;
diff --git a/src/mongo/db/exec/requires_index_stage.cpp b/src/mongo/db/exec/requires_index_stage.cpp
new file mode 100644
index 00000000000..4c7150e1920
--- /dev/null
+++ b/src/mongo/db/exec/requires_index_stage.cpp
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2018-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/exec/requires_index_stage.h"
+
+namespace mongo {
+
+void RequiresIndexStage::doSaveStateRequiresCollection() {
+ doSaveStateRequiresIndex();
+
+ // During yield, we relinquish our shared ownership of the index catalog entry. This allows the
+ // index to be dropped during yield, but permits us to check via the weak_ptr interface
+ // whether the index is still valid on yield recovery.
+ //
+ // We also set catalog pointers to null, since accessing these pointers is illegal during yield.
+ _indexCatalogEntry.reset();
+ _indexDescriptor = nullptr;
+ _indexAccessMethod = nullptr;
+}
+
+void RequiresIndexStage::doRestoreStateRequiresCollection() {
+ // Reacquire shared ownership of the index catalog entry. If we're unable to do so, then the
+ // our index is no longer valid, and the query should die.
+ _indexCatalogEntry = _weakIndexCatalogEntry.lock();
+ uassert(ErrorCodes::QueryPlanKilled,
+ str::stream() << "query plan killed :: index named '" << _indexName
+ << "' is no longer valid",
+ _indexCatalogEntry);
+
+ _indexDescriptor = _indexCatalogEntry->descriptor();
+ _indexAccessMethod = _indexCatalogEntry->accessMethod();
+
+ doRestoreStateRequiresIndex();
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/exec/requires_index_stage.h b/src/mongo/db/exec/requires_index_stage.h
new file mode 100644
index 00000000000..320a43a6444
--- /dev/null
+++ b/src/mongo/db/exec/requires_index_stage.h
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2018-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/db/exec/requires_collection_stage.h"
+
+namespace mongo {
+
+/**
+ * A base class for plan stages which require access to a particular index within a particular
+ * collection. Provides subclasses access to the index's Collection*, as well as to catalog types
+ * representing the index itself such as the IndexDescriptor. This base class is responsible for
+ * checking that the collection and index are still valid (e.g. have not been dropped) when
+ * recovering from yield.
+ *
+ * Subclasses must implement doSaveStateRequiresIndex() and doRestoreStateRequiresIndex() in order
+ * to supply custom yield preparation and yield recovery logic.
+ */
+class RequiresIndexStage : public RequiresCollectionStage {
+public:
+ RequiresIndexStage(const char* stageType,
+ OperationContext* opCtx,
+ const IndexDescriptor* indexDescriptor)
+ : RequiresCollectionStage(stageType, opCtx, indexDescriptor->getCollection()),
+ _weakIndexCatalogEntry(collection()->getIndexCatalog()->getEntryShared(indexDescriptor)),
+ _indexCatalogEntry(_weakIndexCatalogEntry.lock()),
+ _indexDescriptor(indexDescriptor),
+ _indexAccessMethod(_indexCatalogEntry->accessMethod()),
+ _indexName(_indexDescriptor->indexName()) {
+ invariant(_indexCatalogEntry);
+ invariant(_indexDescriptor);
+ invariant(_indexAccessMethod);
+ }
+
+ virtual ~RequiresIndexStage() = default;
+
+protected:
+ /**
+ * Performs yield preparation specific to a stage which subclasses from RequiresIndexStage.
+ */
+ virtual void doSaveStateRequiresIndex() = 0;
+
+ /**
+ * Performs yield recovery specific to a stage which subclasses from RequiresIndexStage.
+ */
+ virtual void doRestoreStateRequiresIndex() = 0;
+
+ void doSaveStateRequiresCollection() override final;
+
+ void doRestoreStateRequiresCollection() override final;
+
+ const IndexDescriptor* indexDescriptor() const {
+ return _indexDescriptor;
+ }
+
+ const IndexAccessMethod* indexAccessMethod() const {
+ return _indexAccessMethod;
+ }
+
+private:
+ // This stage shares ownership of the index catalog entry when the query is running, and
+ // relinquishes its shared ownership when in a saved state for a yield or between getMores. We
+ // keep a weak_ptr to the entry in order to reacquire shared ownership on yield recovery,
+ // throwing a query-fatal exception if the weak_ptr indicates that the underlying catalog object
+ // has been destroyed.
+ //
+ // This is necessary to protect against that case that our index is dropped and then recreated
+ // during yield. Such an event should cause the query to be killed, since index cursors may have
+ // pointers into catalog objects that no longer exist. Since indices do not have UUIDs,
+ // different epochs of the index cannot be distinguished. The weak_ptr allows us to relinquish
+ // ownership of the index during yield, but also determine whether the pointed-to object has
+ // been destroyed during yield recovery.
+ std::weak_ptr<const IndexCatalogEntry> _weakIndexCatalogEntry;
+ std::shared_ptr<const IndexCatalogEntry> _indexCatalogEntry;
+
+ const IndexDescriptor* _indexDescriptor;
+ const IndexAccessMethod* _indexAccessMethod;
+
+ const std::string _indexName;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index df13e4a5985..ebcd2208952 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -302,7 +302,7 @@ public:
uassert(40223, str::stream() << "Can't find index: " << name.toString(), desc);
}
- IndexScanParams params(opCtx, *desc);
+ IndexScanParams params(opCtx, desc);
params.bounds.isSimpleRange = true;
params.bounds.startKey = stripFieldNames(nodeArgs["startKey"].Obj());
params.bounds.endKey = stripFieldNames(nodeArgs["endKey"].Obj());
diff --git a/src/mongo/db/exec/subplan.h b/src/mongo/db/exec/subplan.h
index 799cf15638d..3f589a2b8ef 100644
--- a/src/mongo/db/exec/subplan.h
+++ b/src/mongo/db/exec/subplan.h
@@ -128,9 +128,9 @@ public:
}
protected:
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final {}
+ void doRestoreStateRequiresCollection() final {}
private:
/**
diff --git a/src/mongo/db/exec/text.cpp b/src/mongo/db/exec/text.cpp
index 4cd25adad23..015b517b005 100644
--- a/src/mongo/db/exec/text.cpp
+++ b/src/mongo/db/exec/text.cpp
@@ -103,7 +103,7 @@ unique_ptr<PlanStage> TextStage::buildTextTree(OperationContext* opCtx,
// Get all the index scans for each term in our query.
std::vector<std::unique_ptr<PlanStage>> indexScanList;
for (const auto& term : _params.query.getTermsForBounds()) {
- IndexScanParams ixparams(opCtx, *_params.index);
+ IndexScanParams ixparams(opCtx, _params.index);
ixparams.bounds.startKey = FTSIndexFormat::getIndexKey(
MAX_WEIGHT, term, _params.indexPrefix, _params.spec.getTextIndexVersion());
ixparams.bounds.endKey = FTSIndexFormat::getIndexKey(
diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp
index 87b79fd5b8b..2a06aa37aa2 100644
--- a/src/mongo/db/exec/update.cpp
+++ b/src/mongo/db/exec/update.cpp
@@ -692,7 +692,7 @@ PlanStage::StageState UpdateStage::doWork(WorkingSetID* out) {
return status;
}
-void UpdateStage::restoreState(RequiresCollTag) {
+void UpdateStage::doRestoreStateRequiresCollection() {
const UpdateRequest& request = *_params.request;
const NamespaceString& nsString(request.getNamespaceString());
diff --git a/src/mongo/db/exec/update.h b/src/mongo/db/exec/update.h
index 21ee75e2612..dc228521fa6 100644
--- a/src/mongo/db/exec/update.h
+++ b/src/mongo/db/exec/update.h
@@ -145,9 +145,9 @@ public:
UpdateStats* stats);
protected:
- void saveState(RequiresCollTag) final {}
+ void doSaveStateRequiresCollection() final {}
- void restoreState(RequiresCollTag) final;
+ void doRestoreStateRequiresCollection() final;
private:
static const UpdateStats kEmptyUpdateStats;
diff --git a/src/mongo/db/query/internal_plans.cpp b/src/mongo/db/query/internal_plans.cpp
index dff69fc1298..6f4d976bd87 100644
--- a/src/mongo/db/query/internal_plans.cpp
+++ b/src/mongo/db/query/internal_plans.cpp
@@ -207,7 +207,7 @@ std::unique_ptr<PlanStage> InternalPlanner::_indexScan(OperationContext* opCtx,
invariant(collection);
invariant(descriptor);
- IndexScanParams params(opCtx, *descriptor);
+ IndexScanParams params(opCtx, descriptor);
params.direction = direction;
params.bounds.isSimpleRange = true;
params.bounds.startKey = startKey;
diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp
index ab5de811f62..0ea2780935e 100644
--- a/src/mongo/db/query/stage_builder.cpp
+++ b/src/mongo/db/query/stage_builder.cpp
@@ -98,7 +98,7 @@ PlanStage* buildStages(OperationContext* opCtx,
// We use the node's internal name, keyPattern and multikey details here. For $**
// indexes, these may differ from the information recorded in the index's descriptor.
- IndexScanParams params{*descriptor,
+ IndexScanParams params{descriptor,
ixn->index.identifier.catalogName,
ixn->index.keyPattern,
ixn->index.multikeyPaths,
diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp
index 7aaf6145e87..16eb156d2c0 100644
--- a/src/mongo/dbtests/query_plan_executor.cpp
+++ b/src/mongo/dbtests/query_plan_executor.cpp
@@ -143,7 +143,7 @@ public:
int end) {
// Build the index scan stage.
auto descriptor = getIndex(db, indexSpec);
- IndexScanParams ixparams(&_opCtx, *descriptor);
+ IndexScanParams ixparams(&_opCtx, descriptor);
ixparams.bounds.isSimpleRange = true;
ixparams.bounds.startKey = BSON("" << start);
ixparams.bounds.endKey = BSON("" << end);
diff --git a/src/mongo/dbtests/query_stage_and.cpp b/src/mongo/dbtests/query_stage_and.cpp
index 9ddb35f4a88..d1c160dfb10 100644
--- a/src/mongo/dbtests/query_stage_and.cpp
+++ b/src/mongo/dbtests/query_stage_and.cpp
@@ -85,7 +85,7 @@ public:
IndexScanParams makeIndexScanParams(OperationContext* opCtx,
const IndexDescriptor* descriptor) {
- IndexScanParams params(opCtx, *descriptor);
+ IndexScanParams params(opCtx, descriptor);
params.bounds.isSimpleRange = true;
params.bounds.endKey = BSONObj();
params.bounds.boundInclusion = BoundInclusion::kIncludeBothStartAndEndKeys;
diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp
index f20a4fc0142..6aa92d6b9d7 100644
--- a/src/mongo/dbtests/query_stage_count.cpp
+++ b/src/mongo/dbtests/query_stage_count.cpp
@@ -205,7 +205,7 @@ public:
IndexDescriptor* descriptor = indexes[0];
// We are not testing indexing here so use maximal bounds
- IndexScanParams params(&_opCtx, *descriptor);
+ IndexScanParams params(&_opCtx, descriptor);
params.bounds.isSimpleRange = true;
params.bounds.startKey = BSON("" << 0);
params.bounds.endKey = BSON("" << kDocuments + 1);
diff --git a/src/mongo/dbtests/query_stage_ixscan.cpp b/src/mongo/dbtests/query_stage_ixscan.cpp
index 1511bd221fa..c617aeb5946 100644
--- a/src/mongo/dbtests/query_stage_ixscan.cpp
+++ b/src/mongo/dbtests/query_stage_ixscan.cpp
@@ -103,7 +103,7 @@ public:
ASSERT_EQ(indexes.size(), 1U);
// We are not testing indexing here so use maximal bounds
- IndexScanParams params(&_opCtx, *indexes[0]);
+ IndexScanParams params(&_opCtx, indexes[0]);
params.bounds.isSimpleRange = true;
params.bounds.startKey = startKey;
params.bounds.endKey = endKey;
@@ -125,7 +125,7 @@ public:
catalog->findIndexesByKeyPattern(&_opCtx, BSON("x" << 1), false, &indexes);
ASSERT_EQ(indexes.size(), 1U);
- IndexScanParams params(&_opCtx, *indexes[0]);
+ IndexScanParams params(&_opCtx, indexes[0]);
params.direction = direction;
OrderedIntervalList oil("x");
@@ -197,10 +197,10 @@ public:
ASSERT_BSONOBJ_EQ(member->keyData[0].keyData, BSON("" << 6));
// Save state and insert a few indexed docs.
- ixscan->saveState();
+ static_cast<PlanStage*>(ixscan.get())->saveState();
insert(fromjson("{_id: 4, x: 10}"));
insert(fromjson("{_id: 5, x: 11}"));
- ixscan->restoreState();
+ static_cast<PlanStage*>(ixscan.get())->restoreState();
member = getNext(ixscan.get());
ASSERT_EQ(WorkingSetMember::RID_AND_IDX, member->getState());
@@ -231,9 +231,9 @@ public:
ASSERT_BSONOBJ_EQ(member->keyData[0].keyData, BSON("" << 6));
// Save state and insert an indexed doc.
- ixscan->saveState();
+ static_cast<PlanStage*>(ixscan.get())->saveState();
insert(fromjson("{_id: 4, x: 7}"));
- ixscan->restoreState();
+ static_cast<PlanStage*>(ixscan.get())->restoreState();
member = getNext(ixscan.get());
ASSERT_EQ(WorkingSetMember::RID_AND_IDX, member->getState());
@@ -264,9 +264,9 @@ public:
ASSERT_BSONOBJ_EQ(member->keyData[0].keyData, BSON("" << 6));
// Save state and insert an indexed doc.
- ixscan->saveState();
+ static_cast<PlanStage*>(ixscan.get())->saveState();
insert(fromjson("{_id: 4, x: 10}"));
- ixscan->restoreState();
+ static_cast<PlanStage*>(ixscan.get())->restoreState();
// Ensure that we're EOF and we don't erroneously return {'': 12}.
WorkingSetID id;
@@ -297,10 +297,10 @@ public:
ASSERT_BSONOBJ_EQ(member->keyData[0].keyData, BSON("" << 8));
// Save state and insert an indexed doc.
- ixscan->saveState();
+ static_cast<PlanStage*>(ixscan.get())->saveState();
insert(fromjson("{_id: 4, x: 6}"));
insert(fromjson("{_id: 5, x: 9}"));
- ixscan->restoreState();
+ static_cast<PlanStage*>(ixscan.get())->restoreState();
// Ensure that we don't erroneously return {'': 9} or {'':3}.
member = getNext(ixscan.get());
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index 49ba59c0ac4..8ae41114dca 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -80,7 +80,7 @@ public:
IndexScanParams makeIndexScanParams(OperationContext* opCtx,
const IndexDescriptor* descriptor) {
- IndexScanParams params(opCtx, *descriptor);
+ IndexScanParams params(opCtx, descriptor);
params.bounds.isSimpleRange = true;
params.bounds.startKey = objWithMinKey(1);
params.bounds.endKey = objWithMaxKey(1);
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index d4cdeb8048f..650036fc692 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -141,7 +141,7 @@ unique_ptr<PlanStage> getIxScanPlan(OperationContext* opCtx,
coll->getIndexCatalog()->findIndexesByKeyPattern(opCtx, BSON("foo" << 1), false, &indexes);
ASSERT_EQ(indexes.size(), 1U);
- IndexScanParams ixparams(opCtx, *indexes[0]);
+ IndexScanParams ixparams(opCtx, indexes[0]);
ixparams.bounds.isSimpleRange = true;
ixparams.bounds.startKey = BSON("" << desiredFooValue);
ixparams.bounds.endKey = BSON("" << desiredFooValue);
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index b08e34443f9..e06137c4e31 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -130,7 +130,7 @@ public:
IndexScanParams makeIndexScanParams(OperationContext* opCtx,
const IndexDescriptor* descriptor) {
- IndexScanParams params(opCtx, *descriptor);
+ IndexScanParams params(opCtx, descriptor);
params.bounds.isSimpleRange = true;
params.bounds.endKey = BSONObj();
params.bounds.boundInclusion = BoundInclusion::kIncludeBothStartAndEndKeys;