You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2007/09/18 14:03:14 UTC
svn commit: r576859 - in /jakarta/httpcomponents/httpcore/trunk: ./
module-nio/src/main/java/org/apache/http/impl/nio/reactor/
module-nio/src/main/java/org/apache/http/nio/reactor/
module-nio/src/test/java/org/apache/http/impl/nio/reactor/ module-nio/s...
Author: olegk
Date: Tue Sep 18 05:03:13 2007
New Revision: 576859
URL: http://svn.apache.org/viewvc?rev=576859&view=rev
Log:
HTTPCORE-86: Allow for optional handling of runtime exceptions thrown by protocol handlers to ensure the I/O dispatch thread remains running.
Modified:
jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractIOReactor.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractMultiworkerIOReactor.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/BaseIOReactor.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultConnectingIOReactor.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultListeningIOReactor.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/reactor/IOReactorExceptionHandler.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/reactor/TestDefaultIOReactors.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpClient.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpServer.java
Modified: jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt (original)
+++ jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt Tue Sep 18 05:03:13 2007
@@ -1,12 +1,17 @@
Changes since release 4.0 Alpha 5
+* [HTTPCORE-86] Allow for optional handling of runtime exceptions
+ thrown by protocol handlers to ensurev the I/O dispatch thread
+ remains running.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
* [HTTPCORE-116] moved parameter names to interfaces
Contributed by Roland Weber <rolandw at apache.org>
* [HTTPCORE-109] Improved shutdown process of the I/O reactors in NIO modules. I/O
reactors now attempt to terminate connections gracefully before shutting down the
underlying socket channels.
- Oleg Kalnichevski <olegk at apache.org>
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
* [HTTPCORE-107] allow sending and receiving of SIP messages
Contributed by Roland Weber <rolandw at apache.org>
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractIOReactor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractIOReactor.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractIOReactor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractIOReactor.java Tue Sep 18 05:03:13 2007
@@ -165,7 +165,7 @@
selectedKeys.clear();
}
- private void processEvent(final SelectionKey key) {
+ protected void processEvent(final SelectionKey key) {
try {
if (key.isAcceptable()) {
acceptable(key);
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractMultiworkerIOReactor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractMultiworkerIOReactor.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractMultiworkerIOReactor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/AbstractMultiworkerIOReactor.java Tue Sep 18 05:03:13 2007
@@ -48,6 +48,7 @@
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.IOReactor;
import org.apache.http.nio.reactor.IOReactorException;
+import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
@@ -65,6 +66,8 @@
private final Worker[] workers;
private final Thread[] threads;
+ protected IOReactorExceptionHandler exceptionHandler;
+
private int currentWorker = 0;
public AbstractMultiworkerIOReactor(
@@ -104,6 +107,14 @@
return this.status;
}
+ public void setExceptionHandler(final IOReactorExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ for (int i = 0; i < this.workerCount; i++) {
+ BaseIOReactor dispatcher = this.dispatchers[i];
+ dispatcher.setExceptionHandler(exceptionHandler);
+ }
+ }
+
protected abstract void processEvents(int count) throws IOReactorException;
public void execute(
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/BaseIOReactor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/BaseIOReactor.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/BaseIOReactor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/BaseIOReactor.java Tue Sep 18 05:03:13 2007
@@ -38,6 +38,7 @@
import org.apache.http.nio.reactor.EventMask;
import org.apache.http.nio.reactor.IOReactorException;
+import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.nio.reactor.IOSession;
public class BaseIOReactor extends AbstractIOReactor {
@@ -47,11 +48,27 @@
private long lastTimeoutCheck;
+ private IOReactorExceptionHandler exceptionHandler;
+
public BaseIOReactor(long selectTimeout) throws IOReactorException {
super(selectTimeout);
this.bufferingSessions = new SessionSet();
this.timeoutCheckInterval = selectTimeout;
this.lastTimeoutCheck = System.currentTimeMillis();
+ }
+
+ public void setExceptionHandler(IOReactorExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+
+ protected void processEvent(final SelectionKey key) {
+ try {
+ super.processEvent(key);
+ } catch (RuntimeException ex) {
+ if (this.exceptionHandler == null || !this.exceptionHandler.handle(ex)) {
+ throw ex;
+ }
+ }
}
protected void acceptable(final SelectionKey key) {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultConnectingIOReactor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultConnectingIOReactor.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultConnectingIOReactor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultConnectingIOReactor.java Tue Sep 18 05:03:13 2007
@@ -114,7 +114,13 @@
key.cancel();
if (channel.isConnected()) {
try {
- prepareSocket(channel.socket());
+ try {
+ prepareSocket(channel.socket());
+ } catch (IOException ex) {
+ if (this.exceptionHandler == null || !this.exceptionHandler.handle(ex)) {
+ throw new IOReactorException("Failure initalizing socket", ex);
+ }
+ }
ChannelEntry entry = new ChannelEntry(channel, sessionRequest);
addChannel(entry);
} catch (IOException ex) {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultListeningIOReactor.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultListeningIOReactor.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultListeningIOReactor.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/reactor/DefaultListeningIOReactor.java Tue Sep 18 05:03:13 2007
@@ -41,7 +41,6 @@
import java.util.Set;
import org.apache.http.nio.reactor.IOReactorException;
-import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.nio.reactor.ListeningIOReactor;
import org.apache.http.params.HttpParams;
import org.apache.http.util.concurrent.ThreadFactory;
@@ -49,8 +48,6 @@
public class DefaultListeningIOReactor extends AbstractMultiworkerIOReactor
implements ListeningIOReactor {
- private IOReactorExceptionHandler exceptionHandler;
-
public DefaultListeningIOReactor(
int workerCount,
final ThreadFactory threadFactory,
@@ -62,10 +59,6 @@
int workerCount,
final HttpParams params) throws IOReactorException {
this(workerCount, null, params);
- }
-
- public void setExceptionHandler(final IOReactorExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
}
protected void processEvents(int readyCount) throws IOReactorException {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/reactor/IOReactorExceptionHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/reactor/IOReactorExceptionHandler.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/reactor/IOReactorExceptionHandler.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/reactor/IOReactorExceptionHandler.java Tue Sep 18 05:03:13 2007
@@ -44,7 +44,7 @@
/**
* This method is expected to examine the I/O exception passed as a parameter
- * and decide whether it is safe to continue execution of the i/O reactor
+ * and decide whether it is safe to continue execution of the I/O reactor
*
* @param ex potentially recoverable I/O exception
* @return <code>true</code> if it is safe to ignore the exception
@@ -52,5 +52,16 @@
* I/O reactor must throw {@link IOReactorException} and terminate
*/
boolean handle(IOException ex);
+
+ /**
+ * This method is expected to examine the runtime exception passed as a parameter
+ * and decide whether it is safe to continue execution of the I/O reactor
+ *
+ * @param ex potentially recoverable runtime exception
+ * @return <code>true</code> if it is safe to ignore the exception
+ * and continue execution of the I/O reactor; <code>false</code> if the
+ * I/O reactor must throw {@link RuntimeException} and terminate
+ */
+ boolean handle(RuntimeException ex);
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/reactor/TestDefaultIOReactors.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/reactor/TestDefaultIOReactors.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/reactor/TestDefaultIOReactors.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/reactor/TestDefaultIOReactors.java Tue Sep 18 05:03:13 2007
@@ -49,6 +49,7 @@
import org.apache.http.nio.protocol.EventListener;
import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
import org.apache.http.nio.reactor.IOReactor;
+import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
@@ -255,4 +256,175 @@
this.server.shutdown();
}
+ public void testUnhandledRuntimeException() throws Exception {
+
+ final RequestCount requestConns = new RequestCount(1);
+
+ HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+ public void handle(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+ throw new IllegalStateException("Oppsie!!!");
+ }
+
+ };
+
+ HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+ public void initalizeContext(final HttpContext context, final Object attachment) {
+ }
+
+ public void finalizeContext(final HttpContext context) {
+ }
+
+ public HttpRequest submitRequest(final HttpContext context) {
+ Boolean b = ((Boolean) context.getAttribute("done"));
+ if (b == null) {
+ BasicHttpRequest get = new BasicHttpRequest("GET", "/");
+ context.setAttribute("done", Boolean.TRUE);
+ return get;
+ } else {
+ return null;
+ }
+ }
+
+ public void handleResponse(final HttpResponse response, final HttpContext context) {
+ }
+
+ };
+
+ IOReactorExceptionHandler exceptionHandler = new IOReactorExceptionHandler() {
+
+ public boolean handle(final IOException ex) {
+ return false;
+ }
+
+ public boolean handle(final RuntimeException ex) {
+ requestConns.decrement();
+ return false;
+ }
+
+ };
+
+ NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+ requestHandler,
+ null,
+ new SimpleEventListener());
+
+ NHttpClientHandler clientHandler = createHttpClientHandler(
+ requestExecutionHandler,
+ new SimpleEventListener());
+
+ this.server.setExceptionHandler(exceptionHandler);
+
+ this.server.start(serviceHandler);
+ this.client.start(clientHandler);
+
+ InetSocketAddress serverAddress = (InetSocketAddress) this.server.getSocketAddress();
+
+ this.client.openConnection(
+ new InetSocketAddress("localhost", serverAddress.getPort()),
+ null);
+
+ requestConns.await(10000);
+ assertEquals(0, requestConns.getValue());
+
+ this.server.join(20000);
+
+ Exception ex = this.server.getException();
+ assertNotNull(ex);
+ assertTrue(ex instanceof IllegalStateException);
+ // I/O reactor shut down itself
+ assertEquals(IOReactor.SHUT_DOWN, this.server.getStatus());
+
+ this.client.shutdown();
+ this.server.shutdown();
+ }
+
+ public void testHandledRuntimeException() throws Exception {
+
+ final RequestCount requestConns = new RequestCount(1);
+
+ HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+ public void handle(
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+ throw new IllegalStateException("Oppsie!!!");
+ }
+
+ };
+
+ HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+ public void initalizeContext(final HttpContext context, final Object attachment) {
+ }
+
+ public void finalizeContext(final HttpContext context) {
+ }
+
+ public HttpRequest submitRequest(final HttpContext context) {
+ Boolean b = ((Boolean) context.getAttribute("done"));
+ if (b == null) {
+ BasicHttpRequest get = new BasicHttpRequest("GET", "/");
+ context.setAttribute("done", Boolean.TRUE);
+ return get;
+ } else {
+ return null;
+ }
+ }
+
+ public void handleResponse(final HttpResponse response, final HttpContext context) {
+ }
+
+ };
+
+ IOReactorExceptionHandler exceptionHandler = new IOReactorExceptionHandler() {
+
+ public boolean handle(final IOException ex) {
+ return false;
+ }
+
+ public boolean handle(final RuntimeException ex) {
+ requestConns.decrement();
+ return true;
+ }
+
+ };
+
+ NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+ requestHandler,
+ null,
+ new SimpleEventListener());
+
+ NHttpClientHandler clientHandler = createHttpClientHandler(
+ requestExecutionHandler,
+ new SimpleEventListener());
+
+ this.server.setExceptionHandler(exceptionHandler);
+
+ this.server.start(serviceHandler);
+ this.client.start(clientHandler);
+
+ InetSocketAddress serverAddress = (InetSocketAddress) this.server.getSocketAddress();
+
+ this.client.openConnection(
+ new InetSocketAddress("localhost", serverAddress.getPort()),
+ null);
+
+ requestConns.await(10000);
+ assertEquals(0, requestConns.getValue());
+
+ this.server.join(1000);
+
+ assertEquals(IOReactor.ACTIVE, this.server.getStatus());
+ assertNull(this.server.getException());
+
+ this.client.shutdown();
+ this.server.shutdown();
+ }
+
}
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpClient.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpClient.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpClient.java Tue Sep 18 05:03:13 2007
@@ -37,13 +37,13 @@
import org.apache.http.impl.nio.DefaultClientIOEventDispatch;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpClientHandler;
-import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
+import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.params.HttpParams;
public class TestHttpClient {
- private final ConnectingIOReactor ioReactor;
+ private final DefaultConnectingIOReactor ioReactor;
private final HttpParams params;
private volatile IOReactorThread thread;
@@ -58,6 +58,10 @@
return this.params;
}
+ public void setExceptionHandler(final IOReactorExceptionHandler exceptionHandler) {
+ this.ioReactor.setExceptionHandler(exceptionHandler);
+ }
+
private void execute(final NHttpClientHandler clientHandler) throws IOException {
IOEventDispatch ioEventDispatch = new DefaultClientIOEventDispatch(
clientHandler,
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpServer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpServer.java?rev=576859&r1=576858&r2=576859&view=diff
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpServer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/mockup/TestHttpServer.java Tue Sep 18 05:03:13 2007
@@ -38,7 +38,7 @@
import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import org.apache.http.nio.NHttpServiceHandler;
import org.apache.http.nio.reactor.IOEventDispatch;
-import org.apache.http.nio.reactor.ListeningIOReactor;
+import org.apache.http.nio.reactor.IOReactorExceptionHandler;
import org.apache.http.params.HttpParams;
/**
@@ -48,7 +48,7 @@
*/
public class TestHttpServer {
- private final ListeningIOReactor ioReactor;
+ private final DefaultListeningIOReactor ioReactor;
private final HttpParams params;
private final Object socketMutex;
@@ -66,6 +66,10 @@
return this.params;
}
+ public void setExceptionHandler(final IOReactorExceptionHandler exceptionHandler) {
+ this.ioReactor.setExceptionHandler(exceptionHandler);
+ }
+
private void execute(final NHttpServiceHandler serviceHandler) throws IOException {
synchronized (this.socketMutex) {
this.address = (InetSocketAddress) this.ioReactor.listen(