Skip to content

Commit 74fe404

Browse files
committed
repl: logKeepAlive can block readers SERVER-1202
1 parent 68bcdb1 commit 74fe404

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

db/concurrency.h

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,26 @@ namespace mongo {
113113
bool atLeastReadLocked() { return _state.get() != 0; }
114114
void assertAtLeastReadLocked() { assert(atLeastReadLocked()); }
115115

116-
void lock() {
116+
bool _checkWriteLockAlready(){
117117
//DEV cout << "LOCK" << endl;
118118
DEV assert( haveClient() );
119119

120120
int s = _state.get();
121121
if( s > 0 ) {
122122
_state.set(s+1);
123-
return;
123+
return true;
124124
}
125+
125126
massert( 10293 , (string)"internal error: locks are not upgradeable: " + sayClientState() , s == 0 );
127+
128+
return false;
129+
}
130+
131+
void lock() {
132+
133+
if ( _checkWriteLockAlready() )
134+
return;
135+
126136
_state.set(1);
127137

128138
curopWaitingForLock( 1 );
@@ -131,6 +141,23 @@ namespace mongo {
131141

132142
_minfo.entered();
133143
}
144+
145+
bool lock_try() {
146+
if ( _checkWriteLockAlready() )
147+
return true;
148+
149+
curopWaitingForLock( 1 );
150+
bool got = _m.try_lock();
151+
curopGotLock();
152+
153+
if ( got ){
154+
_minfo.entered();
155+
_state.set(1);
156+
}
157+
158+
return got;
159+
}
160+
134161
void unlock() {
135162
//DEV cout << "UNLOCK" << endl;
136163
int s = _state.get();
@@ -227,12 +254,21 @@ namespace mongo {
227254
void lock() {
228255
#ifdef HAVE_READLOCK
229256
m.lock();
257+
#error this should be impossible?
230258
#else
231259
boost::detail::thread::lock_ops<boost::recursive_mutex>::lock(m);
232260
#endif
233261
_minfo.entered();
234262
}
235263

264+
bool lock_try(){
265+
bool got = boost::detail::thread::lock_ops<boost::recursive_mutex>::trylock(m);
266+
if ( got ){
267+
_minfo.entered();
268+
}
269+
return got;
270+
}
271+
236272
void releaseEarly() {
237273
assertWriteLocked(); // aso must not be recursive, although we don't verify that in the old boost version
238274
assert( !_releasedEarly.get() );
@@ -326,6 +362,23 @@ namespace mongo {
326362
}
327363
bool _got;
328364
};
365+
366+
struct writelocktry {
367+
writelocktry( const string&ns ){
368+
_got = dbMutex.lock_try();
369+
}
370+
~writelocktry() {
371+
if ( _got ){
372+
dbunlocking_write();
373+
dbMutex.unlock();
374+
}
375+
}
376+
bool got(){
377+
return _got;
378+
}
379+
bool _got;
380+
};
381+
329382

330383
struct atleastreadlock {
331384
atleastreadlock( const string& ns ){

db/repl.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,22 +1720,21 @@ namespace mongo {
17201720
sleepsecs(4);
17211721
Client::initThread("replmaster");
17221722
while( 1 ) {
1723-
{
1724-
dblock lk;
1725-
cc().getAuthenticationInfo()->authorize("admin");
1726-
}
17271723
sleepsecs(10);
17281724
/* write a keep-alive like entry to the log. this will make things like
17291725
printReplicationStatus() and printSlaveReplicationStatus() stay up-to-date
17301726
even when things are idle.
17311727
*/
17321728
{
1733-
writelock lk("");
1734-
try {
1735-
logKeepalive();
1736-
}
1737-
catch(...) {
1738-
log() << "caught exception in replMasterThread()" << endl;
1729+
writelocktry lk("");
1730+
if ( lk.got() ){
1731+
cc().getAuthenticationInfo()->authorize("admin");
1732+
try {
1733+
logKeepalive();
1734+
}
1735+
catch(...) {
1736+
log() << "caught exception in replMasterThread()" << endl;
1737+
}
17391738
}
17401739
}
17411740
}

0 commit comments

Comments
 (0)