You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by mb...@apache.org on 2007/02/19 20:52:44 UTC
svn commit: r509320 - in /jakarta/commons/proper/httpclient/trunk:
release_notes.txt
src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java
src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java
Author: mbecke
Date: Mon Feb 19 11:52:43 2007
New Revision: 509320
URL: http://svn.apache.org/viewvc?view=rev&rev=509320
Log:
[HTTPCLIENT-633]: MultithreadedConnectionManager's handling of thread interrupts.
Contributed by: Michael Becke
Reviewed by: Roland Weber and Oleg Kalnichevski
Modified:
jakarta/commons/proper/httpclient/trunk/release_notes.txt
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java
jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java
Modified: jakarta/commons/proper/httpclient/trunk/release_notes.txt
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/release_notes.txt?view=diff&rev=509320&r1=509319&r2=509320
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/release_notes.txt (original)
+++ jakarta/commons/proper/httpclient/trunk/release_notes.txt Mon Feb 19 11:52:43 2007
@@ -1,4 +1,8 @@
Changes since Release 3.1 Beta 1:
+* [HTTPCLIENT-633] - Changed MultiThreadedHttpConnectionManager's handling of thread
+ interrupts. IllegalThreadStateException is now thrown when waiting threads
+ are interrupted from outside of the connection manager.
+ Contributed by Michael Becke <mbecke at apache.org>
* [HTTPCLIENT-628] - IOException in AutoCloseInputStream.available()
Contributed by Roland Weber <rolandw at apache.org>
Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java?view=diff&rev=509320&r1=509319&r2=509320
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java (original)
+++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java Mon Feb 19 11:52:43 2007
@@ -505,6 +505,8 @@
waitingThread = new WaitingThread();
waitingThread.hostConnectionPool = hostPool;
waitingThread.thread = Thread.currentThread();
+ } else {
+ waitingThread.interruptedByConnectionPool = false;
}
if (useTimeout) {
@@ -514,14 +516,24 @@
hostPool.waitingThreads.addLast(waitingThread);
connectionPool.waitingThreads.addLast(waitingThread);
connectionPool.wait(timeToWait);
-
- // we have not been interrupted so we need to remove ourselves from the
- // wait queue
- hostPool.waitingThreads.remove(waitingThread);
- connectionPool.waitingThreads.remove(waitingThread);
} catch (InterruptedException e) {
- // do nothing
+ if (!waitingThread.interruptedByConnectionPool) {
+ LOG.debug("Interrupted while waiting for connection", e);
+ throw new IllegalThreadStateException(
+ "Interrupted while waiting in MultiThreadedHttpConnectionManager");
+ }
+ // Else, do nothing, we were interrupted by the connection pool
+ // and should now have a connection waiting for us, continue
+ // in the loop and let's get it.
} finally {
+ if (!waitingThread.interruptedByConnectionPool) {
+ // Either we timed out, experienced a "spurious wakeup", or were
+ // interrupted by an external thread. Regardless we need to
+ // cleanup for ourselves in the wait queue.
+ hostPool.waitingThreads.remove(waitingThread);
+ connectionPool.waitingThreads.remove(waitingThread);
+ }
+
if (useTimeout) {
endWait = System.currentTimeMillis();
timeToWait -= (endWait - startWait);
@@ -725,6 +737,7 @@
while (iter.hasNext()) {
WaitingThread waiter = (WaitingThread) iter.next();
iter.remove();
+ waiter.interruptedByConnectionPool = true;
waiter.thread.interrupt();
}
@@ -923,7 +936,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Notifying thread waiting on host pool, hostConfig="
+ hostPool.hostConfiguration);
- }
+ }
waitingThread = (WaitingThread) hostPool.waitingThreads.removeFirst();
waitingThreads.remove(waitingThread);
} else if (waitingThreads.size() > 0) {
@@ -937,6 +950,7 @@
}
if (waitingThread != null) {
+ waitingThread.interruptedByConnectionPool = true;
waitingThread.thread.interrupt();
}
}
@@ -1033,6 +1047,11 @@
/** The connection pool the thread is waiting for */
public HostConnectionPool hostConnectionPool;
+
+ /** Flag to indicate if the thread was interrupted by the ConnectionPool. Set
+ * to true inside {@link ConnectionPool#notifyWaitingThread(HostConnectionPool)}
+ * before the thread is interrupted. */
+ public boolean interruptedByConnectionPool = false;
}
/**
Modified: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java?view=diff&rev=509320&r1=509319&r2=509320
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java (original)
+++ jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java Mon Feb 19 11:52:43 2007
@@ -655,6 +655,59 @@
assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(client.getHostConfiguration()), 0);
}
+ /**
+ * Tests that thread waiting in the MultiThreadedHttpConnectionManager can be
+ * interrupted.
+ */
+ public void testWaitingThreadInterrupted() {
+
+ this.server.setHttpService(new EchoService());
+
+ MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+ connectionManager.getParams().setIntParameter(
+ HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
+
+ HostConfiguration host1 = new HostConfiguration();
+ host1.setHost("host1", -1, "http");
+
+ // hold on to the only connection
+ HttpConnection connection = connectionManager.getConnection(host1);
+
+ // wait for a connection on another thread
+ GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 1000);
+ getConn.start();
+
+ // give the thread a chance to block
+ synchronized (this) {
+ try {
+ this.wait(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // interrupt the thread, this should cancel waiting with a RuntimeException
+ getConn.interrupt();
+
+ try {
+ getConn.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // make sure the correct exception was thrown
+ assertTrue(getConn.exception != null);
+ assertEquals(getConn.exception.getClass(), IllegalThreadStateException.class);
+
+ // make sure the connection manager is still working
+ connection.releaseConnection();
+ try {
+ connectionManager.getConnectionWithTimeout(host1, 10);
+ } catch (ConnectionPoolTimeoutException e) {
+ fail("Connection not available");
+ }
+ }
+
public void testReclaimUnusedConnection() {
this.server.setHttpService(new EchoService());
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org