void BtreeCursor::skipAndCheck() { long long startNscanned = _nscanned; skipUnusedKeys(); while( 1 ) { if ( !skipOutOfRangeKeysAndCheckEnd() ) { break; } do { // If nscanned is increased by more than 20 before a matching key is found, abort // skipping through the btree to find a matching key. This iteration cutoff // prevents unbounded internal iteration within BtreeCursor::init() and // BtreeCursor::advance() (the callers of skipAndCheck()). See SERVER-3448. if ( _nscanned > startNscanned + 20 ) { skipUnusedKeys(); // If iteration is aborted before a key matching _bounds is identified, the // cursor may be left pointing at a key that is not within bounds // (_bounds->matchesKey( currKey() ) may be false). Set _boundsMustMatch to // false accordingly. _boundsMustMatch = false; return; } } while( skipOutOfRangeKeysAndCheckEnd() ); if ( !skipUnusedKeys() ) { break; } } }
// Check the current key with respect to our key bounds, whether // it be provided by independent field ranges or by start/end keys. bool IndexCursor::checkCurrentAgainstBounds() { if ( _bounds == NULL ) { checkEnd(); if ( ok() ) { ++_nscanned; } } else { // If nscanned is increased by more than 20 before a matching key is found, abort // skipping through the index to find a matching key. This iteration cutoff // prevents unbounded internal iteration within IndexCursor::initializeDBC and // IndexCursor::advance(). See SERVER-3448. const long long startNscanned = _nscanned; if ( skipOutOfRangeKeysAndCheckEnd() ) { do { if ( _nscanned > startNscanned + 20 ) { // If iteration is aborted before a key matching _bounds is identified, the // cursor may be left pointing at a key that is not within bounds // (_bounds->matchesKey( currKey() ) may be false). Set _boundsMustMatch to // false accordingly. _boundsMustMatch = false; break; } } while ( skipOutOfRangeKeysAndCheckEnd() ); } } return ok(); }
void BtreeCursor::skipAndCheck() { skipUnusedKeys( true ); while( 1 ) { if ( !skipOutOfRangeKeysAndCheckEnd() ) { break; } while( skipOutOfRangeKeysAndCheckEnd() ); if ( !skipUnusedKeys( true ) ) { break; } } }
void BtreeCursor::skipAndCheck() { long long startNscanned = _nscanned; skipUnusedKeys(); while( 1 ) { if ( !skipOutOfRangeKeysAndCheckEnd() ) { break; } do { if ( _nscanned > startNscanned + 20 ) { skipUnusedKeys(); return; } } while( skipOutOfRangeKeysAndCheckEnd() ); if ( !skipUnusedKeys() ) { break; } } }
/* skip unused keys. */ bool BtreeCursor::skipUnusedKeys( bool mayJump ) { int u = 0; while ( 1 ) { if ( !ok() ) break; BtreeBucket *b = bucket.btree(); _KeyNode& kn = b->k(keyOfs); if ( kn.isUsed() ) break; bucket = b->advance(bucket, keyOfs, direction, "skipUnusedKeys"); u++; if ( mayJump && ( u % 10 == 0 ) ) { skipOutOfRangeKeysAndCheckEnd(); } } if ( u > 10 ) OCCASIONALLY log() << "btree unused skipped:" << u << '\n'; return u; }
/* skip unused keys. */ bool BtreeCursor::skipUnusedKeys( bool mayJump ) { int u = 0; while ( 1 ) { if ( !ok() ) break; const _KeyNode& kn = keyNode(keyOfs); if ( kn.isUsed() ) break; bucket = _advance(bucket, keyOfs, _direction, "skipUnusedKeys"); u++; //don't include unused keys in nscanned //++_nscanned; if ( mayJump && ( u % 10 == 0 ) ) { skipOutOfRangeKeysAndCheckEnd(); } } if ( u > 10 ) OCCASIONALLY log() << "btree unused skipped:" << u << '\n'; return u; }