Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

SERVER-3448 prevent excessive scanning in BtreeCursor functions

  • Loading branch information...
commit 10dd86fb966fc6cfa81c4337414ab9ad53ffda66 1 parent b65d137
@astaple astaple authored
Showing with 41 additions and 12 deletions.
  1. +1 −1  db/btree.h
  2. +14 −11 db/btreecursor.cpp
  3. +26 −0 dbtests/cursortests.cpp
View
2  db/btree.h
@@ -1071,7 +1071,7 @@ namespace mongo {
* Our btrees may (rarely) have "unused" keys when items are deleted.
* Skip past them.
*/
- virtual bool skipUnusedKeys( bool mayJump ) = 0;
+ virtual bool skipUnusedKeys() = 0;
bool skipOutOfRangeKeysAndCheckEnd();
void skipAndCheck();
View
25 db/btreecursor.cpp
@@ -68,7 +68,7 @@ namespace mongo {
return !currKeyNode().prevChildBucket.isNull();
}
- bool skipUnusedKeys( bool mayJump ) {
+ bool skipUnusedKeys() {
int u = 0;
while ( 1 ) {
if ( !ok() )
@@ -80,9 +80,6 @@ namespace mongo {
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';
@@ -120,7 +117,7 @@ namespace mongo {
if ( !kn.isUsed() ) {
// we were deleted but still exist as an unused
// marker key. advance.
- skipUnusedKeys( false );
+ skipUnusedKeys();
}
return;
}
@@ -149,7 +146,7 @@ namespace mongo {
bucket = _locate(keyAtKeyOfs, locAtKeyOfs);
RARELY log() << "key seems to have moved in the index, refinding. " << bucket.toString() << endl;
if ( ! bucket.isNull() )
- skipUnusedKeys( false );
+ skipUnusedKeys();
}
@@ -329,18 +326,24 @@ namespace mongo {
if ( ok() ) {
_nscanned = 1;
}
- skipUnusedKeys( false );
+ skipUnusedKeys();
checkEnd();
}
void BtreeCursor::skipAndCheck() {
- skipUnusedKeys( true );
+ int startNscanned = _nscanned;
+ skipUnusedKeys();
while( 1 ) {
if ( !skipOutOfRangeKeysAndCheckEnd() ) {
break;
}
- while( skipOutOfRangeKeysAndCheckEnd() );
- if ( !skipUnusedKeys( true ) ) {
+ do {
+ if ( _nscanned > startNscanned + 20 ) {
+ skipUnusedKeys();
+ return;
+ }
+ } while( skipOutOfRangeKeysAndCheckEnd() );
+ if ( !skipUnusedKeys() ) {
break;
}
}
@@ -395,7 +398,7 @@ namespace mongo {
bucket = _advance(bucket, keyOfs, _direction, "BtreeCursor::advance");
if ( !_independentFieldRanges ) {
- skipUnusedKeys( false );
+ skipUnusedKeys();
checkEnd();
if ( ok() ) {
++_nscanned;
View
26 dbtests/cursortests.cpp
@@ -33,6 +33,7 @@ namespace CursorTests {
class Base {
protected:
+ static const char *ns() { return "unittests.cursortests.Base"; }
FieldRangeVector *vec( int *vals, int len, int direction = 1 ) {
FieldRangeSet s( "", BSON( "a" << 1 ), true );
for( int i = 0; i < len; i += 2 ) {
@@ -49,6 +50,7 @@ namespace CursorTests {
IndexSpec *idxSpec = new IndexSpec( BSON( "a" << 1 ) );
return new FieldRangeVector( s, *idxSpec, direction );
}
+ DBDirectClient _c;
private:
vector< BSONObj > _objs;
};
@@ -258,6 +260,29 @@ namespace CursorTests {
}
virtual BSONObj idx() const { return BSON( "a" << 1 << "b" << 1 ); }
};
+
+ class AbortImplicitScan : public Base {
+ public:
+ void run() {
+ dblock lk;
+ IndexSpec idx( BSON( "a" << 1 << "b" << 1 ) );
+ _c.ensureIndex( ns(), idx.keyPattern );
+ for( int i = 0; i < 300; ++i ) {
+ _c.insert( ns(), BSON( "a" << i << "b" << 5 ) );
+ }
+ FieldRangeSet frs( ns(), BSON( "b" << 3 ), true );
+ shared_ptr<FieldRangeVector> frv( new FieldRangeVector( frs, idx, 1 ) );
+ Client::Context ctx( ns() );
+ scoped_ptr<BtreeCursor> c( BtreeCursor::make( nsdetails( ns() ), 1, nsdetails( ns() )->idx(1), frv, 1 ) );
+ int initialNscanned = c->nscanned();
+ ASSERT( initialNscanned < 200 );
+ ASSERT( c->ok() );
+ c->advance();
+ ASSERT( c->nscanned() > initialNscanned );
+ ASSERT( c->nscanned() < 200 );
+ ASSERT( c->ok() );
+ }
+ };
} // namespace BtreeCursorTests
@@ -274,6 +299,7 @@ namespace CursorTests {
add< BtreeCursorTests::EqIn >();
add< BtreeCursorTests::RangeEq >();
add< BtreeCursorTests::RangeIn >();
+ add< BtreeCursorTests::AbortImplicitScan >();
}
} myall;
} // namespace CursorTests
Please sign in to comment.
Something went wrong with that request. Please try again.