SERVER-119731 Allow re-entering low priority operations in ordered queue even if maxQueueDepth is exceeded (#49077)

Co-authored-by: Pol Pinol Castuera <pol.pinol@mongodb.com>
GitOrigin-RevId: ce084777b81af22b48f0e0ccb9acddd482b187c8
This commit is contained in:
Marcos Grillo
2026-03-09 19:17:38 +01:00
committed by MongoDB Bot
parent 64eec475c2
commit 2cc62a244f
2 changed files with 40 additions and 1 deletions

View File

@@ -49,7 +49,8 @@ bool OrderedTicketSemaphore::acquire(OperationContext* opCtx,
return true; return true;
} }
if (static_cast<int>(_waitQueue.size()) >= _maxWaiters.loadRelaxed()) { if (admCtx->getLowAdmissions() == 0 &&
static_cast<int>(_waitQueue.size()) >= _maxWaiters.loadRelaxed()) {
admCtx->recordOperationLoadShed(); admCtx->recordOperationLoadShed();
lk.unlock(); lk.unlock();
uasserted(ErrorCodes::AdmissionQueueOverflow, uasserted(ErrorCodes::AdmissionQueueOverflow,

View File

@@ -370,4 +370,42 @@ TEST_F(OrderedTicketSemaphoreTest, TryAcquireReturnsFalseWhenWaitersQueued) {
future.get(); future.get();
ASSERT_EQ(sem->available(), 0); ASSERT_EQ(sem->available(), 0);
} }
/**
* Test that operations with lowAdmissions > 0 can bypass the max waiters limit.
*/
TEST_F(OrderedTicketSemaphoreTest, LowAdmissionsCanBypassMaxWaitersLimit) {
auto sem = makeSemaphore(0, 1); // 0 tickets, max 1 waiter.
MockAdmissionContext admCtx1, admCtx2WithLowAdmissions, admCtx3NoLowAdmissions;
auto future1 = launchAsync([&]() {
auto [client, opCtx] = makeOpCtx();
ASSERT_TRUE(sem->acquire(opCtx.get(), &admCtx1, Date_t::max(), true));
});
waitForQueuedThreads(sem, 1);
ASSERT_EQ(sem->waiters(), 1);
ASSERT_THROWS_CODE(sem->acquire(opCtx(), &admCtx3NoLowAdmissions, getDeadline(), true),
DBException,
ErrorCodes::AdmissionQueueOverflow);
ASSERT_EQ(sem->waiters(), 1); // Queue unchanged.
// An operation with lowAdmissions > 0 should be able to bypass the limit.
admCtx2WithLowAdmissions.recordLowAdmission();
ASSERT_GT(admCtx2WithLowAdmissions.getLowAdmissions(), 0);
auto future2 = launchAsync([&]() {
auto [client, opCtx] = makeOpCtx();
ASSERT_TRUE(sem->acquire(opCtx.get(), &admCtx2WithLowAdmissions, Date_t::max(), true));
});
waitForQueuedThreads(sem, 2);
ASSERT_EQ(sem->waiters(), 2);
sem->resize(2);
future1.get();
future2.get();
}
} // namespace mongo } // namespace mongo