summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-12-17 17:18:47 +0000
committerevergreen <evergreen@mongodb.com>2019-12-17 17:18:47 +0000
commitd1df25b244934d387a1662294859da8e7b4d5192 (patch)
treedf32452ac1a98830e912c7450f85ab96baa56624 /src/mongo/db/concurrency
parent69fa20563044a4afff2fad76ed81c67bf487bc5d (diff)
downloadmongo-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/SConscript2
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp7
-rw-r--r--src/mongo/db/concurrency/lock_state_test.cpp40
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.