You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by Sanjiva Weerawarana <sa...@opensource.lk> on 2006/11/07 11:31:59 UTC

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

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