0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-2977 assert rather than crash on invalid cursor access

This commit is contained in:
Aaron 2011-05-09 10:56:11 -07:00
parent f3a9c31c5c
commit 217b88af17
3 changed files with 47 additions and 11 deletions

View File

@ -478,8 +478,9 @@ namespace mongo {
* @return a cursor interface to the query optimizer. The implementation may
* utilize a single query plan or interleave results from multiple query
* plans before settling on a single query plan. Note that the schema of
* currKey() documents may change over the course of iteration.
*
* currKey() documents, the matcher(), and the isMultiKey() nature of the
* cursor may change over the course of iteration.
*
* This is a work in progress. Partial list of features not yet implemented:
* - ordered/sorted document iteration
* - yielding

View File

@ -97,16 +97,17 @@ namespace mongo {
}
virtual bool ok() { return !currLoc().isNull(); }
virtual Record* _current() { return currLoc().rec(); }
virtual BSONObj current() { return currLoc().obj(); }
virtual DiskLoc currLoc() {
virtual Record* _current() { assertOk(); return currLoc().rec(); }
virtual BSONObj current() { assertOk(); return currLoc().obj(); }
virtual DiskLoc currLoc() { return _currLoc(); }
DiskLoc _currLoc() const {
if ( _takeover ) {
return _takeover->currLoc();
return _takeover->currLoc();
}
if ( _currOp ) {
return _currOp->currLoc();
}
return DiskLoc();
return DiskLoc();
}
virtual bool advance() {
if ( _takeover ) {
@ -131,7 +132,10 @@ namespace mongo {
return ok();
}
virtual BSONObj currKey() const { return _takeover ? _takeover->currKey() : _currOp->currKey(); }
virtual BSONObj currKey() const {
assertOk();
return _takeover ? _takeover->currKey() : _currOp->currKey();
}
virtual DiskLoc refLoc() { return DiskLoc(); }
@ -141,6 +145,7 @@ namespace mongo {
virtual string toString() { return "QueryOptimizerCursor"; }
virtual bool getsetdup(DiskLoc loc) {
assertOk();
if ( !_takeover ) {
return getsetdupInternal( loc );
}
@ -150,18 +155,28 @@ namespace mongo {
return _takeover->getsetdup( loc );
}
virtual bool isMultiKey() const { return _takeover ? _takeover->isMultiKey() : _currOp->cursor()->isMultiKey(); }
virtual bool isMultiKey() const {
assertOk();
return _takeover ? _takeover->isMultiKey() : _currOp->cursor()->isMultiKey();
}
virtual bool modifiedKeys() const { return true; }
virtual long long nscanned() { return -1; }
virtual CoveredIndexMatcher *matcher() const { return _takeover ? _takeover->matcher() : _currOp->matcher().get(); }
virtual CoveredIndexMatcher *matcher() const {
assertOk();
return _takeover ? _takeover->matcher() : _currOp->matcher().get();
}
private:
void assertOk() const {
massert( 14809, "Invalid access for cursor that is not ok()", !_currLoc().isNull() );
}
bool getsetdupInternal(const DiskLoc &loc) {
pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc);
return !p.second;
return !p.second;
}
bool getdupInternal(const DiskLoc &loc) {

View File

@ -996,6 +996,25 @@ namespace QueryOptimizerTests {
shared_ptr<Cursor> _c;
};
/** No results for empty collection. */
class Empty : public Base {
public:
void run() {
dblock lk;
Client::Context ctx( ns() );
shared_ptr<Cursor> c = newQueryOptimizerCursor( ns(), BSONObj() );
ASSERT( !c->ok() );
ASSERT_EXCEPTION( c->_current(), AssertionException );
ASSERT_EXCEPTION( c->current(), AssertionException );
ASSERT( c->currLoc().isNull() );
ASSERT( !c->advance() );
ASSERT_EXCEPTION( c->currKey(), AssertionException );
ASSERT_EXCEPTION( c->getsetdup( DiskLoc() ), AssertionException );
ASSERT_EXCEPTION( c->isMultiKey(), AssertionException );
ASSERT_EXCEPTION( c->matcher(), AssertionException );
}
};
/** Basic test with two indexes and deduping requirement. */
class Basic : public Base {
public:
@ -1642,6 +1661,7 @@ namespace QueryOptimizerTests {
add<QueryPlanSetTests::EqualityThenIn>();
add<QueryPlanSetTests::NotEqualityThenIn>();
add<BestGuess>();
add<QueryOptimizerCursorTests::Empty>();
add<QueryOptimizerCursorTests::Basic>();
add<QueryOptimizerCursorTests::NoMatch>();
add<QueryOptimizerCursorTests::Interleaved>();