diff options
24 files changed, 265 insertions, 244 deletions
diff --git a/src/mongo/db/catalog/collection_catalog_bm.cpp b/src/mongo/db/catalog/collection_catalog_bm.cpp index eedb6bf1e1c..3ff0e3375bd 100644 --- a/src/mongo/db/catalog/collection_catalog_bm.cpp +++ b/src/mongo/db/catalog/collection_catalog_bm.cpp @@ -51,7 +51,7 @@ public: void onDestroyClient(Client* client) final {} void onCreateOperationContext(OperationContext* opCtx) override { - opCtx->setLockState(std::make_unique<LockerImpl>()); + opCtx->setLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); } void onDestroyOperationContext(OperationContext* opCtx) final {} diff --git a/src/mongo/db/catalog_raii_test.cpp b/src/mongo/db/catalog_raii_test.cpp index 2e615b22061..8e849db9c7e 100644 --- a/src/mongo/db/catalog_raii_test.cpp +++ b/src/mongo/db/catalog_raii_test.cpp @@ -57,7 +57,7 @@ public: ClientAndCtx makeClientWithLocker(const std::string& clientName) { auto client = getServiceContext()->makeClient(clientName); auto opCtx = client->makeOperationContext(); - client->swapLockState(std::make_unique<LockerImpl>()); + client->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); return std::make_pair(std::move(client), std::move(opCtx)); } diff --git a/src/mongo/db/concurrency/d_concurrency_bm.cpp b/src/mongo/db/concurrency/d_concurrency_bm.cpp index dd9b3223081..d59755db9db 100644 --- a/src/mongo/db/concurrency/d_concurrency_bm.cpp +++ b/src/mongo/db/concurrency/d_concurrency_bm.cpp @@ -58,7 +58,7 @@ public: void onDestroyClient(Client* client) final {} void onCreateOperationContext(OperationContext* opCtx) override { - opCtx->setLockState(std::make_unique<LockerImpl>()); + opCtx->setLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); } void onDestroyOperationContext(OperationContext* opCtx) final {} @@ -83,6 +83,7 @@ public: auto client = getGlobalServiceContext()->makeClient(str::stream() << "test client for thread " << i); auto opCtx = client->makeOperationContext(); + locker[i] = std::make_unique<LockerImpl>(opCtx->getServiceContext()); clients.emplace_back(std::move(client), std::move(opCtx)); } } @@ -90,7 +91,7 @@ public: protected: std::vector<std::pair<ServiceContext::UniqueClient, ServiceContext::UniqueOperationContext>> clients; - std::array<LockerImpl, kMaxPerfThreads> locker; + std::array<std::unique_ptr<LockerImpl>, kMaxPerfThreads> locker; }; BENCHMARK_DEFINE_F(DConcurrencyTest, BM_StdMutex)(benchmark::State& state) { @@ -105,7 +106,7 @@ BENCHMARK_DEFINE_F(DConcurrencyTest, BM_ResourceMutexShared)(benchmark::State& s static Lock::ResourceMutex mtx("testMutex"); for (auto keepRunning : state) { - Lock::SharedLock lk(&locker[state.thread_index], mtx); + Lock::SharedLock lk(locker[state.thread_index].get(), mtx); } } @@ -113,7 +114,7 @@ BENCHMARK_DEFINE_F(DConcurrencyTest, BM_ResourceMutexExclusive)(benchmark::State static Lock::ResourceMutex mtx("testMutex"); for (auto keepRunning : state) { - Lock::ExclusiveLock lk(&locker[state.thread_index], mtx); + Lock::ExclusiveLock lk(locker[state.thread_index].get(), mtx); } } diff --git a/src/mongo/db/concurrency/d_concurrency_test.cpp b/src/mongo/db/concurrency/d_concurrency_test.cpp index b4b0f801efa..233d1dd1842 100644 --- a/src/mongo/db/concurrency/d_concurrency_test.cpp +++ b/src/mongo/db/concurrency/d_concurrency_test.cpp @@ -71,15 +71,18 @@ const auto kMaxClockJitterMillis = Milliseconds(0); class UseGlobalThrottling { public: explicit UseGlobalThrottling(OperationContext* opCtx, int numTickets) { - auto& ticketHolders = ticketHoldersDecoration(getGlobalServiceContext()); + auto& ticketHolders = TicketHolders::get(opCtx->getServiceContext()); ticketHolders.setGlobalThrottling( std::make_unique<SemaphoreTicketHolder>(numTickets, nullptr), std::make_unique<SemaphoreTicketHolder>(numTickets, nullptr)); + _ticketHolders = &ticketHolders; } ~UseGlobalThrottling() noexcept(false) { - auto& ticketHolders = ticketHoldersDecoration(getGlobalServiceContext()); - ticketHolders.setGlobalThrottling(nullptr, nullptr); + _ticketHolders->setGlobalThrottling(nullptr, nullptr); } + +private: + TicketHolders* _ticketHolders; }; @@ -98,7 +101,7 @@ public: auto client = getServiceContext()->makeClient(str::stream() << "test client for thread " << i); auto opCtx = client->makeOperationContext(); - client->swapLockState(std::make_unique<LockerImpl>()); + client->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); clients.emplace_back(std::move(client), std::move(opCtx)); } return clients; @@ -134,13 +137,13 @@ public: TEST_F(DConcurrencyTestFixture, WriteConflictRetryInstantiatesOK) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); writeConflictRetry(opCtx.get(), "", "", [] {}); } TEST_F(DConcurrencyTestFixture, WriteConflictRetryRetriesFunctionOnWriteConflictException) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto&& opDebug = CurOp::get(opCtx.get())->debug(); ASSERT_EQUALS(0, opDebug.additiveMetrics.writeConflicts.load()); ASSERT_EQUALS(100, writeConflictRetry(opCtx.get(), "", "", [&opDebug] { @@ -154,7 +157,7 @@ TEST_F(DConcurrencyTestFixture, WriteConflictRetryRetriesFunctionOnWriteConflict TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesNonWriteConflictException) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); ASSERT_THROWS_CODE(writeConflictRetry(opCtx.get(), "", "", @@ -169,7 +172,7 @@ TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesNonWriteConflictExce TEST_F(DConcurrencyTestFixture, WriteConflictRetryPropagatesWriteConflictExceptionIfAlreadyInAWriteUnitOfWork) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::GlobalWrite globalWrite(opCtx.get()); WriteUnitOfWork wuow(opCtx.get()); ASSERT_THROWS(writeConflictRetry(opCtx.get(), "", "", [] { throw WriteConflictException(); }), @@ -178,9 +181,10 @@ TEST_F(DConcurrencyTestFixture, TEST_F(DConcurrencyTestFixture, ResourceMutex) { Lock::ResourceMutex mtx("testMutex"); - LockerImpl locker1; - LockerImpl locker2; - LockerImpl locker3; + auto opCtx = makeOperationContext(); + LockerImpl locker1(opCtx->getServiceContext()); + LockerImpl locker2(opCtx->getServiceContext()); + LockerImpl locker3(opCtx->getServiceContext()); struct State { void check(int n) { @@ -257,7 +261,7 @@ TEST_F(DConcurrencyTestFixture, ResourceMutex) { TEST_F(DConcurrencyTestFixture, GlobalRead) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::GlobalRead globalRead(opCtx.get()); ASSERT(opCtx->lockState()->isR()); ASSERT_EQ(opCtx->lockState()->getLockMode(resourceIdReplicationStateTransitionLock), MODE_IX); @@ -265,7 +269,7 @@ TEST_F(DConcurrencyTestFixture, GlobalRead) { TEST_F(DConcurrencyTestFixture, GlobalWrite) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::GlobalWrite globalWrite(opCtx.get()); ASSERT(opCtx->lockState()->isW()); ASSERT_EQ(opCtx->lockState()->getLockMode(resourceIdReplicationStateTransitionLock), MODE_IX); @@ -273,7 +277,7 @@ TEST_F(DConcurrencyTestFixture, GlobalWrite) { TEST_F(DConcurrencyTestFixture, GlobalWriteAndGlobalRead) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::GlobalWrite globalWrite(opCtx.get()); @@ -291,7 +295,7 @@ TEST_F(DConcurrencyTestFixture, GlobalWriteAndGlobalRead) { TEST_F(DConcurrencyTestFixture, GlobalWriteRequiresExplicitDowngradeToIntentWriteModeIfDestroyedWhileHoldingDatabaseLock) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); auto globalWrite = std::make_unique<Lock::GlobalWrite>(opCtx.get()); @@ -333,7 +337,7 @@ TEST_F(DConcurrencyTestFixture, TEST_F(DConcurrencyTestFixture, GlobalWriteRequiresSupportsDowngradeToIntentWriteModeWhileHoldingDatabaseLock) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); auto globalWrite = std::make_unique<Lock::GlobalWrite>(opCtx.get()); @@ -374,7 +378,7 @@ TEST_F(DConcurrencyTestFixture, TEST_F(DConcurrencyTestFixture, NestedGlobalWriteSupportsDowngradeToIntentWriteModeWhileHoldingDatabaseLock) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); auto outerGlobalWrite = std::make_unique<Lock::GlobalWrite>(opCtx.get()); @@ -1066,7 +1070,7 @@ TEST_F(DConcurrencyTestFixture, LockCompleteInterruptedWhenUncontested) { TEST_F(DConcurrencyTestFixture, DBLockTakesS) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbRead(opCtx.get(), "db", MODE_S); const ResourceId resIdDb(RESOURCE_DATABASE, std::string("db")); @@ -1075,7 +1079,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesS) { TEST_F(DConcurrencyTestFixture, DBLockTakesX) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbWrite(opCtx.get(), "db", MODE_X); const ResourceId resIdDb(RESOURCE_DATABASE, std::string("db")); @@ -1084,7 +1088,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesX) { TEST_F(DConcurrencyTestFixture, DBLockTakesISForAdminIS) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbRead(opCtx.get(), "admin", MODE_IS); ASSERT(opCtx->lockState()->getLockMode(resourceIdAdminDB) == MODE_IS); @@ -1092,7 +1096,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesISForAdminIS) { TEST_F(DConcurrencyTestFixture, DBLockTakesSForAdminS) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbRead(opCtx.get(), "admin", MODE_S); ASSERT(opCtx->lockState()->getLockMode(resourceIdAdminDB) == MODE_S); @@ -1100,7 +1104,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesSForAdminS) { TEST_F(DConcurrencyTestFixture, DBLockTakesIXForAdminIX) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbWrite(opCtx.get(), "admin", MODE_IX); ASSERT(opCtx->lockState()->getLockMode(resourceIdAdminDB) == MODE_IX); @@ -1108,7 +1112,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesIXForAdminIX) { TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminX) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock dbWrite(opCtx.get(), "admin", MODE_X); ASSERT(opCtx->lockState()->getLockMode(resourceIdAdminDB) == MODE_X); @@ -1116,7 +1120,7 @@ TEST_F(DConcurrencyTestFixture, DBLockTakesXForAdminX) { TEST_F(DConcurrencyTestFixture, MultipleWriteDBLocksOnSameThread) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); Lock::DBLock r1(opCtx.get(), "db1", MODE_X); Lock::DBLock r2(opCtx.get(), "db1", MODE_X); @@ -1125,7 +1129,7 @@ TEST_F(DConcurrencyTestFixture, MultipleWriteDBLocksOnSameThread) { TEST_F(DConcurrencyTestFixture, MultipleConflictingDBLocksOnSameThread) { auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::DBLock r1(opCtx.get(), "db1", MODE_X); Lock::DBLock r2(opCtx.get(), "db1", MODE_S); @@ -1138,7 +1142,7 @@ TEST_F(DConcurrencyTestFixture, IsDbLockedForSMode) { const std::string dbName("db"); auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), dbName, MODE_S); @@ -1152,7 +1156,7 @@ TEST_F(DConcurrencyTestFixture, IsDbLockedForXMode) { const std::string dbName("db"); auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), dbName, MODE_X); @@ -1166,7 +1170,7 @@ TEST_F(DConcurrencyTestFixture, IsCollectionLocked_DB_Locked_IS) { const NamespaceString ns("db1.coll"); auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), "db1", MODE_IS); @@ -1194,7 +1198,7 @@ TEST_F(DConcurrencyTestFixture, IsCollectionLocked_DB_Locked_IX) { const NamespaceString ns("db1.coll"); auto opCtx = makeOperationContext(); - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto lockState = opCtx->lockState(); Lock::DBLock dbLock(opCtx.get(), "db1", MODE_IX); @@ -2188,9 +2192,9 @@ TEST_F(DConcurrencyTestFixture, FailPointInLockDoesNotFailUninterruptibleGlobalN FailPointEnableBlock failWaitingNonPartitionedLocks("failNonIntentLocksIfWaitNeeded"); - LockerImpl locker1; - LockerImpl locker2; - LockerImpl locker3; + LockerImpl locker1(opCtx->getServiceContext()); + LockerImpl locker2(opCtx->getServiceContext()); + LockerImpl locker3(opCtx->getServiceContext()); { locker1.lockGlobal(opCtx.get(), MODE_IX); @@ -2232,9 +2236,9 @@ TEST_F(DConcurrencyTestFixture, FailPointInLockDoesNotFailUninterruptibleNonInte FailPointEnableBlock failWaitingNonPartitionedLocks("failNonIntentLocksIfWaitNeeded"); - LockerImpl locker1; - LockerImpl locker2; - LockerImpl locker3; + LockerImpl locker1(opCtx->getServiceContext()); + LockerImpl locker2(opCtx->getServiceContext()); + LockerImpl locker3(opCtx->getServiceContext()); // Granted MODE_X lock, fail incoming MODE_S and MODE_X. const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); diff --git a/src/mongo/db/concurrency/lock_manager_test.cpp b/src/mongo/db/concurrency/lock_manager_test.cpp index 73787f72c1e..ffc72d559b1 100644 --- a/src/mongo/db/concurrency/lock_manager_test.cpp +++ b/src/mongo/db/concurrency/lock_manager_test.cpp @@ -29,10 +29,13 @@ #include "mongo/db/concurrency/lock_manager_defs.h" #include "mongo/db/concurrency/lock_manager_test_help.h" +#include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" namespace mongo { +class LockManagerTest : public ServiceContextTest {}; + TEST(ResourceId, Semantics) { ResourceId resIdDb(RESOURCE_DATABASE, 324334234); ASSERT(resIdDb.getType() == RESOURCE_DATABASE); @@ -81,11 +84,11 @@ TEST(ResourceId, Masking) { // LockManager // -TEST(LockManager, Grant) { +TEST_F(LockManagerTest, Grant) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); TrackingLockGrantNotification notify; LockRequest request; @@ -100,11 +103,11 @@ TEST(LockManager, Grant) { ASSERT(request.recursiveCount == 0); } -TEST(LockManager, GrantMultipleNoConflict) { +TEST_F(LockManagerTest, GrantMultipleNoConflict) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); TrackingLockGrantNotification notify; LockRequest request[6]; @@ -133,13 +136,13 @@ TEST(LockManager, GrantMultipleNoConflict) { lockMgr.unlock(&request[4]); } -TEST(LockManager, GrantMultipleFIFOOrder) { +TEST_F(LockManagerTest, GrantMultipleFIFOOrder) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); std::unique_ptr<LockerImpl> locker[6]; for (int i = 0; i < 6; i++) { - locker[i].reset(new LockerImpl()); + locker[i].reset(new LockerImpl(getServiceContext())); } TrackingLockGrantNotification notify[6]; @@ -166,11 +169,11 @@ TEST(LockManager, GrantMultipleFIFOOrder) { lockMgr.unlock(&request[5]); } -TEST(LockManager, GrantRecursive) { +TEST_F(LockManagerTest, GrantRecursive) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); LockRequestCombo request(&locker); ASSERT(LOCK_OK == lockMgr.lock(resId, &request, MODE_S)); @@ -194,11 +197,11 @@ TEST(LockManager, GrantRecursive) { ASSERT(request.recursiveCount == 0); } -TEST(LockManager, GrantRecursiveCompatibleConvertUp) { +TEST_F(LockManagerTest, GrantRecursiveCompatibleConvertUp) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); LockRequestCombo request(&locker); ASSERT(LOCK_OK == lockMgr.lock(resId, &request, MODE_IS)); @@ -222,11 +225,11 @@ TEST(LockManager, GrantRecursiveCompatibleConvertUp) { ASSERT(request.recursiveCount == 0); } -TEST(LockManager, GrantRecursiveNonCompatibleConvertUp) { +TEST_F(LockManagerTest, GrantRecursiveNonCompatibleConvertUp) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); LockRequestCombo request(&locker); ASSERT(LOCK_OK == lockMgr.lock(resId, &request, MODE_S)); @@ -250,11 +253,11 @@ TEST(LockManager, GrantRecursiveNonCompatibleConvertUp) { ASSERT(request.recursiveCount == 0); } -TEST(LockManager, GrantRecursiveNonCompatibleConvertDown) { +TEST_F(LockManagerTest, GrantRecursiveNonCompatibleConvertDown) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); LockRequestCombo request(&locker); ASSERT(LOCK_OK == lockMgr.lock(resId, &request, MODE_X)); @@ -278,12 +281,12 @@ TEST(LockManager, GrantRecursiveNonCompatibleConvertDown) { ASSERT(request.recursiveCount == 0); } -TEST(LockManager, Conflict) { +TEST_F(LockManagerTest, Conflict) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(getServiceContext()); + LockerImpl locker2(getServiceContext()); LockRequestCombo request1(&locker1); LockRequestCombo request2(&locker2); @@ -317,11 +320,11 @@ TEST(LockManager, Conflict) { ASSERT(request2.numNotifies == 1); } -TEST(LockManager, MultipleConflict) { +TEST_F(LockManagerTest, MultipleConflict) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); TrackingLockGrantNotification notify; LockRequest request[6]; @@ -350,14 +353,14 @@ TEST(LockManager, MultipleConflict) { } } -TEST(LockManager, ConflictCancelWaiting) { +TEST_F(LockManagerTest, ConflictCancelWaiting) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); TrackingLockGrantNotification notify1; - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); TrackingLockGrantNotification notify2; LockRequest request1; @@ -383,11 +386,11 @@ TEST(LockManager, ConflictCancelWaiting) { lockMgr.unlock(&request1); } -TEST(LockManager, ConflictCancelMultipleWaiting) { +TEST_F(LockManagerTest, ConflictCancelMultipleWaiting) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); TrackingLockGrantNotification notify; LockRequest request[6]; @@ -416,12 +419,12 @@ TEST(LockManager, ConflictCancelMultipleWaiting) { lockMgr.unlock(&request[0]); } -TEST(LockManager, CancelWaitingConversionWeakModes) { +TEST_F(LockManagerTest, CancelWaitingConversionWeakModes) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(getServiceContext()); + LockerImpl locker2(getServiceContext()); LockRequestCombo request1(&locker1); LockRequestCombo request2(&locker2); @@ -451,12 +454,12 @@ TEST(LockManager, CancelWaitingConversionWeakModes) { lockMgr.unlock(&request2); } -TEST(LockManager, CancelWaitingConversionStrongModes) { +TEST_F(LockManagerTest, CancelWaitingConversionStrongModes) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(getServiceContext()); + LockerImpl locker2(getServiceContext()); LockRequestCombo request1(&locker1); LockRequestCombo request2(&locker2); @@ -486,12 +489,12 @@ TEST(LockManager, CancelWaitingConversionStrongModes) { lockMgr.unlock(&request2); } -TEST(LockManager, ConflictingConversion) { +TEST_F(LockManagerTest, ConflictingConversion) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(getServiceContext()); + LockerImpl locker2(getServiceContext()); LockRequestCombo request1(&locker1); LockRequestCombo request2(&locker2); @@ -521,11 +524,11 @@ TEST(LockManager, ConflictingConversion) { lockMgr.unlock(&request1); } -TEST(LockManager, ConflictingConversionInTheMiddle) { +TEST_F(LockManagerTest, ConflictingConversionInTheMiddle) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker; + LockerImpl locker(getServiceContext()); TrackingLockGrantNotification notify; LockRequest request[3]; @@ -553,15 +556,15 @@ TEST(LockManager, ConflictingConversionInTheMiddle) { lockMgr.unlock(&request[1]); } -TEST(LockManager, ConvertUpgrade) { +TEST_F(LockManagerTest, ConvertUpgrade) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); LockRequestCombo request1(&locker1); ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S)); - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); LockRequestCombo request2(&locker2); ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S)); @@ -574,15 +577,15 @@ TEST(LockManager, ConvertUpgrade) { ASSERT(lockMgr.unlock(&request2)); } -TEST(LockManager, Downgrade) { +TEST_F(LockManagerTest, Downgrade) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); LockRequestCombo request1(&locker1); ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_X)); - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); LockRequestCombo request2(&locker2); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request2, MODE_S)); @@ -599,18 +602,21 @@ TEST(LockManager, Downgrade) { // Lock conflict matrix tests -static void checkConflict(LockMode existingMode, LockMode newMode, bool hasConflict) { +static void checkConflict(ServiceContext* serviceContext, + LockMode existingMode, + LockMode newMode, + bool hasConflict) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl lockerExisting; + LockerImpl lockerExisting(serviceContext); TrackingLockGrantNotification notifyExisting; LockRequest requestExisting; requestExisting.initNew(&lockerExisting, ¬ifyExisting); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestExisting, existingMode)); - LockerImpl lockerNew; + LockerImpl lockerNew(serviceContext); TrackingLockGrantNotification notifyNew; LockRequest requestNew; requestNew.initNew(&lockerNew, ¬ifyNew); @@ -626,45 +632,45 @@ static void checkConflict(LockMode existingMode, LockMode newMode, bool hasConfl lockMgr.unlock(&requestExisting); } -TEST(LockManager, ValidateConflictMatrix) { - checkConflict(MODE_IS, MODE_IS, false); - checkConflict(MODE_IS, MODE_IX, false); - checkConflict(MODE_IS, MODE_S, false); - checkConflict(MODE_IS, MODE_X, true); - - checkConflict(MODE_IX, MODE_IS, false); - checkConflict(MODE_IX, MODE_IX, false); - checkConflict(MODE_IX, MODE_S, true); - checkConflict(MODE_IX, MODE_X, true); - - checkConflict(MODE_S, MODE_IS, false); - checkConflict(MODE_S, MODE_IX, true); - checkConflict(MODE_S, MODE_S, false); - checkConflict(MODE_S, MODE_X, true); - - checkConflict(MODE_X, MODE_IS, true); - checkConflict(MODE_X, MODE_IX, true); - checkConflict(MODE_X, MODE_S, true); - checkConflict(MODE_X, MODE_X, true); +TEST_F(LockManagerTest, ValidateConflictMatrix) { + checkConflict(getServiceContext(), MODE_IS, MODE_IS, false); + checkConflict(getServiceContext(), MODE_IS, MODE_IX, false); + checkConflict(getServiceContext(), MODE_IS, MODE_S, false); + checkConflict(getServiceContext(), MODE_IS, MODE_X, true); + + checkConflict(getServiceContext(), MODE_IX, MODE_IS, false); + checkConflict(getServiceContext(), MODE_IX, MODE_IX, false); + checkConflict(getServiceContext(), MODE_IX, MODE_S, true); + checkConflict(getServiceContext(), MODE_IX, MODE_X, true); + + checkConflict(getServiceContext(), MODE_S, MODE_IS, false); + checkConflict(getServiceContext(), MODE_S, MODE_IX, true); + checkConflict(getServiceContext(), MODE_S, MODE_S, false); + checkConflict(getServiceContext(), MODE_S, MODE_X, true); + + checkConflict(getServiceContext(), MODE_X, MODE_IS, true); + checkConflict(getServiceContext(), MODE_X, MODE_IX, true); + checkConflict(getServiceContext(), MODE_X, MODE_S, true); + checkConflict(getServiceContext(), MODE_X, MODE_X, true); } -TEST(LockManager, EnqueueAtFront) { +TEST_F(LockManagerTest, EnqueueAtFront) { LockManager lockMgr; const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection")); - LockerImpl lockerX; + LockerImpl lockerX(getServiceContext()); LockRequestCombo requestX(&lockerX); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestX, MODE_X)); // The subsequent request will block - LockerImpl lockerLow; + LockerImpl lockerLow(getServiceContext()); LockRequestCombo requestLow(&lockerLow); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestLow, MODE_X)); // This is a "queue jumping request", which will go before locker 2 above - LockerImpl lockerHi; + LockerImpl lockerHi(getServiceContext()); LockRequestCombo requestHi(&lockerHi); requestHi.enqueueAtFront = true; @@ -686,18 +692,18 @@ TEST(LockManager, EnqueueAtFront) { ASSERT(lockMgr.unlock(&requestLow)); } -TEST(LockManager, CompatibleFirstImmediateGrant) { +TEST_F(LockManagerTest, CompatibleFirstImmediateGrant) { LockManager lockMgr; const ResourceId resId(RESOURCE_GLOBAL, 0); - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); LockRequestCombo request1(&locker1); - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); LockRequestCombo request2(&locker2); request2.compatibleFirst = true; - LockerImpl locker3; + LockerImpl locker3(getServiceContext()); LockRequestCombo request3(&locker3); // Lock all in IS mode @@ -706,14 +712,14 @@ TEST(LockManager, CompatibleFirstImmediateGrant) { ASSERT(LOCK_OK == lockMgr.lock(resId, &request3, MODE_IS)); // Now an exclusive mode comes, which would block - LockerImpl lockerX; + LockerImpl lockerX(getServiceContext()); LockRequestCombo requestX(&lockerX); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestX, MODE_X)); // If an S comes, it should be granted, because of request2 { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -724,7 +730,7 @@ TEST(LockManager, CompatibleFirstImmediateGrant) { // If S comes again, it should be granted, because of request2 still there { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -734,7 +740,7 @@ TEST(LockManager, CompatibleFirstImmediateGrant) { ASSERT(lockMgr.unlock(&request2)); { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -745,7 +751,7 @@ TEST(LockManager, CompatibleFirstImmediateGrant) { ASSERT(lockMgr.unlock(&requestX)); } -TEST(LockManager, CompatibleFirstGrantAlreadyQueued) { +TEST_F(LockManagerTest, CompatibleFirstGrantAlreadyQueued) { LockManager lockMgr; const ResourceId resId(RESOURCE_GLOBAL, 0); @@ -760,17 +766,17 @@ TEST(LockManager, CompatibleFirstGrantAlreadyQueued) { for (LockMode writerMode : conflictingModes) { for (UnblockMethod unblockMethod : unblockMethods) { - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); LockRequestCombo request1(&locker1); - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); LockRequestCombo request2(&locker2); request2.compatibleFirst = true; - LockerImpl locker3; + LockerImpl locker3(getServiceContext()); LockRequestCombo request3(&locker3); - LockerImpl locker4; + LockerImpl locker4(getServiceContext()); LockRequestCombo request4(&locker4); // Hold the lock in X and establish the S IX|X IS queue. @@ -805,22 +811,22 @@ TEST(LockManager, CompatibleFirstGrantAlreadyQueued) { } } -TEST(LockManager, CompatibleFirstDelayedGrant) { +TEST_F(LockManagerTest, CompatibleFirstDelayedGrant) { LockManager lockMgr; const ResourceId resId(RESOURCE_GLOBAL, 0); - LockerImpl lockerXInitial; + LockerImpl lockerXInitial(getServiceContext()); LockRequestCombo requestXInitial(&lockerXInitial); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestXInitial, MODE_X)); - LockerImpl locker1; + LockerImpl locker1(getServiceContext()); LockRequestCombo request1(&locker1); - LockerImpl locker2; + LockerImpl locker2(getServiceContext()); LockRequestCombo request2(&locker2); request2.compatibleFirst = true; - LockerImpl locker3; + LockerImpl locker3(getServiceContext()); LockRequestCombo request3(&locker3); // Lock all in IS mode (should block behind the global lock) @@ -829,7 +835,7 @@ TEST(LockManager, CompatibleFirstDelayedGrant) { ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request3, MODE_IS)); // Now an exclusive mode comes, which would block behind the IS modes - LockerImpl lockerX; + LockerImpl lockerX(getServiceContext()); LockRequestCombo requestX(&lockerX); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestX, MODE_X)); @@ -841,7 +847,7 @@ TEST(LockManager, CompatibleFirstDelayedGrant) { // If an S comes, it should be granted, because of request2 { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -852,7 +858,7 @@ TEST(LockManager, CompatibleFirstDelayedGrant) { // If S comes again, it should be granted, because of request2 still there { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -862,7 +868,7 @@ TEST(LockManager, CompatibleFirstDelayedGrant) { ASSERT(lockMgr.unlock(&request2)); { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -873,26 +879,26 @@ TEST(LockManager, CompatibleFirstDelayedGrant) { ASSERT(lockMgr.unlock(&requestX)); } -TEST(LockManager, CompatibleFirstCancelWaiting) { +TEST_F(LockManagerTest, CompatibleFirstCancelWaiting) { LockManager lockMgr; const ResourceId resId(RESOURCE_GLOBAL, 0); - LockerImpl lockerSInitial; + LockerImpl lockerSInitial(getServiceContext()); LockRequestCombo requestSInitial(&lockerSInitial); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestSInitial, MODE_S)); - LockerImpl lockerX; + LockerImpl lockerX(getServiceContext()); LockRequestCombo requestX(&lockerX); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestX, MODE_X)); - LockerImpl lockerPending; + LockerImpl lockerPending(getServiceContext()); LockRequestCombo requestPending(&lockerPending); requestPending.compatibleFirst = true; ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestPending, MODE_S)); // S1 is not granted yet, so the policy should still be FIFO { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -902,7 +908,7 @@ TEST(LockManager, CompatibleFirstCancelWaiting) { ASSERT(lockMgr.unlock(&requestPending)); { - LockerImpl lockerS; + LockerImpl lockerS(getServiceContext()); LockRequestCombo requestS(&lockerS); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestS, MODE_S)); ASSERT(lockMgr.unlock(&requestS)); @@ -913,26 +919,26 @@ TEST(LockManager, CompatibleFirstCancelWaiting) { ASSERT(lockMgr.unlock(&requestX)); } -TEST(LockManager, Fairness) { +TEST_F(LockManagerTest, Fairness) { LockManager lockMgr; const ResourceId resId(RESOURCE_GLOBAL, 0); // Start with some 'regular' intent locks - LockerImpl lockerIS; + LockerImpl lockerIS(getServiceContext()); LockRequestCombo requestIS(&lockerIS); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestIS, MODE_IS)); - LockerImpl lockerIX; + LockerImpl lockerIX(getServiceContext()); LockRequestCombo requestIX(&lockerIX); ASSERT(LOCK_OK == lockMgr.lock(resId, &requestIX, MODE_IX)); // Now a conflicting lock comes - LockerImpl lockerX; + LockerImpl lockerX(getServiceContext()); LockRequestCombo requestX(&lockerX); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestX, MODE_X)); // Now, whoever comes next should be blocked - LockerImpl lockerIX1; + LockerImpl lockerIX1(getServiceContext()); LockRequestCombo requestIX1(&lockerIX1); ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestIX1, MODE_IX)); diff --git a/src/mongo/db/concurrency/lock_manager_test_help.h b/src/mongo/db/concurrency/lock_manager_test_help.h index bfd0cd273b2..5eba9d33dbd 100644 --- a/src/mongo/db/concurrency/lock_manager_test_help.h +++ b/src/mongo/db/concurrency/lock_manager_test_help.h @@ -36,7 +36,8 @@ namespace mongo { class LockerForTests : public LockerImpl { public: - explicit LockerForTests(OperationContext* opCtx, LockMode globalLockMode) { + explicit LockerForTests(OperationContext* opCtx, LockMode globalLockMode) + : LockerImpl(opCtx->getServiceContext()) { lockGlobal(opCtx, globalLockMode); } diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index e53c23a09f9..a968d2eee6e 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -291,8 +291,11 @@ void CondVarLockGrantNotification::notify(ResourceId resId, LockResult result) { // Locker // -LockerImpl::LockerImpl() - : _id(idCounter.addAndFetch(1)), _wuowNestingLevel(0), _threadId(stdx::this_thread::get_id()) {} +LockerImpl::LockerImpl(ServiceContext* serviceCtx) + : _id(idCounter.addAndFetch(1)), + _wuowNestingLevel(0), + _threadId(stdx::this_thread::get_id()), + _ticketHolders(&TicketHolders::get(serviceCtx)) {} stdx::thread::id LockerImpl::getThreadId() const { return _threadId; @@ -361,8 +364,7 @@ void LockerImpl::reacquireTicket(OperationContext* opCtx) { bool LockerImpl::_acquireTicket(OperationContext* opCtx, LockMode mode, Date_t deadline) { const bool reader = isSharedLockMode(mode); - auto& ticketHolders = ticketHoldersDecoration(getGlobalServiceContext()); - auto holder = shouldAcquireTicket() ? ticketHolders.getTicketHolder(mode) : nullptr; + auto holder = shouldAcquireTicket() ? _ticketHolders->getTicketHolder(mode) : nullptr; if (holder) { _clientState.store(reader ? kQueuedReader : kQueuedWriter); @@ -1074,8 +1076,7 @@ void LockerImpl::releaseTicket() { } void LockerImpl::_releaseTicket() { - auto& ticketHolders = ticketHoldersDecoration(getGlobalServiceContext()); - auto holder = shouldAcquireTicket() ? ticketHolders.getTicketHolder(_modeForTicket) : nullptr; + auto holder = shouldAcquireTicket() ? _ticketHolders->getTicketHolder(_modeForTicket) : nullptr; if (holder) { holder->release(&_admCtx, std::move(*_ticket)); } diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h index 31096da3cf8..a6677385e2f 100644 --- a/src/mongo/db/concurrency/lock_state.h +++ b/src/mongo/db/concurrency/lock_state.h @@ -35,6 +35,7 @@ #include "mongo/db/concurrency/lock_manager_defs.h" #include "mongo/db/concurrency/locker.h" #include "mongo/db/operation_context.h" +#include "mongo/db/storage/ticketholders.h" #include "mongo/platform/atomic_word.h" #include "mongo/util/concurrency/admission_context.h" #include "mongo/util/concurrency/spin_lock.h" @@ -85,7 +86,6 @@ private: LockResult _result; }; - /** * Interface for acquiring locks. One of those objects will have to be instantiated for each * request (transaction). @@ -101,7 +101,7 @@ public: * Instantiates new locker. Must be given a unique identifier for disambiguation. Lockers * having the same identifier will not conflict on lock acquisition. */ - LockerImpl(); + LockerImpl(ServiceContext* serviceContext); virtual ~LockerImpl(); @@ -381,6 +381,9 @@ private: // Keeps state and statistics related to admission control. AdmissionContext _admCtx; + // The global ticketholders of the service context. + TicketHolders* _ticketHolders; + // This will only be valid when holding a ticket. boost::optional<Ticket> _ticket; diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index 86aeb32e3f4..32d819899e1 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -55,7 +55,7 @@ TEST_F(LockerImplTest, LockNoConflict) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); locker.lock(resId, MODE_X); @@ -75,7 +75,7 @@ TEST_F(LockerImplTest, ReLockNoConflict) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); locker.lock(resId, MODE_S); @@ -95,11 +95,11 @@ TEST_F(LockerImplTest, ConflictWithTimeout) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker1; + LockerImpl locker1(opCtx->getServiceContext()); locker1.lockGlobal(opCtx.get(), MODE_IX); locker1.lock(resId, MODE_X); - LockerImpl locker2; + LockerImpl locker2(opCtx->getServiceContext()); locker2.lockGlobal(opCtx.get(), MODE_IX); ASSERT_THROWS_CODE(locker2.lock(opCtx.get(), resId, MODE_S, Date_t::now()), @@ -119,11 +119,11 @@ TEST_F(LockerImplTest, ConflictUpgradeWithTimeout) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker1; + LockerImpl locker1(opCtx->getServiceContext()); locker1.lockGlobal(opCtx.get(), MODE_IS); locker1.lock(resId, MODE_S); - LockerImpl locker2; + LockerImpl locker2(opCtx->getServiceContext()); locker2.lockGlobal(opCtx.get(), MODE_IS); locker2.lock(resId, MODE_S); @@ -144,19 +144,19 @@ TEST_F(LockerImplTest, FailPointInLockFailsGlobalNonIntentLocksIfTheyCannotBeImm AlternativeClientRegion acr(newClient); auto newOpCtx = cc().makeOperationContext(); - LockerImpl locker1; + LockerImpl locker1(newOpCtx->getServiceContext()); locker1.lockGlobal(newOpCtx.get(), MODE_IX); { FailPointEnableBlock failWaitingNonPartitionedLocks("failNonIntentLocksIfWaitNeeded"); // MODE_S attempt. - LockerImpl locker2; + LockerImpl locker2(newOpCtx->getServiceContext()); ASSERT_THROWS_CODE( locker2.lockGlobal(newOpCtx.get(), MODE_S), DBException, ErrorCodes::LockTimeout); // MODE_X attempt. - LockerImpl locker3; + LockerImpl locker3(newOpCtx->getServiceContext()); ASSERT_THROWS_CODE( locker3.lockGlobal(newOpCtx.get(), MODE_X), DBException, ErrorCodes::LockTimeout); } @@ -175,7 +175,7 @@ TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediate // Granted MODE_X lock, fail incoming MODE_S and MODE_X. const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker1; + LockerImpl locker1(newOpCtx->getServiceContext()); locker1.lockGlobal(newOpCtx.get(), MODE_IX); locker1.lock(newOpCtx.get(), resId, MODE_X); @@ -183,7 +183,7 @@ TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediate FailPointEnableBlock failWaitingNonPartitionedLocks("failNonIntentLocksIfWaitNeeded"); // MODE_S attempt. - LockerImpl locker2; + LockerImpl locker2(newOpCtx->getServiceContext()); locker2.lockGlobal(newOpCtx.get(), MODE_IS); ASSERT_THROWS_CODE(locker2.lock(newOpCtx.get(), resId, MODE_S, Date_t::max()), DBException, @@ -195,7 +195,7 @@ TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediate locker2.unlockGlobal(); // MODE_X attempt. - LockerImpl locker3; + LockerImpl locker3(newOpCtx->getServiceContext()); locker3.lockGlobal(newOpCtx.get(), MODE_IX); ASSERT_THROWS_CODE(locker3.lock(newOpCtx.get(), resId, MODE_X, Date_t::max()), DBException, @@ -213,7 +213,7 @@ TEST_F(LockerImplTest, FailPointInLockFailsNonIntentLocksIfTheyCannotBeImmediate TEST_F(LockerImplTest, ReadTransaction) { auto opCtx = makeOperationContext(); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IS); locker.unlockGlobal(); @@ -235,7 +235,7 @@ TEST_F(LockerImplTest, saveAndRestoreGlobal) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); // No lock requests made, no locks held. locker.saveLockStateAndUnlock(&lockInfo); @@ -264,7 +264,7 @@ TEST_F(LockerImplTest, saveAndRestoreRSTL) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); @@ -303,7 +303,7 @@ TEST_F(LockerImplTest, saveAndRestoreGlobalAcquiredTwice) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); // No lock requests made, no locks held. locker.saveLockStateAndUnlock(&lockInfo); @@ -331,7 +331,7 @@ TEST_F(LockerImplTest, saveAndRestoreDBAndCollection) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -361,7 +361,7 @@ TEST_F(LockerImplTest, releaseWriteUnitOfWork) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -391,7 +391,7 @@ TEST_F(LockerImplTest, restoreWriteUnitOfWork) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -433,7 +433,7 @@ TEST_F(LockerImplTest, releaseAndRestoreWriteUnitOfWorkWithoutUnlock) { Locker::WUOWLockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -549,7 +549,7 @@ TEST_F(LockerImplTest, releaseAndRestoreReadOnlyWriteUnitOfWork) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -591,7 +591,8 @@ TEST_F(LockerImplTest, releaseAndRestoreReadOnlyWriteUnitOfWork) { TEST_F(LockerImplTest, releaseAndRestoreEmptyWriteUnitOfWork) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); // Snapshot transactions delay shared locks as well. locker.setSharedLocksShouldTwoPhaseLock(true); @@ -615,7 +616,7 @@ TEST_F(LockerImplTest, releaseAndRestoreWriteUnitOfWorkWithRecursiveLocks) { Locker::LockSnapshot lockInfo; - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); const ResourceId resIdDatabase(RESOURCE_DATABASE, "TestDB"_sd); const ResourceId resIdCollection(RESOURCE_COLLECTION, "TestDB.collection"_sd); @@ -700,7 +701,7 @@ TEST_F(LockerImplTest, DefaultLocker) { const ResourceId resId(RESOURCE_DATABASE, "TestDB"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); locker.lock(resId, MODE_X); @@ -727,7 +728,7 @@ TEST_F(LockerImplTest, SharedLocksShouldTwoPhaseLockIsTrue) { const ResourceId resId3(RESOURCE_COLLECTION, "TestDB.collection3"_sd); const ResourceId resId4(RESOURCE_COLLECTION, "TestDB.collection4"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.setSharedLocksShouldTwoPhaseLock(true); locker.lockGlobal(opCtx.get(), MODE_IS); @@ -783,7 +784,7 @@ TEST_F(LockerImplTest, ModeIXAndXLockParticipatesInTwoPhaseLocking) { const ResourceId resId3(RESOURCE_COLLECTION, "TestDB.collection3"_sd); const ResourceId resId4(RESOURCE_COLLECTION, "TestDB.collection4"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); ASSERT_EQ(locker.getLockMode(resourceIdGlobal), MODE_IX); @@ -826,7 +827,8 @@ TEST_F(LockerImplTest, ModeIXAndXLockParticipatesInTwoPhaseLocking) { } TEST_F(LockerImplTest, RSTLUnlocksWithNestedLock) { - LockerImpl locker; + auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); locker.lock(resourceIdReplicationStateTransitionLock, MODE_IX); ASSERT_EQ(locker.getLockMode(resourceIdReplicationStateTransitionLock), MODE_IX); @@ -851,7 +853,8 @@ TEST_F(LockerImplTest, RSTLUnlocksWithNestedLock) { } TEST_F(LockerImplTest, RSTLModeIXWithTwoPhaseLockingCanBeUnlockedWhenPrepared) { - LockerImpl locker; + auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); locker.lock(resourceIdReplicationStateTransitionLock, MODE_IX); ASSERT_EQ(locker.getLockMode(resourceIdReplicationStateTransitionLock), MODE_IX); @@ -875,7 +878,8 @@ TEST_F(LockerImplTest, RSTLModeIXWithTwoPhaseLockingCanBeUnlockedWhenPrepared) { } TEST_F(LockerImplTest, RSTLModeISWithTwoPhaseLockingCanBeUnlockedWhenPrepared) { - LockerImpl locker; + auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); locker.lock(resourceIdReplicationStateTransitionLock, MODE_IS); ASSERT_EQ(locker.getLockMode(resourceIdReplicationStateTransitionLock), MODE_IS); @@ -896,7 +900,8 @@ TEST_F(LockerImplTest, RSTLModeISWithTwoPhaseLockingCanBeUnlockedWhenPrepared) { } TEST_F(LockerImplTest, RSTLTwoPhaseLockingBehaviorModeIS) { - LockerImpl locker; + auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); locker.lock(resourceIdReplicationStateTransitionLock, MODE_IS); ASSERT_EQ(locker.getLockMode(resourceIdReplicationStateTransitionLock), MODE_IS); @@ -922,8 +927,8 @@ TEST_F(LockerImplTest, OverrideLockRequestTimeout) { const ResourceId resIdFirstDB(RESOURCE_DATABASE, "FirstDB"_sd); const ResourceId resIdSecondDB(RESOURCE_DATABASE, "SecondDB"_sd); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(opCtx->getServiceContext()); + LockerImpl locker2(opCtx->getServiceContext()); // Set up locker2 to override lock requests' provided timeout if greater than 1000 milliseconds. locker2.setMaxLockTimeout(Milliseconds(1000)); @@ -959,8 +964,8 @@ TEST_F(LockerImplTest, DoNotWaitForLockAcquisition) { const ResourceId resIdFirstDB(RESOURCE_DATABASE, "FirstDB"_sd); const ResourceId resIdSecondDB(RESOURCE_DATABASE, "SecondDB"_sd); - LockerImpl locker1; - LockerImpl locker2; + LockerImpl locker1(opCtx->getServiceContext()); + LockerImpl locker2(opCtx->getServiceContext()); // Set up locker2 to immediately return if a lock is unavailable, regardless of supplied // deadlines in the lock request. @@ -1015,7 +1020,7 @@ TEST_F(LockerImplTest, GetLockerInfoShouldReportHeldLocks) { const ResourceId collectionId(RESOURCE_COLLECTION, "TestDB.collection"_sd); // Take an exclusive lock on the collection. - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); locker.lock(dbId, MODE_IX); locker.lock(collectionId, MODE_X); @@ -1041,13 +1046,13 @@ TEST_F(LockerImplTest, GetLockerInfoShouldReportPendingLocks) { const ResourceId collectionId(RESOURCE_COLLECTION, "TestDB.collection"_sd); // Take an exclusive lock on the collection. - LockerImpl successfulLocker; + LockerImpl successfulLocker(opCtx->getServiceContext()); successfulLocker.lockGlobal(opCtx.get(), MODE_IX); successfulLocker.lock(dbId, MODE_IX); successfulLocker.lock(collectionId, MODE_X); // Now attempt to get conflicting locks. - LockerImpl conflictingLocker; + LockerImpl conflictingLocker(opCtx->getServiceContext()); conflictingLocker.lockGlobal(opCtx.get(), MODE_IS); conflictingLocker.lock(dbId, MODE_IS); ASSERT_EQ(LOCK_WAITING, @@ -1085,7 +1090,7 @@ TEST_F(LockerImplTest, ReaquireLockPendingUnlock) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IS); locker.lock(resId, MODE_X); @@ -1115,7 +1120,7 @@ TEST_F(LockerImplTest, AcquireLockPendingUnlockWithCoveredMode) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IS); locker.lock(resId, MODE_X); @@ -1145,7 +1150,7 @@ TEST_F(LockerImplTest, ConvertLockPendingUnlock) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IS); locker.lock(resId, MODE_IX); @@ -1179,7 +1184,7 @@ TEST_F(LockerImplTest, ConvertLockPendingUnlockAndUnlock) { const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IS); locker.lock(resId, MODE_IX); @@ -1250,7 +1255,7 @@ DEATH_TEST_F(LockerImplTest, const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), MODE_IX); locker.lock(resId, MODE_X); diff --git a/src/mongo/db/concurrency/lock_stats_test.cpp b/src/mongo/db/concurrency/lock_stats_test.cpp index c06bb260b9b..bce10971dae 100644 --- a/src/mongo/db/concurrency/lock_stats_test.cpp +++ b/src/mongo/db/concurrency/lock_stats_test.cpp @@ -165,7 +165,7 @@ void assertGlobalAcquisitionStats(OperationContext* opCtx, ResourceId rid) { reportGlobalLockingStats(&stats); ASSERT_EQUALS(0, stats.get(rid, LockMode::MODE_IX).numAcquisitions); - LockerImpl locker; + LockerImpl locker(opCtx->getServiceContext()); if (rid == resourceIdGlobal) { locker.lockGlobal(opCtx, LockMode::MODE_IX); } else { @@ -205,8 +205,8 @@ TEST_F(LockStatsTest, ServerStatus) { ASSERT_EQUALS(0, builder.done().nFields()); // Take the global, PBWM and RSTL locks in MODE_IX to create acquisition stats for them. - LockerImpl locker; auto opCtx = makeOperationContext(); + LockerImpl locker(opCtx->getServiceContext()); locker.lockGlobal(opCtx.get(), LockMode::MODE_IX); locker.lock(resourceIdParallelBatchWriterMode, LockMode::MODE_IX); locker.lock(resourceIdReplicationStateTransitionLock, LockMode::MODE_IX); diff --git a/src/mongo/db/db_raii_multi_collection_test.cpp b/src/mongo/db/db_raii_multi_collection_test.cpp index 1ad777c076a..f64224deb8a 100644 --- a/src/mongo/db/db_raii_multi_collection_test.cpp +++ b/src/mongo/db/db_raii_multi_collection_test.cpp @@ -51,7 +51,7 @@ public: ClientAndCtx makeClientWithLocker(const std::string& clientName) { auto client = getServiceContext()->makeClient(clientName); auto opCtx = client->makeOperationContext(); - client->swapLockState(std::make_unique<LockerImpl>()); + client->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); return std::make_pair(std::move(client), std::move(opCtx)); } diff --git a/src/mongo/db/db_raii_test.cpp b/src/mongo/db/db_raii_test.cpp index 3c578a29370..0e0ae201252 100644 --- a/src/mongo/db/db_raii_test.cpp +++ b/src/mongo/db/db_raii_test.cpp @@ -57,7 +57,7 @@ public: ClientAndCtx makeClientWithLocker(const std::string& clientName) { auto client = getServiceContext()->makeClient(clientName); auto opCtx = client->makeOperationContext(); - client->swapLockState(std::make_unique<LockerImpl>()); + client->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); return std::make_pair(std::move(client), std::move(opCtx)); } diff --git a/src/mongo/db/exec/sbe/abt/sbe_abt_diff_test.cpp b/src/mongo/db/exec/sbe/abt/sbe_abt_diff_test.cpp index 3112ec3c88a..252b7ce52b4 100644 --- a/src/mongo/db/exec/sbe/abt/sbe_abt_diff_test.cpp +++ b/src/mongo/db/exec/sbe/abt/sbe_abt_diff_test.cpp @@ -133,7 +133,7 @@ public: void onDestroyClient(Client* client) final {} void onCreateOperationContext(OperationContext* opCtx) override { - opCtx->setLockState(std::make_unique<LockerImpl>()); + opCtx->setLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); } void onDestroyOperationContext(OperationContext* opCtx) final {} diff --git a/src/mongo/db/mongod_main.cpp b/src/mongo/db/mongod_main.cpp index 02c2ba93904..bce1bc1815c 100644 --- a/src/mongo/db/mongod_main.cpp +++ b/src/mongo/db/mongod_main.cpp @@ -1412,7 +1412,7 @@ void shutdownTask(const ShutdownTaskArgs& shutdownArgs) { // of this function to prevent any operations from running that need a lock. // LOGV2(4784929, "Acquiring the global lock for shutdown"); - LockerImpl* globalLocker = new LockerImpl(); + LockerImpl* globalLocker = new LockerImpl(serviceContext); globalLocker->lockGlobal(nullptr, MODE_X); // Global storage engine may not be started in all cases before we exit diff --git a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface_test.cpp b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface_test.cpp index ba3fe548407..5c3f7eebf97 100644 --- a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface_test.cpp +++ b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface_test.cpp @@ -44,7 +44,7 @@ TEST_F(ShardedProcessInterfaceTest, TestInsert) { setupNShards(2); // Need a real locker for storage operations. - getClient()->swapLockState(std::make_unique<LockerImpl>()); + getClient()->swapLockState(std::make_unique<LockerImpl>(expCtx()->opCtx->getServiceContext())); const NamespaceString kOutNss = NamespaceString{"unittests-out", "sharded_agg_test"}; auto outStage = DocumentSourceOut::create(kOutNss, expCtx()); diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp index cf24f3712b4..218951db1a9 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp @@ -2203,7 +2203,8 @@ TEST_F(StepDownTest, // locker to test this, or otherwise stepDown will be granted the lock automatically. ReplicationStateTransitionLockGuard transitionGuard(opCtx.get(), MODE_X); ASSERT_TRUE(opCtx->lockState()->isRSTLExclusive()); - auto locker = getClient()->swapLockState(std::make_unique<LockerImpl>()); + auto locker = + getClient()->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); ASSERT_THROWS_CODE( getReplCoord()->stepDown(opCtx.get(), false, Milliseconds(0), Milliseconds(1000)), diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index df50322d6c2..f47f6487ba3 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -269,7 +269,7 @@ public: // It is necessary to lock the client to change the Locker on the OperationContext. stdx::lock_guard<Client> lk(*opCtx->getClient()); invariant(!opCtx->lockState()->isLocked()); - opCtx->swapLockState(std::make_unique<LockerImpl>(), lk); + opCtx->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext()), lk); } std::unique_ptr<PolymorphicScoped> scopedOperationCompletionShardingActions( diff --git a/src/mongo/db/storage/storage_engine_init.cpp b/src/mongo/db/storage/storage_engine_init.cpp index 97f935e32a9..7c345ddcfe6 100644 --- a/src/mongo/db/storage/storage_engine_init.cpp +++ b/src/mongo/db/storage/storage_engine_init.cpp @@ -168,29 +168,28 @@ StorageEngine::LastShutdownState initializeStorageEngine(OperationContext* opCtx auto writeTransactions = gConcurrentWriteTransactions.load(); writeTransactions = writeTransactions == 0 ? DEFAULT_TICKETS_VALUE : writeTransactions; - // TODO SERVER-64467: Remove the globalServiceContext for TicketHolders - auto serviceContext = getGlobalServiceContext(); - auto& ticketHolders = ticketHoldersDecoration(serviceContext); + auto svcCtx = opCtx->getServiceContext(); + auto& ticketHolders = TicketHolders::get(svcCtx); if (feature_flags::gFeatureFlagExecutionControl.isEnabledAndIgnoreFCV()) { LOGV2_DEBUG(5190400, 1, "Enabling new ticketing policies"); switch (gTicketQueueingPolicy) { case QueueingPolicyEnum::Semaphore: LOGV2_DEBUG(6382201, 1, "Using Semaphore-based ticketing scheduler"); ticketHolders.setGlobalThrottling( - std::make_unique<SemaphoreTicketHolder>(readTransactions, serviceContext), - std::make_unique<SemaphoreTicketHolder>(writeTransactions, serviceContext)); + std::make_unique<SemaphoreTicketHolder>(readTransactions, svcCtx), + std::make_unique<SemaphoreTicketHolder>(writeTransactions, svcCtx)); break; case QueueingPolicyEnum::FifoQueue: LOGV2_DEBUG(6382200, 1, "Using FIFO queue-based ticketing scheduler"); ticketHolders.setGlobalThrottling( - std::make_unique<FifoTicketHolder>(readTransactions, serviceContext), - std::make_unique<FifoTicketHolder>(writeTransactions, serviceContext)); + std::make_unique<FifoTicketHolder>(readTransactions, svcCtx), + std::make_unique<FifoTicketHolder>(writeTransactions, svcCtx)); break; } } else { ticketHolders.setGlobalThrottling( - std::make_unique<SemaphoreTicketHolder>(readTransactions, serviceContext), - std::make_unique<SemaphoreTicketHolder>(writeTransactions, serviceContext)); + std::make_unique<SemaphoreTicketHolder>(readTransactions, svcCtx), + std::make_unique<SemaphoreTicketHolder>(writeTransactions, svcCtx)); } } @@ -255,13 +254,6 @@ void shutdownGlobalStorageEngineCleanly(ServiceContext* service, lockFile->clearPidAndUnlock(); lockFile = boost::none; } - // TODO SERVER-64467: Remove the globalServiceContext for TicketHolders - // Cleanup the ticket holders. - if (hasGlobalServiceContext() && !forRestart) { - auto serviceContext = getGlobalServiceContext(); - auto& ticketHolders = ticketHoldersDecoration(serviceContext); - ticketHolders.setGlobalThrottling(nullptr, nullptr); - } } } /* namespace */ @@ -412,7 +404,7 @@ public: void onDestroyClient(Client* client) override{}; void onCreateOperationContext(OperationContext* opCtx) { // Use a fully fledged lock manager even when the storage engine is not set. - opCtx->setLockState(std::make_unique<LockerImpl>()); + opCtx->setLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext())); auto service = opCtx->getServiceContext(); diff --git a/src/mongo/db/storage/ticketholders.cpp b/src/mongo/db/storage/ticketholders.cpp index 1fcc8371946..36dc23f0a7a 100644 --- a/src/mongo/db/storage/ticketholders.cpp +++ b/src/mongo/db/storage/ticketholders.cpp @@ -30,27 +30,34 @@ #include "mongo/db/storage/ticketholders.h" #include "mongo/util/concurrency/ticketholder.h" +namespace { +const auto ticketHoldersDecoration = + mongo::ServiceContext::declareDecoration<mongo::TicketHolders>(); +} + namespace mongo { Status TicketHolders::updateConcurrentWriteTransactions(const int& newWriteTransactions) { - if (hasGlobalServiceContext()) { - auto serviceContext = getGlobalServiceContext(); - auto& ticketHolders = ticketHoldersDecoration(serviceContext); - auto& writer = ticketHolders._openWriteTransaction; - if (writer) { - return writer->resize(newWriteTransactions); + if (auto client = Client::getCurrent()) { + if (auto svcCtx = client->getServiceContext()) { + auto& ticketHolders = TicketHolders::get(svcCtx); + auto& writer = ticketHolders._openWriteTransaction; + if (writer) { + return writer->resize(newWriteTransactions); + } } } return Status::OK(); }; Status TicketHolders::updateConcurrentReadTransactions(const int& newReadTransactions) { - if (hasGlobalServiceContext()) { - auto serviceContext = getGlobalServiceContext(); - auto& ticketHolders = ticketHoldersDecoration(serviceContext); - auto& reader = ticketHolders._openReadTransaction; - if (reader) { - return reader->resize(newReadTransactions); + if (auto client = Client::getCurrent()) { + if (auto svcCtx = client->getServiceContext()) { + auto& ticketHolders = TicketHolders::get(svcCtx); + auto& reader = ticketHolders._openReadTransaction; + if (reader) { + return reader->resize(newReadTransactions); + } } } return Status::OK(); @@ -74,8 +81,12 @@ TicketHolder* TicketHolders::getTicketHolder(LockMode mode) { } } -const Decorable<ServiceContext>::Decoration<TicketHolders> ticketHoldersDecoration = - ServiceContext::declareDecoration<TicketHolders>(); +TicketHolders& TicketHolders::get(ServiceContext* svcCtx) { + return ticketHoldersDecoration(svcCtx); +} +TicketHolders& TicketHolders::get(ServiceContext& svcCtx) { + return ticketHoldersDecoration(svcCtx); +} } // namespace mongo diff --git a/src/mongo/db/storage/ticketholders.h b/src/mongo/db/storage/ticketholders.h index 31fdfb8db32..cdaee0f7315 100644 --- a/src/mongo/db/storage/ticketholders.h +++ b/src/mongo/db/storage/ticketholders.h @@ -45,6 +45,8 @@ public: static Status updateConcurrentReadTransactions(const int& newReadTransactions); + static TicketHolders& get(ServiceContext* svcCtx); + static TicketHolders& get(ServiceContext& svcCtx); /** * Sets the TicketHolder implementation to use to obtain tickets from 'reading' (for MODE_S and * MODE_IS), and from 'writing' (for MODE_IX) in order to throttle database access. There is no @@ -62,9 +64,4 @@ private: std::unique_ptr<TicketHolder> _openReadTransaction; }; -/** - * Decorated accessor to the 'TicketHolders' stored in 'ServiceContext'. - */ -extern const Decorable<ServiceContext>::Decoration<TicketHolders> ticketHoldersDecoration; - } // namespace mongo diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp index 2763f082246..d26015451c9 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp @@ -604,10 +604,9 @@ void WiredTigerKVEngine::notifyStartupComplete() { WiredTigerUtil::notifyStartupComplete(); } -void WiredTigerKVEngine::appendGlobalStats(BSONObjBuilder& b) { +void WiredTigerKVEngine::appendGlobalStats(OperationContext* opCtx, BSONObjBuilder& b) { BSONObjBuilder bb(b.subobjStart("concurrentTransactions")); - auto serviceContext = getGlobalServiceContext(); - auto& ticketHolders = ticketHoldersDecoration(serviceContext); + auto& ticketHolders = TicketHolders::get(opCtx->getServiceContext()); { auto writer = ticketHolders.getTicketHolder(MODE_IX); BSONObjBuilder bbb(bb.subobjStart("write")); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h index 7360c65f3ec..688db855b74 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h @@ -316,7 +316,7 @@ public: return _oplogManager.get(); } - static void appendGlobalStats(BSONObjBuilder& b); + static void appendGlobalStats(OperationContext* opCtx, BSONObjBuilder& b); Timestamp getStableTimestamp() const override; Timestamp getOldestTimestamp() const override; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_server_status.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_server_status.cpp index be978059c17..caf44b7c2bd 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_server_status.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_server_status.cpp @@ -90,7 +90,7 @@ BSONObj WiredTigerServerStatusSection::generateSection(OperationContext* opCtx, bob.append("reason", status.reason()); } - WiredTigerKVEngine::appendGlobalStats(bob); + WiredTigerKVEngine::appendGlobalStats(opCtx, bob); WiredTigerKVEngine* engine = checked_cast<WiredTigerKVEngine*>( opCtx->getServiceContext()->getStorageEngine()->getEngine()); diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index 298cf5b3cc2..84e83664b92 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -1161,7 +1161,7 @@ TransactionParticipant::TxnResources::TxnResources(WithLock wl, _ruState = opCtx->getWriteUnitOfWork()->release(); opCtx->setWriteUnitOfWork(nullptr); - _locker = opCtx->swapLockState(std::make_unique<LockerImpl>(), wl); + _locker = opCtx->swapLockState(std::make_unique<LockerImpl>(opCtx->getServiceContext()), wl); // Inherit the locking setting from the original one. opCtx->lockState()->setShouldConflictWithSecondaryBatchApplication( _locker->shouldConflictWithSecondaryBatchApplication()); |