// We switch in a new state manager temporarily so that the interaction to get to the "connection open"
// state works, without us having to terminate any existing "state waiters". We could theoretically
// have a state waiter waiting until the connection is closed for some reason. Or in future we may have
// a slightly more complex state model therefore I felt it was worthwhile doing this.
AMQStateManager existingStateManager = _amqProtocolHandler.getStateManager();
// Use a fresh new StateManager for the reconnection attempts
_amqProtocolHandler.setStateManager(new AMQStateManager());
if (!_amqProtocolHandler.getConnection().firePreFailover(_host != null))
{
_logger.info("Failover process veto-ed by client");
//Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);
//todo: ritchiem these exceptions are useless... Would be better to attempt to propogate exception that
// prompted the failover event.
if (_host != null)
{
_amqProtocolHandler.getConnection().exceptionReceived(new AMQDisconnectedException("Redirect was vetoed by client", null));
}
else
{
_amqProtocolHandler.getConnection().exceptionReceived(new AMQDisconnectedException("Failover was vetoed by client", null));
}
_amqProtocolHandler.getFailoverLatch().countDown();
_amqProtocolHandler.setFailoverLatch(null);
return;
}
_logger.info("Starting failover process");
boolean failoverSucceeded;
// when host is non null we have a specified failover host otherwise we all the client to cycle through
// all specified hosts
// if _host has value then we are performing a redirect.
if (_host != null)
{
failoverSucceeded = _amqProtocolHandler.getConnection().attemptReconnection(_host, _port);
}
else
{
failoverSucceeded = _amqProtocolHandler.getConnection().attemptReconnection();
}
if (!failoverSucceeded)
{
//Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);
_amqProtocolHandler.getConnection().exceptionReceived(
new AMQDisconnectedException("Server closed connection and no failover " +
"was successful", null));
}
else
{
// Set the new Protocol Session in the StateManager.
existingStateManager.setProtocolSession(_amqProtocolHandler.getProtocolSession());
// Now that the ProtocolHandler has been reconnected clean up
// the state of the old state manager. As if we simply reinstate
// it any old exception that had occured prior to failover may
// prohibit reconnection.
// e.g. During testing when the broker is shutdown gracefully.
// The broker
// Clear any exceptions we gathered
if (existingStateManager.getCurrentState() != AMQState.CONNECTION_OPEN)
{
// Clear the state of the previous state manager as it may
// have received an exception
existingStateManager.clearLastException();
existingStateManager.changeState(AMQState.CONNECTION_OPEN);
}
//Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);