Index: src/java/org/apache/commons/httpclient/HttpConnection.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v retrieving revision 1.92 diff -u -r1.92 HttpConnection.java --- src/java/org/apache/commons/httpclient/HttpConnection.java 1 Jun 2004 00:55:10 -0000 1.92 +++ src/java/org/apache/commons/httpclient/HttpConnection.java 8 Jun 2004 12:52:07 -0000 @@ -383,19 +383,31 @@ } /** - * Returns true if the connection is open, - * false otherwise. + * Tests if the connection is open. * - * @return true if the connection is open + * @return true if the connection is open */ public boolean isOpen() { - if (used && isOpen && this.params.isStaleCheckingEnabled() && isStale()) { + return isOpen; + } + + /** + * Closes the connection if stale. + * + * @return true if the connection was stale and therefore closed, + * false otherwise. + * + * @see #isStale() + */ + public boolean closeIfStale() { + if (used && isOpen && isStale()) { LOG.debug("Connection is stale, closing..."); close(); + return true; } - return isOpen; + return false; } - + /** * Tests if stale checking is enabled. * Index: src/java/org/apache/commons/httpclient/HttpMethodDirector.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodDirector.java,v retrieving revision 1.25 diff -u -r1.25 HttpMethodDirector.java --- src/java/org/apache/commons/httpclient/HttpMethodDirector.java 13 May 2004 04:03:25 -0000 1.25 +++ src/java/org/apache/commons/httpclient/HttpMethodDirector.java 8 Jun 2004 12:52:08 -0000 @@ -339,6 +339,9 @@ if (LOG.isTraceEnabled()) { LOG.trace("Attempt number " + execCount + " to process request"); } + if (this.conn.getParams().isStaleCheckingEnabled()) { + this.conn.closeIfStale(); + } if (!this.conn.isOpen()) { // this connection must be opened before it can be used // This has nothing to do with opening a secure tunnel @@ -402,7 +405,7 @@ releaseConnection = true; throw e; } catch (RuntimeException e) { - if (this.conn.isOpen()) { + if (this.conn.isOpen) { LOG.debug("Closing the connection."); this.conn.close(); } Index: src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v retrieving revision 1.39 diff -u -r1.39 MultiThreadedHttpConnectionManager.java --- src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 13 May 2004 04:03:25 -0000 1.39 +++ src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 8 Jun 2004 12:52:08 -0000 @@ -527,30 +527,72 @@ } /** + * Gets the total number of pooled connections for the given host configuration. This + * is the total number of connections that have been created and are still in use + * by this connection manager for the host configuration. This value will + * not exceed the {@link #getMaxConnectionsPerHost() maximum number of connections per + * host}. + * + * @param hostConfiguration The host configuration + * @return The total number of pooled connections + */ + public int getConnectionsInPool(HostConfiguration hostConfiguration) { + synchronized (connectionPool) { + HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration); + return hostPool.numConnections; + } + } + + /** + * Gets the total number of pooled connections. This is the total number of + * connections that have been created and are still in use by this connection + * manager. This value will not exceed the {@link #getMaxTotalConnections() + * maximum number of connections}. + * + * @return the total number of pooled connections + */ + public int getConnectionsInPool() { + synchronized (connectionPool) { + return connectionPool.numConnections; + } + } + + /** * Gets the number of connections in use for this configuration. * * @param hostConfiguration the key that connections are tracked on * @return the number of connections in use + * + * @deprecated Use {@link #getConnectionsInPool(HostConfiguration)} */ public int getConnectionsInUse(HostConfiguration hostConfiguration) { - synchronized (connectionPool) { - HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration); - return hostPool.numConnections; - } + return getConnectionsInPool(hostConfiguration); } /** * Gets the total number of connections in use. * * @return the total number of connections in use + * + * @deprecated Use {@link #getConnectionsInPool()} */ public int getConnectionsInUse() { - synchronized (connectionPool) { - return connectionPool.numConnections; - } + return getConnectionsInPool(); } /** + * Deletes all closed connections. Only connections currently owned by the connection + * manager are processed. + * + * @see HttpConnection#isClosed() + * + * @since 3.0 + */ + public void deleteClosedConnections() { + connectionPool.deleteClosedConnections(); + } + + /** * @since 3.0 */ public void closeIdleConnections(long idleTimeout) { @@ -794,6 +836,22 @@ } return connection; } + + /** + * Deletes all closed connections. + */ + public synchronized void deleteClosedConnections() { + + Iterator iter = freeConnections.iterator(); + + while (iter.hasNext()) { + HttpConnection conn = (HttpConnection) iter.next(); + if (!conn.isOpen()) { + iter.remove(); + deleteConnection(conn); + } + } + } /** * Closes idle connections. @@ -804,31 +862,43 @@ } /** - * Close and delete an old, unused connection to make room for a new one. + * Deletes the given connection. This will remove all reference to the connection + * so that it can be GCed. + * + *

Note: Does not remove the connection from the freeConnections list. It + * is assumed that the caller has already handled this case.

+ * + * @param connection The connection to delete */ - public synchronized void deleteLeastUsedConnection() { + private synchronized void deleteConnection(HttpConnection connection) { + + HostConfiguration connectionConfiguration = configurationForConnection(connection); - HttpConnection connection = (HttpConnection) freeConnections.removeFirst(); + if (LOG.isDebugEnabled()) { + LOG.debug("Reclaiming connection, hostConfig=" + connectionConfiguration); + } - if (connection != null) { - HostConfiguration connectionConfiguration = configurationForConnection(connection); + connection.close(); - if (LOG.isDebugEnabled()) { - LOG.debug("Reclaiming unused connection, hostConfig=" - + connectionConfiguration); - } + HostConnectionPool hostPool = getHostPool(connectionConfiguration); + + hostPool.freeConnections.remove(connection); + hostPool.numConnections--; + numConnections--; - connection.close(); + // remove the connection from the timeout handler + idleConnectionHandler.remove(connection); + } + + /** + * Close and delete an old, unused connection to make room for a new one. + */ + public synchronized void deleteLeastUsedConnection() { - HostConnectionPool hostPool = getHostPool(connectionConfiguration); - - hostPool.freeConnections.remove(connection); - hostPool.numConnections--; - numConnections--; + HttpConnection connection = (HttpConnection) freeConnections.removeFirst(); - // remove the connection from the timeout handler - idleConnectionHandler.remove(connection); - + if (connection != null) { + deleteConnection(connection); } else if (LOG.isDebugEnabled()) { LOG.debug("Attempted to reclaim an unused connection but there were none."); } @@ -1212,6 +1282,14 @@ public boolean isOpen() { if (hasConnection()) { return wrappedConnection.isOpen(); + } else { + return false; + } + } + + public boolean closeIfStale() { + if (hasConnection()) { + return wrappedConnection.closeIfStale(); } else { return false; } Index: src/test/org/apache/commons/httpclient/TestHttpConnection.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnection.java,v retrieving revision 1.16 diff -u -r1.16 TestHttpConnection.java --- src/test/org/apache/commons/httpclient/TestHttpConnection.java 13 Apr 2004 21:47:29 -0000 1.16 +++ src/test/org/apache/commons/httpclient/TestHttpConnection.java 8 Jun 2004 12:52:08 -0000 @@ -80,7 +80,7 @@ public void testConstructThenClose() { HttpConnection conn = new HttpConnection(getHost(), getPort()); conn.close(); - assertTrue( ! conn.isOpen() ); + assertTrue(!conn.isOpen()); } public void testConnTimeoutRelease() { Index: src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v retrieving revision 1.21 diff -u -r1.21 TestHttpConnectionManager.java --- src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java 13 Apr 2004 21:47:29 -0000 1.21 +++ src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java 8 Jun 2004 12:52:08 -0000 @@ -583,6 +583,31 @@ } + public void testDeleteClosedConnections() { + + MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager(); + + HostConfiguration hostConfig = new HostConfiguration(); + + configureHostConfiguration(hostConfig); + + HttpConnection conn = manager.getConnection(hostConfig); + + assertEquals("connectionsInPool", manager.getConnectionsInPool(), 1); + assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 1); + + conn.close(); + conn.releaseConnection(); + + assertEquals("connectionsInPool", manager.getConnectionsInPool(), 1); + assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 1); + + manager.deleteClosedConnections(); + + assertEquals("connectionsInPool", manager.getConnectionsInPool(), 0); + assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 0); + } + public void testReclaimUnusedConnection() { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); Index: src/test/org/apache/commons/httpclient/TestLocalHostBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestLocalHostBase.java,v retrieving revision 1.5 diff -u -r1.5 TestLocalHostBase.java --- src/test/org/apache/commons/httpclient/TestLocalHostBase.java 22 Feb 2004 18:08:49 -0000 1.5 +++ src/test/org/apache/commons/httpclient/TestLocalHostBase.java 8 Jun 2004 12:52:08 -0000 @@ -99,13 +99,22 @@ } else { client = new HttpClient(connectionManager); } - - client.getHostConfiguration().setHost(host, port, protocol); - if (proxyHost != null) { - client.getHostConfiguration().setProxy(proxyHost, proxyPort); - } + + configureHostConfiguration(client.getHostConfiguration()); return client; + } + + /** + * Configures the host config with the correct host and proxy settings. + * + * @param hostConfiguration + */ + public void configureHostConfiguration(HostConfiguration hostConfiguration) { + hostConfiguration.setHost(host, port, protocol); + if (proxyHost != null) { + hostConfiguration.setProxy(proxyHost, proxyPort); + } } /**