TEST(LockManager, ConflictingConversionInTheMiddle) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); MMAPV1LockerImpl locker; TrackingLockGrantNotification notify; LockRequest request[3]; for (int i = 0; i < 3; i++) { request[i].initNew(&locker, ¬ify); lockMgr.lock(resId, &request[i], MODE_S); } // Upgrade the one in the middle (not the first one) ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request[1], MODE_X)); ASSERT(notify.numNotifies == 0); // Release the two shared modes lockMgr.unlock(&request[0]); ASSERT(notify.numNotifies == 0); lockMgr.unlock(&request[2]); ASSERT(notify.numNotifies == 1); ASSERT(request[1].mode == MODE_X); // Request 1 should be unlocked twice lockMgr.unlock(&request[1]); lockMgr.unlock(&request[1]); }
TEST(LockManager, CancelWaitingConversionStrongModes) { 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_S)); ASSERT(request1.numNotifies == 0); // Second request is granted right away ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S)); ASSERT(request2.numNotifies == 0); // Convert second request to conflicting ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request2, MODE_X)); ASSERT(request2.mode == MODE_S); ASSERT(request2.convertMode == MODE_X); ASSERT(request2.numNotifies == 0); // Cancel the conflicting upgrade lockMgr.unlock(&request2); ASSERT(request2.mode == MODE_S); ASSERT(request2.convertMode == MODE_NONE); ASSERT(request2.numNotifies == 0); // Free the remaining locks so the LockManager destructor does not complain lockMgr.unlock(&request1); lockMgr.unlock(&request2); }
TEST(LockManager, ConflictingConversion) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); MMAPV1LockerImpl locker1; MMAPV1LockerImpl locker2; LockRequestCombo request1(&locker1); LockRequestCombo request2(&locker2); // The S requests are granted right away ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S)); ASSERT(request1.numNotifies == 0); ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S)); ASSERT(request2.numNotifies == 0); // Convert first request to conflicting ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request1, MODE_X)); ASSERT(request1.numNotifies == 0); // Free the second lock and make sure the first is granted lockMgr.unlock(&request2); ASSERT(request1.mode == MODE_X); ASSERT(request1.numNotifies == 1); ASSERT(request2.numNotifies == 0); // Frees the first reference, mode remains X lockMgr.unlock(&request1); ASSERT(request1.mode == MODE_X); ASSERT(request1.recursiveCount == 1); lockMgr.unlock(&request1); }
TEST(LockManager, GrantRecursiveNonCompatibleConvertDown) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); MMAPV1LockerImpl locker; LockRequestCombo request(&locker); ASSERT(LOCK_OK == lockMgr.lock(resId, &request, MODE_X)); ASSERT(request.mode == MODE_X); ASSERT(request.recursiveCount == 1); ASSERT(request.numNotifies == 0); // Acquire again, in *non-compatible*, but less strict mode ASSERT(LOCK_OK == lockMgr.convert(resId, &request, MODE_S)); ASSERT(request.mode == MODE_X); ASSERT(request.recursiveCount == 2); ASSERT(request.numNotifies == 0); // Release first acquire lockMgr.unlock(&request); ASSERT(request.mode == MODE_X); ASSERT(request.recursiveCount == 1); // Release second acquire lockMgr.unlock(&request); ASSERT(request.recursiveCount == 0); }
TEST(LockManager, ConvertUpgrade) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); MMAPV1LockerImpl locker1; LockRequestCombo request1(&locker1); ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S)); MMAPV1LockerImpl locker2; LockRequestCombo request2(&locker2); ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S)); // Upgrade the S lock to X ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request1, MODE_X)); ASSERT(!lockMgr.unlock(&request1)); ASSERT(lockMgr.unlock(&request1)); ASSERT(lockMgr.unlock(&request2)); }