summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-10-07 12:00:20 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-10-07 12:01:03 -0400
commit2b7b105b3c26bc779d30d3c7ec4b93a0115569a8 (patch)
treeb5420116eed11e15cc41b212ee26b39a25426941 /src/mongo
parentc4f1421ec0e64832f7d79c5bcd624a8cf93452d9 (diff)
downloadmongo-2b7b105b3c26bc779d30d3c7ec4b93a0115569a8.tar.gz
SERVER-14668 Change read paths to acquire IS lock on the DB instead of S
Also change respective assertions, which are checking for S-lock on the database.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp4
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp26
-rw-r--r--src/mongo/db/concurrency/lock_state.h2
-rw-r--r--src/mongo/db/concurrency/locker.h2
-rw-r--r--src/mongo/db/dbhelpers.cpp4
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp1
-rw-r--r--src/mongo/db/prefetch.cpp5
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp23
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);