summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-09-05 11:04:55 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2014-09-05 12:54:30 -0400
commit51fbe5568f0b76fda292a9864f65299df77b61fa (patch)
tree36b5cba05795310dfc51b7b479564aa6119cf2ac /src
parentc175aede88469969320d4935f3b2afb5a07cd4fc (diff)
downloadmongo-51fbe5568f0b76fda292a9864f65299df77b61fa.tar.gz
SERVER-14668 Fix the LockManager conflict matrix and add unit-test
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new.cpp16
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new.h10
-rw-r--r--src/mongo/db/concurrency/lock_mgr_new_test.cpp55
3 files changed, 76 insertions, 5 deletions
diff --git a/src/mongo/db/concurrency/lock_mgr_new.cpp b/src/mongo/db/concurrency/lock_mgr_new.cpp
index 0c3a48c0f56..95bea2b5783 100644
--- a/src/mongo/db/concurrency/lock_mgr_new.cpp
+++ b/src/mongo/db/concurrency/lock_mgr_new.cpp
@@ -51,13 +51,13 @@ namespace newlm {
0,
// MODE_IS
- 1 << MODE_X,
+ (1 << MODE_X),
// MODE_IX
- 1 << MODE_X,
+ (1 << MODE_S) | (1 << MODE_X),
// MODE_S
- 1 << MODE_X,
+ (1 << MODE_IX) | (1 << MODE_X),
// MODE_X
(1 << MODE_S) | (1 << MODE_X) | (1 << MODE_IS) | (1 << MODE_IX),
@@ -88,7 +88,7 @@ namespace newlm {
// LockManager
//
- LockManager::LockManager() {
+ LockManager::LockManager() : _noCheckForLeakedLocksTestOnly(false) {
// TODO: Generate this based on the # of CPUs. For now, use 1 bucket to make debugging
// easier.
_numLockBuckets = 1;
@@ -100,7 +100,9 @@ namespace newlm {
LockBucket* bucket = &_lockBuckets[i];
// TODO: dump more information about the non-empty bucket to see what locks were leaked
- invariant(bucket->data.empty());
+ if (!_noCheckForLeakedLocksTestOnly) {
+ invariant(bucket->data.empty());
+ }
}
}
@@ -274,6 +276,10 @@ namespace newlm {
}
}
+ void LockManager::setNoCheckForLeakedLocksTestOnly(bool newValue) {
+ _noCheckForLeakedLocksTestOnly = newValue;
+ }
+
void LockManager::_recalcAndGrant(LockHead* lock,
LockRequest* unlocked,
LockRequest* changed) {
diff --git a/src/mongo/db/concurrency/lock_mgr_new.h b/src/mongo/db/concurrency/lock_mgr_new.h
index fc64d416060..5833deb76a8 100644
--- a/src/mongo/db/concurrency/lock_mgr_new.h
+++ b/src/mongo/db/concurrency/lock_mgr_new.h
@@ -311,6 +311,13 @@ namespace newlm {
void dump() const;
+
+ //
+ // Test-only methods
+ //
+
+ void setNoCheckForLeakedLocksTestOnly(bool newValue);
+
private:
typedef std::map<const ResourceId, LockHead*> LockHeadMap;
@@ -349,6 +356,9 @@ namespace newlm {
unsigned _numLockBuckets;
LockBucket* _lockBuckets;
+
+ // This is for tests only and removes the validation for leaked locks in the destructor
+ bool _noCheckForLeakedLocksTestOnly;
};
} // namespace newlm
diff --git a/src/mongo/db/concurrency/lock_mgr_new_test.cpp b/src/mongo/db/concurrency/lock_mgr_new_test.cpp
index a846c3b6f7f..dfaebb4378b 100644
--- a/src/mongo/db/concurrency/lock_mgr_new_test.cpp
+++ b/src/mongo/db/concurrency/lock_mgr_new_test.cpp
@@ -552,5 +552,60 @@ namespace newlm {
lockMgr.unlock(&request[1]);
}
+
+
+ static void checkConflict(LockMode existingMode, LockMode newMode, bool hasConflict) {
+ LockManager lockMgr;
+ lockMgr.setNoCheckForLeakedLocksTestOnly(true);
+
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+
+ {
+ LockState locker;
+ TrackingLockGrantNotification notify;
+ LockRequest request;
+ request.initNew(resId, &locker, &notify);
+
+ ASSERT(LOCK_OK == lockMgr.lock(resId, &request, existingMode));
+ }
+
+ {
+ LockState locker;
+ TrackingLockGrantNotification notify;
+ LockRequest request;
+ request.initNew(resId, &locker, &notify);
+
+ LockResult result = lockMgr.lock(resId, &request, newMode);
+ if (hasConflict) {
+ ASSERT_EQUALS(LOCK_WAITING, result);
+ }
+ else {
+ ASSERT_EQUALS(LOCK_OK, result);
+ }
+ }
+ }
+
+ TEST(LockManager, ValidateConflictMatrix) {
+ checkConflict(MODE_IS, MODE_IS, false);
+ checkConflict(MODE_IS, MODE_IX, false);
+ checkConflict(MODE_IS, MODE_S, false);
+ checkConflict(MODE_IS, MODE_X, true);
+
+ checkConflict(MODE_IX, MODE_IS, false);
+ checkConflict(MODE_IX, MODE_IX, false);
+ checkConflict(MODE_IX, MODE_S, true);
+ checkConflict(MODE_IX, MODE_X, true);
+
+ checkConflict(MODE_S, MODE_IS, false);
+ checkConflict(MODE_S, MODE_IX, true);
+ checkConflict(MODE_S, MODE_S, false);
+ checkConflict(MODE_S, MODE_X, true);
+
+ checkConflict(MODE_X, MODE_IS, true);
+ checkConflict(MODE_X, MODE_IX, true);
+ checkConflict(MODE_X, MODE_S, true);
+ checkConflict(MODE_X, MODE_X, true);
+ }
+
} // namespace newlm
} // namespace mongo