summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2016-05-31 12:39:51 +0300
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2016-06-15 13:57:58 -0400
commita481e3a9987a8dc7059402c66dd22bfe51d1a818 (patch)
tree9fe137eff8151bbda295e1f7096e07591261b09d
parentb968ee2da9478d13408c83f606194caec34ea169 (diff)
downloadmongo-a481e3a9987a8dc7059402c66dd22bfe51d1a818.tar.gz
SERVER-24316 Add lock conversion cancellation unit-test
This change adds a unit-test to ensure that upgrade from 'weak mode' to 'strong mode' preserves the grant counts correctly. It also tightens the assertions around lock mode conversion.
-rw-r--r--src/mongo/db/concurrency/lock_manager.cpp1
-rw-r--r--src/mongo/db/concurrency/lock_manager_test.cpp37
2 files changed, 37 insertions, 1 deletions
diff --git a/src/mongo/db/concurrency/lock_manager.cpp b/src/mongo/db/concurrency/lock_manager.cpp
index b2b04e788ef..6d2450086fe 100644
--- a/src/mongo/db/concurrency/lock_manager.cpp
+++ b/src/mongo/db/concurrency/lock_manager.cpp
@@ -619,6 +619,7 @@ bool LockManager::unlock(LockRequest* request) {
} else if (request->status == LockRequest::STATUS_CONVERTING) {
// This cancels a pending convert request
invariant(request->recursiveCount > 0);
+ invariant(lock->conversionsCount > 0);
// Lock only goes from GRANTED to CONVERTING, so cancelling the conversion request
// brings it back to the previous granted mode.
diff --git a/src/mongo/db/concurrency/lock_manager_test.cpp b/src/mongo/db/concurrency/lock_manager_test.cpp
index aa2edef04b4..218dd6227ad 100644
--- a/src/mongo/db/concurrency/lock_manager_test.cpp
+++ b/src/mongo/db/concurrency/lock_manager_test.cpp
@@ -414,7 +414,42 @@ TEST(LockManager, ConflictCancelMultipleWaiting) {
lockMgr.unlock(&request[0]);
}
-TEST(LockManager, ConflictCancelWaitingConversion) {
+TEST(LockManager, CancelWaitingConversionWeakModes) {
+ LockManager lockMgr;
+ const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));
+
+ MMAPV1LockerImpl locker1;
+ MMAPV1LockerImpl locker2;
+
+ LockRequestCombo request1(&locker1);
+ LockRequestCombo request2(&locker2);
+
+ // First request granted right away
+ ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_IS));
+ ASSERT(request1.numNotifies == 0);
+
+ // Second request is granted right away
+ ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_IX));
+ ASSERT(request2.numNotifies == 0);
+
+ // Convert first request to conflicting
+ ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request1, MODE_S));
+ ASSERT(request1.mode == MODE_IS);
+ ASSERT(request1.convertMode == MODE_S);
+ ASSERT(request1.numNotifies == 0);
+
+ // Cancel the conflicting conversion
+ lockMgr.unlock(&request1);
+ ASSERT(request1.mode == MODE_IS);
+ ASSERT(request1.convertMode == MODE_NONE);
+ ASSERT(request1.numNotifies == 0);
+
+ // Free the remaining locks so the LockManager destructor does not complain
+ lockMgr.unlock(&request1);
+ lockMgr.unlock(&request2);
+}
+
+TEST(LockManager, CancelWaitingConversionStrongModes) {
LockManager lockMgr;
const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));