PlanStage::StageState Count::work(WorkingSetID* out) { if (NULL == _btreeCursor.get()) { // First call to work(). Perform cursor init. initIndexCursor(); checkEnd(); return PlanStage::NEED_TIME; } if (isEOF()) { return PlanStage::IS_EOF; } DiskLoc loc = _btreeCursor->getValue(); _btreeCursor->next(); checkEnd(); if (_shouldDedup) { if (_returned.end() != _returned.find(loc)) { return PlanStage::NEED_TIME; } else { _returned.insert(loc); } } *out = WorkingSet::INVALID_ID; return PlanStage::ADVANCED; }
PlanStage::StageState DistinctScan::work(WorkingSetID* out) { ++_commonStats.works; if (NULL == _btreeCursor.get()) { // First call to work(). Perform cursor init. initIndexCursor(); checkEnd(); } if (isEOF()) { return PlanStage::IS_EOF; } // Grab the next (key, value) from the index. BSONObj ownedKeyObj = _btreeCursor->getKey().getOwned(); DiskLoc loc = _btreeCursor->getValue(); // The underlying IndexCursor points at the *next* thing we want to return. We do this so // that if we're scanning an index looking for docs to delete we don't continually clobber // the thing we're pointing at. // We skip to the next value of the _params.fieldNo-th field in the index key pattern. // This is the field we're distinct-ing over. _btreeCursor->skip(_btreeCursor->getKey(), _params.fieldNo + 1, true, _keyElts, _keyEltsInc); // And make sure we're within the bounds. checkEnd(); // Package up the result for the caller. WorkingSetID id = _workingSet->allocate(); WorkingSetMember* member = _workingSet->get(id); member->loc = loc; member->keyData.push_back(IndexKeyDatum(_descriptor->keyPattern(), ownedKeyObj)); member->state = WorkingSetMember::LOC_AND_IDX; *out = id; ++_commonStats.advanced; return PlanStage::ADVANCED; }
PlanStage::StageState Count::work(WorkingSetID* out) { ++_commonStats.works; // Adds the amount of time taken by work() to executionTimeMillis. ScopedTimer timer(&_commonStats.executionTimeMillis); if (NULL == _btreeCursor.get()) { // First call to work(). Perform cursor init. initIndexCursor(); checkEnd(); ++_commonStats.needTime; return PlanStage::NEED_TIME; } if (isEOF()) { return PlanStage::IS_EOF; } DiskLoc loc = _btreeCursor->getValue(); _btreeCursor->next(); checkEnd(); ++_specificStats.keysExamined; if (_shouldDedup) { if (_returned.end() != _returned.find(loc)) { ++_commonStats.needTime; return PlanStage::NEED_TIME; } else { _returned.insert(loc); } } *out = WorkingSet::INVALID_ID; ++_commonStats.advanced; return PlanStage::ADVANCED; }
PlanStage::StageState IndexScan::work(WorkingSetID* out) { ++_commonStats.works; if (NULL == _indexCursor.get()) { // First call to work(). Perform cursor init. initIndexCursor(); checkEnd(); } else if (_yieldMovedCursor) { _yieldMovedCursor = false; // Note that we're not calling next() here. We got the next thing when we recovered // from yielding. } if (isEOF()) { return PlanStage::IS_EOF; } // Grab the next (key, value) from the index. BSONObj keyObj = _indexCursor->getKey(); DiskLoc loc = _indexCursor->getValue(); // Move to the next result. // The underlying IndexCursor points at the *next* thing we want to return. We do this so // that if we're scanning an index looking for docs to delete we don't continually clobber // the thing we're pointing at. _indexCursor->next(); checkEnd(); if (_shouldDedup) { ++_specificStats.dupsTested; if (_returned.end() != _returned.find(loc)) { ++_specificStats.dupsDropped; ++_commonStats.needTime; return PlanStage::NEED_TIME; } else { _returned.insert(loc); } } if (Filter::passes(keyObj, _keyPattern, _filter)) { if (NULL != _filter) { ++_specificStats.matchTested; } // We must make a copy of the on-disk data since it can mutate during the execution of // this query. BSONObj ownedKeyObj = keyObj.getOwned(); // Fill out the WSM. WorkingSetID id = _workingSet->allocate(); WorkingSetMember* member = _workingSet->get(id); member->loc = loc; member->keyData.push_back(IndexKeyDatum(_keyPattern, ownedKeyObj)); member->state = WorkingSetMember::LOC_AND_IDX; if (_params.addKeyMetadata) { BSONObjBuilder bob; bob.appendKeys(_keyPattern, ownedKeyObj); member->addComputed(new IndexKeyComputedData(bob.obj())); } *out = id; ++_commonStats.advanced; return PlanStage::ADVANCED; } ++_commonStats.needTime; return PlanStage::NEED_TIME; }