diff options
author | Dwight <dwight@10gen.com> | 2012-02-08 15:04:31 -0500 |
---|---|---|
committer | Dwight <dwight@10gen.com> | 2012-02-08 15:04:31 -0500 |
commit | 8fe187da766ac272dea4ecabc23d75baf3400667 (patch) | |
tree | d2fc1e0bea654a6e027c749b04f47950c50e6c3d /src/mongo | |
parent | 79a6d37c13ca2126bc7040d47b7ded36e40b1003 (diff) | |
download | mongo-8fe187da766ac272dea4ecabc23d75baf3400667.tar.gz |
SERVER-4328 goodbye MongoMutex [almost]
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/client.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/client.h | 3 | ||||
-rwxr-xr-x | src/mongo/db/d_concurrency.cpp | 31 | ||||
-rw-r--r-- | src/mongo/db/d_globals.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/dur.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/mongommf.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/mongomutex.h | 201 | ||||
-rw-r--r-- | src/mongo/db/pdfile.cpp | 2 | ||||
-rw-r--r-- | src/mongo/dbtests/threadedtests.cpp | 10 |
9 files changed, 42 insertions, 216 deletions
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index 0584c419fa9..d64e2015381 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -266,7 +266,7 @@ namespace mongo { checkNotStale(); _client->_context = this; _client->_curOp->enter( this ); - checkNsAccess( doauth, d.dbMutex.getState() ); + checkNsAccess( doauth ); } void Client::Context::_finishInit( bool doauth ) { @@ -324,6 +324,9 @@ namespace mongo { _auth( lockState ); } } + void Client::Context::checkNsAccess( bool doauth ) { + checkNsAccess( doauth, Lock::isWriteLocked() ? 1 : 0 ); + } void Client::appendLastOp( BSONObjBuilder& b ) const { // _lastOp is never set if replication is off diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index 6fc33b6a4f4..592dfbd0f3b 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -222,7 +222,8 @@ namespace mongo { void _finishInit( bool doauth=true); void _auth( int lockState ); void checkNotStale() const; - void checkNsAccess( bool doauth, int lockState = d.dbMutex.getState() ); + void checkNsAccess( bool doauth ); + void checkNsAccess( bool doauth, int lockState ); Client * const _client; Context * const _oldContext; const string _path; diff --git a/src/mongo/db/d_concurrency.cpp b/src/mongo/db/d_concurrency.cpp index 0bb4474e2be..367b1eb8b23 100755 --- a/src/mongo/db/d_concurrency.cpp +++ b/src/mongo/db/d_concurrency.cpp @@ -21,6 +21,9 @@ namespace mongo { + void lockedExclusively(); + void unlockingExclusively(); + static QLock& q = *new QLock(); Lock::Nongreedy::Nongreedy() { @@ -51,17 +54,21 @@ namespace mongo { static bool lock_W_try(int ms) { assert( threadState == 0 ); bool got = q.lock_W(ms); - if( got ) + if( got ) { threadState = 'W'; + lockedExclusively(); + } return got; } static void lock_W() { assert( threadState == 0 ); threadState = 'W'; q.lock_W(); + lockedExclusively(); } static void unlock_W() { wassert( threadState == 'W' ); + unlockingExclusively(); threadState = 0; q.unlock_W(); } @@ -281,20 +288,24 @@ namespace mongo { return Lock::isW(); } - // this tie-in temporary until MongoMutex is folded in more directly.Exclud - // called when the lock has been achieved - void MongoMutex::lockedExclusively() { + void curopGotLock(Client*); + + void lockedExclusively() { Client& c = cc(); - curopGotLock(&c); // hopefully lockStatus replaces one day - _minfo.entered(); // hopefully eliminate one day + curopGotLock(&c); + d.dbMutex._minfo.entered(); // hopefully eliminate one day } - void MongoMutex::unlockingExclusively() { - Client& c = cc(); - _minfo.leaving(); + namespace dur { + void releasingWriteLock(); // because it's hard to include dur.h here + } + + void unlockingExclusively() { + dur::releasingWriteLock(); + d.dbMutex._minfo.leaving(); } - MongoMutex::MongoMutex(const char *name) : _m(name) { + MongoMutex::MongoMutex() { static int n = 0; assert( ++n == 1 ); // below releasingWriteLock we assume MongoMutex is a singleton, and uses dbMutex ref above } diff --git a/src/mongo/db/d_globals.cpp b/src/mongo/db/d_globals.cpp index 37110590360..c8333542b7b 100644 --- a/src/mongo/db/d_globals.cpp +++ b/src/mongo/db/d_globals.cpp @@ -9,7 +9,7 @@ namespace mongo { DGlobals::DGlobals() : - dbMutex( *(new MongoMutex("dbMutex")) ), + dbMutex( *(new MongoMutex()) ), clientCursorMonitor( *(new ClientCursorMonitor()) ) { } diff --git a/src/mongo/db/dur.cpp b/src/mongo/db/dur.cpp index 39343608d08..4b56a44c8f9 100644 --- a/src/mongo/db/dur.cpp +++ b/src/mongo/db/dur.cpp @@ -780,7 +780,7 @@ namespace mongo { void releasingWriteLock() { DEV notesThisLock = 0; - // implicit commitIfNeeded check on each write unlock + // implicit commitIfNeeded check on each global write unlock DEV commitJob._nSinceCommitIfNeededCall = 0; // implicit commit if needed if( commitJob.bytes() > UncommittedBytesLimit || cmdLine.durOptions & CmdLine::DurAlwaysCommit ) { stats.curr->_earlyCommits++; diff --git a/src/mongo/db/mongommf.cpp b/src/mongo/db/mongommf.cpp index 71b95c97fbc..1fbfe332ff3 100644 --- a/src/mongo/db/mongommf.cpp +++ b/src/mongo/db/mongommf.cpp @@ -329,7 +329,7 @@ namespace mongo { if( !d.dbMutex.isWriteLocked() ) { assert( inShutdown() ); DEV { - log() << "is it really ok to close a mongommf outside a write lock? dbmutex status:" << d.dbMutex.getState() << " file:" << filename() << endl; + log() << "is it really ok to close a mongommf outside a write lock? file:" << filename() << endl; } } } diff --git a/src/mongo/db/mongomutex.h b/src/mongo/db/mongomutex.h index 41f8d87ae44..75dfe9c2a40 100644 --- a/src/mongo/db/mongomutex.h +++ b/src/mongo/db/mongomutex.h @@ -26,8 +26,6 @@ namespace mongo { class Client; - Client* curopWaitingForLock( int type ); - void curopGotLock(Client*); /* mongomutex time stats */ class MutexInfo { @@ -58,207 +56,18 @@ namespace mongo { unsigned long long getTimeLocked() const { return timeLocked; } }; - /** the 'big lock'. a read/write lock. - there is one of these, d.dbMutex. - - generally if you need to declare a mutex use the right primitive class, not this. - - use readlock and writelock classes for scoped locks on this rather than direct - manipulation. - */ - class MongoMutex { + /** old. see Lock class in d_concurrency.h instead. */ + class MongoMutex : boost::noncopyable { public: - MongoMutex(const char * name); - - /** @return - * > 0 write lock - * = 0 no lock - * < 0 read lock - */ - int getState() const { return _state.get(); } - + MongoMutex(); static bool atLeastReadLocked(); - void assertAtLeastReadLocked() const { assert(atLeastReadLocked()); } + void assertAtLeastReadLocked() const { assert( atLeastReadLocked() ); } static bool isWriteLocked(); - void assertWriteLocked() const { - assert( isWriteLocked() ); - DEV assert( !_releasedEarly.get() ); - } - - // write lock. use the writelock scoped lock class, not this directly. - void lock() { - if ( _writeLockedAlready() ) - return; - - _state.set(1); - - curopWaitingForLock( 1 ); // stats - _m.lock(); - MongoFile::markAllWritable(); // for _DEBUG validation -- a no op for release build - _acquiredWriteLock(); - } - - // try write lock - bool lock_try( int millis ) { - if ( _writeLockedAlready() ) // adjusts _state - return true; - - curopWaitingForLock( 1 ); - bool got = _m.lock_try( millis ); - - if ( got ) { - _state.set(1); - MongoFile::markAllWritable(); // for _DEBUG validation -- a no op for release build - _acquiredWriteLock(); - } - - return got; - } - - // un write lock - void unlock() { - int s = _state.get(); - if( s > 1 ) { - _state.set(s-1); // recursive lock case - return; - } - if( s != 1 ) { - if( _releasedEarly.get() ) { - _releasedEarly.set(false); - return; - } - massert( 12599, "internal error: attempt to unlock when wasn't in a write lock", false); - } - _releasingWriteLock(); - MongoFile::unmarkAllWritable(); // _DEBUG validation - _state.set(0); - _m.unlock(); - } - - /* unlock (write lock), and when unlock() is called later, - be smart then and don't unlock it again. - */ - void releaseEarly() { - assert( getState() == 1 ); // must not be recursive - assert( !_releasedEarly.get() ); - _releasedEarly.set(true); - unlock(); - } - - // read lock. don't call directly, use readlock. - void lock_shared() { - int s = _state.get(); - if( s ) { - if( s > 0 ) { - // already in write lock - just be recursive and stay write locked - _state.set(s+1); - } - else { - // already in read lock - recurse - _state.set(s-1); - } - } - else { - _state.set(-1); - Client *c = curopWaitingForLock( -1 ); - _m.lock_shared(); - curopGotLock(c); - } - } - - // try read lock - bool lock_shared_try( int millis ) { - int s = _state.get(); - if ( s ) { - // we already have a lock, so no need to try - lock_shared(); - return true; - } - - /* [dm] should there be - Client *c = curopWaitingForLock( 1 ); - here? i think so. seems to be missing. - */ - bool got = _m.lock_shared_try( millis ); - if ( got ) - _state.set(-1); - return got; - } - - void unlock_shared() { - int s = _state.get(); - if( s > 0 ) { - wassert( s > 1 ); /* we must have done a lock write first to have s > 1 */ - _state.set(s-1); - return; - } - if( s < -1 ) { - _state.set(s+1); - return; - } - wassert( s == -1 ); - _state.set(0); - _m.unlock_shared(); - } - + void assertWriteLocked() const { assert( isWriteLocked() ); } MutexInfo& info() { return _minfo; } - - private: - void lockedExclusively(); - void unlockingExclusively(); - void _acquiredWriteLock(); - void _releasingWriteLock(); - - /* @return true if was already write locked. increments recursive lock count. */ - bool _writeLockedAlready(); - - RWLock _m; - - /* > 0 write lock with recurse count - < 0 read lock - */ - ThreadLocalValue<int> _state; - MutexInfo _minfo; - - /* See the releaseEarly() method. - we use a separate TLS value for releasedEarly - that is ok as - our normal/common code path, we never even touch it */ - ThreadLocalValue<bool> _releasedEarly; - - /* this is for fsyncAndLock command. otherwise write lock's greediness will - make us block on any attempted write lock the the fsync's lock. - */ - //volatile bool _blockWrites; }; - namespace dur { - void REMAPPRIVATEVIEW(); - void releasingWriteLock(); // because it's hard to include dur.h here - } - - inline void MongoMutex::_releasingWriteLock() { - dur::releasingWriteLock(); - unlockingExclusively(); - } - - inline void MongoMutex::_acquiredWriteLock() { - lockedExclusively(); - } - - string sayClientState(); - - /* @return true if was already write locked. increments recursive lock count. */ - inline bool MongoMutex::_writeLockedAlready() { - int s = _state.get(); - if( s > 0 ) { - _state.set(s+1); - return true; - } - massert( 10293 , string("internal error: locks are not upgradeable: ") + sayClientState() , s == 0 ); - return false; - } - class readlocktry : boost::noncopyable { bool _already; bool _got; diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp index 6d46041493e..409a03731dc 100644 --- a/src/mongo/db/pdfile.cpp +++ b/src/mongo/db/pdfile.cpp @@ -1562,7 +1562,7 @@ namespace mongo { void prep(const char *ns, NamespaceDetails *d) { assertInWriteLock(); - uassert( 13130 , "can't start bg index b/c in recursive lock (db.eval?)" , mongo::d.dbMutex.getState() == 1 ); + uassert( 13130 , "can't start bg index b/c in recursive lock (db.eval?)" , !Lock::nested() ); bgJobsInProgress.insert(d); } void done(const char *ns, NamespaceDetails *d) { diff --git a/src/mongo/dbtests/threadedtests.cpp b/src/mongo/dbtests/threadedtests.cpp index 6eed3e7e7f3..52d5248ee82 100644 --- a/src/mongo/dbtests/threadedtests.cpp +++ b/src/mongo/dbtests/threadedtests.cpp @@ -147,10 +147,12 @@ namespace ThreadedTests { } virtual void validate() { ASSERT( !d.dbMutex.atLeastReadLocked() ); - d.dbMutex.lock(); - d.dbMutex.unlock(); - d.dbMutex.lock_shared(); - d.dbMutex.unlock_shared(); + { + Lock::GlobalWrite w; + } + { + Lock::GlobalRead r; + } } }; |