Coverage Report - org.mule.providers.SimpleRetryConnectionStrategy
 
Classes in this File Line Coverage Branch Coverage Complexity
SimpleRetryConnectionStrategy
0%
0/42
0%
0/7
2.4
SimpleRetryConnectionStrategy$RetryCounter
0%
0/6
N/A
2.4
 
 1  
 /*
 2  
  * $Id: SimpleRetryConnectionStrategy.java 7976 2007-08-21 14:26:13Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.providers;
 12  
 
 13  
 import org.mule.config.ExceptionHelper;
 14  
 import org.mule.config.i18n.CoreMessages;
 15  
 import org.mule.umo.provider.UMOConnectable;
 16  
 import org.mule.util.ObjectUtils;
 17  
 
 18  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
 19  
 
 20  
 /**
 21  
  * A simple connection retry strategy where the a connection will be attempted X
 22  
  * number of retryCount every Y milliseconds. The <i>retryCount</i> and <i>frequency</i>
 23  
  * properties can be set to customise the behaviour.
 24  
  */
 25  
 
 26  0
 public class SimpleRetryConnectionStrategy extends AbstractConnectionStrategy
 27  
 {
 28  
     public static final int DEFAULT_FREQUENCY = 2000;
 29  
     public static final int DEFAULT_RETRY_COUNT = 2;
 30  
     public static final int RETRY_COUNT_FOREVER = -1;
 31  
 
 32  0
     protected static class RetryCounter extends ThreadLocal
 33  
     {
 34  
         public int countRetry()
 35  
         {
 36  0
             return ((AtomicInteger) get()).incrementAndGet();
 37  
         }
 38  
         
 39  
         public void reset()
 40  
         {
 41  0
             ((AtomicInteger) get()).set(0);
 42  0
         }
 43  
 
 44  
         public AtomicInteger current()
 45  
         {
 46  0
             return (AtomicInteger) get();
 47  
         }
 48  
 
 49  
         // @Override
 50  
         protected Object initialValue()
 51  
         {
 52  0
             return new AtomicInteger(0);
 53  
         }
 54  
     }
 55  
 
 56  0
     protected static final RetryCounter retryCounter = new RetryCounter();
 57  
 
 58  0
     protected static final ThreadLocal called = new ThreadLocal();
 59  
 
 60  0
     private volatile int retryCount = DEFAULT_RETRY_COUNT;
 61  0
     private volatile long frequency = DEFAULT_FREQUENCY;
 62  
 
 63  
     protected void doConnect(UMOConnectable connectable) throws FatalConnectException
 64  
     {
 65  
         while (true)
 66  
         {
 67  0
             final Boolean recursiveCallDetected = (Boolean) ObjectUtils.defaultIfNull(called.get(), Boolean.FALSE);
 68  0
             if (!recursiveCallDetected.booleanValue())
 69  
             {
 70  0
                 retryCounter.countRetry();
 71  
             }
 72  0
             called.set(Boolean.TRUE);
 73  
 
 74  
             try
 75  
             {
 76  0
                 connectable.connect();
 77  0
                 if (logger.isDebugEnabled())
 78  
                 {
 79  0
                     logger.debug("Successfully connected to " + getDescription(connectable));
 80  
                 }
 81  
                 break;
 82  
             }
 83  0
             catch (InterruptedException ie)
 84  
             {
 85  
                 // If we were interrupted it's probably because the server is
 86  
                 // shutting down
 87  0
                 throw new FatalConnectException(
 88  
                     // TODO it's not only endpoint that is reconnected, connectors too
 89  
                     CoreMessages.reconnectStrategyFailed(this.getClass(), 
 90  
                         this.getDescription(connectable)), ie, connectable);
 91  
             }
 92  0
             catch (Exception e)
 93  
             {
 94  0
                 if (e instanceof FatalConnectException)
 95  
                 {
 96  
                     // rethrow
 97  0
                     throw (FatalConnectException) e;
 98  
                 }
 99  0
                 if (retryCount != RETRY_COUNT_FOREVER && retryCounter.current().get() >= retryCount)
 100  
                 {
 101  0
                     throw new FatalConnectException(
 102  
                         // TODO it's not only endpoint that is reconnected, connectors too
 103  
                         CoreMessages.reconnectStrategyFailed(this.getClass(),
 104  
                             this.getDescription(connectable)), e, connectable);
 105  
                 }
 106  
 
 107  0
                 if (logger.isErrorEnabled())
 108  
                 {
 109  0
                     StringBuffer msg = new StringBuffer(512);
 110  0
                     msg.append("Failed to connect/reconnect: ").append(
 111  
                             getDescription(connectable));
 112  0
                     Throwable t = ExceptionHelper.getRootException(e);
 113  0
                     msg.append(". Root Exception was: ").append(ExceptionHelper.writeException(t));
 114  0
                     logger.error(msg.toString(), e);
 115  
                 }
 116  
 
 117  0
                 if (logger.isInfoEnabled())
 118  
                 {
 119  0
                     logger.info("Waiting for " + frequency + "ms before reconnecting. Failed attempt "
 120  
                                 + retryCounter.current().get() + " of " +
 121  
                                 (retryCount != RETRY_COUNT_FOREVER ? String.valueOf(retryCount) : "unlimited"));
 122  
                 }
 123  
 
 124  
                 try
 125  
                 {
 126  0
                     Thread.sleep(frequency);
 127  
                 }
 128  0
                 catch (InterruptedException e1)
 129  
                 {
 130  0
                     throw new FatalConnectException(
 131  
                         // TODO it's not only endpoint that is reconnected, connectors too
 132  
                         CoreMessages.reconnectStrategyFailed(this.getClass(), 
 133  
                             this.getDescription(connectable)), e, connectable);
 134  0
                 }
 135  
             }
 136  
             finally
 137  
             {
 138  0
                 called.set(Boolean.FALSE);
 139  0
             }
 140  
         }
 141  0
     }
 142  
 
 143  
     /**
 144  
      * Resets any state stored in the retry strategy
 145  
      */
 146  
     public synchronized void resetState()
 147  
     {
 148  0
         retryCounter.reset();
 149  0
     }
 150  
 
 151  
     public int getRetryCount()
 152  
     {
 153  0
         return retryCount;
 154  
     }
 155  
 
 156  
     /**
 157  
      * How many times to retry. Set to -1 to retry forever.
 158  
      * @param retryCount number of retries
 159  
      */
 160  
     public void setRetryCount(int retryCount)
 161  
     {
 162  0
         this.retryCount = retryCount;
 163  0
     }
 164  
 
 165  
     public long getFrequency()
 166  
     {
 167  0
         return frequency;
 168  
     }
 169  
 
 170  
     public void setFrequency(long frequency)
 171  
     {
 172  0
         this.frequency = frequency;
 173  0
     }
 174  
 }