Ejemplo n.º 1
0
    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;
    }
Ejemplo n.º 2
0
    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;
    }
Ejemplo n.º 3
0
    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;
    }
Ejemplo n.º 4
0
    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;
    }