summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-09-11 11:12:52 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-09-11 16:10:27 -0400
commitb47b91801021f5125fbcee07bf827b237ad1b4ee (patch)
tree40551bc8f376fee6814d6ee0812d6d1ae35d056b
parent4c429ebe0a44521a293103c8e3b2fb90f14f056e (diff)
downloadmongo-b47b91801021f5125fbcee07bf827b237ad1b4ee.tar.gz
SERVER-14668 Make Locker an interface
Turns the Locker class into an interface and changes most usages of LockState to now be either accesses to this interface or to use the default interface implementation.
-rw-r--r--src/mongo/db/auth/authz_session_external_state_d.cpp4
-rw-r--r--src/mongo/db/catalog/database_holder.cpp3
-rw-r--r--src/mongo/db/catalog/database_holder.h1
-rw-r--r--src/mongo/db/client.cpp1
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp110
-rw-r--r--src/mongo/db/concurrency/d_concurrency.h96
-rw-r--r--src/mongo/db/concurrency/d_concurrency_test.cpp5
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new.cpp4
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new.h3
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new_test.cpp4
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp95
-rw-r--r--src/mongo/db/concurrency/lock_state.h151
-rw-r--r--src/mongo/db/concurrency/lock_state_test.cpp23
-rw-r--r--src/mongo/db/concurrency/locker.h157
-rw-r--r--src/mongo/db/global_environment_experiment.cpp1
-rw-r--r--src/mongo/db/global_environment_noop.cpp2
-rw-r--r--src/mongo/db/operation_context.h5
-rw-r--r--src/mongo/db/operation_context_impl.cpp9
-rw-r--r--src/mongo/db/operation_context_impl.h4
-rw-r--r--src/mongo/db/operation_context_noop.h5
-rw-r--r--src/mongo/db/stats/snapshots_webplugins.cpp1
-rw-r--r--src/mongo/db/storage/mmap_v1/catalog/namespace_details.cpp3
-rw-r--r--src/mongo/db/storage/mmap_v1/catalog/namespace_index.cpp1
-rw-r--r--src/mongo/db/storage/mmap_v1/data_file.cpp2
-rw-r--r--src/mongo/db/storage/mmap_v1/dur.cpp1
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_commitjob.h1
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp1
-rw-r--r--src/mongo/dbtests/framework.cpp2
-rw-r--r--src/mongo/dbtests/mmaptests.cpp1
-rw-r--r--src/mongo/dbtests/threadedtests.cpp1
30 files changed, 412 insertions, 285 deletions
diff --git a/src/mongo/db/auth/authz_session_external_state_d.cpp b/src/mongo/db/auth/authz_session_external_state_d.cpp
index c7d289f7fc2..6c8e270b72c 100644
--- a/src/mongo/db/auth/authz_session_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_d.cpp
@@ -33,10 +33,12 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/client.h"
#include "mongo/db/dbhelpers.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/operation_context.h"
#include "mongo/scripting/engine.h"
+#include "mongo/util/assert_util.h"
+
namespace mongo {
diff --git a/src/mongo/db/catalog/database_holder.cpp b/src/mongo/db/catalog/database_holder.cpp
index df9a92412ef..591b5f7e240 100644
--- a/src/mongo/db/catalog/database_holder.cpp
+++ b/src/mongo/db/catalog/database_holder.cpp
@@ -38,9 +38,8 @@
#include "mongo/db/clientcursor.h"
#include "mongo/db/catalog/database_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/global_environment_experiment.h"
-#include "mongo/db/operation_context_impl.h"
+#include "mongo/db/operation_context.h"
#include "mongo/db/storage/mmap_v1/dur.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/util/file_allocator.h"
diff --git a/src/mongo/db/catalog/database_holder.h b/src/mongo/db/catalog/database_holder.h
index 1d067af7c00..043892b8fe8 100644
--- a/src/mongo/db/catalog/database_holder.h
+++ b/src/mongo/db/catalog/database_holder.h
@@ -32,7 +32,6 @@
#include "mongo/base/string_data.h"
#include "mongo/db/catalog/database.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/namespace_string.h"
#include "mongo/util/string_map.h"
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp
index 23a2b053c07..0423e4b5b23 100644
--- a/src/mongo/db/client.cpp
+++ b/src/mongo/db/client.cpp
@@ -54,7 +54,6 @@
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
#include "mongo/db/jsobj.h"
-#include "mongo/db/operation_context.h"
#include "mongo/db/repl/handshake_args.h"
#include "mongo/db/repl/repl_coordinator_global.h"
#include "mongo/db/repl/rs.h"
diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp
index 1df65984c7e..05b08abd372 100644
--- a/src/mongo/db/concurrency/d_concurrency.cpp
+++ b/src/mongo/db/concurrency/d_concurrency.cpp
@@ -1,32 +1,30 @@
-// @file d_concurrency.cpp
-
/**
-* Copyright (C) 2008-2014 MongoDB Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* As a special exception, the copyright holders give permission to link the
-* code of portions of this program with the OpenSSL library under certain
-* conditions as described in each individual source file and distribute
-* linked combinations including the program with the OpenSSL library. You
-* must comply with the GNU Affero General Public License in all respects for
-* all of the code used other than as permitted herein. If you modify file(s)
-* with this exception, you may extend this exception to your version of the
-* file(s), but you are not obligated to do so. If you do not wish to do so,
-* delete this exception statement from your version. If you delete this
-* exception statement from all source files in the program, then also delete
-* it in the license file.
-*/
+ * Copyright (C) 2008-2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
#include "mongo/platform/basic.h"
@@ -36,7 +34,9 @@
#include "mongo/db/commands/server_status.h"
#include "mongo/db/curop.h"
#include "mongo/db/global_environment_experiment.h"
+#include "mongo/db/concurrency/locker.h"
#include "mongo/db/concurrency/lock_stat.h"
+#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/operation_context.h"
#include "mongo/util/assert_util.h"
@@ -64,13 +64,13 @@ namespace mongo {
QLock q;
LockStat stats;
- void lock_R(LockState* lockState) {
+ void lock_R(Locker* lockState) {
invariant(lockState->threadState() == 0);
lockState->lockedStart('R');
q.lock_R();
}
- void lock_W(LockState* lockState) {
+ void lock_W(Locker* lockState) {
if (lockState->threadState()) {
log() << "can't lock_W, threadState=" << (int)lockState->threadState() << endl;
fassert(16114,false);
@@ -81,7 +81,7 @@ namespace mongo {
}
// how to count try's that fail is an interesting question. we should get rid of try().
- bool lock_R_try(LockState* lockState, int millis) {
+ bool lock_R_try(Locker* lockState, int millis) {
verify(lockState->threadState() == 0);
bool got = q.lock_R_try(millis);
if (got) {
@@ -90,7 +90,7 @@ namespace mongo {
return got;
}
- bool lock_W_try(LockState* lockState, int millis) {
+ bool lock_W_try(Locker* lockState, int millis) {
verify(lockState->threadState() == 0);
bool got = q.lock_W_try(millis);
if( got ) {
@@ -99,13 +99,13 @@ namespace mongo {
return got;
}
- void unlock_R(LockState* lockState) {
+ void unlock_R(Locker* lockState) {
wassert(lockState->threadState() == 'R');
lockState->unlocked();
q.unlock_R();
}
- void unlock_W(LockState* lockState) {
+ void unlock_W(Locker* lockState) {
wassert(lockState->threadState() == 'W');
lockState->unlocked();
q.unlock_W();
@@ -146,27 +146,27 @@ namespace mongo {
class AcquiringParallelWriter {
public:
- AcquiringParallelWriter(LockState* ls)
+ AcquiringParallelWriter(Locker* ls)
: _ls(ls) {
- _ls->_lockPendingParallelWriter = true;
+ _ls->setLockPendingParallelWriter(true);
}
~AcquiringParallelWriter() {
- _ls->_lockPendingParallelWriter = false;
+ _ls->setLockPendingParallelWriter(false);
}
private:
- LockState* const _ls;
+ Locker* const _ls;
};
RWLockRecursive &Lock::ParallelBatchWriterMode::_batchLock = *(new RWLockRecursive("special"));
- void Lock::ParallelBatchWriterMode::iAmABatchParticipant(LockState* lockState) {
- lockState->_batchWriter = true;
+ void Lock::ParallelBatchWriterMode::iAmABatchParticipant(Locker* lockState) {
+ lockState->setIsBatchWriter(true);
}
- Lock::ScopedLock::ParallelBatchWriterSupport::ParallelBatchWriterSupport(LockState* lockState)
+ Lock::ScopedLock::ParallelBatchWriterSupport::ParallelBatchWriterSupport(Locker* lockState)
: _lockState(lockState) {
relock();
}
@@ -176,14 +176,14 @@ namespace mongo {
}
void Lock::ScopedLock::ParallelBatchWriterSupport::relock() {
- if (!_lockState->_batchWriter) {
+ if (!_lockState->isBatchWriter()) {
AcquiringParallelWriter a(_lockState);
_lk.reset( new RWLockRecursive::Shared(ParallelBatchWriterMode::_batchLock) );
}
}
- Lock::ScopedLock::ScopedLock(LockState* lockState, char type)
+ Lock::ScopedLock::ScopedLock(Locker* lockState, char type)
: _lockState(lockState), _pbws_lk(lockState), _type(type) {
_lockState->enterScopedLock(this);
@@ -213,7 +213,7 @@ namespace mongo {
}
}
- Lock::TempRelease::TempRelease(LockState* lockState)
+ Lock::TempRelease::TempRelease(Locker* lockState)
: cant(lockState->isRecursive()), _lockState(lockState) {
if (cant) {
@@ -292,7 +292,7 @@ namespace mongo {
lockDB();
}
- Lock::GlobalWrite::GlobalWrite(LockState* lockState, int timeoutms)
+ Lock::GlobalWrite::GlobalWrite(Locker* lockState, int timeoutms)
: ScopedLock(lockState, 'W') {
char ts = _lockState->threadState();
@@ -346,7 +346,7 @@ namespace mongo {
_lockState->changeLockState('W');
}
- Lock::GlobalRead::GlobalRead(LockState* lockState, int timeoutms)
+ Lock::GlobalRead::GlobalRead(Locker* lockState, int timeoutms)
: ScopedLock(lockState, 'R') {
char ts = _lockState->threadState();
@@ -382,7 +382,7 @@ namespace mongo {
}
- Lock::DBWrite::DBWrite(LockState* lockState, const StringData& dbOrNs)
+ Lock::DBWrite::DBWrite(Locker* lockState, const StringData& dbOrNs)
: ScopedLock(lockState, 'w'),
_lockAcquired(false),
_ns(dbOrNs.toString()) {
@@ -474,7 +474,7 @@ namespace mongo {
}
- Lock::DBRead::DBRead(LockState* lockState, const StringData& dbOrNs)
+ Lock::DBRead::DBRead(Locker* lockState, const StringData& dbOrNs)
: ScopedLock(lockState, 'r'),
_lockAcquired(false),
_ns(dbOrNs.toString()) {
@@ -548,7 +548,7 @@ namespace mongo {
}
- Lock::UpgradeGlobalLockToExclusive::UpgradeGlobalLockToExclusive(LockState* lockState)
+ Lock::UpgradeGlobalLockToExclusive::UpgradeGlobalLockToExclusive(Locker* lockState)
: _lockState(lockState) {
fassert( 16187, _lockState->threadState() == 'w' );
@@ -577,7 +577,7 @@ namespace mongo {
_lockState->resetLockTime();
}
- writelocktry::writelocktry(LockState* lockState, int tryms) :
+ writelocktry::writelocktry(Locker* lockState, int tryms) :
_got( false ),
_dbwlock( NULL )
{
@@ -595,7 +595,7 @@ namespace mongo {
}
// note: the 'already' concept here might be a bad idea as a temprelease wouldn't notice it is nested then
- readlocktry::readlocktry(LockState* lockState, int tryms) :
+ readlocktry::readlocktry(Locker* lockState, int tryms) :
_got( false ),
_dbrlock( NULL )
{
@@ -616,9 +616,9 @@ namespace mongo {
* This is passed to the iterator for global environments and aggregates information about the
* locks which are currently being held or waited on.
*/
- class LockStateAggregator : public GlobalEnvironmentExperiment::ProcessOperationContext {
+ class LockerAggregator : public GlobalEnvironmentExperiment::ProcessOperationContext {
public:
- LockStateAggregator(bool blockedOnly)
+ LockerAggregator(bool blockedOnly)
: numWriteLocked(0),
numReadLocked(0),
_blockedOnly(blockedOnly) {
@@ -664,7 +664,7 @@ namespace mongo {
{
BSONObjBuilder ttt( t.subobjStart( "currentQueue" ) );
- LockStateAggregator blocked(true);
+ LockerAggregator blocked(true);
getGlobalEnvironment()->forEachOperationContext(&blocked);
ttt.append("total", blocked.numReadLocked + blocked.numWriteLocked);
@@ -677,7 +677,7 @@ namespace mongo {
{
BSONObjBuilder ttt( t.subobjStart( "activeClients" ) );
- LockStateAggregator active(false);
+ LockerAggregator active(false);
getGlobalEnvironment()->forEachOperationContext(&active);
ttt.append("total", active.numReadLocked + active.numWriteLocked);
diff --git a/src/mongo/db/concurrency/d_concurrency.h b/src/mongo/db/concurrency/d_concurrency.h
index bf77649601d..2e1243cd2ce 100644
--- a/src/mongo/db/concurrency/d_concurrency.h
+++ b/src/mongo/db/concurrency/d_concurrency.h
@@ -1,32 +1,30 @@
-// @file d_concurrency.h
-
/**
-* Copyright (C) 2008-2014 MongoDB Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* As a special exception, the copyright holders give permission to link the
-* code of portions of this program with the OpenSSL library under certain
-* conditions as described in each individual source file and distribute
-* linked combinations including the program with the OpenSSL library. You
-* must comply with the GNU Affero General Public License in all respects for
-* all of the code used other than as permitted herein. If you modify file(s)
-* with this exception, you may extend this exception to your version of the
-* file(s), but you are not obligated to do so. If you do not wish to do so,
-* delete this exception statement from your version. If you delete this
-* exception statement from all source files in the program, then also delete
-* it in the license file.
-*/
+ * Copyright (C) 2008-2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
// only used by mongod, thus the name ('d')
@@ -34,15 +32,17 @@
#pragma once
+#include <boost/scoped_ptr.hpp>
+
#include "mongo/base/string_data.h"
-#include "mongo/db/jsobj.h"
#include "mongo/db/concurrency/lock_stat.h"
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/concurrency/rwlock.h"
+
namespace mongo {
- class LockState;
+ class Locker;
class Lock : boost::noncopyable {
public:
@@ -50,12 +50,12 @@ namespace mongo {
// note: avoid TempRelease when possible. not a good thing.
struct TempRelease {
- TempRelease(LockState* lockState);
+ TempRelease(Locker* lockState);
~TempRelease();
const bool cant; // true if couldn't because of recursive locking
// Not owned
- LockState* _lockState;
+ Locker* _lockState;
ScopedLock *scopedLk;
};
@@ -68,7 +68,7 @@ namespace mongo {
RWLockRecursive::Exclusive _lk;
public:
ParallelBatchWriterMode() : _lk(_batchLock) {}
- static void iAmABatchParticipant(LockState* lockState);
+ static void iAmABatchParticipant(Locker* lockState);
static RWLockRecursive &_batchLock;
};
@@ -85,7 +85,7 @@ namespace mongo {
void recordTime();
protected:
- explicit ScopedLock(LockState* lockState, char type );
+ explicit ScopedLock(Locker* lockState, char type );
private:
friend struct TempRelease;
@@ -97,20 +97,20 @@ namespace mongo {
virtual void _tempRelease() = 0;
virtual void _relock() = 0;
- LockState* _lockState;
+ Locker* _lockState;
private:
class ParallelBatchWriterSupport : boost::noncopyable {
public:
- ParallelBatchWriterSupport(LockState* lockState);
+ ParallelBatchWriterSupport(Locker* lockState);
private:
void tempRelease();
void relock();
- LockState* _lockState;
- scoped_ptr<RWLockRecursive::Shared> _lk;
+ Locker* _lockState;
+ boost::scoped_ptr<RWLockRecursive::Shared> _lk;
friend class ScopedLock;
};
@@ -131,7 +131,7 @@ namespace mongo {
public:
// stopGreed is removed and does NOT work
// timeoutms is only for writelocktry -- deprecated -- do not use
- GlobalWrite(LockState* lockState, int timeoutms = -1);
+ GlobalWrite(Locker* lockState, int timeoutms = -1);
virtual ~GlobalWrite();
void downgrade(); // W -> R
void upgrade(); // caution see notes
@@ -145,7 +145,7 @@ namespace mongo {
void _relock();
public:
// timeoutms is only for readlocktry -- deprecated -- do not use
- GlobalRead(LockState* lockState, int timeoutms = -1);
+ GlobalRead(Locker* lockState, int timeoutms = -1);
virtual ~GlobalRead();
};
@@ -160,7 +160,7 @@ namespace mongo {
void _relock();
public:
- DBWrite(LockState* lockState, const StringData& dbOrNs);
+ DBWrite(Locker* lockState, const StringData& dbOrNs);
virtual ~DBWrite();
private:
@@ -179,7 +179,7 @@ namespace mongo {
void _relock();
public:
- DBRead(LockState* lockState, const StringData& dbOrNs);
+ DBRead(Locker* lockState, const StringData& dbOrNs);
virtual ~DBRead();
private:
@@ -193,31 +193,31 @@ namespace mongo {
*/
class UpgradeGlobalLockToExclusive : private boost::noncopyable {
public:
- UpgradeGlobalLockToExclusive(LockState* lockState);
+ UpgradeGlobalLockToExclusive(Locker* lockState);
~UpgradeGlobalLockToExclusive();
bool gotUpgrade() const { return _gotUpgrade; }
private:
- LockState* _lockState;
+ Locker* _lockState;
bool _gotUpgrade;
};
};
class readlocktry : boost::noncopyable {
bool _got;
- scoped_ptr<Lock::GlobalRead> _dbrlock;
+ boost::scoped_ptr<Lock::GlobalRead> _dbrlock;
public:
- readlocktry(LockState* lockState, int tryms);
+ readlocktry(Locker* lockState, int tryms);
~readlocktry();
bool got() const { return _got; }
};
class writelocktry : boost::noncopyable {
bool _got;
- scoped_ptr<Lock::GlobalWrite> _dbwlock;
+ boost::scoped_ptr<Lock::GlobalWrite> _dbwlock;
public:
- writelocktry(LockState* lockState, int tryms);
+ writelocktry(Locker* lockState, int tryms);
~writelocktry();
bool got() const { return _got; }
};
diff --git a/src/mongo/db/concurrency/d_concurrency_test.cpp b/src/mongo/db/concurrency/d_concurrency_test.cpp
index f29dbbc3c28..0dbe084f2d1 100644
--- a/src/mongo/db/concurrency/d_concurrency_test.cpp
+++ b/src/mongo/db/concurrency/d_concurrency_test.cpp
@@ -28,11 +28,8 @@
#include "mongo/platform/basic.h"
-#include <boost/scoped_ptr.hpp>
-#include <boost/thread/thread.hpp>
-
#include "mongo/db/concurrency/d_concurrency.h"
-#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/db/concurrency/lock_mgr_test_help.h"
#include "mongo/unittest/unittest.h"
diff --git a/src/mongo/db/concurrency/lock_mgr_new.cpp b/src/mongo/db/concurrency/lock_mgr_new.cpp
index c0410883ab1..b837e9d6904 100644
--- a/src/mongo/db/concurrency/lock_mgr_new.cpp
+++ b/src/mongo/db/concurrency/lock_mgr_new.cpp
@@ -30,9 +30,7 @@
#include "mongo/db/concurrency/lock_mgr_new.h"
-#include <boost/thread/locks.hpp>
-
-#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/db/concurrency/locker.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/log.h"
#include "mongo/util/stringutils.h"
diff --git a/src/mongo/db/concurrency/lock_mgr_new.h b/src/mongo/db/concurrency/lock_mgr_new.h
index c37ae8b0763..da71b7b0b3c 100644
--- a/src/mongo/db/concurrency/lock_mgr_new.h
+++ b/src/mongo/db/concurrency/lock_mgr_new.h
@@ -45,10 +45,11 @@
*/
namespace mongo {
-namespace newlm {
class Locker;
+namespace newlm {
+
/**
* Lock modes. Refer to the compatiblity matrix in the source file for information on how
* these conflict.
diff --git a/src/mongo/db/concurrency/lock_mgr_new_test.cpp b/src/mongo/db/concurrency/lock_mgr_new_test.cpp
index a7dd19bc981..c3ae8e40354 100644
--- a/src/mongo/db/concurrency/lock_mgr_new_test.cpp
+++ b/src/mongo/db/concurrency/lock_mgr_new_test.cpp
@@ -26,10 +26,8 @@
* it in the license file.
*/
-#include "mongo/unittest/unittest.h"
-#include "mongo/db/concurrency/lock_mgr_new.h"
#include "mongo/db/concurrency/lock_mgr_test_help.h"
-#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/unittest/unittest.h"
namespace mongo {
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index ec4ebcc40ea..da95a7cff06 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -30,45 +30,46 @@
#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/namespace_string.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
+namespace newlm {
- // Counts the Locker instance identifiers
- static AtomicUInt64 idCounter(0);
-
-
-
- LockState::LockState() : Locker(idCounter.addAndFetch(1)) {
+ namespace {
+ // Counts the Locker instance identifiers
+ static AtomicUInt64 idCounter(0);
+ // Global lock manager instance
+ static LockManager globalLockManagerInstance;
+ static LockManager* globalLockManagerPtr = &globalLockManagerInstance;
}
-namespace newlm {
- bool Locker::isRW() const {
+ bool LockerImpl::isRW() const {
return _threadState == 'R' || _threadState == 'W';
}
- bool Locker::isW() const {
+ bool LockerImpl::isW() const {
return _threadState == 'W';
}
- bool Locker::hasAnyReadLock() const {
+ bool LockerImpl::hasAnyReadLock() const {
return _threadState == 'r' || _threadState == 'R';
}
- bool Locker::isLocked() const {
+ bool LockerImpl::isLocked() const {
return threadState() != 0;
}
- bool Locker::isWriteLocked() const {
+ bool LockerImpl::isWriteLocked() const {
return (threadState() == 'W' || threadState() == 'w');
}
- bool Locker::isWriteLocked(const StringData& ns) const {
+ bool LockerImpl::isWriteLocked(const StringData& ns) const {
if (isWriteLocked()) {
return true;
}
@@ -79,7 +80,7 @@ namespace newlm {
return isLockHeldForMode(resIdNs, newlm::MODE_X);
}
- bool Locker::isAtLeastReadLocked(const StringData& ns) const {
+ bool LockerImpl::isAtLeastReadLocked(const StringData& ns) const {
if (threadState() == 'R' || threadState() == 'W')
return true; // global
if (threadState() == 0)
@@ -91,15 +92,15 @@ namespace newlm {
return isLockHeldForMode(resIdNs, newlm::MODE_S);
}
- bool Locker::isLockedForCommitting() const {
+ bool LockerImpl::isLockedForCommitting() const {
return threadState() == 'R' || threadState() == 'W';
}
- bool Locker::isRecursive() const {
+ bool LockerImpl::isRecursive() const {
return recursiveCount() > 1;
}
- void Locker::assertWriteLocked(const StringData& ns) const {
+ void LockerImpl::assertWriteLocked(const StringData& ns) const {
if (!isWriteLocked(ns)) {
dump();
msgasserted(
@@ -107,7 +108,7 @@ namespace newlm {
}
}
- void Locker::assertAtLeastReadLocked(const StringData& ns) const {
+ void LockerImpl::assertAtLeastReadLocked(const StringData& ns) const {
if (!isAtLeastReadLocked(ns)) {
log() << "error expected " << ns << " to be locked " << std::endl;
dump();
@@ -116,20 +117,20 @@ namespace newlm {
}
}
- void Locker::lockedStart( char newState ) {
+ void LockerImpl::lockedStart( char newState ) {
_threadState = newState;
}
- void Locker::unlocked() {
+ void LockerImpl::unlocked() {
_threadState = 0;
}
- void Locker::changeLockState( char newState ) {
+ void LockerImpl::changeLockState( char newState ) {
fassert( 16169 , _threadState != 0 );
_threadState = newState;
}
- BSONObj Locker::reportState() {
+ BSONObj LockerImpl::reportState() {
BSONObjBuilder b;
reportState(&b);
@@ -140,7 +141,7 @@ namespace newlm {
thread. So be careful about thread safety here. For example reading
this->otherName would not be safe as-is!
*/
- void Locker::reportState(BSONObjBuilder* res) {
+ void LockerImpl::reportState(BSONObjBuilder* res) {
BSONObjBuilder b;
if( _threadState ) {
char buf[2];
@@ -158,7 +159,7 @@ namespace newlm {
res->append("waitingForLock", _lockPending);
}
- void Locker::dump() const {
+ void LockerImpl::dump() const {
char s = threadState();
StringBuilder ss;
ss << "lock status: ";
@@ -171,7 +172,7 @@ namespace newlm {
log() << ss.str() << std::endl;
}
- void Locker::enterScopedLock(Lock::ScopedLock* lock) {
+ void LockerImpl::enterScopedLock(Lock::ScopedLock* lock) {
_recursive++;
if (_recursive == 1) {
invariant(_scopedLk == NULL);
@@ -179,12 +180,12 @@ namespace newlm {
}
}
- Lock::ScopedLock* Locker::getCurrentScopedLock() const {
+ Lock::ScopedLock* LockerImpl::getCurrentScopedLock() const {
invariant(_recursive == 1);
return _scopedLk;
}
- void Locker::leaveScopedLock(Lock::ScopedLock* lock) {
+ void LockerImpl::leaveScopedLock(Lock::ScopedLock* lock) {
if (_recursive == 1) {
// Sanity check we are releasing the same lock
invariant(_scopedLk == lock);
@@ -194,13 +195,6 @@ namespace newlm {
}
- /**
- * Global lock manager instance.
- */
- static LockManager globalLockManagerInstance;
- static LockManager* globalLockManagerPtr = &globalLockManagerInstance;
-
-
//
// CondVarLockGrantNotification
//
@@ -238,7 +232,7 @@ namespace newlm {
// Locker
//
- Locker::Locker(uint64_t id)
+ LockerImpl::LockerImpl(uint64_t id)
: _id(id),
_batchWriter(false),
_lockPendingParallelWriter(false),
@@ -249,18 +243,29 @@ namespace newlm {
}
- Locker::~Locker() {
+ LockerImpl::LockerImpl()
+ : _id(idCounter.addAndFetch(1)),
+ _batchWriter(false),
+ _lockPendingParallelWriter(false),
+ _recursive(0),
+ _threadState(0),
+ _scopedLk(NULL),
+ _lockPending(false) {
+
+ }
+
+ LockerImpl::~LockerImpl() {
// Cannot delete the Locker while there are still outstanding requests, because the
// LockManager may attempt to access deleted memory. Besides it is probably incorrect
// to delete with unaccounted locks anyways.
invariant(_requests.empty());
}
- LockResult Locker::lock(const ResourceId& resId, LockMode mode, unsigned timeoutMs) {
+ LockResult LockerImpl::lock(const ResourceId& resId, LockMode mode, unsigned timeoutMs) {
return _lockImpl(resId, mode, timeoutMs);
}
- bool Locker::unlock(const ResourceId& resId) {
+ bool LockerImpl::unlock(const ResourceId& resId) {
_lock.lock();
LockRequest* request = _find(resId);
invariant(request != NULL);
@@ -275,7 +280,7 @@ namespace newlm {
return _unlockAndUpdateRequestsList(resId, request);
}
- LockMode Locker::getLockMode(const ResourceId& resId) const {
+ LockMode LockerImpl::getLockMode(const ResourceId& resId) const {
scoped_spinlock scopedLock(_lock);
const LockRequest* request = _find(resId);
@@ -284,23 +289,23 @@ namespace newlm {
return request->mode;
}
- bool Locker::isLockHeldForMode(const ResourceId& resId, LockMode mode) const {
+ bool LockerImpl::isLockHeldForMode(const ResourceId& resId, LockMode mode) const {
return getLockMode(resId) >= mode;
}
// Static
- void Locker::dumpGlobalLockManager() {
+ void LockerImpl::dumpGlobalLockManager() {
globalLockManagerPtr->dump();
}
- LockRequest* Locker::_find(const ResourceId& resId) const {
+ LockRequest* LockerImpl::_find(const ResourceId& resId) const {
LockRequestsMap::const_iterator it = _requests.find(resId);
if (it == _requests.end()) return NULL;
return it->second;
}
- LockResult Locker::_lockImpl(const ResourceId& resId, LockMode mode, unsigned timeoutMs) {
+ LockResult LockerImpl::_lockImpl(const ResourceId& resId, LockMode mode, unsigned timeoutMs) {
_notify.clear();
_lock.lock();
@@ -337,7 +342,7 @@ namespace newlm {
return result;
}
- bool Locker::_unlockAndUpdateRequestsList(const ResourceId& resId, LockRequest* request) {
+ bool LockerImpl::_unlockAndUpdateRequestsList(const ResourceId& resId, LockRequest* request) {
globalLockManagerPtr->unlock(request);
const int recursiveCount = request->recursiveCount;
@@ -360,7 +365,7 @@ namespace newlm {
}
// Static
- void Locker::changeGlobalLockManagerForTestingOnly(LockManager* newLockMgr) {
+ void LockerImpl::changeGlobalLockManagerForTestingOnly(LockManager* newLockMgr) {
if (newLockMgr != NULL) {
globalLockManagerPtr = newLockMgr;
}
diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h
index 2588171ab94..cf9dd024e91 100644
--- a/src/mongo/db/concurrency/lock_state.h
+++ b/src/mongo/db/concurrency/lock_state.h
@@ -28,8 +28,7 @@
#pragma once
-#include "mongo/db/concurrency/d_concurrency.h"
-#include "mongo/db/concurrency/lock_mgr_new.h"
+#include "mongo/db/concurrency/locker.h"
namespace mongo {
@@ -76,59 +75,29 @@ namespace newlm {
* Lock/unlock methods must always be called from a single thread.
*
* All instances reference a single global lock manager.
- *
- * TODO: At some point, this will have to be renamed to LockState.
*/
- class Locker {
- MONGO_DISALLOW_COPYING(Locker);
+ class LockerImpl : public Locker {
public:
/**
* Instantiates a new lock space with the specified unique identifier used for
* disambiguation.
*/
- explicit Locker(uint64_t id);
- ~Locker();
+ LockerImpl(uint64_t id);
+ LockerImpl();
- inline uint64_t getId() const { return _id; }
+ virtual ~LockerImpl();
- /**
- * Acquires lock on the specified resource in the specified mode and returns the outcome
- * of the operation. See the details for LockResult for more information on what the
- * different results mean.
- *
- * Acquiring the same resource twice increments the reference count of the lock so each
- * call to lock, which doesn't time out (return value LOCK_TIMEOUT) must be matched with a
- * corresponding call to unlock.
- *
- * @param resId Id of the resource to be locked.
- * @param mode Mode in which the resource should be locked. Lock upgrades are allowed.
- * @param timeoutMs How many milliseconds to wait for the lock to be granted, before
- * returning LOCK_TIMEOUT. This parameter defaults to UINT_MAX, which means
- * wait infinitely. If 0 is passed, the request will return immediately, if
- * the request could not be granted right away.
- *
- * @return All LockResults except for LOCK_WAITING, because it blocks.
- */
- LockResult lock(const ResourceId& resId, LockMode mode, unsigned timeoutMs = UINT_MAX);
+ virtual uint64_t getId() const { return _id; }
- /**
- * Releases a lock previously acquired through a lock call. It is an error to try to
- * release lock which has not been previously acquired (invariant violation).
- *
- * @return true if the lock was actually released; false if only the reference count was
- * decremented, but the lock is still held.
- */
- bool unlock(const ResourceId& resId);
+ virtual LockResult lock(const ResourceId& resId,
+ LockMode mode,
+ unsigned timeoutMs = UINT_MAX);
- /**
- * Retrieves the mode in which a lock is held or checks whether the lock held for a
- * particular resource covers the specified mode.
- *
- * For example MODE_X covers MODE_S.
- */
- LockMode getLockMode(const ResourceId& resId) const;
- bool isLockHeldForMode(const ResourceId& resId, LockMode mode) const;
+ virtual bool unlock(const ResourceId& resId);
+
+ virtual LockMode getLockMode(const ResourceId& resId) const;
+ virtual bool isLockHeldForMode(const ResourceId& resId, LockMode mode) const;
/**
* Dumps all locks, on the global lock manager to the log for debugging purposes.
@@ -168,7 +137,7 @@ namespace newlm {
// The only reason we have this spin lock here is for the diagnostic tools, which could
// iterate through the LockRequestsMap on a separate thread and need it to be stable.
- // Apart from that, all accesses to the Locker are always from a single thread.
+ // Apart from that, all accesses to the LockerImpl are always from a single thread.
//
// This has to be locked inside const methods, hence the mutable.
mutable SpinLock _lock;
@@ -179,66 +148,73 @@ namespace newlm {
//////////////////////////////////////////////////////////////////////////////////////////
//
// Methods merged from LockState, which should eventually be removed or changed to methods
- // on the Locker interface.
+ // on the LockerImpl interface.
//
public:
- void dump() const;
+ virtual void dump() const;
- BSONObj reportState();
- void reportState(BSONObjBuilder* b);
+ virtual BSONObj reportState();
+ virtual void reportState(BSONObjBuilder* b);
- unsigned recursiveCount() const { return _recursive; }
+ virtual unsigned recursiveCount() const { return _recursive; }
/**
- * Indicates the mode of acquisition of the GlobalLock by this particular thread. The
- * return values are '0' (no global lock is held), 'r', 'w', 'R', 'W'. See the commends of
- * QLock for more information on what these modes mean.
- */
- char threadState() const { return _threadState; }
+ * Indicates the mode of acquisition of the GlobalLock by this particular thread. The
+ * return values are '0' (no global lock is held), 'r', 'w', 'R', 'W'. See the commends of
+ * QLock for more information on what these modes mean.
+ */
+ virtual char threadState() const { return _threadState; }
- bool isRW() const; // RW
- bool isW() const; // W
- bool hasAnyReadLock() const; // explicitly rR
+ virtual bool isRW() const; // RW
+ virtual bool isW() const; // W
+ virtual bool hasAnyReadLock() const; // explicitly rR
- bool isLocked() const;
- bool isWriteLocked() const;
- bool isWriteLocked(const StringData& ns) const;
- bool isAtLeastReadLocked(const StringData& ns) const;
- bool isLockedForCommitting() const;
- bool isRecursive() const;
+ virtual bool isLocked() const;
+ virtual bool isWriteLocked() const;
+ virtual bool isWriteLocked(const StringData& ns) const;
+ virtual bool isAtLeastReadLocked(const StringData& ns) const;
+ virtual bool isLockedForCommitting() const;
+ virtual bool isRecursive() const;
- void assertWriteLocked(const StringData& ns) const;
- void assertAtLeastReadLocked(const StringData& ns) 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 */
- bool hasLockPending() const { return _lockPending || _lockPendingParallelWriter; }
+ /**
+ * Pending means we are currently trying to get a lock.
+ */
+ virtual bool hasLockPending() const { return _lockPending || _lockPendingParallelWriter; }
// ----
-
- void lockedStart(char newState); // RWrw
- void unlocked(); // _threadState = 0
+ virtual void lockedStart(char newState); // RWrw
+ virtual void unlocked(); // _threadState = 0
/**
- * you have to be locked already to call this
- * this is mostly for W_to_R or R_to_W
- */
- void changeLockState(char newstate);
+ * you have to be locked already to call this
+ * this is mostly for W_to_R or R_to_W
+ */
+ virtual void changeLockState(char newstate);
// Those are only used for TempRelease. Eventually they should be removed.
- void enterScopedLock(Lock::ScopedLock* lock);
- Lock::ScopedLock* getCurrentScopedLock() const;
- void leaveScopedLock(Lock::ScopedLock* lock);
+ virtual void enterScopedLock(Lock::ScopedLock* lock);
+ virtual Lock::ScopedLock* getCurrentScopedLock() const;
+ virtual void leaveScopedLock(Lock::ScopedLock* lock);
- bool _batchWriter;
- bool _lockPendingParallelWriter;
+ virtual void recordLockTime() { _scopedLk->recordTime(); }
+ virtual void resetLockTime() { _scopedLk->resetTime(); }
- void recordLockTime() { _scopedLk->recordTime(); }
- void resetLockTime() { _scopedLk->resetTime(); }
+ virtual void setIsBatchWriter(bool newValue) { _batchWriter = newValue; }
+ virtual bool isBatchWriter() const { return _batchWriter; }
+ virtual void setLockPendingParallelWriter(bool newValue) {
+ _lockPendingParallelWriter = newValue;
+ }
private:
+ bool _batchWriter;
+ bool _lockPendingParallelWriter;
+
unsigned _recursive; // we allow recursively asking for a lock; we track that here
// global lock related
@@ -256,16 +232,11 @@ namespace newlm {
/**
- * One of these exists per OperationContext and serves as interface for acquiring locks and
- * obtaining lock statistics for this particular operation.
- *
- * TODO: It is only temporary that this class inherits from Locker. Both will eventually be
- * merged and most of the code in LockState will go away (i.e., once we move the GlobalLock to
- * be its own lock resource under the lock manager).
+ * This will go away as a separate step.
*/
- class LockState : public newlm::Locker {
+ class LockState : public newlm::LockerImpl {
public:
- LockState();
+ LockState() { }
};
diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp
index 9f263dd48c4..cc98525c178 100644
--- a/src/mongo/db/concurrency/lock_state_test.cpp
+++ b/src/mongo/db/concurrency/lock_state_test.cpp
@@ -28,19 +28,17 @@
#include "mongo/platform/basic.h"
-#include "mongo/unittest/unittest.h"
-#include "mongo/db/concurrency/lock_mgr.h"
#include "mongo/db/concurrency/lock_mgr_test_help.h"
-#include "mongo/db/concurrency/lock_state.h"
+#include "mongo/unittest/unittest.h"
namespace mongo {
namespace newlm {
- TEST(Locker, LockNoConflict) {
+ TEST(LockerImpl, LockNoConflict) {
const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- Locker locker(1);
+ LockerImpl locker(1);
ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
@@ -52,10 +50,10 @@ namespace newlm {
ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
}
- TEST(Locker, ReLockNoConflict) {
+ TEST(LockerImpl, ReLockNoConflict) {
const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- Locker locker(1);
+ LockerImpl locker(1);
ASSERT(LOCK_OK == locker.lock(resId, MODE_S));
ASSERT(LOCK_OK == locker.lock(resId, MODE_X));
@@ -67,23 +65,18 @@ namespace newlm {
ASSERT(locker.isLockHeldForMode(resId, MODE_NONE));
}
- TEST(Locker, ConflictWithTimeout) {
+ TEST(LockerImpl, ConflictWithTimeout) {
const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
- Locker locker1(1);
+ LockerImpl locker1(1);
ASSERT(LOCK_OK == locker1.lock(resId, MODE_X));
- Locker locker2(2);
+ LockerImpl locker2(2);
ASSERT(LOCK_TIMEOUT == locker2.lock(resId, MODE_S, 0));
ASSERT(locker2.isLockHeldForMode(resId, MODE_NONE));
ASSERT(locker1.unlock(resId));
}
- // Randomly acquires and releases locks, just to make sure that no assertions pop-up
- TEST(Locker, RandomizedAcquireRelease) {
- // TODO: Make sure to print the seed
- }
-
} // namespace newlm
} // namespace mongo
diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h
new file mode 100644
index 00000000000..2992ed7d3b9
--- /dev/null
+++ b/src/mongo/db/concurrency/locker.h
@@ -0,0 +1,157 @@
+/**
+ * Copyright (C) 2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/bson/bsonobj.h"
+#include "mongo/db/concurrency/d_concurrency.h"
+#include "mongo/db/concurrency/lock_mgr_new.h"
+
+
+namespace mongo {
+
+ /**
+ * Interface for acquiring locks. One of those objects will have to be instantiated for each
+ * request (transaction).
+ *
+ * Lock/unlock methods must always be called from a single thread.
+ */
+ class Locker {
+ MONGO_DISALLOW_COPYING(Locker);
+ public:
+ virtual ~Locker() {}
+
+ virtual uint64_t getId() const = 0;
+
+ /**
+ * Acquires lock on the specified resource in the specified mode and returns the outcome
+ * of the operation. See the details for LockResult for more information on what the
+ * different results mean.
+ *
+ * Acquiring the same resource twice increments the reference count of the lock so each
+ * call to lock, which doesn't time out (return value LOCK_TIMEOUT) must be matched with a
+ * corresponding call to unlock.
+ *
+ * @param resId Id of the resource to be locked.
+ * @param mode Mode in which the resource should be locked. Lock upgrades are allowed.
+ * @param timeoutMs How many milliseconds to wait for the lock to be granted, before
+ * returning LOCK_TIMEOUT. This parameter defaults to UINT_MAX, which means
+ * wait infinitely. If 0 is passed, the request will return immediately, if
+ * the request could not be granted right away.
+ *
+ * @return All LockResults except for LOCK_WAITING, because it blocks.
+ */
+ virtual newlm::LockResult lock(const newlm::ResourceId& resId,
+ newlm::LockMode mode,
+ unsigned timeoutMs = UINT_MAX) = 0;
+
+ /**
+ * Releases a lock previously acquired through a lock call. It is an error to try to
+ * release lock which has not been previously acquired (invariant violation).
+ *
+ * @return true if the lock was actually released; false if only the reference count was
+ * decremented, but the lock is still held.
+ */
+ virtual bool unlock(const newlm::ResourceId& resId) = 0;
+
+ /**
+ * Retrieves the mode in which a lock is held or checks whether the lock held for a
+ * particular resource covers the specified mode.
+ *
+ * For example isLockHeldForMode will return true for MODE_S, if MODE_X is already held,
+ * because MODE_X covers MODE_S.
+ */
+ virtual newlm::LockMode getLockMode(const newlm::ResourceId& resId) const;
+ virtual bool isLockHeldForMode(const newlm::ResourceId& resId, newlm::LockMode mode) const;
+
+ //
+ // These methods are legacy from LockState and will eventually go away or be converted to
+ // calls into the Locker methods
+ //
+
+ virtual void dump() const = 0;
+
+ virtual BSONObj reportState() = 0;
+ virtual void reportState(BSONObjBuilder* b) = 0;
+
+ virtual unsigned recursiveCount() const = 0;
+
+ /**
+ * Indicates the mode of acquisition of the GlobalLock by this particular thread. The
+ * return values are '0' (no global lock is held), 'r', 'w', 'R', 'W'. See the commends of
+ * QLock for more information on what these modes mean.
+ */
+ virtual char threadState() const = 0;
+
+ virtual bool isRW() const = 0; // RW
+ virtual bool isW() const = 0; // W
+ virtual bool hasAnyReadLock() const = 0; // explicitly rR
+
+ virtual bool isLocked() const = 0;
+ virtual bool isWriteLocked() const = 0;
+ virtual bool isWriteLocked(const StringData& ns) const = 0;
+ virtual bool isAtLeastReadLocked(const StringData& ns) const = 0;
+ virtual bool isLockedForCommitting() 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;
+
+ // ----
+
+ virtual void lockedStart(char newState) = 0; // RWrw
+ virtual void unlocked() = 0; // _threadState = 0
+
+ /**
+ * you have to be locked already to call this
+ * this is mostly for W_to_R or R_to_W
+ */
+ virtual void changeLockState(char newstate) = 0;
+
+ // Those are only used for TempRelease. Eventually they should be removed.
+ virtual void enterScopedLock(Lock::ScopedLock* lock) = 0;
+ virtual Lock::ScopedLock* getCurrentScopedLock() const = 0;
+ virtual void leaveScopedLock(Lock::ScopedLock* lock) = 0;
+
+ virtual void recordLockTime() = 0;
+ virtual void resetLockTime() = 0;
+
+ // Used for the replication parallel log op application threads
+ virtual void setIsBatchWriter(bool newValue) = 0;
+ virtual bool isBatchWriter() const = 0;
+ virtual void setLockPendingParallelWriter(bool newValue) = 0;
+
+ protected:
+ Locker() { }
+ };
+
+} // namespace mongo
diff --git a/src/mongo/db/global_environment_experiment.cpp b/src/mongo/db/global_environment_experiment.cpp
index 12095af4851..4d5230b63ba 100644
--- a/src/mongo/db/global_environment_experiment.cpp
+++ b/src/mongo/db/global_environment_experiment.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/global_environment_experiment.h"
#include "mongo/db/operation_context.h"
+#include "mongo/util/assert_util.h"
namespace mongo {
diff --git a/src/mongo/db/global_environment_noop.cpp b/src/mongo/db/global_environment_noop.cpp
index b99af713101..69bfbe0b532 100644
--- a/src/mongo/db/global_environment_noop.cpp
+++ b/src/mongo/db/global_environment_noop.cpp
@@ -26,6 +26,8 @@
* it in the license file.
*/
+#include "mongo/platform/basic.h"
+
#include "mongo/db/global_environment_noop.h"
#include "mongo/db/operation_context_noop.h"
diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h
index e425b6941ab..b4a0a6c6a49 100644
--- a/src/mongo/db/operation_context.h
+++ b/src/mongo/db/operation_context.h
@@ -34,11 +34,12 @@
#include "mongo/base/status.h"
#include "mongo/base/string_data.h"
#include "mongo/db/storage/recovery_unit.h"
+#include "mongo/db/concurrency/locker.h"
#include "mongo/db/concurrency/lock_mgr.h"
-#include "mongo/db/concurrency/lock_state.h"
namespace mongo {
+
class Client;
class CurOp;
class ProgressMeter;
@@ -63,7 +64,7 @@ namespace mongo {
/**
* Interface for locking. Caller DOES NOT own pointer.
*/
- virtual LockState* lockState() const = 0;
+ virtual Locker* lockState() const = 0;
// --- operation level info? ---
diff --git a/src/mongo/db/operation_context_impl.cpp b/src/mongo/db/operation_context_impl.cpp
index 07fef4bd3d9..1f482f23127 100644
--- a/src/mongo/db/operation_context_impl.cpp
+++ b/src/mongo/db/operation_context_impl.cpp
@@ -26,9 +26,12 @@
* it in the license file.
*/
+#include "mongo/platform/basic.h"
+
#include "mongo/db/operation_context_impl.h"
#include "mongo/db/client.h"
+#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/curop.h"
#include "mongo/db/global_environment_experiment.h"
#include "mongo/db/namespace_string.h"
@@ -45,6 +48,8 @@ namespace mongo {
invariant(storageEngine);
_recovery.reset(storageEngine->newRecoveryUnit(this));
+ _locker.reset(new newlm::LockerImpl());
+
getGlobalEnvironment()->registerOperationContext(this);
}
@@ -56,8 +61,8 @@ namespace mongo {
return _recovery.get();
}
- LockState* OperationContextImpl::lockState() const {
- return const_cast<LockState*>(&_lockState);
+ Locker* OperationContextImpl::lockState() const {
+ return _locker.get();
}
ProgressMeter* OperationContextImpl::setMessage(const char * msg,
diff --git a/src/mongo/db/operation_context_impl.h b/src/mongo/db/operation_context_impl.h
index 95e09e7f1c1..c178936271f 100644
--- a/src/mongo/db/operation_context_impl.h
+++ b/src/mongo/db/operation_context_impl.h
@@ -43,7 +43,7 @@ namespace mongo {
virtual RecoveryUnit* recoveryUnit() const;
- virtual LockState* lockState() const;
+ virtual Locker* lockState() const;
virtual ProgressMeter* setMessage(const char* msg,
const std::string& name,
@@ -71,7 +71,7 @@ namespace mongo {
private:
boost::scoped_ptr<RecoveryUnit> _recovery;
Transaction _tx;
- LockState _lockState;
+ boost::scoped_ptr<Locker> _locker;
};
} // namespace mongo
diff --git a/src/mongo/db/operation_context_noop.h b/src/mongo/db/operation_context_noop.h
index 7f47193a78f..7aca695854d 100644
--- a/src/mongo/db/operation_context_noop.h
+++ b/src/mongo/db/operation_context_noop.h
@@ -61,9 +61,8 @@ namespace mongo {
return _recoveryUnit.get();
}
- virtual LockState* lockState() const {
- // TODO: Eventually, this should return an actual LockState object. For now,
- // LockState depends on the whole world and is not necessary for testing.
+ virtual Locker* lockState() const {
+ // TODO: This should return an actual object if necessary for testing.
return NULL;
}
diff --git a/src/mongo/db/stats/snapshots_webplugins.cpp b/src/mongo/db/stats/snapshots_webplugins.cpp
index e01065d71f1..d777f0c692a 100644
--- a/src/mongo/db/stats/snapshots_webplugins.cpp
+++ b/src/mongo/db/stats/snapshots_webplugins.cpp
@@ -28,7 +28,6 @@
#include "mongo/platform/basic.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/dbwebserver.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/stats/snapshots.h"
diff --git a/src/mongo/db/storage/mmap_v1/catalog/namespace_details.cpp b/src/mongo/db/storage/mmap_v1/catalog/namespace_details.cpp
index 45cfe0d5d4b..5a5364403c4 100644
--- a/src/mongo/db/storage/mmap_v1/catalog/namespace_details.cpp
+++ b/src/mongo/db/storage/mmap_v1/catalog/namespace_details.cpp
@@ -26,7 +26,7 @@
* it in the license file.
*/
-#include "mongo/pch.h"
+#include "mongo/platform/basic.h"
#include "mongo/db/storage/mmap_v1/catalog/namespace_details.h"
@@ -38,6 +38,7 @@
#include "mongo/db/catalog/collection_options.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands/server_status.h"
+#include "mongo/db/concurrency/locker.h"
#include "mongo/db/db.h"
#include "mongo/db/index_legacy.h"
#include "mongo/db/json.h"
diff --git a/src/mongo/db/storage/mmap_v1/catalog/namespace_index.cpp b/src/mongo/db/storage/mmap_v1/catalog/namespace_index.cpp
index eb72d376e19..f8e7d65f398 100644
--- a/src/mongo/db/storage/mmap_v1/catalog/namespace_index.cpp
+++ b/src/mongo/db/storage/mmap_v1/catalog/namespace_index.cpp
@@ -35,7 +35,6 @@
#include <boost/filesystem/operations.hpp>
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/storage/mmap_v1/catalog/namespace_details.h"
#include "mongo/util/exit.h"
diff --git a/src/mongo/db/storage/mmap_v1/data_file.cpp b/src/mongo/db/storage/mmap_v1/data_file.cpp
index 2fdd13b69e1..44ee1412831 100644
--- a/src/mongo/db/storage/mmap_v1/data_file.cpp
+++ b/src/mongo/db/storage/mmap_v1/data_file.cpp
@@ -36,12 +36,12 @@
#include <boost/filesystem/operations.hpp>
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/storage/mmap_v1/dur.h"
#include "mongo/db/operation_context.h"
#include "mongo/util/file_allocator.h"
#include "mongo/util/log.h"
+
namespace mongo {
BOOST_STATIC_ASSERT( sizeof(DataFileHeader)-4 == 8192 );
diff --git a/src/mongo/db/storage/mmap_v1/dur.cpp b/src/mongo/db/storage/mmap_v1/dur.cpp
index 7d169e59713..eff05332558 100644
--- a/src/mongo/db/storage/mmap_v1/dur.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur.cpp
@@ -79,6 +79,7 @@
#include "mongo/db/client.h"
#include "mongo/db/commands/fsync.h"
#include "mongo/db/commands/server_status.h"
+#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/operation_context_impl.h"
#include "mongo/db/storage/storage_engine.h"
#include "mongo/db/storage/mmap_v1/dur.h"
diff --git a/src/mongo/db/storage/mmap_v1/dur_commitjob.h b/src/mongo/db/storage/mmap_v1/dur_commitjob.h
index 89a97a5ba3c..05cbb3754ac 100644
--- a/src/mongo/db/storage/mmap_v1/dur_commitjob.h
+++ b/src/mongo/db/storage/mmap_v1/dur_commitjob.h
@@ -30,7 +30,6 @@
#pragma once
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/storage/mmap_v1/dur.h"
#include "mongo/db/storage/mmap_v1/durop.h"
#include "mongo/util/alignedbuilder.h"
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 d55cfd39824..e9f7d8331b4 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
@@ -36,7 +36,6 @@
#include "mongo/db/audit.h"
#include "mongo/db/client.h"
-#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/storage/mmap_v1/dur.h"
#include "mongo/db/storage/mmap_v1/data_file.h"
#include "mongo/db/storage/mmap_v1/record.h"
diff --git a/src/mongo/dbtests/framework.cpp b/src/mongo/dbtests/framework.cpp
index 8354c6fb0e3..bff325eaa4a 100644
--- a/src/mongo/dbtests/framework.cpp
+++ b/src/mongo/dbtests/framework.cpp
@@ -96,7 +96,7 @@ namespace mongo {
warning() << currentTestName << " has been running for more than " << minutesRunning-1 << " minutes." << endl;
// See what is stuck
- newlm::Locker::dumpGlobalLockManager();
+ newlm::LockerImpl::dumpGlobalLockManager();
}
}
}
diff --git a/src/mongo/dbtests/mmaptests.cpp b/src/mongo/dbtests/mmaptests.cpp
index 9a9363aa451..88c97841e76 100644
--- a/src/mongo/dbtests/mmaptests.cpp
+++ b/src/mongo/dbtests/mmaptests.cpp
@@ -32,6 +32,7 @@
#include <boost/filesystem/operations.hpp>
+#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/storage/mmap_v1/durable_mapped_file.h"
#include "mongo/util/timer.h"
#include "mongo/dbtests/dbtests.h"
diff --git a/src/mongo/dbtests/threadedtests.cpp b/src/mongo/dbtests/threadedtests.cpp
index ff03f10d65f..054aadbac7c 100644
--- a/src/mongo/dbtests/threadedtests.cpp
+++ b/src/mongo/dbtests/threadedtests.cpp
@@ -36,6 +36,7 @@
#include <boost/thread.hpp>
#include "mongo/db/concurrency/d_concurrency.h"
+#include "mongo/db/concurrency/lock_state.h"
#include "mongo/db/operation_context_impl.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/platform/atomic_word.h"