diff options
author | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-02-12 19:11:06 -0500 |
---|---|---|
committer | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-03-04 18:59:23 -0500 |
commit | 6f3c3df4fc0abda76fd97e970ced4a01f0c48007 (patch) | |
tree | 45945a8d3bfd8ccead97946be88168b01298d817 /src/mongo/db/concurrency | |
parent | a8ecb4270d7a5590c9509ff47c2670432122bf07 (diff) | |
download | mongo-6f3c3df4fc0abda76fd97e970ced4a01f0c48007.tar.gz |
SERVER-39154 Create a fail point to make it so if a LockManager lock cannot be acquired immediately, then the operation fails
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state_test.cpp | 29 |
2 files changed, 42 insertions, 0 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index 0ce20b0aa3b..fc5457d3172 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -42,11 +42,15 @@ #include "mongo/util/background.h" #include "mongo/util/concurrency/ticketholder.h" #include "mongo/util/debug_util.h" +#include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" #include "mongo/util/scopeguard.h" namespace mongo { + +MONGO_FAIL_POINT_DEFINE(failNonIntentLocksIfWaitNeeded); + namespace { /** @@ -474,6 +478,15 @@ void LockerImpl::lock(OperationContext* opCtx, ResourceId resId, LockMode mode, invariant(result == LOCK_WAITING); + // This failpoint is used to time out non-intent locks if they cannot be granted immediately. + // Testing-only. + if (MONGO_FAIL_POINT(failNonIntentLocksIfWaitNeeded)) { + uassert(ErrorCodes::LockTimeout, + str::stream() << "Cannot immediately acquire lock '" << resId.toString() + << "'. Timing out due to failpoint.", + (mode == MODE_IS || mode == MODE_IX)); + } + lockComplete(opCtx, resId, mode, deadline); } diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index 115d1b5c42b..e6bc546b11f 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -39,6 +39,7 @@ #include "mongo/db/concurrency/lock_manager_test_help.h" #include "mongo/db/concurrency/locker.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" #include "mongo/util/timer.h" @@ -120,6 +121,34 @@ TEST(LockerImpl, ConflictUpgradeWithTimeout) { locker2.unlockGlobal(); } +TEST(LockerImpl, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediatelyGranted) { + // Granted MODE_X lock, fail incoming MODE_S and MODE_X. + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + LockerImpl locker1; + locker1.lockGlobal(MODE_IX); + locker1.lock(resId, MODE_X); + + { + FailPointEnableBlock failWaitingNonPartitionedLocks("failNonIntentLocksIfWaitNeeded"); + + // MODE_S attempt. + LockerImpl locker2; + locker2.lockGlobal(MODE_IS); + ASSERT_THROWS_CODE( + locker2.lock(resId, MODE_S, Date_t::max()), DBException, ErrorCodes::LockTimeout); + locker2.unlockGlobal(); + + // MODE_X attempt. + LockerImpl locker3; + locker3.lockGlobal(MODE_IX); + ASSERT_THROWS_CODE( + locker3.lock(resId, MODE_X, Date_t::max()), DBException, ErrorCodes::LockTimeout); + locker3.unlockGlobal(); + } + + locker1.unlockGlobal(); +} TEST(LockerImpl, ReadTransaction) { LockerImpl locker; |