diff options
-rw-r--r-- | src/mongo/db/concurrency/d_concurrency.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 26 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.h | 2 | ||||
-rw-r--r-- | src/mongo/db/concurrency/locker.h | 2 | ||||
-rw-r--r-- | src/mongo/db/dbhelpers.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_d.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/prefetch.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp | 23 |
8 files changed, 40 insertions, 27 deletions
diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp index bdd78c68f83..1e33f5246e7 100644 --- a/src/mongo/db/concurrency/d_concurrency.cpp +++ b/src/mongo/db/concurrency/d_concurrency.cpp @@ -259,11 +259,11 @@ namespace mongo { _lockState->lockGlobal(isRead ? newlm::MODE_IS : newlm::MODE_IX); - if (supportsDocLocking()) { + if (supportsDocLocking() || isRead) { _lockState->lock(_id, _mode); } else { - _lockState->lock(_id, isRead ? newlm::MODE_S : newlm::MODE_X); + _lockState->lock(_id, newlm::MODE_X); } resetTime(); diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index 777e482991a..b9f6d037798 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -63,6 +63,10 @@ namespace newlm { const ResourceId resourceIdLocalDB = ResourceId(RESOURCE_DATABASE, string("local")); + + bool isSharedMode(newlm::LockMode mode) { + return (mode == newlm::MODE_IS || mode == newlm::MODE_S); + } } @@ -98,6 +102,19 @@ namespace newlm { return isLockHeldForMode(resIdNs, newlm::MODE_X); } + bool LockerImpl::isDbLockedForMode(const StringData& dbName, newlm::LockMode mode) const { + DEV { + const NamespaceString nss(dbName); + dassert(nss.coll().empty()); + }; + + if (isW()) return true; + if (isR() && isSharedMode(mode)) return true; + + const newlm::ResourceId resIdDb(newlm::RESOURCE_DATABASE, dbName); + return isLockHeldForMode(resIdDb, mode); + } + bool LockerImpl::isAtLeastReadLocked(const StringData& ns) const { if (threadState() == 'R' || threadState() == 'W') { return true; // global @@ -139,15 +156,6 @@ namespace newlm { } } - void LockerImpl::assertAtLeastReadLocked(const StringData& ns) const { - if (!isAtLeastReadLocked(ns)) { - log() << "error expected " << ns << " to be locked " << std::endl; - dump(); - msgasserted( - 16104, mongoutils::str::stream() << "expected to be read locked for " << ns); - } - } - BSONObj LockerImpl::reportState() { BSONObjBuilder b; reportState(&b); diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h index 3c710a03b1d..2201a4fc9e0 100644 --- a/src/mongo/db/concurrency/lock_state.h +++ b/src/mongo/db/concurrency/lock_state.h @@ -217,11 +217,11 @@ namespace newlm { virtual bool isLocked() const; virtual bool isWriteLocked() const; virtual bool isWriteLocked(const StringData& ns) const; + virtual bool isDbLockedForMode(const StringData& dbName, newlm::LockMode mode) const; virtual bool isAtLeastReadLocked(const StringData& ns) const; virtual bool isRecursive() const; virtual void assertWriteLocked(const StringData& ns) const; - virtual void assertAtLeastReadLocked(const StringData& ns) const; /** * Pending means we are currently trying to get a lock. diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h index e059a30d434..e8d68eafdd3 100644 --- a/src/mongo/db/concurrency/locker.h +++ b/src/mongo/db/concurrency/locker.h @@ -222,11 +222,11 @@ namespace mongo { virtual bool isLocked() const = 0; virtual bool isWriteLocked() const = 0; virtual bool isWriteLocked(const StringData& ns) const = 0; + virtual bool isDbLockedForMode(const StringData& dbName, newlm::LockMode mode) const = 0; virtual bool isAtLeastReadLocked(const StringData& ns) const = 0; virtual bool isRecursive() const = 0; virtual void assertWriteLocked(const StringData& ns) const = 0; - virtual void assertAtLeastReadLocked(const StringData& ns) const = 0; /** pending means we are currently trying to get a lock */ virtual bool hasLockPending() const = 0; diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index a2f5e964a70..d8de49742fb 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -144,8 +144,8 @@ namespace mongo { BSONObj& result, bool* nsFound, bool* indexFound) { - txn->lockState()->assertAtLeastReadLocked(ns); - invariant( database ); + + invariant(database); Collection* collection = database->getCollection( txn, ns ); if ( !collection ) { diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index b9d4ca9795e..90706aed99b 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -81,7 +81,6 @@ namespace { const intrusive_ptr<ExpressionContext>& pExpCtx) { // get the full "namespace" name const string& fullName = pExpCtx->ns.ns(); - pExpCtx->opCtx->lockState()->assertAtLeastReadLocked(fullName); // We will be modifying the source vector as we go Pipeline::SourceContainer& sources = pPipeline->sources; diff --git a/src/mongo/db/prefetch.cpp b/src/mongo/db/prefetch.cpp index 2bda9526e42..958f6039046 100644 --- a/src/mongo/db/prefetch.cpp +++ b/src/mongo/db/prefetch.cpp @@ -172,7 +172,10 @@ namespace { BSONObj obj = op.getObjectField(opField); const char *ns = op.getStringField("ns"); - txn->lockState()->assertAtLeastReadLocked(ns); + // This will have to change for engines other than MMAP V1, because they might not have + // means for directly prefetching pages from the collection. For this purpose, acquire S + // lock on the database, instead of optimizing with IS. + Lock::CollectionLock collLock(txn->lockState(), ns, newlm::MODE_S); Collection* collection = db->getCollection( txn, ns ); if (!collection) { diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp index 07bd682d3dc..6e2696a7a2f 100644 --- a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp @@ -138,8 +138,13 @@ namespace mongo { int n, int sizeNeeded , bool preallocateOnly) { - verify(this); - DEV txn->lockState()->assertAtLeastReadLocked( _dbname ); + + if (!txn->lockState()->isWriteLocked(_dbname)) { + log() << "error: getFile() called in a read lock, yet file to return is not yet open"; + log() << " getFile(" << n << ") _files.size:" + <<_files.size() << ' ' << fileName(n).string(); + invariant(false); + } if ( n < 0 || n >= DiskLoc::MaxFiles ) { log() << "getFile(): n=" << n << endl; @@ -151,22 +156,20 @@ namespace mongo { log() << "getFile(): n=" << n << endl; } } + DataFile* p = 0; if ( !preallocateOnly ) { while ( n >= (int) _files.size() ) { - verify(this); - if (!txn->lockState()->isWriteLocked(_dbname)) { - log() << "error: getFile() called in a read lock, yet file to return is not yet open"; - log() << " getFile(" << n << ") _files.size:" <<_files.size() << ' ' << fileName(n).string(); - invariant(false); - } _files.push_back(0); } p = _files[n]; } + if ( p == 0 ) { - if ( n == 0 ) audit::logCreateDatabase( currentClient.get(), _dbname ); - DEV txn->lockState()->assertWriteLocked( _dbname ); + if (n == 0) { + audit::logCreateDatabase(currentClient.get(), _dbname); + } + boost::filesystem::path fullName = fileName( n ); string fullNameString = fullName.string(); p = new DataFile(n); |