// Keep trying until the message is sent.
for (int i = 0; !disposed; i++) {
try {
// Wait for transport to be connected.
Transport transport = connectedTransport.get();
long start = System.currentTimeMillis();
boolean timedout = false;
while (transport == null && !disposed && connectionFailure == null
&& !Thread.currentThread().isInterrupted()) {
LOG.trace("Waiting for transport to reconnect..: " + command);
long end = System.currentTimeMillis();
if (timeout > 0 && (end - start > timeout)) {
timedout = true;
LOG.info("Failover timed out after " + (end - start) + "ms");
break;
}
try {
reconnectMutex.wait(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.debug("Interupted: " + e, e);
}
transport = connectedTransport.get();
}
if (transport == null) {
// Previous loop may have exited due to use being
// disposed.
if (disposed) {
error = new IOException("Transport disposed.");
} else if (connectionFailure != null) {
error = connectionFailure;
} else if (timedout == true) {
error = new IOException("Failover timeout of " + timeout + " ms reached.");
} else {
error = new IOException("Unexpected failure.");
}
break;
}
// If it was a request and it was not being tracked by
// the state tracker,
// then hold it in the requestMap so that we can replay
// it later.
Tracked tracked = stateTracker.track(command);
synchronized (requestMap) {
if (tracked != null && tracked.isWaitingForResponse()) {
requestMap.put(Integer.valueOf(command.getCommandId()), tracked);
} else if (tracked == null && command.isResponseRequired()) {
requestMap.put(Integer.valueOf(command.getCommandId()), command);
}
}
// Send the message.
try {
transport.oneway(command);
stateTracker.trackBack(command);
} catch (IOException e) {
// If the command was not tracked.. we will retry in
// this method