diff options
author | Antonin Kral <a.kral@bobek.cz> | 2011-03-17 00:05:43 +0100 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2011-03-17 00:05:43 +0100 |
commit | 582fc32574a3b158c81e49cb00e6ae59205e66ba (patch) | |
tree | ac64a3243e0d2121709f685695247052858115c8 /db/btreecursor.cpp | |
parent | 2761bffa96595ac1698d86bbc2e95ebb0d4d6e93 (diff) | |
download | mongodb-582fc32574a3b158c81e49cb00e6ae59205e66ba.tar.gz |
Imported Upstream version 1.8.0
Diffstat (limited to 'db/btreecursor.cpp')
-rw-r--r-- | db/btreecursor.cpp | 145 |
1 files changed, 79 insertions, 66 deletions
diff --git a/db/btreecursor.cpp b/db/btreecursor.cpp index d6d0c09..9cab95f 100644 --- a/db/btreecursor.cpp +++ b/db/btreecursor.cpp @@ -20,54 +20,56 @@ #include "btree.h" #include "pdfile.h" #include "jsobj.h" -#include "curop.h" +#include "curop-inl.h" namespace mongo { extern int otherTraceLevel; - BtreeCursor::BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails &_id, + BtreeCursor::BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails &_id, const BSONObj &_startKey, const BSONObj &_endKey, bool endKeyInclusive, int _direction ) : - d(_d), idxNo(_idxNo), - startKey( _startKey ), - endKey( _endKey ), - endKeyInclusive_( endKeyInclusive ), - multikey( d->isMultikey( idxNo ) ), - indexDetails( _id ), - order( _id.keyPattern() ), - _ordering( Ordering::make( order ) ), - direction( _direction ), - _spec( _id.getSpec() ), - _independentFieldRanges( false ) - { + d(_d), idxNo(_idxNo), + startKey( _startKey ), + endKey( _endKey ), + _endKeyInclusive( endKeyInclusive ), + _multikey( d->isMultikey( idxNo ) ), + indexDetails( _id ), + _order( _id.keyPattern() ), + _ordering( Ordering::make( _order ) ), + _direction( _direction ), + _spec( _id.getSpec() ), + _independentFieldRanges( false ), + _nscanned( 0 ) { audit(); init(); - DEV assert( dups.size() == 0 ); + dassert( _dups.size() == 0 ); } BtreeCursor::BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails& _id, const shared_ptr< FieldRangeVector > &_bounds, int _direction ) : - d(_d), idxNo(_idxNo), - endKeyInclusive_( true ), - multikey( d->isMultikey( idxNo ) ), - indexDetails( _id ), - order( _id.keyPattern() ), - _ordering( Ordering::make( order ) ), - direction( _direction ), - bounds_( ( assert( _bounds.get() ), _bounds ) ), - _boundsIterator( new FieldRangeVector::Iterator( *bounds_ ) ), - _spec( _id.getSpec() ), - _independentFieldRanges( true ) - { + d(_d), idxNo(_idxNo), + _endKeyInclusive( true ), + _multikey( d->isMultikey( idxNo ) ), + indexDetails( _id ), + _order( _id.keyPattern() ), + _ordering( Ordering::make( _order ) ), + _direction( _direction ), + _bounds( ( assert( _bounds.get() ), _bounds ) ), + _boundsIterator( new FieldRangeVector::Iterator( *_bounds ) ), + _spec( _id.getSpec() ), + _independentFieldRanges( true ), + _nscanned( 0 ) { massert( 13384, "BtreeCursor FieldRangeVector constructor doesn't accept special indexes", !_spec.getType() ); audit(); - startKey = bounds_->startKey(); - bool found; + startKey = _bounds->startKey(); _boundsIterator->advance( startKey ); // handles initialization - bucket = indexDetails.head.btree()-> - locate(indexDetails, indexDetails.head, startKey, _ordering, keyOfs, found, direction > 0 ? minDiskLoc : maxDiskLoc, direction); + _boundsIterator->prepDive(); + pair< DiskLoc, int > noBestParent; + bucket = indexDetails.head; + keyOfs = 0; + indexDetails.head.btree()->customLocate( bucket, keyOfs, startKey, 0, false, _boundsIterator->cmp(), _boundsIterator->inc(), _ordering, _direction, noBestParent ); skipAndCheck(); - DEV assert( dups.size() == 0 ); + dassert( _dups.size() == 0 ); } void BtreeCursor::audit() { @@ -76,7 +78,7 @@ namespace mongo { if ( otherTraceLevel >= 12 ) { if ( otherTraceLevel >= 200 ) { out() << "::BtreeCursor() qtl>200. validating entire index." << endl; - indexDetails.head.btree()->fullValidate(indexDetails.head, order); + indexDetails.head.btree()->fullValidate(indexDetails.head, _order); } else { out() << "BTreeCursor(). dumping head bucket" << endl; @@ -86,17 +88,20 @@ namespace mongo { } void BtreeCursor::init() { - if ( _spec.getType() ){ + if ( _spec.getType() ) { startKey = _spec.getType()->fixKey( startKey ); endKey = _spec.getType()->fixKey( endKey ); } bool found; bucket = indexDetails.head.btree()-> - locate(indexDetails, indexDetails.head, startKey, _ordering, keyOfs, found, direction > 0 ? minDiskLoc : maxDiskLoc, direction); + locate(indexDetails, indexDetails.head, startKey, _ordering, keyOfs, found, _direction > 0 ? minDiskLoc : maxDiskLoc, _direction); + if ( ok() ) { + _nscanned = 1; + } skipUnusedKeys( false ); checkEnd(); } - + void BtreeCursor::skipAndCheck() { skipUnusedKeys( true ); while( 1 ) { @@ -109,7 +114,7 @@ namespace mongo { } } } - + bool BtreeCursor::skipOutOfRangeKeysAndCheckEnd() { if ( !ok() ) { return false; @@ -118,25 +123,30 @@ namespace mongo { if ( ret == -2 ) { bucket = DiskLoc(); return false; - } else if ( ret == -1 ) { + } + else if ( ret == -1 ) { + ++_nscanned; return false; } - advanceTo( currKeyNode().key, ret, _boundsIterator->cmp() ); + ++_nscanned; + advanceTo( currKeyNode().key, ret, _boundsIterator->after(), _boundsIterator->cmp(), _boundsIterator->inc() ); return true; } - + /* 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); + const BtreeBucket *b = bucket.btree(); + const _KeyNode& kn = b->k(keyOfs); if ( kn.isUsed() ) break; - bucket = b->advance(bucket, keyOfs, direction, "skipUnusedKeys"); + bucket = b->advance(bucket, keyOfs, _direction, "skipUnusedKeys"); u++; + //don't include unused keys in nscanned + //++_nscanned; if ( mayJump && ( u % 10 == 0 ) ) { skipOutOfRangeKeysAndCheckEnd(); } @@ -158,31 +168,34 @@ namespace mongo { if ( bucket.isNull() ) return; if ( !endKey.isEmpty() ) { - int cmp = sgn( endKey.woCompare( currKey(), order ) ); - if ( ( cmp != 0 && cmp != direction ) || - ( cmp == 0 && !endKeyInclusive_ ) ) + int cmp = sgn( endKey.woCompare( currKey(), _order ) ); + if ( ( cmp != 0 && cmp != _direction ) || + ( cmp == 0 && !_endKeyInclusive ) ) bucket = DiskLoc(); } } - - void BtreeCursor::advanceTo( const BSONObj &keyBegin, int keyBeginLen, const vector< const BSONElement * > &keyEnd) { - bucket.btree()->advanceTo( indexDetails, bucket, keyOfs, keyBegin, keyBeginLen, keyEnd, _ordering, direction ); + + void BtreeCursor::advanceTo( const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive) { + bucket.btree()->advanceTo( bucket, keyOfs, keyBegin, keyBeginLen, afterKey, keyEnd, keyEndInclusive, _ordering, _direction ); } - + bool BtreeCursor::advance() { killCurrentOp.checkForInterrupt(); if ( bucket.isNull() ) return false; - bucket = bucket.btree()->advance(bucket, keyOfs, direction, "BtreeCursor::advance"); + bucket = bucket.btree()->advance(bucket, keyOfs, _direction, "BtreeCursor::advance"); if ( !_independentFieldRanges ) { skipUnusedKeys( false ); checkEnd(); - return ok(); + if ( ok() ) { + ++_nscanned; + } + } + else { + skipAndCheck(); } - - skipAndCheck(); return ok(); } @@ -207,10 +220,10 @@ namespace mongo { if ( eof() ) return; - multikey = d->isMultikey(idxNo); + _multikey = d->isMultikey(idxNo); if ( keyOfs >= 0 ) { - BtreeBucket *b = bucket.btree(); + const BtreeBucket *b = bucket.btree(); assert( !keyAtKeyOfs.isEmpty() ); @@ -219,17 +232,17 @@ namespace mongo { int x = 0; while( 1 ) { if ( b->keyAt(keyOfs).woEqual(keyAtKeyOfs) && - b->k(keyOfs).recordLoc == locAtKeyOfs ) { - if ( !b->k(keyOfs).isUsed() ) { - /* we were deleted but still exist as an unused - marker key. advance. - */ - skipUnusedKeys( false ); - } - return; + b->k(keyOfs).recordLoc == locAtKeyOfs ) { + if ( !b->k(keyOfs).isUsed() ) { + /* we were deleted but still exist as an unused + marker key. advance. + */ + skipUnusedKeys( false ); + } + return; } - /* we check one key earlier too, in case a key was just deleted. this is + /* we check one key earlier too, in case a key was just deleted. this is important so that multi updates are reasonably fast. */ if( keyOfs == 0 || x++ ) @@ -245,7 +258,7 @@ namespace mongo { bool found; /* TODO: Switch to keep indexdetails and do idx.head! */ - bucket = indexDetails.head.btree()->locate(indexDetails, indexDetails.head, keyAtKeyOfs, _ordering, keyOfs, found, locAtKeyOfs, direction); + bucket = indexDetails.head.btree()->locate(indexDetails, indexDetails.head, keyAtKeyOfs, _ordering, keyOfs, found, locAtKeyOfs, _direction); RARELY log() << " key seems to have moved in the index, refinding. found:" << found << endl; if ( ! bucket.isNull() ) skipUnusedKeys( false ); |