From a7635d3b09aa9421cb02a92366d0bf63705435ea Mon Sep 17 00:00:00 2001 From: Eliot Horowitz Date: Thu, 17 Dec 2009 16:54:40 -0500 Subject: [PATCH] when doing large delete, unlock so other things can go: SERVER-494 --- db/clientcursor.cpp | 16 +++++++++------- db/clientcursor.h | 11 ++++++++--- db/query.cpp | 36 ++++++++++++++++++++++++++---------- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/db/clientcursor.cpp b/db/clientcursor.cpp index b4928c61b4dcd..4b70b11b0f266 100644 --- a/db/clientcursor.cpp +++ b/db/clientcursor.cpp @@ -135,13 +135,15 @@ namespace mongo { } wassert( toAdvance.size() < 5000 ); + + for ( vector::iterator i = toAdvance.begin(); i != toAdvance.end(); ++i ){ + ClientCursor* cc = *i; + + if ( cc->_doingDeletes ) continue; - for ( vector::iterator i = toAdvance.begin(); - i != toAdvance.end(); ++i ) - { - Cursor *c = (*i)->c.get(); + Cursor *c = cc->c.get(); if ( c->capped() ){ - delete *i; + delete cc; continue; } @@ -154,11 +156,11 @@ namespace mongo { c->advance(); if ( c->eof() ) { // advanced to end -- delete cursor - delete *i; + delete cc; } else { wassert( c->refLoc() != dl ); - (*i)->updateLocation(); + cc->updateLocation(); } } } diff --git a/db/clientcursor.h b/db/clientcursor.h index e076daa98735e..969482ee8a06e 100644 --- a/db/clientcursor.h +++ b/db/clientcursor.h @@ -51,11 +51,12 @@ namespace mongo { DiskLoc _lastLoc; // use getter and setter not this (important) unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time bool _liveForever; // if true, never time out cursor - + bool _doingDeletes; + static CCById clientCursorsById; static CCByLoc byLoc; static boost::recursive_mutex ccmutex; // must use this for all statics above! - + static CursorId allocCursorId_inlock(); public: @@ -66,7 +67,7 @@ namespace mongo { int pos; // # objects into the cursor so far BSONObj query; - ClientCursor() : _idleAgeMillis(0), _liveForever(false), pos(0) { + ClientCursor() : _idleAgeMillis(0), _liveForever(false), _doingDeletes(false), pos(0) { recursive_boostlock lock(ccmutex); cursorid = allocCursorId_inlock(); clientCursorsById.insert( make_pair(cursorid, this) ); @@ -147,6 +148,10 @@ namespace mongo { _liveForever = true; } + void setDoingDeletes( bool doingDeletes ){ + _doingDeletes = doingDeletes; + } + static unsigned byLocSize(); // just for diagnostics // static void idleTimeReport(unsigned millis); diff --git a/db/query.cpp b/db/query.cpp index 41ebe36942491..384f6eced231d 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -132,29 +132,43 @@ namespace mongo { int best = 0; DeleteOp original( justOne, best ); shared_ptr< DeleteOp > bestOp = s.runOp( original ); - auto_ptr< Cursor > c = bestOp->newCursor(); + auto_ptr< Cursor > creal = bestOp->newCursor(); - if( !c->ok() ) + if( !creal->ok() ) return nDeleted; - KeyValJSMatcher matcher(pattern, c->indexKeyPattern()); + KeyValJSMatcher matcher(pattern, creal->indexKeyPattern()); + ClientCursor cc; + cc.c = creal; + cc.ns = ns; + cc.liveForever(); + cc.setDoingDeletes( true ); do { - DiskLoc rloc = c->currLoc(); - BSONObj key = c->currKey(); - c->advance(); + if ( nDeleted % 100 == 99 ){ + cc.updateLocation(); + cc.setDoingDeletes( false ); + dbtemprelease unlock; + } + cc.setDoingDeletes( true ); + + DiskLoc rloc = cc.c->currLoc(); + BSONObj key = cc.c->currKey(); + + cc.c->advance(); + cc.updateLocation(); if ( ! matcher.matches( key , rloc ) ) continue; - assert( !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. */ - c->noteLocation(); + cc.c->noteLocation(); } if ( logop ) { @@ -168,12 +182,14 @@ namespace mongo { problem() << "deleted object without id, not logging" << endl; } } + theDataFileMgr.deleteRecord(ns, rloc.rec(), rloc); nDeleted++; if ( justOne ) break; - c->checkLocation(); - } while ( c->ok() ); + cc.c->checkLocation(); + + } while ( cc.c->ok() ); return nDeleted; }