FileDocCategorySizeDatePackage
HARMIClient.javaAPI DocJBoss 4.2.110517Fri Jul 13 20:52:36 BST 2007org.jboss.ha.framework.interfaces

HARMIClient

public class HARMIClient extends Object implements InvocationHandler, HARMIProxy, Serializable
author
Sacha Labourey
author
Bill Burke
version
$Revision: 57188 $

Fields Summary
private static final long
serialVersionUID
The serialVersionUID
private static final Logger
log
protected static final Method
TO_STRING
{@link Object#toString} method reference.
protected static final Method
HASH_CODE
{@link Object#hashCode} method reference.
protected static final Method
EQUALS
{@link Object#equals} method reference.
protected String
key
protected LoadBalancePolicy
loadBalancePolicy
protected transient Object
local
protected transient boolean
trace
FamilyClusterInfo
familyClusterInfo
Constructors Summary
public HARMIClient()


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

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

     
public HARMIClient(ArrayList targets, LoadBalancePolicy policy, String key)

      this(targets, 0, policy, key, null);
   
public HARMIClient(ArrayList targets, long initViewId, LoadBalancePolicy policy, String key, Object local)

      this.familyClusterInfo = ClusteringTargetsRepository.initTarget (key, targets, initViewId);

      //this.targets = targets;
      this.loadBalancePolicy = policy;
      this.loadBalancePolicy.init(this);
      this.key = key;
      this.local = local;
      this.trace = log.isTraceEnabled();
      if( trace )
         log.trace("Init, cluterInfo: "+familyClusterInfo+", policy="+loadBalancePolicy);
   
Methods Summary
public java.lang.reflect.MethodfindLocalMethod(java.lang.reflect.Method method, java.lang.Object[] args)

      return method;
   
public java.lang.ObjectgetRemoteTarget()

      //      System.out.println("number of targets: " + targets.size());
      return loadBalancePolicy.chooseTarget(this.familyClusterInfo, null); // legacy, no Invocation object in raw HA-RMI
   
public java.lang.Objectinvoke(java.lang.Object proxy, java.lang.reflect.Method method, java.lang.Object[] args)

      // The isLocal call is handled by the proxy
      String name = method.getName();
      if (method.equals(TO_STRING))
      {
         StringBuffer tmp = new StringBuffer(super.toString());
         tmp.append('(");
         tmp.append(familyClusterInfo);
         tmp.append(')");
         return tmp.toString();
      }
      else if (name.equals("equals"))
      {
         return method.invoke(this, args);
      }
      else if (name.equals("hashCode"))
      {
         return method.invoke(this, args);
      }
      else if (name.equals("isLocal") && (args == null || args.length == 0))
      {
         return method.invoke(this, args);
      }

      // we try to optimize the call locally first
      //
      if (local != null)
      {
         try
         {
            Method localMethod = findLocalMethod(method, args);
            return localMethod.invoke(local, args);
         }
         catch (java.lang.reflect.InvocationTargetException ite)
         {
            throw ite.getTargetException();
         }
      }
      else
      {
         return invokeRemote(null, method, args);
      }
   
public java.lang.ObjectinvokeRemote(java.lang.Object proxy, java.lang.reflect.Method method, java.lang.Object[] args)

      boolean trace = log.isTraceEnabled();
      HARMIServer target = (HARMIServer)getRemoteTarget();
      while (target != null)
      {
         Exception lastException = null;
         try
         {
            if( trace )
               log.trace("Invoking on target="+target);
            MarshalledInvocation mi = new MarshalledInvocation(null, method, args, null, null, null);
            mi.setObjectName (""); //FIXME: Fake value! Bill's optimisations regarding MI make the hypothesis
                                   // that ObjectName is always here otherwise the writeExternal code of MI
                                   // "out.writeInt(payload.size() - 3);" is wrong
            HARMIResponse rsp = target.invoke(this.familyClusterInfo.getCurrentViewId (), mi);
            if (rsp.newReplicants != null)
            {
               if( trace )
               {
                  log.trace("newReplicants: "+rsp.newReplicants);
               }
               updateClusterInfo (rsp.newReplicants, rsp.currentViewId);
               //setTargets(rsp.newReplicants);
               //currentViewId = rsp.currentViewId;
            }

            return rsp.response;
         }
         catch (java.rmi.ConnectException e)
         {
            lastException = e;
         }
         catch (java.rmi.ConnectIOException e)
         {
            lastException = e;
         }
         catch (java.rmi.NoSuchObjectException e)
         {
            lastException = e;
         }
         catch (java.rmi.UnmarshalException e)
         {
            lastException = e;
         }
         catch (java.rmi.UnknownHostException e)
         {
            lastException = e;
         }
         if( trace )
            log.trace("Invoke failed, target="+target, lastException);
         // If we reach here, this means that we must fail-over
         remoteTargetHasFailed(target);
         target = (HARMIServer)getRemoteTarget();
      }
      // if we get here this means list was exhausted
      throw new java.rmi.RemoteException("Service unavailable.");

   
public booleanisLocal()

      return local != null;
   
private voidreadObject(java.io.ObjectInputStream stream)

      this.key = stream.readUTF();
      ArrayList targets = (ArrayList)stream.readObject();
      long vid = stream.readLong ();
      this.loadBalancePolicy = (LoadBalancePolicy)stream.readObject();
      HARMIServer server = (HARMIServer)HARMIServer.rmiServers.get(key);

      // keep a reference on our family object
      //
      this.familyClusterInfo = ClusteringTargetsRepository.initTarget (this.key, targets, vid);

      this.loadBalancePolicy.init(this);

      if (server != null)
      {
         synchronized (targets)
         {
            try
            {
               targets = (ArrayList)server.getReplicants();
               local = server.getLocal();
            }
            catch (Exception ignored)
            {}
         }
      }
      this.trace = log.isTraceEnabled();
      if( trace )
         log.trace("Init, clusterInfo: "+familyClusterInfo+", policy="+loadBalancePolicy);
   
public voidremoteTargetHasFailed(java.lang.Object target)

      removeDeadTarget(target);
   
protected voidremoveDeadTarget(java.lang.Object target)

      //System.out.println("Size before : " + Integer.toString(targets.length));
      if (this.familyClusterInfo != null)
         this.familyClusterInfo.removeDeadTarget (target);
   
public voidupdateClusterInfo(java.util.ArrayList targets, long viewId)

      if (familyClusterInfo != null)
         this.familyClusterInfo.updateClusterInfo (targets, viewId);
   
private voidwriteObject(java.io.ObjectOutputStream stream)

      // JBAS-2071 - sync on FCI to ensure targets and vid are consistent
      ArrayList currentTargets = null;
      long vid = 0;
      synchronized (this.familyClusterInfo)
      {
         currentTargets = this.familyClusterInfo.getTargets();
         vid = this.familyClusterInfo.getCurrentViewId ();
      }
      stream.writeUTF(key);
      stream.writeObject(currentTargets);
      stream.writeLong(vid);
      stream.writeObject(loadBalancePolicy);