summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency/lock_state_test.cpp
diff options
context:
space:
mode:
authorMaria van Keulen <maria@mongodb.com>2018-03-23 11:32:55 -0400
committerMaria van Keulen <maria@mongodb.com>2018-04-05 12:00:29 -0400
commit6fbc1bbfcd5ffcfb451c300a6ef523f19d5edb55 (patch)
tree1c4af42fa4ce1e066fd5e62c0a2fd0528edceb10 /src/mongo/db/concurrency/lock_state_test.cpp
parent8cfec8c4e548e90b11f3002fb2347827473c4816 (diff)
downloadmongo-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.cpp121
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