summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2010-06-08 11:04:18 -0400
committerEliot Horowitz <eliot@10gen.com>2010-06-08 11:04:18 -0400
commit74fe4041a0b25917bc13ad5d8644b46a09cebde7 (patch)
tree4b8cce478b6cacca9f2d392c9a9f2e08fee4531a
parent68bcdb17fbebd8d071e6fca845dacd6e940813c2 (diff)
downloadmongo-74fe4041a0b25917bc13ad5d8644b46a09cebde7.tar.gz
repl: logKeepAlive can block readers SERVER-1202
-rw-r--r--db/concurrency.h57
-rw-r--r--db/repl.cpp19
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;
+ }
}
}
}