summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorDwight <dwight@10gen.com>2012-02-08 15:04:31 -0500
committerDwight <dwight@10gen.com>2012-02-08 15:04:31 -0500
commit8fe187da766ac272dea4ecabc23d75baf3400667 (patch)
treed2fc1e0bea654a6e027c749b04f47950c50e6c3d /src/mongo
parent79a6d37c13ca2126bc7040d47b7ded36e40b1003 (diff)
downloadmongo-8fe187da766ac272dea4ecabc23d75baf3400667.tar.gz
SERVER-4328 goodbye MongoMutex [almost]
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/client.cpp5
-rw-r--r--src/mongo/db/client.h3
-rwxr-xr-xsrc/mongo/db/d_concurrency.cpp31
-rw-r--r--src/mongo/db/d_globals.cpp2
-rw-r--r--src/mongo/db/dur.cpp2
-rw-r--r--src/mongo/db/mongommf.cpp2
-rw-r--r--src/mongo/db/mongomutex.h201
-rw-r--r--src/mongo/db/pdfile.cpp2
-rw-r--r--src/mongo/dbtests/threadedtests.cpp10
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;
+ }
}
};