diff options
-rw-r--r-- | db/concurrency.h | 57 | ||||
-rw-r--r-- | db/repl.cpp | 19 |
2 files changed, 64 insertions, 12 deletions
diff --git a/db/concurrency.h b/db/concurrency.h index de8f242d61f..5c5c11c9c9a 100644 --- a/db/concurrency.h +++ b/db/concurrency.h @@ -113,16 +113,26 @@ namespace mongo { bool atLeastReadLocked() { return _state.get() != 0; } void assertAtLeastReadLocked() { assert(atLeastReadLocked()); } - void lock() { + bool _checkWriteLockAlready(){ //DEV cout << "LOCK" << endl; DEV assert( haveClient() ); int s = _state.get(); if( s > 0 ) { _state.set(s+1); - return; + return true; } + massert( 10293 , (string)"internal error: locks are not upgradeable: " + sayClientState() , s == 0 ); + + return false; + } + + void lock() { + + if ( _checkWriteLockAlready() ) + return; + _state.set(1); curopWaitingForLock( 1 ); @@ -131,6 +141,23 @@ namespace mongo { _minfo.entered(); } + + bool lock_try() { + if ( _checkWriteLockAlready() ) + return true; + + curopWaitingForLock( 1 ); + bool got = _m.try_lock(); + curopGotLock(); + + if ( got ){ + _minfo.entered(); + _state.set(1); + } + + return got; + } + void unlock() { //DEV cout << "UNLOCK" << endl; int s = _state.get(); @@ -227,12 +254,21 @@ namespace mongo { void lock() { #ifdef HAVE_READLOCK m.lock(); +#error this should be impossible? #else boost::detail::thread::lock_ops<boost::recursive_mutex>::lock(m); #endif _minfo.entered(); } + bool lock_try(){ + bool got = boost::detail::thread::lock_ops<boost::recursive_mutex>::trylock(m); + if ( got ){ + _minfo.entered(); + } + return got; + } + void releaseEarly() { assertWriteLocked(); // aso must not be recursive, although we don't verify that in the old boost version assert( !_releasedEarly.get() ); @@ -326,6 +362,23 @@ namespace mongo { } bool _got; }; + + struct writelocktry { + writelocktry( const string&ns ){ + _got = dbMutex.lock_try(); + } + ~writelocktry() { + if ( _got ){ + dbunlocking_write(); + dbMutex.unlock(); + } + } + bool got(){ + return _got; + } + bool _got; + }; + struct atleastreadlock { atleastreadlock( const string& ns ){ diff --git a/db/repl.cpp b/db/repl.cpp index a0ac16e9bc1..efb078b3ac3 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -1720,22 +1720,21 @@ namespace mongo { sleepsecs(4); Client::initThread("replmaster"); while( 1 ) { - { - dblock lk; - cc().getAuthenticationInfo()->authorize("admin"); - } sleepsecs(10); /* write a keep-alive like entry to the log. this will make things like printReplicationStatus() and printSlaveReplicationStatus() stay up-to-date even when things are idle. */ { - writelock lk(""); - try { - logKeepalive(); - } - catch(...) { - log() << "caught exception in replMasterThread()" << endl; + writelocktry lk(""); + if ( lk.got() ){ + cc().getAuthenticationInfo()->authorize("admin"); + try { + logKeepalive(); + } + catch(...) { + log() << "caught exception in replMasterThread()" << endl; + } } } } |