diff options
author | Gregory Wlodarek <gregory.wlodarek@mongodb.com> | 2019-12-17 17:18:47 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-12-17 17:18:47 +0000 |
commit | d1df25b244934d387a1662294859da8e7b4d5192 (patch) | |
tree | df32452ac1a98830e912c7450f85ab96baa56624 /src/mongo/db/concurrency | |
parent | 69fa20563044a4afff2fad76ed81c67bf487bc5d (diff) | |
download | mongo-d1df25b244934d387a1662294859da8e7b4d5192.tar.gz |
SERVER-45135 Make the 'failNonIntentLocksIfWaitNeeded' fail point only throw LockTimeout for user operations
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r-- | src/mongo/db/concurrency/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state_test.cpp | 40 |
3 files changed, 36 insertions, 13 deletions
diff --git a/src/mongo/db/concurrency/SConscript b/src/mongo/db/concurrency/SConscript index 752fe830f1f..ce94b838109 100644 --- a/src/mongo/db/concurrency/SConscript +++ b/src/mongo/db/concurrency/SConscript @@ -92,6 +92,8 @@ env.CppUnitTest( '$BUILD_DIR/mongo/db/curop', '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/util/progress_meter', + '$BUILD_DIR/mongo/transport/transport_layer_common', + '$BUILD_DIR/mongo/transport/transport_layer_mock', 'lock_manager', 'write_conflict_exception', ] diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index 508713b7d02..6cc0f0ee260 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -893,9 +893,10 @@ void LockerImpl::_lockComplete(OperationContext* opCtx, _unlockImpl(&it); }); - // This failpoint is used to time out non-intent locks if they cannot be granted immediately. - // Testing-only. - if (!_uninterruptibleLocksRequested && + // This failpoint is used to time out non-intent locks if they cannot be granted immediately + // for user operations. Testing-only. + const bool isUserOperation = opCtx && opCtx->getClient()->isFromUserConnection(); + if (!_uninterruptibleLocksRequested && isUserOperation && MONGO_unlikely(failNonIntentLocksIfWaitNeeded.shouldFail())) { uassert(ErrorCodes::LockTimeout, str::stream() << "Cannot immediately acquire lock '" << resId.toString() diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index 81a6f59968a..95e907260ef 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -39,6 +39,8 @@ #include "mongo/db/concurrency/lock_manager_test_help.h" #include "mongo/db/concurrency/locker.h" #include "mongo/db/service_context_test_fixture.h" +#include "mongo/transport/session.h" +#include "mongo/transport/transport_layer_mock.h" #include "mongo/unittest/unittest.h" #include "mongo/util/fail_point.h" #include "mongo/util/log.h" @@ -129,6 +131,13 @@ TEST_F(LockerImplTest, ConflictUpgradeWithTimeout) { } TEST_F(LockerImplTest, FailPointInLockFailsGlobalNonIntentLocksIfTheyCannotBeImmediatelyGranted) { + transport::TransportLayerMock transportLayer; + transport::SessionHandle session = transportLayer.createSession(); + + auto newClient = getServiceContext()->makeClient("userClient", session); + AlternativeClientRegion acr(newClient); + auto newOpCtx = cc().makeOperationContext(); + LockerImpl locker1; locker1.lockGlobal(MODE_IX); @@ -137,32 +146,42 @@ TEST_F(LockerImplTest, FailPointInLockFailsGlobalNonIntentLocksIfTheyCannotBeImm // MODE_S attempt. LockerImpl locker2; - ASSERT_THROWS_CODE(locker2.lockGlobal(MODE_S), DBException, ErrorCodes::LockTimeout); + ASSERT_THROWS_CODE( + locker2.lockGlobal(newOpCtx.get(), MODE_S), DBException, ErrorCodes::LockTimeout); // MODE_X attempt. LockerImpl locker3; - ASSERT_THROWS_CODE(locker3.lockGlobal(MODE_X), DBException, ErrorCodes::LockTimeout); + ASSERT_THROWS_CODE( + locker3.lockGlobal(newOpCtx.get(), MODE_X), DBException, ErrorCodes::LockTimeout); } locker1.unlockGlobal(); } TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediatelyGranted) { + transport::TransportLayerMock transportLayer; + transport::SessionHandle session = transportLayer.createSession(); + + auto newClient = getServiceContext()->makeClient("userClient", session); + AlternativeClientRegion acr(newClient); + auto newOpCtx = cc().makeOperationContext(); + // 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); + locker1.lockGlobal(newOpCtx.get(), MODE_IX); + locker1.lock(newOpCtx.get(), 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.lockGlobal(newOpCtx.get(), MODE_IS); + ASSERT_THROWS_CODE(locker2.lock(newOpCtx.get(), resId, MODE_S, Date_t::max()), + DBException, + ErrorCodes::LockTimeout); // The timed out MODE_S attempt shouldn't be present in the map of lock requests because it // won't ever be granted. @@ -171,9 +190,10 @@ TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediate // MODE_X attempt. LockerImpl locker3; - locker3.lockGlobal(MODE_IX); - ASSERT_THROWS_CODE( - locker3.lock(resId, MODE_X, Date_t::max()), DBException, ErrorCodes::LockTimeout); + locker3.lockGlobal(newOpCtx.get(), MODE_IX); + ASSERT_THROWS_CODE(locker3.lock(newOpCtx.get(), resId, MODE_X, Date_t::max()), + DBException, + ErrorCodes::LockTimeout); // The timed out MODE_X attempt shouldn't be present in the map of lock requests because it // won't ever be granted. |