diff options
author | Aaron <aaron@10gen.com> | 2011-11-30 22:20:07 -0800 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2011-12-24 11:30:54 -0800 |
commit | b8447afd0e907e9d9df7f94a98dbbe159fcf9df6 (patch) | |
tree | 8f2e1778d622a070020e179cd44f2f3d24bff662 | |
parent | 53bc8fe36122e83157d0840241d24b1f5d69c2ba (diff) | |
download | mongo-b8447afd0e907e9d9df7f94a98dbbe159fcf9df6.tar.gz |
SERVER-4400 don't record query plan if a client cursor yield recovery fails; this patch violates the QueryOp abstraction a bit, but we are replacing that code soon anyway
-rw-r--r-- | db/ops/query.cpp | 15 | ||||
-rw-r--r-- | db/queryoptimizercursor.cpp | 6 | ||||
-rw-r--r-- | jstests/queryoptimizer3.js | 33 |
3 files changed, 49 insertions, 5 deletions
diff --git a/db/ops/query.cpp b/db/ops/query.cpp index cf4dc98a649..36f25367163 100644 --- a/db/ops/query.cpp +++ b/db/ops/query.cpp @@ -221,7 +221,8 @@ namespace mongo { _skip( spec["skip"].numberLong() ), _limit( spec["limit"].numberLong() ), _nscanned(), - _bc() { + _bc(), + _yieldRecoveryFailed() { } virtual void _init() { @@ -251,6 +252,7 @@ namespace mongo { virtual void recoverFromYield() { if ( _cc && !ClientCursor::recoverFromYield( _yieldData ) ) { + _yieldRecoveryFailed = true; _c.reset(); _cc.reset(); @@ -309,7 +311,7 @@ namespace mongo { } long long count() const { return _count; } virtual bool mayRecordPlan() const { - return ( _myCount > _limit / 2 ) || ( complete() && !stopRequested() ); + return !_yieldRecoveryFailed && ( ( _myCount > _limit / 2 ) || ( complete() && !stopRequested() ) ); } private: @@ -343,6 +345,7 @@ namespace mongo { ClientCursor::CleanupPointer _cc; ClientCursor::YieldData _yieldData; + bool _yieldRecoveryFailed; }; /* { count: "collectionname"[, query: <query>] } @@ -474,7 +477,8 @@ namespace mongo { _oplogReplay( pq.hasOption( QueryOption_OplogReplay) ), _response( response ), _eb( eb ), - _curop( curop ) + _curop( curop ), + _yieldRecoveryFailed() {} virtual void _init() { @@ -531,6 +535,7 @@ namespace mongo { _findingStartCursor->recoverFromYield(); } else if ( _cc && !ClientCursor::recoverFromYield( _yieldData ) ) { + _yieldRecoveryFailed = true; _c.reset(); _cc.reset(); _so.reset(); @@ -723,7 +728,7 @@ namespace mongo { } virtual bool mayRecordPlan() const { - return ( _pq.getNumToReturn() != 1 ) && ( ( _n > _pq.getNumToReturn() / 2 ) || ( complete() && !stopRequested() ) ); + return !_yieldRecoveryFailed && ( _pq.getNumToReturn() != 1 ) && ( ( _n > _pq.getNumToReturn() / 2 ) || ( complete() && !stopRequested() ) ); } virtual QueryOp *_createChild() const { @@ -791,6 +796,8 @@ namespace mongo { ExplainBuilder &_eb; CurOp &_curop; OpTime _slaveReadTill; + + bool _yieldRecoveryFailed; }; /* run a query -- includes checking for and running a Command \ diff --git a/db/queryoptimizercursor.cpp b/db/queryoptimizercursor.cpp index 92608895dcf..80041dcc92d 100644 --- a/db/queryoptimizercursor.cpp +++ b/db/queryoptimizercursor.cpp @@ -35,7 +35,9 @@ namespace mongo { * @param aggregateNscanned - shared int counting total nscanned for * query ops for all cursors. */ - QueryOptimizerCursorOp( long long &aggregateNscanned ) : _matchCount(), _mustAdvance(), _nscanned(), _aggregateNscanned( aggregateNscanned ) {} + QueryOptimizerCursorOp( long long &aggregateNscanned ) : + _matchCount(), _mustAdvance(), _nscanned(), _capped(), + _aggregateNscanned( aggregateNscanned ), _yieldRecoveryFailed() {} virtual void _init() { if ( qp().scanAndOrderRequired() ) { @@ -64,6 +66,7 @@ namespace mongo { virtual void recoverFromYield() { if ( _cc && !ClientCursor::recoverFromYield( _yieldData ) ) { + _yieldRecoveryFailed = true; _c.reset(); _cc.reset(); @@ -134,6 +137,7 @@ namespace mongo { DiskLoc _posBeforeYield; ClientCursor::YieldData _yieldData; long long &_aggregateNscanned; + bool _yieldRecoveryFailed; }; /** diff --git a/jstests/queryoptimizer3.js b/jstests/queryoptimizer3.js new file mode 100644 index 00000000000..76bc5b6be30 --- /dev/null +++ b/jstests/queryoptimizer3.js @@ -0,0 +1,33 @@ +// Check cases where index scans are aborted due to the collection being dropped. + +t = db.jstests_queryoptimizer3; +t.drop(); + +p = startParallelShell( 'for( i = 0; i < 400; ++i ) { sleep( 50 ); db.jstests_queryoptimizer3.drop(); }' ); + +for( i = 0; i < 100; ++i ) { + t.drop(); + t.ensureIndex({a:1}); + t.ensureIndex({b:1}); + for( j = 0; j < 100; ++j ) { + t.save({a:j,b:j}); + } + m = i % 5; + if ( m == 0 ) { + t.count({a:{$gte:0},b:{$gte:0}}); + } + else if ( m == 1 ) { + t.find({a:{$gte:0},b:{$gte:0}}).itcount(); + } + else if ( m == 2 ) { + t.remove({a:{$gte:0},b:{$gte:0}}); + } + else if ( m == 3 ) { + t.update({a:{$gte:0},b:{$gte:0}},{}); + } + else if ( m == 4 ) { + t.distinct('x',{a:{$gte:0},b:{$gte:0}}); + } +} + +p(); |