diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2014-09-05 11:04:55 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2014-09-05 12:54:30 -0400 |
commit | 51fbe5568f0b76fda292a9864f65299df77b61fa (patch) | |
tree | 36b5cba05795310dfc51b7b479564aa6119cf2ac /src | |
parent | c175aede88469969320d4935f3b2afb5a07cd4fc (diff) | |
download | mongo-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.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_mgr_new.h | 10 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_mgr_new_test.cpp | 55 |
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, ¬ify); + + ASSERT(LOCK_OK == lockMgr.lock(resId, &request, existingMode)); + } + + { + LockState locker; + TrackingLockGrantNotification notify; + LockRequest request; + request.initNew(resId, &locker, ¬ify); + + 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 |