Skip to content

Commit 23bb1c8

Browse files
committed
LaxConnPool: Deallocate pool entry upon discarding expired connection
1 parent 2b2b44e commit 23bb1c8

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ private PoolEntry<T, C> getAvailableEntry(final Object state) {
444444
it.remove();
445445
if (entry.getExpiryDeadline().isExpired() || !Objects.equals(entry.getState(), state)) {
446446
entry.discardConnection(CloseMode.GRACEFUL);
447+
deallocatePoolEntry();
447448
} else {
448449
return entry;
449450
}

httpcore5/src/test/java/org/apache/hc/core5/pool/TestLaxConnPool.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,4 +475,32 @@ void testGetMaxPerRoute() {
475475
Assertions.assertEquals(max, pool.getMaxPerRoute(route));
476476
}
477477
}
478+
479+
@Test
480+
void testExpiredEntryDeallocatesSlot() throws Exception {
481+
final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
482+
483+
try (final LaxConnPool<String, HttpConnection> pool = new LaxConnPool<>(1)) {
484+
// Lease, assign, expire, then release back to available
485+
final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
486+
final PoolEntry<String, HttpConnection> entry1 = future1.get();
487+
entry1.assignConnection(conn1);
488+
entry1.updateExpiry(TimeValue.of(1, TimeUnit.MILLISECONDS));
489+
pool.release(entry1, true);
490+
491+
Thread.sleep(10);
492+
493+
// Lease again — the expired entry should be discarded and the slot freed
494+
final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
495+
Assertions.assertTrue(future2.isDone());
496+
final PoolEntry<String, HttpConnection> entry2 = future2.get();
497+
Assertions.assertNotNull(entry2);
498+
499+
// The expired entry was discarded, so a new entry was allocated.
500+
// With maxPerRoute=1, this only works if the expired entry's slot was deallocated.
501+
final PoolStats stats = pool.getStats("somehost");
502+
Assertions.assertEquals(1, stats.getLeased());
503+
Assertions.assertEquals(0, stats.getAvailable());
504+
}
505+
}
478506
}

0 commit comments

Comments
 (0)