summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2011-11-30 22:20:07 -0800
committerAaron <aaron@10gen.com>2011-12-24 11:30:54 -0800
commitb8447afd0e907e9d9df7f94a98dbbe159fcf9df6 (patch)
tree8f2e1778d622a070020e179cd44f2f3d24bff662
parent53bc8fe36122e83157d0840241d24b1f5d69c2ba (diff)
downloadmongo-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.cpp15
-rw-r--r--db/queryoptimizercursor.cpp6
-rw-r--r--jstests/queryoptimizer3.js33
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();