Пример #1
0
 IndexCursor::IndexCursor( Collection *cl, const IndexDetails &idx,
                           const BSONObj &startKey, const BSONObj &endKey,
                           bool endKeyInclusive, int direction, int numWanted ) :
     _cl(cl),
     _idx(idx),
     _ordering(Ordering::make(_idx.keyPattern())),
     _startKey(startKey),
     _endKey(endKey),
     _endKeyInclusive(endKeyInclusive),
     _multiKey(_cl->isMultikey(_cl->idxNo(_idx))),
     _direction(direction),
     _bounds(),
     _boundsMustMatch(true),
     _nscanned(0),
     _nscannedObjects(0),
     _prelock(!cc().opSettings().getJustOne() && numWanted == 0),
     _cursor(_idx, cursor_flags()),
     _tailable(false),
     _ok(false),
     _getf_iteration(0)
 {
     verify( _cl != NULL );
     TOKULOG(3) << toString() << ": constructor: bounds " << prettyIndexBounds() << endl;
     DBC* cursor = _cursor.dbc();
     cursor->c_set_check_interrupt_callback(cursor, cursor_check_interrupt, &_interrupt_extra);
     initializeDBC();
 }
Пример #2
0
    IndexCursor::IndexCursor( Collection *cl, const IndexDetails &idx,
                              const shared_ptr< FieldRangeVector > &bounds,
                              int singleIntervalLimit, int direction, int numWanted ) :
        _cl(cl),
        _idx(idx),
        _ordering(Ordering::make(_idx.keyPattern())),
        _startKey(),
        _endKey(),
        _endKeyInclusive(true),
        _multiKey(_cl->isMultikey(_cl->idxNo(_idx))),
        _direction(direction),
        _bounds(bounds),
        _boundsMustMatch(true),
        _nscanned(0),
        _nscannedObjects(0),
        _prelock(!cc().opSettings().getJustOne() && numWanted == 0),
        _cursor(_idx, cursor_flags()),
        _tailable(false),
        _ok(false),
        _getf_iteration(0)
    {
        verify( _cl != NULL );
        _boundsIterator.reset( new FieldRangeVectorIterator( *_bounds , singleIntervalLimit ) );
        _boundsIterator->prepDive();
        _startKey = _bounds->startKey();
        _endKey = _bounds->endKey();
        _endKeyInclusive = _bounds->endKeyInclusive();
        TOKULOG(3) << toString() << ": constructor: bounds " << prettyIndexBounds() << endl;
        DBC* cursor = _cursor.dbc();
        cursor->c_set_check_interrupt_callback(cursor, cursor_check_interrupt, &_interrupt_extra);
        initializeDBC();

        // Fairly bad hack:
        //
        // Primary keys are not skipped properly when a non-inclusive start bound is specified.
        // See IndexCursor::skipToNextKey()
        //
        // Do a single advance here - the PK is unique so the next key is guaranteed to be
        // strictly greater than the start key. We have to play games with _nscanned because
        // advance()'s checkCurrentAgainstBounds() is going to increment it by 1 (we don't want that).
        if (ok() && _cl->isPKIndex(_idx) && !_bounds->startKeyInclusive() && _currKey == _startKey) {
            const long long oldNScanned = _nscanned;
            advance();
            verify(oldNScanned <= _nscanned);
            _nscanned = oldNScanned;
        }
        DEV {
            // At this point, the current key should be consistent with
            // _startKey and _bounds->startKeyInclusive()
            if (ok() && !_bounds->startKeyInclusive()) {
                if (forward()) {
                    verify(_currKey.woCompare(_startKey, _ordering) > 0);
                } else {
                    verify(_currKey.woCompare(_startKey, _ordering) < 0);
                }
            }
        }
    }