diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java index 7c874e335f67..7d4258d41240 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectionPool.java @@ -254,10 +254,10 @@ protected void proceed() protected Connection activate() { Pool.Entry entry = pool.acquire(); - if (LOG.isDebugEnabled()) - LOG.debug("activated '{}'", entry); if (entry != null) { + if (LOG.isDebugEnabled()) + LOG.debug("activated {}", entry); Connection connection = entry.getPooled(); acquired(connection); return connection; @@ -298,15 +298,13 @@ protected boolean deactivate(Connection connection) Pool.Entry entry = (Pool.Entry)attachable.getAttachment(); if (entry == null) return true; - if (LOG.isDebugEnabled()) - LOG.debug("releasing {}", entry); boolean reusable = pool.release(entry); - if (!reusable) - { - remove(connection); - return false; - } - return true; + if (LOG.isDebugEnabled()) + LOG.debug("Released ({}) {}", reusable, entry); + if (reusable) + return true; + remove(connection); + return false; } @Override @@ -325,9 +323,9 @@ protected boolean remove(Connection connection, boolean force) if (entry == null) return false; attachable.setAttachment(null); - if (LOG.isDebugEnabled()) - LOG.debug("removing {}", entry); boolean removed = pool.remove(entry); + if (LOG.isDebugEnabled()) + LOG.debug("Removed ({}) {}", removed, entry); if (removed || force) { released(connection); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java index ca16ffde0c58..b040c134df1f 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java @@ -351,6 +351,42 @@ public void resolve(String host, int port, Promise> prom assertThat(connectionPool.getConnectionCount(), Matchers.lessThanOrEqualTo(count)); } + @ParameterizedTest + @MethodSource("pools") + public void testConnectionMaxUsage(ConnectionPoolFactory factory) throws Exception + { + startServer(new EmptyServerHandler()); + + int maxUsageCount = 2; + startClient(destination -> + { + AbstractConnectionPool connectionPool = (AbstractConnectionPool)factory.factory.newConnectionPool(destination); + connectionPool.setMaxUsageCount(maxUsageCount); + return connectionPool; + }); + client.setMaxConnectionsPerDestination(1); + + // Send first request, we are within the max usage count. + ContentResponse response1 = client.newRequest("localhost", connector.getLocalPort()).send(); + assertEquals(HttpStatus.OK_200, response1.getStatus()); + + HttpDestination destination = (HttpDestination)client.getDestinations().get(0); + AbstractConnectionPool connectionPool = (AbstractConnectionPool)destination.getConnectionPool(); + + assertEquals(0, connectionPool.getActiveConnectionCount()); + assertEquals(1, connectionPool.getIdleConnectionCount()); + assertEquals(1, connectionPool.getConnectionCount()); + + // Send second request, max usage count will be reached, + // the only connection must be closed. + ContentResponse response2 = client.newRequest("localhost", connector.getLocalPort()).send(); + assertEquals(HttpStatus.OK_200, response2.getStatus()); + + assertEquals(0, connectionPool.getActiveConnectionCount()); + assertEquals(0, connectionPool.getIdleConnectionCount()); + assertEquals(0, connectionPool.getConnectionCount()); + } + private static class ConnectionPoolFactory { private final String name; diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Pool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Pool.java index 5cb32da926d9..4172e145743a 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/Pool.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Pool.java @@ -545,7 +545,7 @@ public int getUsageCount() public String toString() { long encoded = state.get(); - return String.format("%s@%x{hi=%d,lo=%d.p=%s}", + return String.format("%s@%x{usage=%d,multiplex=%d,pooled=%s}", getClass().getSimpleName(), hashCode(), AtomicBiInteger.getHi(encoded),