summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/geo_near.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/geo_near.cpp')
-rw-r--r--src/mongo/db/exec/geo_near.cpp177
1 files changed, 48 insertions, 129 deletions
diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp
index 7eaeeac9f9a..db54e778da7 100644
--- a/src/mongo/db/exec/geo_near.cpp
+++ b/src/mongo/db/exec/geo_near.cpp
@@ -259,8 +259,10 @@ static R2Annulus twoDDistanceBounds(const GeoNearParams& nearParams,
class GeoNear2DStage::DensityEstimator {
public:
- DensityEstimator(const IndexDescriptor* twoDindex, const GeoNearParams* nearParams)
- : _twoDIndex(twoDindex), _nearParams(nearParams), _currentLevel(0) {
+ DensityEstimator(PlanStage::Children* children,
+ const IndexDescriptor* twoDindex,
+ const GeoNearParams* nearParams)
+ : _children(children), _twoDIndex(twoDindex), _nearParams(nearParams), _currentLevel(0) {
GeoHashConverter::Parameters hashParams;
Status status = GeoHashConverter::parseParameters(_twoDIndex->infoObj(), &hashParams);
// The index status should always be valid.
@@ -281,16 +283,13 @@ public:
WorkingSetID* out,
double* estimatedDistance);
- void saveState();
- void restoreState(OperationContext* txn);
- void invalidate(OperationContext* txn, const RecordId& dl, InvalidationType type);
-
private:
void buildIndexScan(OperationContext* txn, WorkingSet* workingSet, Collection* collection);
+ PlanStage::Children* _children; // Points to PlanStage::_children in the NearStage.
const IndexDescriptor* _twoDIndex; // Not owned here.
const GeoNearParams* _nearParams; // Not owned here.
- unique_ptr<IndexScan> _indexScan;
+ IndexScan* _indexScan = nullptr; // Owned in PlanStage::_children.
unique_ptr<GeoHashConverter> _converter;
GeoHash _centroidCell;
unsigned _currentLevel;
@@ -335,7 +334,9 @@ void GeoNear2DStage::DensityEstimator::buildIndexScan(OperationContext* txn,
// in the scan (i.e. $within)
IndexBoundsBuilder::intersectize(oil, &scanParams.bounds.fields[twoDFieldPosition]);
- _indexScan.reset(new IndexScan(txn, scanParams, workingSet, NULL));
+ invariant(!_indexScan);
+ _indexScan = new IndexScan(txn, scanParams, workingSet, NULL);
+ _children->emplace_back(_indexScan);
}
// Return IS_EOF is we find a document in it's ancestor cells and set estimated distance
@@ -359,7 +360,9 @@ PlanStage::StageState GeoNear2DStage::DensityEstimator::work(OperationContext* t
// Advance to the next level and search again.
_currentLevel--;
// Reset index scan for the next level.
- _indexScan.reset(NULL);
+ invariant(_children->back().get() == _indexScan);
+ _indexScan = nullptr;
+ _children->pop_back();
return PlanStage::NEED_TIME;
}
@@ -380,33 +383,12 @@ PlanStage::StageState GeoNear2DStage::DensityEstimator::work(OperationContext* t
return state;
}
-void GeoNear2DStage::DensityEstimator::saveState() {
- if (_indexScan) {
- _indexScan->saveState();
- }
-}
-
-void GeoNear2DStage::DensityEstimator::restoreState(OperationContext* txn) {
- if (_indexScan) {
- _indexScan->restoreState(txn);
- }
-}
-
-void GeoNear2DStage::DensityEstimator::invalidate(OperationContext* txn,
- const RecordId& dl,
- InvalidationType type) {
- if (_indexScan) {
- _indexScan->invalidate(txn, dl, type);
- }
-}
-
-
PlanStage::StageState GeoNear2DStage::initialize(OperationContext* txn,
WorkingSet* workingSet,
Collection* collection,
WorkingSetID* out) {
if (!_densityEstimator) {
- _densityEstimator.reset(new DensityEstimator(_twoDIndex, &_nearParams));
+ _densityEstimator.reset(new DensityEstimator(&_children, _twoDIndex, &_nearParams));
}
double estimatedDistance;
@@ -451,40 +433,16 @@ GeoNear2DStage::GeoNear2DStage(const GeoNearParams& nearParams,
WorkingSet* workingSet,
Collection* collection,
IndexDescriptor* twoDIndex)
- : NearStage(txn,
- workingSet,
- collection,
- new PlanStageStats(CommonStats(kTwoDIndexNearStage.c_str()), STAGE_GEO_NEAR_2D)),
+ : NearStage(txn, kTwoDIndexNearStage.c_str(), STAGE_GEO_NEAR_2D, workingSet, collection),
_nearParams(nearParams),
_twoDIndex(twoDIndex),
_fullBounds(twoDDistanceBounds(nearParams, twoDIndex)),
_currBounds(_fullBounds.center(), -1, _fullBounds.getInner()),
_boundsIncrement(0.0) {
- getNearStats()->keyPattern = twoDIndex->keyPattern();
- getNearStats()->indexName = twoDIndex->indexName();
+ _specificStats.keyPattern = twoDIndex->keyPattern();
+ _specificStats.indexName = twoDIndex->indexName();
}
-GeoNear2DStage::~GeoNear2DStage() {}
-
-void GeoNear2DStage::finishSaveState() {
- if (_densityEstimator) {
- _densityEstimator->saveState();
- }
-}
-
-void GeoNear2DStage::finishRestoreState(OperationContext* txn) {
- if (_densityEstimator) {
- _densityEstimator->restoreState(txn);
- }
-}
-
-void GeoNear2DStage::finishInvalidate(OperationContext* txn,
- const RecordId& dl,
- InvalidationType type) {
- if (_densityEstimator) {
- _densityEstimator->invalidate(txn, dl, type);
- }
-}
namespace {
@@ -665,10 +623,8 @@ StatusWith<NearStage::CoveredInterval*> //
// Setup the next interval
//
- const NearStats* stats = getNearStats();
-
- if (!stats->intervalStats.empty()) {
- const IntervalStats& lastIntervalStats = stats->intervalStats.back();
+ if (!_specificStats.intervalStats.empty()) {
+ const IntervalStats& lastIntervalStats = _specificStats.intervalStats.back();
// TODO: Generally we want small numbers of results fast, then larger numbers later
if (lastIntervalStats.numResultsBuffered < 300)
@@ -805,10 +761,13 @@ StatusWith<NearStage::CoveredInterval*> //
}
// FetchStage owns index scan
- FetchStage* fetcher(new FetchStageWithMatch(txn, workingSet, scan, docMatcher, collection));
+ _children.emplace_back(new FetchStageWithMatch(txn, workingSet, scan, docMatcher, collection));
- return StatusWith<CoveredInterval*>(new CoveredInterval(
- fetcher, true, nextBounds.getInner(), nextBounds.getOuter(), isLastInterval));
+ return StatusWith<CoveredInterval*>(new CoveredInterval(_children.back().get(),
+ true,
+ nextBounds.getInner(),
+ nextBounds.getOuter(),
+ isLastInterval));
}
StatusWith<double> GeoNear2DStage::computeDistance(WorkingSetMember* member) {
@@ -843,18 +802,14 @@ GeoNear2DSphereStage::GeoNear2DSphereStage(const GeoNearParams& nearParams,
WorkingSet* workingSet,
Collection* collection,
IndexDescriptor* s2Index)
- : NearStage(
- txn,
- workingSet,
- collection,
- new PlanStageStats(CommonStats(kS2IndexNearStage.c_str()), STAGE_GEO_NEAR_2DSPHERE)),
+ : NearStage(txn, kS2IndexNearStage.c_str(), STAGE_GEO_NEAR_2DSPHERE, workingSet, collection),
_nearParams(nearParams),
_s2Index(s2Index),
_fullBounds(geoNearDistanceBounds(*nearParams.nearQuery)),
_currBounds(_fullBounds.center(), -1, _fullBounds.getInner()),
_boundsIncrement(0.0) {
- getNearStats()->keyPattern = s2Index->keyPattern();
- getNearStats()->indexName = s2Index->indexName();
+ _specificStats.keyPattern = s2Index->keyPattern();
+ _specificStats.indexName = s2Index->indexName();
}
GeoNear2DSphereStage::~GeoNear2DSphereStage() {}
@@ -940,8 +895,10 @@ private:
// Estimate the density of data by search the nearest cells level by level around center.
class GeoNear2DSphereStage::DensityEstimator {
public:
- DensityEstimator(const IndexDescriptor* s2Index, const GeoNearParams* nearParams)
- : _s2Index(s2Index), _nearParams(nearParams), _currentLevel(0) {
+ DensityEstimator(PlanStage::Children* children,
+ const IndexDescriptor* s2Index,
+ const GeoNearParams* nearParams)
+ : _children(children), _s2Index(s2Index), _nearParams(nearParams), _currentLevel(0) {
S2IndexingParams params;
ExpressionParams::parse2dsphereParams(_s2Index->infoObj(), &params);
// Since cellId.AppendVertexNeighbors(level, output) requires level < cellId.level(),
@@ -959,17 +916,14 @@ public:
WorkingSetID* out,
double* estimatedDistance);
- void saveState();
- void restoreState(OperationContext* txn);
- void invalidate(OperationContext* txn, const RecordId& dl, InvalidationType type);
-
private:
void buildIndexScan(OperationContext* txn, WorkingSet* workingSet, Collection* collection);
+ PlanStage::Children* _children; // Points to PlanStage::_children in the NearStage.
const IndexDescriptor* _s2Index; // Not owned here.
const GeoNearParams* _nearParams; // Not owned here.
int _currentLevel;
- unique_ptr<IndexScan> _indexScan;
+ IndexScan* _indexScan = nullptr; // Owned in PlanStage::_children.
};
// Setup the index scan stage for neighbors at this level.
@@ -1016,7 +970,9 @@ void GeoNear2DSphereStage::DensityEstimator::buildIndexScan(OperationContext* tx
invariant(coveredIntervals->isValidFor(1));
// Index scan
- _indexScan.reset(new IndexScan(txn, scanParams, workingSet, NULL));
+ invariant(!_indexScan);
+ _indexScan = new IndexScan(txn, scanParams, workingSet, NULL);
+ _children->emplace_back(_indexScan);
}
PlanStage::StageState GeoNear2DSphereStage::DensityEstimator::work(OperationContext* txn,
@@ -1038,7 +994,9 @@ PlanStage::StageState GeoNear2DSphereStage::DensityEstimator::work(OperationCont
// Advance to the next level and search again.
_currentLevel--;
// Reset index scan for the next level.
- _indexScan.reset(NULL);
+ invariant(_children->back().get() == _indexScan);
+ _indexScan = nullptr;
+ _children->pop_back();
return PlanStage::NEED_TIME;
}
@@ -1059,33 +1017,13 @@ PlanStage::StageState GeoNear2DSphereStage::DensityEstimator::work(OperationCont
return state;
}
-void GeoNear2DSphereStage::DensityEstimator::saveState() {
- if (_indexScan) {
- _indexScan->saveState();
- }
-}
-
-void GeoNear2DSphereStage::DensityEstimator::restoreState(OperationContext* txn) {
- if (_indexScan) {
- _indexScan->restoreState(txn);
- }
-}
-
-void GeoNear2DSphereStage::DensityEstimator::invalidate(OperationContext* txn,
- const RecordId& dl,
- InvalidationType type) {
- if (_indexScan) {
- _indexScan->invalidate(txn, dl, type);
- }
-}
-
PlanStage::StageState GeoNear2DSphereStage::initialize(OperationContext* txn,
WorkingSet* workingSet,
Collection* collection,
WorkingSetID* out) {
if (!_densityEstimator) {
- _densityEstimator.reset(new DensityEstimator(_s2Index, &_nearParams));
+ _densityEstimator.reset(new DensityEstimator(&_children, _s2Index, &_nearParams));
}
double estimatedDistance;
@@ -1110,26 +1048,6 @@ PlanStage::StageState GeoNear2DSphereStage::initialize(OperationContext* txn,
return state;
}
-void GeoNear2DSphereStage::finishSaveState() {
- if (_densityEstimator) {
- _densityEstimator->saveState();
- }
-}
-
-void GeoNear2DSphereStage::finishRestoreState(OperationContext* txn) {
- if (_densityEstimator) {
- _densityEstimator->restoreState(txn);
- }
-}
-
-void GeoNear2DSphereStage::finishInvalidate(OperationContext* txn,
- const RecordId& dl,
- InvalidationType type) {
- if (_densityEstimator) {
- _densityEstimator->invalidate(txn, dl, type);
- }
-}
-
StatusWith<NearStage::CoveredInterval*> //
GeoNear2DSphereStage::nextInterval(OperationContext* txn,
WorkingSet* workingSet,
@@ -1143,10 +1061,8 @@ StatusWith<NearStage::CoveredInterval*> //
// Setup the next interval
//
- const NearStats* stats = getNearStats();
-
- if (!stats->intervalStats.empty()) {
- const IntervalStats& lastIntervalStats = stats->intervalStats.back();
+ if (!_specificStats.intervalStats.empty()) {
+ const IntervalStats& lastIntervalStats = _specificStats.intervalStats.back();
// TODO: Generally we want small numbers of results fast, then larger numbers later
if (lastIntervalStats.numResultsBuffered < 300)
@@ -1196,10 +1112,13 @@ StatusWith<NearStage::CoveredInterval*> //
IndexScan* scan = new IndexScanWithMatch(txn, scanParams, workingSet, keyMatcher);
// FetchStage owns index scan
- FetchStage* fetcher(new FetchStage(txn, workingSet, scan, _nearParams.filter, collection));
+ _children.emplace_back(new FetchStage(txn, workingSet, scan, _nearParams.filter, collection));
- return StatusWith<CoveredInterval*>(new CoveredInterval(
- fetcher, true, nextBounds.getInner(), nextBounds.getOuter(), isLastInterval));
+ return StatusWith<CoveredInterval*>(new CoveredInterval(_children.back().get(),
+ true,
+ nextBounds.getInner(),
+ nextBounds.getOuter(),
+ isLastInterval));
}
StatusWith<double> GeoNear2DSphereStage::computeDistance(WorkingSetMember* member) {