summaryrefslogtreecommitdiff
path: root/db/queryoptimizercursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/queryoptimizercursor.cpp')
-rw-r--r--db/queryoptimizercursor.cpp80
1 files changed, 44 insertions, 36 deletions
diff --git a/db/queryoptimizercursor.cpp b/db/queryoptimizercursor.cpp
index 9260889..f8b57f7 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();
@@ -113,12 +116,15 @@ namespace mongo {
DiskLoc currLoc() const { return _c ? _c->currLoc() : DiskLoc(); }
BSONObj currKey() const { return _c ? _c->currKey() : BSONObj(); }
virtual bool mayRecordPlan() const {
- return complete() && !stopRequested();
+ return !_yieldRecoveryFailed && complete() && !stopRequested();
}
shared_ptr<Cursor> cursor() const { return _c; }
private:
void mayAdvance() {
- if ( _mustAdvance && _c ) {
+ if ( !_c ) {
+ return;
+ }
+ if ( _mustAdvance ) {
_c->advance();
_mustAdvance = false;
}
@@ -134,6 +140,7 @@ namespace mongo {
DiskLoc _posBeforeYield;
ClientCursor::YieldData _yieldData;
long long &_aggregateNscanned;
+ bool _yieldRecoveryFailed;
};
/**
@@ -181,36 +188,7 @@ namespace mongo {
return DiskLoc();
}
virtual bool advance() {
- if ( _takeover ) {
- return _takeover->advance();
- }
-
- // Ok to advance if currOp in an error state due to failed yield recovery.
- // This may be the case when advance() is called by recoverFromYield().
- if ( !( _currOp && _currOp->error() ) && !ok() ) {
- return false;
- }
-
- _currOp = 0;
- shared_ptr<QueryOp> op = _mps->nextOp();
- rethrowOnError( op );
-
- QueryOptimizerCursorOp *qocop = dynamic_cast<QueryOptimizerCursorOp*>( op.get() );
- if ( !op->complete() ) {
- // 'qocop' will be valid until we call _mps->nextOp() again.
- _currOp = qocop;
- }
- else if ( op->stopRequested() ) {
- if ( qocop->cursor() ) {
- _takeover.reset( new MultiCursor( _mps,
- qocop->cursor(),
- op->matcher( qocop->cursor() ),
- *op,
- _nscanned - qocop->cursor()->nscanned() ) );
- }
- }
-
- return ok();
+ return _advance( false );
}
virtual BSONObj currKey() const {
if ( _takeover ) {
@@ -252,9 +230,9 @@ namespace mongo {
}
if ( _currOp ) {
_mps->recoverFromYield();
- if ( _currOp->error() ) {
- // See if we can advance to a non error op.
- advance();
+ if ( _currOp->error() || !ok() ) {
+ // Advance to a non error op or a following $or clause if possible.
+ _advance( true );
}
}
}
@@ -304,6 +282,36 @@ namespace mongo {
}
private:
+ bool _advance( bool force ) {
+ if ( _takeover ) {
+ return _takeover->advance();
+ }
+
+ if ( !force && !ok() ) {
+ return false;
+ }
+
+ _currOp = 0;
+ shared_ptr<QueryOp> op = _mps->nextOp();
+ rethrowOnError( op );
+
+ QueryOptimizerCursorOp *qocop = dynamic_cast<QueryOptimizerCursorOp*>( op.get() );
+ if ( !op->complete() ) {
+ // 'qocop' will be valid until we call _mps->nextOp() again.
+ _currOp = qocop;
+ }
+ else if ( op->stopRequested() ) {
+ if ( qocop->cursor() ) {
+ _takeover.reset( new MultiCursor( _mps,
+ qocop->cursor(),
+ op->matcher( qocop->cursor() ),
+ *op,
+ _nscanned - qocop->cursor()->nscanned() ) );
+ }
+ }
+
+ return ok();
+ }
void rethrowOnError( const shared_ptr< QueryOp > &op ) {
// If all plans have erred out, assert.
if ( op->error() ) {