You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by ch...@apache.org on 2006/11/07 06:52:16 UTC

svn commit: r471995 - in /webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server: ConnectionListenerFailureHandler.java DefaultConnectionListener.java DefaultConnectionListenerFailureHandler.java

Author: chuckw
Date: Mon Nov  6 21:52:15 2006
New Revision: 471995

URL: http://svn.apache.org/viewvc?view=rev&rev=471995
Log:
Make the default connection listener thread in SimpleHttpServer more robust, solving a problem where
a failure in this thread could leave an axis2 service quietly cut off from its clients.

ConnectListenerFailureHandler provides an interface for managing exceptions in the connection listener
thread.  DefaultConnectionListenerFailureHandler tries to re-establish the listen several times before
giving up, always logging the issues, and provides a notification mechanism if the thread ever terminates.
This is all easily configurable through HttpFactory.

Resolves AXIS2-1607


Added:
    webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
    webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
Modified:
    webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java

Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java?view=auto&rev=471995
==============================================================================
--- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java (added)
+++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
@@ -0,0 +1,48 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.axis2.transport.http.server;
+
+public interface ConnectionListenerFailureHandler {
+    
+    /** The associated connection listener IOProcessor has failed
+     * @param connectionListener the associated connection listener
+     * @param cause cause of failure
+     * @return true if the listener should attempt to re-establish itself, false if it should terminate.
+     */
+    public boolean failed(IOProcessor connectionListener, Throwable cause);
+    
+    /** The associated connection listener IOProcessor is terminating abnormally
+     * @param connectionListener the associated connection listener
+     * @param message explanation of termination
+     * @param cause last exception that is causing termination
+     */
+    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause);
+    
+}

Modified: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java?view=diff&rev=471995&r1=471994&r2=471995
==============================================================================
--- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java (original)
+++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java Mon Nov  6 21:52:15 2006
@@ -43,25 +43,34 @@
     private static Log LOG = LogFactory.getLog(DefaultConnectionListener.class);
 	
     private volatile boolean destroyed = false;
-    
+
+    private final int port;
     private final HttpConnectionFactory connfactory;
     private final HttpConnectionManager connmanager;
-    private final ServerSocket serversocket;
-        
-    public DefaultConnectionListener(
-    		int port,
-            final HttpConnectionFactory connfactory,
-            final HttpConnectionManager connmanager) throws IOException {
+    private ServerSocket serversocket;
+    private final ConnectionListenerFailureHandler failureHandler;
+    
+    /** Default constructor called by HttpFactory.  A custom HttpFactory subclass can call the other constructor to provide a custom ConnectionListenerErrorHandler */
+    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager) throws IOException {
+        this(port, connfactory, connmanager, new DefaultConnectionListenerFailureHandler());
+    }
+
+    /** Use this constructor to provide a custom ConnectionListenerFailureHandler, e.g. by subclassing DefaultConnectionListenerFailureHandler */
+    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager,
+                                     ConnectionListenerFailureHandler failureHandler)
+    throws IOException {
     	super();
-        if (connfactory == null) {
+        if (connfactory == null)
             throw new IllegalArgumentException("Connection factory may not be null");
-        }
-        if (connmanager == null) {
+        if (connmanager == null)
             throw new IllegalArgumentException("Connection manager may not be null");
-        }
+        if (failureHandler == null)
+            throw new IllegalArgumentException("Failure handler may not be null");
+        this.port = port;
         this.connmanager = connmanager;
         this.connfactory = connfactory;
         this.serversocket = new ServerSocket(port);
+        this.failureHandler = failureHandler;
     }
 
     public void run() {
@@ -69,8 +78,10 @@
             LOG.info("Listening on port " + this.serversocket.getLocalPort());
     	}
         try {
-            while (!this.serversocket.isClosed() && !Thread.interrupted()) {
+            while (!Thread.interrupted()) {
                 try {
+                    if (serversocket.isClosed())
+                        serversocket = new ServerSocket(port);
                     LOG.debug("Waiting for incoming HTTP connection");
                     Socket socket = this.serversocket.accept();
                     if (LOG.isDebugEnabled()) {
@@ -79,23 +90,11 @@
                     }
                     HttpServerConnection conn = this.connfactory.newConnection(socket);
                     this.connmanager.process(conn);
-                } catch (IOException ex) {
-                    if (ex instanceof SocketException) {
-                        if (LOG.isDebugEnabled() 
-                                && !this.destroyed && !Thread.interrupted()) {
-                            LOG.debug("Connection listener terminated due to an I/O error: " + 
-                                    ex.getMessage());
-                        }
-                    } else {
-                        if (LOG.isWarnEnabled()) {
-                            LOG.warn("Connection listener terminated due to an I/O error: " + 
-                                    ex.getMessage(), ex);
-                        }
-                    }
-                    break;
                 } catch (Throwable ex) {
-                    LOG.error("Connection listener terminated due to a runtime error", ex);
-                    break;
+                    if (Thread.interrupted())
+                        break;
+                    if (!failureHandler.failed(this, ex))
+                        break;
                 }
             }
         } finally {

Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java?view=auto&rev=471995
==============================================================================
--- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java (added)
+++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
@@ -0,0 +1,102 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.axis2.transport.http.server;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/** Default hander for failures in connection listener IOProcessors.
+ *  Supports configuration of number retries, delay per retry, and uptime interval considered a success (resets number retries to zero).
+ */
+public class DefaultConnectionListenerFailureHandler implements ConnectionListenerFailureHandler {
+    
+    private static final Log LOG = LogFactory.getLog(DefaultConnectionListenerFailureHandler.class);
+
+    protected int retryDelay;
+    protected int successInterval;
+    protected int maxRetries;
+    
+    private long lastFailure;
+    private long lastFirstFailure;
+    private int numRetries;
+    
+    /** Create a new DefaultConnectionListenerFailureHandler with default settings.
+     * retryDelay is 1 second, successInterval is 60 seconds, maxRetries is 10
+     */
+    public DefaultConnectionListenerFailureHandler() {
+        this(1000, 60000, 10);
+    }
+
+    /** Create a new DefaultConnectionListenerFailureHandler
+     * @param retryDelay millis to wait before retrying
+     * @param successInterval millis after which an initial or retry attempt will be deemed a success, resetting retry count to 0
+     * @param maxRetries maximum number of retries allowed without a success, after which the listener will terminate
+     */
+    public DefaultConnectionListenerFailureHandler(int retryDelay, int successInterval, int maxRetries) {
+        this.retryDelay = retryDelay;
+        this.successInterval = successInterval;
+        this.maxRetries = maxRetries;
+        this.lastFailure = this.lastFirstFailure = Long.MIN_VALUE;
+        this.numRetries = 0;
+    }
+
+    /** Default behavior is to log a warning and attempt retry per constructor config, eventually failing with a logged error and notification.
+     * May subclass and override this method to change the behavior.
+     */
+    public boolean failed(IOProcessor connectionListener, Throwable cause) {
+        long now = System.currentTimeMillis();
+        if (now > lastFailure+successInterval) {
+            numRetries = 0;
+            lastFirstFailure = now;
+        }
+        lastFailure = now;
+        if (numRetries >= maxRetries) {
+            notifyAbnormalTermination(
+                    connectionListener,
+                    "Terminating connection listener " + connectionListener + " after " + numRetries + "retries in " + (now-lastFirstFailure)/1000 + " seconds.",
+                    cause);
+            return false;
+        } else {
+            numRetries++;
+            if (LOG.isWarnEnabled())
+                LOG.warn("Attempt number " + numRetries + " of " + maxRetries + " to reestalish connection listener " + connectionListener + " due to failure ",
+                         cause);
+            return true;
+        }
+    }
+
+    /** Default bevarior is to log the error.
+     * May subclass and override this method to change behavior.
+     */
+    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause) {
+        LOG.error(message, cause);
+    }
+    
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org


Re: svn commit: r471995 - in /webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server: ConnectionListenerFailureHandler.java DefaultConnectionListener.java DefaultConnectionListenerFailureHandler.java

Posted by Sanjiva Weerawarana <sa...@opensource.lk>.
Hi Chuck,

Is there a testcase in this commit too? I'm a bit worried since its late
in the release cycle. Sorry if I missed discussion on the list.

Sanjiva.

On Tue, 2006-11-07 at 05:52 +0000, chuckw@apache.org wrote:
> Author: chuckw
> Date: Mon Nov  6 21:52:15 2006
> New Revision: 471995
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=471995
> Log:
> Make the default connection listener thread in SimpleHttpServer more robust, solving a problem where
> a failure in this thread could leave an axis2 service quietly cut off from its clients.
> 
> ConnectListenerFailureHandler provides an interface for managing exceptions in the connection listener
> thread.  DefaultConnectionListenerFailureHandler tries to re-establish the listen several times before
> giving up, always logging the issues, and provides a notification mechanism if the thread ever terminates.
> This is all easily configurable through HttpFactory.
> 
> Resolves AXIS2-1607
> 
> 
> Added:
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
> Modified:
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java
> 
> Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java?view=auto&rev=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java (added)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
> @@ -0,0 +1,48 @@
> +/*
> + * $HeadURL$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + *  Copyright 1999-2006 The Apache Software Foundation
> + *
> + *  Licensed under the Apache License, Version 2.0 (the "License");
> + *  you may not use this file except in compliance with the License.
> + *  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.axis2.transport.http.server;
> +
> +public interface ConnectionListenerFailureHandler {
> +    
> +    /** The associated connection listener IOProcessor has failed
> +     * @param connectionListener the associated connection listener
> +     * @param cause cause of failure
> +     * @return true if the listener should attempt to re-establish itself, false if it should terminate.
> +     */
> +    public boolean failed(IOProcessor connectionListener, Throwable cause);
> +    
> +    /** The associated connection listener IOProcessor is terminating abnormally
> +     * @param connectionListener the associated connection listener
> +     * @param message explanation of termination
> +     * @param cause last exception that is causing termination
> +     */
> +    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause);
> +    
> +}
> 
> Modified: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java?view=diff&rev=471995&r1=471994&r2=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java (original)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java Mon Nov  6 21:52:15 2006
> @@ -43,25 +43,34 @@
>      private static Log LOG = LogFactory.getLog(DefaultConnectionListener.class);
>  	
>      private volatile boolean destroyed = false;
> -    
> +
> +    private final int port;
>      private final HttpConnectionFactory connfactory;
>      private final HttpConnectionManager connmanager;
> -    private final ServerSocket serversocket;
> -        
> -    public DefaultConnectionListener(
> -    		int port,
> -            final HttpConnectionFactory connfactory,
> -            final HttpConnectionManager connmanager) throws IOException {
> +    private ServerSocket serversocket;
> +    private final ConnectionListenerFailureHandler failureHandler;
> +    
> +    /** Default constructor called by HttpFactory.  A custom HttpFactory subclass can call the other constructor to provide a custom ConnectionListenerErrorHandler */
> +    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager) throws IOException {
> +        this(port, connfactory, connmanager, new DefaultConnectionListenerFailureHandler());
> +    }
> +
> +    /** Use this constructor to provide a custom ConnectionListenerFailureHandler, e.g. by subclassing DefaultConnectionListenerFailureHandler */
> +    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager,
> +                                     ConnectionListenerFailureHandler failureHandler)
> +    throws IOException {
>      	super();
> -        if (connfactory == null) {
> +        if (connfactory == null)
>              throw new IllegalArgumentException("Connection factory may not be null");
> -        }
> -        if (connmanager == null) {
> +        if (connmanager == null)
>              throw new IllegalArgumentException("Connection manager may not be null");
> -        }
> +        if (failureHandler == null)
> +            throw new IllegalArgumentException("Failure handler may not be null");
> +        this.port = port;
>          this.connmanager = connmanager;
>          this.connfactory = connfactory;
>          this.serversocket = new ServerSocket(port);
> +        this.failureHandler = failureHandler;
>      }
>  
>      public void run() {
> @@ -69,8 +78,10 @@
>              LOG.info("Listening on port " + this.serversocket.getLocalPort());
>      	}
>          try {
> -            while (!this.serversocket.isClosed() && !Thread.interrupted()) {
> +            while (!Thread.interrupted()) {
>                  try {
> +                    if (serversocket.isClosed())
> +                        serversocket = new ServerSocket(port);
>                      LOG.debug("Waiting for incoming HTTP connection");
>                      Socket socket = this.serversocket.accept();
>                      if (LOG.isDebugEnabled()) {
> @@ -79,23 +90,11 @@
>                      }
>                      HttpServerConnection conn = this.connfactory.newConnection(socket);
>                      this.connmanager.process(conn);
> -                } catch (IOException ex) {
> -                    if (ex instanceof SocketException) {
> -                        if (LOG.isDebugEnabled() 
> -                                && !this.destroyed && !Thread.interrupted()) {
> -                            LOG.debug("Connection listener terminated due to an I/O error: " + 
> -                                    ex.getMessage());
> -                        }
> -                    } else {
> -                        if (LOG.isWarnEnabled()) {
> -                            LOG.warn("Connection listener terminated due to an I/O error: " + 
> -                                    ex.getMessage(), ex);
> -                        }
> -                    }
> -                    break;
>                  } catch (Throwable ex) {
> -                    LOG.error("Connection listener terminated due to a runtime error", ex);
> -                    break;
> +                    if (Thread.interrupted())
> +                        break;
> +                    if (!failureHandler.failed(this, ex))
> +                        break;
>                  }
>              }
>          } finally {
> 
> Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java?view=auto&rev=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java (added)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
> @@ -0,0 +1,102 @@
> +/*
> + * $HeadURL$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + *  Copyright 1999-2006 The Apache Software Foundation
> + *
> + *  Licensed under the Apache License, Version 2.0 (the "License");
> + *  you may not use this file except in compliance with the License.
> + *  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.axis2.transport.http.server;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +
> +/** Default hander for failures in connection listener IOProcessors.
> + *  Supports configuration of number retries, delay per retry, and uptime interval considered a success (resets number retries to zero).
> + */
> +public class DefaultConnectionListenerFailureHandler implements ConnectionListenerFailureHandler {
> +    
> +    private static final Log LOG = LogFactory.getLog(DefaultConnectionListenerFailureHandler.class);
> +
> +    protected int retryDelay;
> +    protected int successInterval;
> +    protected int maxRetries;
> +    
> +    private long lastFailure;
> +    private long lastFirstFailure;
> +    private int numRetries;
> +    
> +    /** Create a new DefaultConnectionListenerFailureHandler with default settings.
> +     * retryDelay is 1 second, successInterval is 60 seconds, maxRetries is 10
> +     */
> +    public DefaultConnectionListenerFailureHandler() {
> +        this(1000, 60000, 10);
> +    }
> +
> +    /** Create a new DefaultConnectionListenerFailureHandler
> +     * @param retryDelay millis to wait before retrying
> +     * @param successInterval millis after which an initial or retry attempt will be deemed a success, resetting retry count to 0
> +     * @param maxRetries maximum number of retries allowed without a success, after which the listener will terminate
> +     */
> +    public DefaultConnectionListenerFailureHandler(int retryDelay, int successInterval, int maxRetries) {
> +        this.retryDelay = retryDelay;
> +        this.successInterval = successInterval;
> +        this.maxRetries = maxRetries;
> +        this.lastFailure = this.lastFirstFailure = Long.MIN_VALUE;
> +        this.numRetries = 0;
> +    }
> +
> +    /** Default behavior is to log a warning and attempt retry per constructor config, eventually failing with a logged error and notification.
> +     * May subclass and override this method to change the behavior.
> +     */
> +    public boolean failed(IOProcessor connectionListener, Throwable cause) {
> +        long now = System.currentTimeMillis();
> +        if (now > lastFailure+successInterval) {
> +            numRetries = 0;
> +            lastFirstFailure = now;
> +        }
> +        lastFailure = now;
> +        if (numRetries >= maxRetries) {
> +            notifyAbnormalTermination(
> +                    connectionListener,
> +                    "Terminating connection listener " + connectionListener + " after " + numRetries + "retries in " + (now-lastFirstFailure)/1000 + " seconds.",
> +                    cause);
> +            return false;
> +        } else {
> +            numRetries++;
> +            if (LOG.isWarnEnabled())
> +                LOG.warn("Attempt number " + numRetries + " of " + maxRetries + " to reestalish connection listener " + connectionListener + " due to failure ",
> +                         cause);
> +            return true;
> +        }
> +    }
> +
> +    /** Default bevarior is to log the error.
> +     * May subclass and override this method to change behavior.
> +     */
> +    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause) {
> +        LOG.error(message, cause);
> +    }
> +    
> +}
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
> For additional commands, e-mail: axis-cvs-help@ws.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org


Re: svn commit: r471995 - in /webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server: ConnectionListenerFailureHandler.java DefaultConnectionListener.java DefaultConnectionListenerFailureHandler.java

Posted by Sanjiva Weerawarana <sa...@opensource.lk>.
Hi Chuck,

Is there a testcase in this commit too? I'm a bit worried since its late
in the release cycle. Sorry if I missed discussion on the list.

Sanjiva.

On Tue, 2006-11-07 at 05:52 +0000, chuckw@apache.org wrote:
> Author: chuckw
> Date: Mon Nov  6 21:52:15 2006
> New Revision: 471995
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=471995
> Log:
> Make the default connection listener thread in SimpleHttpServer more robust, solving a problem where
> a failure in this thread could leave an axis2 service quietly cut off from its clients.
> 
> ConnectListenerFailureHandler provides an interface for managing exceptions in the connection listener
> thread.  DefaultConnectionListenerFailureHandler tries to re-establish the listen several times before
> giving up, always logging the issues, and provides a notification mechanism if the thread ever terminates.
> This is all easily configurable through HttpFactory.
> 
> Resolves AXIS2-1607
> 
> 
> Added:
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
> Modified:
>     webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java
> 
> Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java?view=auto&rev=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java (added)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/ConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
> @@ -0,0 +1,48 @@
> +/*
> + * $HeadURL$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + *  Copyright 1999-2006 The Apache Software Foundation
> + *
> + *  Licensed under the Apache License, Version 2.0 (the "License");
> + *  you may not use this file except in compliance with the License.
> + *  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.axis2.transport.http.server;
> +
> +public interface ConnectionListenerFailureHandler {
> +    
> +    /** The associated connection listener IOProcessor has failed
> +     * @param connectionListener the associated connection listener
> +     * @param cause cause of failure
> +     * @return true if the listener should attempt to re-establish itself, false if it should terminate.
> +     */
> +    public boolean failed(IOProcessor connectionListener, Throwable cause);
> +    
> +    /** The associated connection listener IOProcessor is terminating abnormally
> +     * @param connectionListener the associated connection listener
> +     * @param message explanation of termination
> +     * @param cause last exception that is causing termination
> +     */
> +    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause);
> +    
> +}
> 
> Modified: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java?view=diff&rev=471995&r1=471994&r2=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java (original)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListener.java Mon Nov  6 21:52:15 2006
> @@ -43,25 +43,34 @@
>      private static Log LOG = LogFactory.getLog(DefaultConnectionListener.class);
>  	
>      private volatile boolean destroyed = false;
> -    
> +
> +    private final int port;
>      private final HttpConnectionFactory connfactory;
>      private final HttpConnectionManager connmanager;
> -    private final ServerSocket serversocket;
> -        
> -    public DefaultConnectionListener(
> -    		int port,
> -            final HttpConnectionFactory connfactory,
> -            final HttpConnectionManager connmanager) throws IOException {
> +    private ServerSocket serversocket;
> +    private final ConnectionListenerFailureHandler failureHandler;
> +    
> +    /** Default constructor called by HttpFactory.  A custom HttpFactory subclass can call the other constructor to provide a custom ConnectionListenerErrorHandler */
> +    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager) throws IOException {
> +        this(port, connfactory, connmanager, new DefaultConnectionListenerFailureHandler());
> +    }
> +
> +    /** Use this constructor to provide a custom ConnectionListenerFailureHandler, e.g. by subclassing DefaultConnectionListenerFailureHandler */
> +    public DefaultConnectionListener(int port, HttpConnectionFactory connfactory, HttpConnectionManager connmanager,
> +                                     ConnectionListenerFailureHandler failureHandler)
> +    throws IOException {
>      	super();
> -        if (connfactory == null) {
> +        if (connfactory == null)
>              throw new IllegalArgumentException("Connection factory may not be null");
> -        }
> -        if (connmanager == null) {
> +        if (connmanager == null)
>              throw new IllegalArgumentException("Connection manager may not be null");
> -        }
> +        if (failureHandler == null)
> +            throw new IllegalArgumentException("Failure handler may not be null");
> +        this.port = port;
>          this.connmanager = connmanager;
>          this.connfactory = connfactory;
>          this.serversocket = new ServerSocket(port);
> +        this.failureHandler = failureHandler;
>      }
>  
>      public void run() {
> @@ -69,8 +78,10 @@
>              LOG.info("Listening on port " + this.serversocket.getLocalPort());
>      	}
>          try {
> -            while (!this.serversocket.isClosed() && !Thread.interrupted()) {
> +            while (!Thread.interrupted()) {
>                  try {
> +                    if (serversocket.isClosed())
> +                        serversocket = new ServerSocket(port);
>                      LOG.debug("Waiting for incoming HTTP connection");
>                      Socket socket = this.serversocket.accept();
>                      if (LOG.isDebugEnabled()) {
> @@ -79,23 +90,11 @@
>                      }
>                      HttpServerConnection conn = this.connfactory.newConnection(socket);
>                      this.connmanager.process(conn);
> -                } catch (IOException ex) {
> -                    if (ex instanceof SocketException) {
> -                        if (LOG.isDebugEnabled() 
> -                                && !this.destroyed && !Thread.interrupted()) {
> -                            LOG.debug("Connection listener terminated due to an I/O error: " + 
> -                                    ex.getMessage());
> -                        }
> -                    } else {
> -                        if (LOG.isWarnEnabled()) {
> -                            LOG.warn("Connection listener terminated due to an I/O error: " + 
> -                                    ex.getMessage(), ex);
> -                        }
> -                    }
> -                    break;
>                  } catch (Throwable ex) {
> -                    LOG.error("Connection listener terminated due to a runtime error", ex);
> -                    break;
> +                    if (Thread.interrupted())
> +                        break;
> +                    if (!failureHandler.failed(this, ex))
> +                        break;
>                  }
>              }
>          } finally {
> 
> Added: webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java
> URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java?view=auto&rev=471995
> ==============================================================================
> --- webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java (added)
> +++ webservices/axis2/branches/java/1_1/modules/kernel/src/org/apache/axis2/transport/http/server/DefaultConnectionListenerFailureHandler.java Mon Nov  6 21:52:15 2006
> @@ -0,0 +1,102 @@
> +/*
> + * $HeadURL$
> + * $Revision$
> + * $Date$
> + *
> + * ====================================================================
> + *
> + *  Copyright 1999-2006 The Apache Software Foundation
> + *
> + *  Licensed under the Apache License, Version 2.0 (the "License");
> + *  you may not use this file except in compliance with the License.
> + *  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + * ====================================================================
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals on behalf of the Apache Software Foundation.  For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + *
> + */
> +
> +package org.apache.axis2.transport.http.server;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +
> +/** Default hander for failures in connection listener IOProcessors.
> + *  Supports configuration of number retries, delay per retry, and uptime interval considered a success (resets number retries to zero).
> + */
> +public class DefaultConnectionListenerFailureHandler implements ConnectionListenerFailureHandler {
> +    
> +    private static final Log LOG = LogFactory.getLog(DefaultConnectionListenerFailureHandler.class);
> +
> +    protected int retryDelay;
> +    protected int successInterval;
> +    protected int maxRetries;
> +    
> +    private long lastFailure;
> +    private long lastFirstFailure;
> +    private int numRetries;
> +    
> +    /** Create a new DefaultConnectionListenerFailureHandler with default settings.
> +     * retryDelay is 1 second, successInterval is 60 seconds, maxRetries is 10
> +     */
> +    public DefaultConnectionListenerFailureHandler() {
> +        this(1000, 60000, 10);
> +    }
> +
> +    /** Create a new DefaultConnectionListenerFailureHandler
> +     * @param retryDelay millis to wait before retrying
> +     * @param successInterval millis after which an initial or retry attempt will be deemed a success, resetting retry count to 0
> +     * @param maxRetries maximum number of retries allowed without a success, after which the listener will terminate
> +     */
> +    public DefaultConnectionListenerFailureHandler(int retryDelay, int successInterval, int maxRetries) {
> +        this.retryDelay = retryDelay;
> +        this.successInterval = successInterval;
> +        this.maxRetries = maxRetries;
> +        this.lastFailure = this.lastFirstFailure = Long.MIN_VALUE;
> +        this.numRetries = 0;
> +    }
> +
> +    /** Default behavior is to log a warning and attempt retry per constructor config, eventually failing with a logged error and notification.
> +     * May subclass and override this method to change the behavior.
> +     */
> +    public boolean failed(IOProcessor connectionListener, Throwable cause) {
> +        long now = System.currentTimeMillis();
> +        if (now > lastFailure+successInterval) {
> +            numRetries = 0;
> +            lastFirstFailure = now;
> +        }
> +        lastFailure = now;
> +        if (numRetries >= maxRetries) {
> +            notifyAbnormalTermination(
> +                    connectionListener,
> +                    "Terminating connection listener " + connectionListener + " after " + numRetries + "retries in " + (now-lastFirstFailure)/1000 + " seconds.",
> +                    cause);
> +            return false;
> +        } else {
> +            numRetries++;
> +            if (LOG.isWarnEnabled())
> +                LOG.warn("Attempt number " + numRetries + " of " + maxRetries + " to reestalish connection listener " + connectionListener + " due to failure ",
> +                         cause);
> +            return true;
> +        }
> +    }
> +
> +    /** Default bevarior is to log the error.
> +     * May subclass and override this method to change behavior.
> +     */
> +    public void notifyAbnormalTermination(IOProcessor connectionListener, String message, Throwable cause) {
> +        LOG.error(message, cause);
> +    }
> +    
> +}
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
> For additional commands, e-mail: axis-cvs-help@ws.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org