diff options
author | Maria van Keulen <maria@mongodb.com> | 2018-03-23 11:32:55 -0400 |
---|---|---|
committer | Maria van Keulen <maria@mongodb.com> | 2018-04-05 12:00:29 -0400 |
commit | 6fbc1bbfcd5ffcfb451c300a6ef523f19d5edb55 (patch) | |
tree | 1c4af42fa4ce1e066fd5e62c0a2fd0528edceb10 /src/mongo/db/concurrency/lock_state_test.cpp | |
parent | 8cfec8c4e548e90b11f3002fb2347827473c4816 (diff) | |
download | mongo-6fbc1bbfcd5ffcfb451c300a6ef523f19d5edb55.tar.gz |
SERVER-33610 Recycle 2-phase-locks pending unlock during lock acquisition
Diffstat (limited to 'src/mongo/db/concurrency/lock_state_test.cpp')
-rw-r--r-- | src/mongo/db/concurrency/lock_state_test.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index a244378fbfe..5e37fdf5e35 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -472,4 +472,125 @@ TEST(LockerImpl, GetLockerInfoShouldReportPendingLocks) { ASSERT(conflictingLocker.unlockGlobal()); } +TEST(LockerImpl, ReaquireLockPendingUnlock) { + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + DefaultLockerImpl locker; + locker.lockGlobal(MODE_IS); + + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_X)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + + locker.beginWriteUnitOfWork(); + + ASSERT_FALSE(locker.unlock(resId)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + // Reacquire lock pending unlock. + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_X)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 0); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 0); + + locker.endWriteUnitOfWork(); + + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + + locker.unlockGlobal(); +} + +TEST(LockerImpl, AcquireLockPendingUnlockWithCoveredMode) { + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + DefaultLockerImpl locker; + locker.lockGlobal(MODE_IS); + + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_X)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + + locker.beginWriteUnitOfWork(); + + ASSERT_FALSE(locker.unlock(resId)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + // Attempt to lock the resource with a mode that is covered by the existing mode. + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_IX)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 0); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 0); + + locker.endWriteUnitOfWork(); + + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IX)); + + locker.unlockGlobal(); +} + +TEST(LockerImpl, ConvertLockPendingUnlock) { + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + DefaultLockerImpl locker; + locker.lockGlobal(MODE_IS); + + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_IX)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IX)); + + locker.beginWriteUnitOfWork(); + + ASSERT_FALSE(locker.unlock(resId)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IX)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + // Convert lock pending unlock. + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_X)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + locker.endWriteUnitOfWork(); + + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 0); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 0); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_X)); + + locker.unlockGlobal(); +} + +TEST(LockerImpl, ConvertLockPendingUnlockAndUnlock) { + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + DefaultLockerImpl locker; + locker.lockGlobal(MODE_IS); + + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_IX)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IX)); + + locker.beginWriteUnitOfWork(); + + ASSERT_FALSE(locker.unlock(resId)); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IX)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + // Convert lock pending unlock. + ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_X)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 1); + + // Unlock the lock conversion. + ASSERT_FALSE(locker.unlock(resId)); + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 1); + ASSERT(locker.getRequestsForTest().find(resId).objAddr()->unlockPending == 2); + + locker.endWriteUnitOfWork(); + + ASSERT(locker.numResourcesToUnlockAtEndUnitOfWorkForTest() == 0); + ASSERT(locker.getRequestsForTest().find(resId).finished()); + ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_NONE)); + + locker.unlockGlobal(); +} + } // namespace mongo |