Package org.jboss.jms.client.container

Source Code of org.jboss.jms.client.container.FailoverValveInterceptor

/**
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.jms.client.container;

import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
import org.jboss.jms.client.FailoverCommandCenter;
import org.jboss.jms.client.FailoverValve2;
import org.jboss.jms.client.FailureDetector;
import org.jboss.jms.client.delegate.ClientSessionDelegate;
import org.jboss.jms.client.delegate.DelegateSupport;
import org.jboss.jms.client.remoting.JMSRemotingConnection;
import org.jboss.jms.client.state.ConnectionState;
import org.jboss.jms.client.state.HierarchicalState;
import org.jboss.jms.util.MessagingNetworkFailureException;
import org.jboss.logging.Logger;

/**
* An interceptor that acts as a failover valve: it allows all invocations to go through as long
* as there is no failover in progress (valve is open), and holds all invocations while client-side
* failover is taking place (valve is closed). The interceptor is also a failover detector, in that
* it catches "failure-triggering" exceptions, and notifies the failover command center.
*
* The interceptor fields org.jboss.jms.client.Valve's method calls.
*
* It is a PER_INSTANCE interceptor.
*
* An instance of this interceptor must guard access to each connection, session, producer, consumer
* and queue browser delegate.
*
* @author <a href="mailto:ovidiu@jboss.org">Ovidiu Feodorov</a>
* @author <a href="mailto:clebert.suconic@jboss.org">Clebert Suconic</a>
* @version <tt>$Revision: 2507 $</tt>
* $Id: FailoverValveInterceptor.java 2507 2007-02-28 23:46:51Z timfox $
*/
public class FailoverValveInterceptor implements Interceptor, FailureDetector
{
   // Constants ------------------------------------------------------------------------------------

   private static final Logger log = Logger.getLogger(FailoverValveInterceptor.class);

   // Static ---------------------------------------------------------------------------------------

   private static boolean trace = log.isTraceEnabled();

   // Attributes -----------------------------------------------------------------------------------

   private DelegateSupport delegate;

   // We need to cache connectionState here.
   // IMPORTANT - We must not cache the fcc or valve since these need to be replaced when failover
   //             occurs and if we cache them we wil end up using the old ones.
   private ConnectionState connectionState;

   // Constructors ---------------------------------------------------------------------------------

   // Interceptor implemenation --------------------------------------------------------------------

   public String getName()
   {
      return "FailoverValveInterceptor";
   }
  
   public Object invoke(Invocation invocation) throws Throwable
   {     
      // maintain a reference to connectionState, so we can ensure we have already tested for fcc.
      // As fcc can be null on non-clustered connections we have to cache connectionState instead
      if (connectionState == null)
      {
         delegate = (DelegateSupport)invocation.getTargetObject();

         HierarchicalState hs = delegate.getState();
         while (hs != null && !(hs instanceof ConnectionState))
         {
            hs = hs.getParent();
         }
        
         connectionState = (ConnectionState)hs;
      }
     
      FailoverCommandCenter fcc = connectionState.getFailoverCommandCenter();
           
      // non clustered, send the invocation forward
      if (fcc == null)
      {
         return invocation.invokeNext();
      }
     
      FailoverValve2 valve = fcc.getValve();
     
      JMSRemotingConnection remotingConnection = null;
      String methodName = ((MethodInvocation)invocation).getMethod().getName();

      boolean left = false;
     
      try
      {
         valve.enter();

         // it's important to retrieve the remotingConnection while inside the Valve
         remotingConnection = fcc.getRemotingConnection();
         return invocation.invokeNext();
      }
      catch (MessagingNetworkFailureException e)
      {
         valve.leave();
         left = true;
        
         log.debug(this + " detected network failure, putting " + methodName +
         "() on hold until failover completes");
     
         fcc.failureDetected(e, this, remotingConnection);
        
         // Set retry flag as true on send() and sendTransaction()
         // more details at http://jira.jboss.org/jira/browse/JBMESSAGING-809

         if (invocation.getTargetObject() instanceof ClientSessionDelegate &&
            (methodName.equals("send") || methodName.equals("sendTransaction")))
         {
            log.debug(this + " caught " + methodName + "() invocation, enabling check for duplicates");

            Object[] arguments = ((MethodInvocation)invocation).getArguments();
            arguments[1] = Boolean.TRUE;
            ((MethodInvocation)invocation).setArguments(arguments);
         }

         // We don't retry the following invocations:
         // cancelDelivery(), cancelDeliveries(), cancelInflightMessages() - the deliveries will
         // already be cancelled after failover.

         if (methodName.equals("cancelDelivery") ||
            methodName.equals("cancelDeliveries"))
         {
            log.debug(this + " NOT resuming " + methodName + "(), let it wither and die");
           
            return null;
         }
         else
         {           
            log.debug(this + " resuming " + methodName + "()");
           
            return invocation.invokeNext();
         }
      }
      catch (Throwable e)
      {
         // not failover-triggering, rethrow
         if (trace) { log.trace(this + " caught not failover-triggering throwable, rethrowing " + e); }
         throw e;
      }
      finally
      {
         if (!left)
         {
            valve.leave();
         }
      }
   }
  
   // Public ---------------------------------------------------------------------------------------

   public String toString()
   {
      return "FailoverValveInterceptor." + (delegate == null ? "UNITIALIZED" : delegate.toString());
   }

   // Package protected ----------------------------------------------------------------------------

   // Protected ------------------------------------------------------------------------------------

   // Private --------------------------------------------------------------------------------------

   // Inner classes --------------------------------------------------------------------------------
}
TOP

Related Classes of org.jboss.jms.client.container.FailoverValveInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.