return InvokerInterceptor.getLocal().invoke(invocation);
}
else
{
// We are going to go through a Remote invocation, switch to a Marshalled Invocation
MarshalledInvocation mi = new MarshalledInvocation(invocation);
// Set the transaction propagation context
mi.setTransactionPropagationContext(getTransactionPropagationContext());
mi.setValue("CLUSTER_VIEW_ID", new Long(this.familyClusterInfo.getCurrentViewId ()));
Invoker target = (Invoker)getRemoteTarget(invocation);
boolean failoverAuthorized = true;
Exception lastException = null;
while (target != null && failoverAuthorized)
{
boolean definitivlyRemoveNodeOnFailure = true;
try
{
if( trace )
log.trace("Invoking on target="+target);
Object rtnObj = target.invoke(mi);
HARMIResponse rsp = null;
if (rtnObj instanceof MarshalledObject)
{
rsp = (HARMIResponse)((MarshalledObject)rtnObj).get();
}
else
{
rsp = (HARMIResponse)rtnObj;
}
if (rsp.newReplicants != null)
{
if( trace )
{
log.trace("newReplicants: "+rsp.newReplicants);
}
updateClusterInfo (rsp.newReplicants, rsp.currentViewId);
}
//else System.out.println("Static set of replicants: " + this.familyClusterInfo.getCurrentViewId () + " (me = " + this + ")");
invocationHasReachedAServer (invocation);
return rsp.response;
}
catch (java.net.ConnectException e)
{
lastException = e;
}
catch (java.net.UnknownHostException e)
{
lastException = e;
}
catch (java.rmi.ConnectException e)
{
lastException = e;
if(e.getCause() != null && e.getCause() instanceof java.io.EOFException)
{
// don't failover as we may of reached the target
invocationHasReachedAServer (invocation);
throw e;
}
}
catch (java.rmi.ConnectIOException e)
{
lastException = e;
}
catch (java.rmi.NoSuchObjectException e)
{
lastException = e;
}
catch (java.rmi.UnknownHostException e)
{
lastException = e;
}
catch (GenericClusteringException e)
{
lastException = e;
// this is a generic clustering exception that contain the
// completion status: usefull to determine if we are authorized
// to re-issue a query to another node
//
if (e.getCompletionStatus () == GenericClusteringException.COMPLETED_NO)
{
// we don't want to remove the node from the list of failed
// node UNLESS there is a risk to indefinitively loop
//
if (totalNumberOfTargets() >= failoverCounter)
{
if (!e.isDefinitive ())
definitivlyRemoveNodeOnFailure = false;
}
}
else
{
invocationHasReachedAServer (invocation);
throw new ServerException("Clustering error", e);
}
}
catch (ServerException e)
{
//Why do NoSuchObjectExceptions get ignored for a retry here
//unlike in the non-HA case?
invocationHasReachedAServer (invocation);
if (e.detail instanceof TransactionRolledbackException)
{
throw (TransactionRolledbackException) e.detail;
}
if (e.detail instanceof RemoteException)
{
throw (RemoteException) e.detail;
}
throw e;
}
catch (Exception e)
{
lastException = e;
invocationHasReachedAServer (invocation);
throw e;
}
if( trace )
log.trace("Invoke failed, target="+target, lastException);
// If we reach here, this means that we must fail-over
remoteTargetHasFailed(target);
if (!definitivlyRemoveNodeOnFailure)
{
resetView ();
}
failoverAuthorized = txContextAllowsFailover (invocation);
target = (Invoker)getRemoteTarget(invocation);
failoverCounter++;
mi.setValue ("FAILOVER_COUNTER", new Integer(failoverCounter), PayloadKey.AS_IS);
}
// if we get here this means list was exhausted
String msg = "Service unavailable.";
if (failoverAuthorized == false)
{