diff options
author | Dianna Hohensee <dianna.hohensee@10gen.com> | 2018-05-18 09:21:41 -0400 |
---|---|---|
committer | Dianna Hohensee <dianna.hohensee@10gen.com> | 2018-05-22 17:33:02 -0400 |
commit | adad00367e75e7c71a781e4610321f7be5d98aa6 (patch) | |
tree | 6d9b3bff2d9ebb956dca39c0ef53a549d03240c5 /src/mongo/db/concurrency/lock_state_test.cpp | |
parent | 018f33cb0e0f64880295b6d910060365c117a835 (diff) | |
download | mongo-adad00367e75e7c71a781e4610321f7be5d98aa6.tar.gz |
SERVER-33198 Add complete two-phase locking testing to lock_state_test.cpp
Diffstat (limited to 'src/mongo/db/concurrency/lock_state_test.cpp')
-rw-r--r-- | src/mongo/db/concurrency/lock_state_test.cpp | 128 |
1 files changed, 70 insertions, 58 deletions
diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index 00e7e2e0755..4aa0888f51e 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -304,67 +304,98 @@ TEST(LockerImpl, CanceledDeadlockUnblocks) { ASSERT(locker3.unlockGlobal()); } -TEST(LockerImpl, MODE_ISLocksUseTwoPhaseLockingWhenSharedLocksShouldTwoPhaseLockIsTrue) { - const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); +TEST(LockerImpl, SharedLocksShouldTwoPhaseLockIsTrue) { + // Test that when setSharedLocksShouldTwoPhaseLock is true and we are in a WUOW, unlock on IS + // and S locks are postponed until endWriteUnitOfWork() is called. Mode IX and X locks always + // participate in two-phased locking, regardless of the setting. + + const ResourceId globalResId(RESOURCE_GLOBAL, ResourceId::SINGLETON_GLOBAL); + const ResourceId resId1(RESOURCE_DATABASE, "TestDB1"_sd); + const ResourceId resId2(RESOURCE_DATABASE, "TestDB2"_sd); + const ResourceId resId3(RESOURCE_COLLECTION, "TestDB.collection3"_sd); + const ResourceId resId4(RESOURCE_COLLECTION, "TestDB.collection4"_sd); DefaultLockerImpl locker; locker.setSharedLocksShouldTwoPhaseLock(true); - locker.lockGlobal(MODE_IS); - - ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_IS)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IS)); - - locker.beginWriteUnitOfWork(); - - ASSERT_FALSE(locker.unlock(resId)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IS)); - - locker.endWriteUnitOfWork(); - - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_NONE)); - locker.unlockGlobal(); -} - -TEST(LockerImpl, MODE_ISLocksDoNotUseTwoPhaseLockingWhenSharedLocksShouldTwoPhaseLockIsFalse) { - const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - - DefaultLockerImpl locker; - locker.lockGlobal(MODE_IS); + ASSERT_EQ(LOCK_OK, locker.lockGlobal(MODE_IS)); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_IS); - ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_IS)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_IS)); + ASSERT_EQ(LOCK_OK, locker.lock(resId1, MODE_IS)); + ASSERT_EQ(LOCK_OK, locker.lock(resId2, MODE_IX)); + ASSERT_EQ(LOCK_OK, locker.lock(resId3, MODE_S)); + ASSERT_EQ(LOCK_OK, locker.lock(resId4, MODE_X)); + ASSERT_EQ(locker.getLockMode(resId1), MODE_IS); + ASSERT_EQ(locker.getLockMode(resId2), MODE_IX); + ASSERT_EQ(locker.getLockMode(resId3), MODE_S); + ASSERT_EQ(locker.getLockMode(resId4), MODE_X); locker.beginWriteUnitOfWork(); - ASSERT_TRUE(locker.unlock(resId)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_NONE)); + ASSERT_FALSE(locker.unlock(resId1)); + ASSERT_FALSE(locker.unlock(resId2)); + ASSERT_FALSE(locker.unlock(resId3)); + ASSERT_FALSE(locker.unlock(resId4)); + ASSERT_EQ(locker.getLockMode(resId1), MODE_IS); + ASSERT_EQ(locker.getLockMode(resId2), MODE_IX); + ASSERT_EQ(locker.getLockMode(resId3), MODE_S); + ASSERT_EQ(locker.getLockMode(resId4), MODE_X); + + ASSERT_FALSE(locker.unlockGlobal()); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_IS); locker.endWriteUnitOfWork(); - locker.unlockGlobal(); + ASSERT_EQ(locker.getLockMode(resId1), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId2), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId3), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId4), MODE_NONE); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_NONE); } -TEST(LockerImpl, MODE_SLocksUseTwoPhaseLockingWhenSharedLocksShouldTwoPhaseLockIsTrue) { - const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); +TEST(LockerImpl, ModeIXAndXLockParticipatesInTwoPhaseLocking) { + // Unlock on mode IX and X locks during a WUOW should always be postponed until + // endWriteUnitOfWork() is called. Mode IS and S locks should unlock immediately. + + const ResourceId globalResId(RESOURCE_GLOBAL, ResourceId::SINGLETON_GLOBAL); + const ResourceId resId1(RESOURCE_DATABASE, "TestDB1"_sd); + const ResourceId resId2(RESOURCE_DATABASE, "TestDB2"_sd); + const ResourceId resId3(RESOURCE_COLLECTION, "TestDB.collection3"_sd); + const ResourceId resId4(RESOURCE_COLLECTION, "TestDB.collection4"_sd); DefaultLockerImpl locker; - locker.setSharedLocksShouldTwoPhaseLock(true); - locker.lockGlobal(MODE_IS); - ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_S)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_S)); + ASSERT_EQ(LOCK_OK, locker.lockGlobal(MODE_IX)); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_IX); + + ASSERT_EQ(LOCK_OK, locker.lock(resId1, MODE_IS)); + ASSERT_EQ(LOCK_OK, locker.lock(resId2, MODE_IX)); + ASSERT_EQ(LOCK_OK, locker.lock(resId3, MODE_S)); + ASSERT_EQ(LOCK_OK, locker.lock(resId4, MODE_X)); + ASSERT_EQ(locker.getLockMode(resId1), MODE_IS); + ASSERT_EQ(locker.getLockMode(resId2), MODE_IX); + ASSERT_EQ(locker.getLockMode(resId3), MODE_S); + ASSERT_EQ(locker.getLockMode(resId4), MODE_X); locker.beginWriteUnitOfWork(); - ASSERT_FALSE(locker.unlock(resId)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_S)); + ASSERT_TRUE(locker.unlock(resId1)); + ASSERT_FALSE(locker.unlock(resId2)); + ASSERT_TRUE(locker.unlock(resId3)); + ASSERT_FALSE(locker.unlock(resId4)); + ASSERT_EQ(locker.getLockMode(resId1), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId2), MODE_IX); + ASSERT_EQ(locker.getLockMode(resId3), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId4), MODE_X); - locker.endWriteUnitOfWork(); + ASSERT_FALSE(locker.unlockGlobal()); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_IX); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_NONE)); + locker.endWriteUnitOfWork(); - locker.unlockGlobal(); + ASSERT_EQ(locker.getLockMode(resId2), MODE_NONE); + ASSERT_EQ(locker.getLockMode(resId4), MODE_NONE); + ASSERT_EQ(locker.getLockMode(globalResId), MODE_NONE); } TEST(LockerImpl, OverrideLockRequestTimeout) { @@ -438,25 +469,6 @@ TEST(LockerImpl, DoNotWaitForLockAcquisition) { ASSERT(locker2.unlockGlobal()); } -TEST(LockerImpl, MODE_SLocksDoNotUseTwoPhaseLockingWhenSharedLocksShouldTwoPhaseLockIsFalse) { - const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - - DefaultLockerImpl locker; - locker.lockGlobal(MODE_IS); - - ASSERT_EQ(LOCK_OK, locker.lock(resId, MODE_S)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_S)); - - locker.beginWriteUnitOfWork(); - - ASSERT_TRUE(locker.unlock(resId)); - ASSERT_TRUE(locker.isLockHeldForMode(resId, MODE_NONE)); - - locker.endWriteUnitOfWork(); - - locker.unlockGlobal(); -} - namespace { /** * Helper function to determine if 'lockerInfo' contains a lock with ResourceId 'resourceId' and |