Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

cleaning ClientCursor to obey kernel rules and encapsulate more so ca…

…n add logic later
  • Loading branch information...
commit 6157d16b47d62294b94295ce45308a693471cc81 1 parent dab6e79
@erh erh authored
View
56 db/clientcursor.cpp
@@ -43,7 +43,7 @@ namespace mongo {
if( clientCursorsById.size() ) {
log() << "ERROR clientcursors exist but should not at this point" << endl;
ClientCursor *cc = clientCursorsById.begin()->second;
- log() << "first one: " << cc->cursorid << ' ' << cc->ns << endl;
+ log() << "first one: " << cc->_cursorid << ' ' << cc->_ns << endl;
clientCursorsById.clear();
assert(false);
}
@@ -51,7 +51,7 @@ namespace mongo {
void ClientCursor::setLastLoc_inlock(DiskLoc L) {
- assert( pos != -2 ); // defensive - see ~ClientCursor
+ assert( _pos != -2 ); // defensive - see ~ClientCursor
if ( L == _lastLoc )
return;
@@ -59,11 +59,11 @@ namespace mongo {
CCByLoc& bl = byLoc();
if ( !_lastLoc.isNull() ) {
- bl.erase( ByLocKey( _lastLoc, cursorid ) );
+ bl.erase( ByLocKey( _lastLoc, _cursorid ) );
}
if ( !L.isNull() )
- bl[ByLocKey(L,cursorid)] = this;
+ bl[ByLocKey(L,_cursorid)] = this;
_lastLoc = L;
}
@@ -96,7 +96,7 @@ namespace mongo {
ClientCursor *cc = i->second;
if( cc->_db != db )
continue;
- if ( strncmp(nsPrefix, cc->ns.c_str(), len) == 0 ) {
+ if ( strncmp(nsPrefix, cc->_ns.c_str(), len) == 0 ) {
toDelete.push_back(i->second);
}
}
@@ -140,7 +140,7 @@ namespace mongo {
i++;
if( j->second->shouldTimeout( millis ) ){
numberTimedOut++;
- log(1) << "killing old cursor " << j->second->cursorid << ' ' << j->second->ns
+ log(1) << "killing old cursor " << j->second->_cursorid << ' ' << j->second->_ns
<< " idle:" << j->second->idleTime() << "ms\n";
delete j->second;
}
@@ -158,7 +158,7 @@ namespace mongo {
log() << "perf warning: byLoc.size=" << bl.size() << " in aboutToDeleteBucket\n";
}
for ( CCByLoc::iterator i = bl.begin(); i != bl.end(); i++ )
- i->second->c->aboutToDeleteBucket(b);
+ i->second->_c->aboutToDeleteBucket(b);
}
void aboutToDeleteBucket(const DiskLoc& b) {
ClientCursor::informAboutToDeleteBucket(b);
@@ -192,12 +192,12 @@ namespace mongo {
if( toAdvance.size() >= 3000 ) {
log() << "perf warning MPW101: " << toAdvance.size() << " cursors for one diskloc "
<< dl.toString()
- << ' ' << toAdvance[1000]->ns
- << ' ' << toAdvance[2000]->ns
+ << ' ' << toAdvance[1000]->_ns
+ << ' ' << toAdvance[2000]->_ns
<< ' ' << toAdvance[1000]->_pinValue
<< ' ' << toAdvance[2000]->_pinValue
- << ' ' << toAdvance[1000]->pos
- << ' ' << toAdvance[2000]->pos
+ << ' ' << toAdvance[1000]->_pos
+ << ' ' << toAdvance[2000]->_pos
<< ' ' << toAdvance[1000]->_idleAgeMillis
<< ' ' << toAdvance[2000]->_idleAgeMillis
<< ' ' << toAdvance[1000]->_doingDeletes
@@ -212,7 +212,7 @@ namespace mongo {
if ( cc->_doingDeletes ) continue;
- Cursor *c = cc->c.get();
+ Cursor *c = cc->_c.get();
if ( c->capped() ){
delete cc;
continue;
@@ -240,16 +240,16 @@ namespace mongo {
void aboutToDelete(const DiskLoc& dl) { ClientCursor::aboutToDelete(dl); }
ClientCursor::~ClientCursor() {
- assert( pos != -2 );
+ assert( _pos != -2 );
{
recursive_scoped_lock lock(ccmutex);
setLastLoc_inlock( DiskLoc() ); // removes us from bylocation multimap
- clientCursorsById.erase(cursorid);
+ clientCursorsById.erase(_cursorid);
// defensive:
- (CursorId&) cursorid = -1;
- pos = -2;
+ (CursorId&)_cursorid = -1;
+ _pos = -2;
}
}
@@ -258,9 +258,9 @@ namespace mongo {
need to call when you are ready to "unlock".
*/
void ClientCursor::updateLocation() {
- assert( cursorid );
+ assert( _cursorid );
_idleAgeMillis = 0;
- DiskLoc cl = c->refLoc();
+ DiskLoc cl = _c->refLoc();
if ( lastLoc() == cl ) {
//log() << "info: lastloc==curloc " << ns << '\n';
} else {
@@ -268,7 +268,7 @@ namespace mongo {
setLastLoc_inlock(cl);
}
// may be necessary for MultiCursor even when cl hasn't changed
- c->noteLocation();
+ _c->noteLocation();
}
int ClientCursor::yieldSuggest() {
@@ -310,10 +310,10 @@ namespace mongo {
}
bool ClientCursor::prepareToYield( YieldData &data ) {
- if ( ! c->supportYields() )
+ if ( ! _c->supportYields() )
return false;
// need to store in case 'this' gets deleted
- data._id = cursorid;
+ data._id = _cursorid;
data._doingDeletes = _doingDeletes;
_doingDeletes = false;
@@ -331,13 +331,13 @@ namespace mongo {
inEmpty = true;
log() << "TEST: manipulate collection during cc:yield" << endl;
if( test == 1 )
- Helpers::emptyCollection(ns.c_str());
+ Helpers::emptyCollection(_ns.c_str());
else if( test == 2 ) {
BSONObjBuilder b; string m;
- dropCollection(ns.c_str(), m, b);
+ dropCollection(_ns.c_str(), m, b);
}
else {
- dropDatabase(ns.c_str());
+ dropDatabase(_ns.c_str());
}
}
}
@@ -352,12 +352,12 @@ namespace mongo {
}
cc->_doingDeletes = data._doingDeletes;
- cc->c->checkLocation();
+ cc->_c->checkLocation();
return true;
}
bool ClientCursor::yield( int micros ) {
- if ( ! c->supportYields() )
+ if ( ! _c->supportYields() )
return true;
YieldData data;
prepareToYield( data );
@@ -404,7 +404,7 @@ namespace mongo {
void ClientCursor::updateSlaveLocation( CurOp& curop ){
if ( _slaveReadTill.isNull() )
return;
- mongo::updateSlaveLocation( curop , ns.c_str() , _slaveReadTill );
+ mongo::updateSlaveLocation( curop , _ns.c_str() , _slaveReadTill );
}
@@ -451,7 +451,7 @@ namespace mongo {
recursive_scoped_lock lock(ccmutex);
for ( CCById::iterator i=clientCursorsById.begin(); i!=clientCursorsById.end(); ++i ){
- if ( i->second->ns == ns )
+ if ( i->second->_ns == ns )
all.insert( i->first );
}
}
View
145 db/clientcursor.h
@@ -70,23 +70,6 @@ namespace mongo {
class ClientCursor {
friend class CmdCursorInfo;
- DiskLoc _lastLoc; // use getter and setter not this (important)
- unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time
-
- /* 0 = normal
- 1 = no timeout allowed
- 100 = in use (pinned) -- see Pointer class
- */
- unsigned _pinValue;
-
- bool _doingDeletes;
- ElapsedTracker _yieldSometimesTracker;
-
- static CCById clientCursorsById;
- static long long numberTimedOut;
- static boost::recursive_mutex ccmutex; // must use this for all statics above!
- static CursorId allocCursorId_inlock();
-
public:
static void assertNoCursors();
@@ -136,7 +119,7 @@ namespace mongo {
}
if ( c ) {
_c = c;
- _id = c->cursorid;
+ _id = c->_cursorid;
} else {
_c = 0;
_id = -1;
@@ -152,40 +135,34 @@ namespace mongo {
CursorId _id;
};
- /*const*/ CursorId cursorid;
- const string ns;
- const shared_ptr<Cursor> c;
- int pos; // # objects into the cursor so far
- const BSONObj query; // used for logging diags only; optional in constructor
- const int _queryOptions; // see enum QueryOptions dbclient.h
- OpTime _slaveReadTill;
- Database * const _db;
-
- ClientCursor(int queryOptions, const shared_ptr<Cursor>& _c, const string& _ns, BSONObj _query = BSONObj()) :
+ ClientCursor(int queryOptions, const shared_ptr<Cursor>& c, const string& ns, BSONObj query = BSONObj()) :
+ _ns(ns), _db( cc().database() ),
+ _c(c), _pos(0),
+ _query(query), _queryOptions(queryOptions),
_idleAgeMillis(0), _pinValue(0),
- _doingDeletes(false), _yieldSometimesTracker(128,10),
- ns(_ns), c(_c),
- pos(0), query(_query),
- _queryOptions(queryOptions),
- _db( cc().database() )
+ _doingDeletes(false), _yieldSometimesTracker(128,10)
{
assert( _db );
assert( str::startsWith(_ns, _db->name) );
if( queryOptions & QueryOption_NoCursorTimeout )
noTimeout();
recursive_scoped_lock lock(ccmutex);
- cursorid = allocCursorId_inlock();
- clientCursorsById.insert( make_pair(cursorid, this) );
+ _cursorid = allocCursorId_inlock();
+ clientCursorsById.insert( make_pair(_cursorid, this) );
}
~ClientCursor();
+ // *************** basic accessors *******************
+
+ CursorId cursorid() const { return _cursorid; }
+ string ns() const { return _ns; }
+ Database * db() const { return _db; }
+ const BSONObj& query() const { return _query; }
+ int queryOptions() const { return _queryOptions; }
+
DiskLoc lastLoc() const { return _lastLoc; }
- shared_ptr< ParsedQuery > pq;
- shared_ptr< FieldMatcher > fields; // which fields query wants returned
- Message originalMessage; // this is effectively an auto ptr for data the matcher points to
-
/* Get rid of cursors for namespaces that begin with nsprefix.
Used by drop, dropIndexes, dropDatabase.
*/
@@ -218,7 +195,7 @@ namespace mongo {
struct YieldLock : boost::noncopyable {
explicit YieldLock( ptr<ClientCursor> cc )
- : _canYield(cc->c->supportYields()) {
+ : _canYield(cc->_c->supportYields()) {
if ( _canYield ){
cc->prepareToYield( _data );
_unlock.reset(new dbtempreleasecond());
@@ -246,17 +223,24 @@ namespace mongo {
};
// --- some pass through helpers for Cursor ---
-
- BSONObj indexKeyPattern() { return c->indexKeyPattern(); }
- bool ok() { return c->ok(); }
- bool advance(){ return c->advance(); }
- BSONObj current() { return c->current(); }
- DiskLoc currLoc() { return c->currLoc(); }
+
+ Cursor* c() const { return _c.get(); }
+ int pos() const { return _pos; }
+
+ void incPos( int n ) { _pos += n; } // TODO: this is bad
+ void setPos( int n ) { _pos = n; } // TODO : this is bad too
+
+ BSONObj indexKeyPattern() { return _c->indexKeyPattern(); }
+ bool ok() { return _c->ok(); }
+ bool advance(){ return _c->advance(); }
+ BSONObj current() { return _c->current(); }
+ DiskLoc currLoc() { return _c->currLoc(); }
+ BSONObj currKey() { return _c->currKey(); }
bool currentMatches(){
- if ( ! c->matcher() )
+ if ( ! _c->matcher() )
return true;
- return c->matcher()->matchesCurrent( c.get() );
+ return _c->matcher()->matchesCurrent( _c.get() );
}
private:
@@ -321,21 +305,70 @@ namespace mongo {
unsigned idleTime() const { return _idleAgeMillis; }
- static void idleTimeReport(unsigned millis);
-private:
- // cursors normally timeout after an inactivy period to prevent excess memory use
- // setting this prevents timeout of the cursor in question.
- void noTimeout() { _pinValue++; }
-
- CCByLoc& byLoc() { return _db->ccByLoc; }
-public:
void setDoingDeletes( bool doingDeletes ) {_doingDeletes = doingDeletes; }
+
+ void slaveReadTill( const OpTime& t ) { _slaveReadTill = t; }
+
+ public: // static methods
+
+ static void idleTimeReport(unsigned millis);
static void appendStats( BSONObjBuilder& result );
static unsigned numCursors() { return clientCursorsById.size(); }
static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const DiskLoc& dl);
static void find( const string& ns , set<CursorId>& all );
+
+
+ private: // methods
+
+ // cursors normally timeout after an inactivy period to prevent excess memory use
+ // setting this prevents timeout of the cursor in question.
+ void noTimeout() { _pinValue++; }
+
+ CCByLoc& byLoc() { return _db->ccByLoc; }
+
+ private:
+
+ CursorId _cursorid;
+
+ const string _ns;
+ Database * _db;
+
+ const shared_ptr<Cursor> _c;
+ int _pos; // # objects into the cursor so far
+
+ const BSONObj _query; // used for logging diags only; optional in constructor
+ int _queryOptions; // see enum QueryOptions dbclient.h
+
+ OpTime _slaveReadTill;
+
+ DiskLoc _lastLoc; // use getter and setter not this (important)
+ unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time
+
+ /* 0 = normal
+ 1 = no timeout allowed
+ 100 = in use (pinned) -- see Pointer class
+ */
+ unsigned _pinValue;
+
+ bool _doingDeletes;
+ ElapsedTracker _yieldSometimesTracker;
+
+ public:
+ shared_ptr< ParsedQuery > pq;
+ shared_ptr< FieldMatcher > fields; // which fields query wants returned
+ Message originalMessage; // this is effectively an auto ptr for data the matcher points to
+
+
+
+ private: // static members
+
+ static CCById clientCursorsById;
+ static long long numberTimedOut;
+ static boost::recursive_mutex ccmutex; // must use this for all statics above!
+ static CursorId allocCursorId_inlock();
+
};
class ClientCursorMonitor : public BackgroundJob {
View
2  db/dbcommands.cpp
@@ -1220,7 +1220,7 @@ namespace mongo {
{
shared_ptr<Cursor> c = theDataFileMgr.findAll( fromNs.c_str(), startLoc );
ClientCursor *cc = new ClientCursor(0, c, fromNs.c_str());
- id = cc->cursorid;
+ id = cc->cursorid();
}
DBDirectClient client;
View
22 db/oplog.h
@@ -76,7 +76,7 @@ namespace mongo {
bool done() const { return !_findingStart; }
shared_ptr<Cursor> cRelease() { return _c; }
void next() {
- if ( !_findingStartCursor || !_findingStartCursor->c->ok() ) {
+ if ( !_findingStartCursor || !_findingStartCursor->ok() ) {
_findingStart = false;
_c = _qp.newCursor(); // on error, start from beginning
destroyClientCursor();
@@ -84,16 +84,16 @@ namespace mongo {
}
switch( _findingStartMode ) {
case Initial: {
- if ( !_matcher->matches( _findingStartCursor->c->currKey(), _findingStartCursor->c->currLoc() ) ) {
+ if ( !_matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
_findingStart = false; // found first record out of query range, so scan normally
- _c = _qp.newCursor( _findingStartCursor->c->currLoc() );
+ _c = _qp.newCursor( _findingStartCursor->currLoc() );
destroyClientCursor();
return;
}
- _findingStartCursor->c->advance();
+ _findingStartCursor->advance();
RARELY {
if ( _findingStartTimer.seconds() >= __findingStartInitialTimeout ) {
- createClientCursor( startLoc( _findingStartCursor->c->currLoc() ) );
+ createClientCursor( startLoc( _findingStartCursor->currLoc() ) );
_findingStartMode = FindExtent;
return;
}
@@ -101,11 +101,11 @@ namespace mongo {
return;
}
case FindExtent: {
- if ( !_matcher->matches( _findingStartCursor->c->currKey(), _findingStartCursor->c->currLoc() ) ) {
+ if ( !_matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
_findingStartMode = InExtent;
return;
}
- DiskLoc prev = prevLoc( _findingStartCursor->c->currLoc() );
+ DiskLoc prev = prevLoc( _findingStartCursor->currLoc() );
if ( prev.isNull() ) { // hit beginning, so start scanning from here
createClientCursor();
_findingStartMode = InExtent;
@@ -117,13 +117,13 @@ namespace mongo {
return;
}
case InExtent: {
- if ( _matcher->matches( _findingStartCursor->c->currKey(), _findingStartCursor->c->currLoc() ) ) {
+ if ( _matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
_findingStart = false; // found first record in query range, so scan normally
- _c = _qp.newCursor( _findingStartCursor->c->currLoc() );
+ _c = _qp.newCursor( _findingStartCursor->currLoc() );
destroyClientCursor();
return;
}
- _findingStartCursor->c->advance();
+ _findingStartCursor->advance();
return;
}
default: {
@@ -188,7 +188,7 @@ namespace mongo {
}
void destroyClientCursor() {
if ( _findingStartCursor ) {
- ClientCursor::erase( _findingStartCursor->cursorid );
+ ClientCursor::erase( _findingStartCursor->cursorid() );
_findingStartCursor = 0;
}
}
View
14 db/pdfile.cpp
@@ -1196,20 +1196,20 @@ namespace mongo {
shared_ptr<Cursor> c = theDataFileMgr.findAll(ns);
cc.reset( new ClientCursor(QueryOption_NoCursorTimeout, c, ns) );
}
- CursorId id = cc->cursorid;
+ CursorId id = cc->cursorid();
- while ( cc->c->ok() ) {
- BSONObj js = cc->c->current();
+ while ( cc->ok() ) {
+ BSONObj js = cc->current();
try {
- _indexRecord(d, idxNo, js, cc->c->currLoc(), dupsAllowed);
- cc->c->advance();
+ _indexRecord(d, idxNo, js, cc->currLoc(), dupsAllowed);
+ cc->advance();
} catch( AssertionException& e ) {
if( e.interrupted() )
throw;
if ( dropDups ) {
- DiskLoc toDelete = cc->c->currLoc();
- bool ok = cc->c->advance();
+ DiskLoc toDelete = cc->currLoc();
+ bool ok = cc->advance();
cc->updateLocation();
theDataFileMgr.deleteRecord( ns, toDelete.rec(), toDelete, false, true );
if( ClientCursor::find(id, false) == 0 ) {
View
38 db/query.cpp
@@ -158,7 +158,7 @@ namespace mongo {
auto_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout, cPtr, ns) );
cc->setDoingDeletes( true );
- CursorId id = cc->cursorid;
+ CursorId id = cc->cursorid();
bool justOne = justOneOrig;
bool canYield = !god && !creal->matcher()->docMatcher().atomic();
@@ -169,7 +169,7 @@ namespace mongo {
// TODO should we assert or something?
break;
}
- if ( !cc->c->ok() ) {
+ if ( !cc->ok() ) {
break; // if we yielded, could have hit the end
}
@@ -177,26 +177,26 @@ namespace mongo {
// as well as some other nuances handled
cc->setDoingDeletes( true );
- DiskLoc rloc = cc->c->currLoc();
- BSONObj key = cc->c->currKey();
+ DiskLoc rloc = cc->currLoc();
+ BSONObj key = cc->currKey();
// NOTE Calling advance() may change the matcher, so it's important
// to try to match first.
bool match = creal->matcher()->matches( key , rloc );
- if ( ! cc->c->advance() )
+ if ( ! cc->advance() )
justOne = true;
if ( ! match )
continue;
- assert( !cc->c->getsetdup(rloc) ); // can't be a dup, we deleted it!
+ assert( !cc->c()->getsetdup(rloc) ); // can't be a dup, we deleted it!
if ( !justOne ) {
/* NOTE: this is SLOW. this is not good, noteLocation() was designed to be called across getMore
blocks. here we might call millions of times which would be bad.
*/
- cc->c->noteLocation();
+ cc->c()->noteLocation();
}
if ( logop ) {
@@ -219,9 +219,9 @@ namespace mongo {
if ( justOne ) {
break;
}
- cc->c->checkLocation();
+ cc->c()->checkLocation();
- } while ( cc->c->ok() );
+ } while ( cc->ok() );
if ( cc.get() && ClientCursor::find( id , false ) == 0 ){
cc.release();
@@ -301,15 +301,15 @@ namespace mongo {
if ( pass == 0 )
cc->updateSlaveLocation( curop );
- int queryOptions = cc->_queryOptions;
+ int queryOptions = cc->queryOptions();
if( pass == 0 ) {
StringBuilder& ss = curop.debug().str;
- ss << " getMore: " << cc->query.toString() << " ";
+ ss << " getMore: " << cc->query().toString() << " ";
}
- start = cc->pos;
- Cursor *c = cc->c.get();
+ start = cc->pos();
+ Cursor *c = cc->c();
c->checkLocation();
DiskLoc last;
@@ -359,7 +359,7 @@ namespace mongo {
if ( (ntoreturn>0 && (n >= ntoreturn || b.len() > MaxBytesToReturnToClientAtOnce)) ||
(ntoreturn==0 && b.len()>1*1024*1024) ) {
c->advance();
- cc->pos += n;
+ cc->incPos( n );
break;
}
}
@@ -371,7 +371,7 @@ namespace mongo {
cc->updateLocation();
cc->mayUpgradeStorage();
cc->storeOpForSlave( last );
- exhaust = cc->_queryOptions & QueryOption_Exhaust;
+ exhaust = cc->queryOptions() & QueryOption_Exhaust;
}
}
@@ -854,7 +854,7 @@ namespace mongo {
void finishForOplogReplay( ClientCursor * cc ){
if ( _oplogReplay && ! _slaveReadTill.isNull() )
- cc->_slaveReadTill = _slaveReadTill;
+ cc->slaveReadTill( _slaveReadTill );
}
private:
@@ -1076,14 +1076,14 @@ namespace mongo {
cursor->setMatcher( dqo.matcher() );
cc = new ClientCursor( queryOptions, cursor, ns, jsobj.getOwned() );
}
- cursorid = cc->cursorid;
+ cursorid = cc->cursorid();
DEV tlog(2) << "query has more, cursorid: " << cursorid << endl;
- cc->pos = n;
+ cc->setPos( n );
cc->pq = pq_shared;
cc->fields = pq.getFieldPtr();
cc->originalMessage = m;
cc->updateLocation();
- if ( !cc->c->ok() && cc->c->tailable() )
+ if ( !cc->ok() && cc->c()->tailable() )
DEV tlog() << "query has no more but tailable, cursorid: " << cursorid << endl;
if( queryOptions & QueryOption_Exhaust ) {
exhaust = ns;
Please sign in to comment.
Something went wrong with that request. Please try again.