in src/main/java/org/mariadb/jdbc/internal/protocol/AuroraProtocol.java [125:303]
public static void loop(
AuroraListener listener,
final GlobalStateInfo globalInfo,
final List<HostAddress> addresses,
SearchFilter initialSearchFilter)
throws SQLException {
SearchFilter searchFilter = initialSearchFilter;
AuroraProtocol protocol;
Deque<HostAddress> loopAddresses = new ArrayDeque<>(addresses);
if (loopAddresses.isEmpty()) {
resetHostList(listener, loopAddresses);
}
int maxConnectionTry = listener.getRetriesAllDown();
SQLException lastQueryException = null;
HostAddress probableMasterHost = null;
boolean firstLoop = true;
while (!loopAddresses.isEmpty() || (!searchFilter.isFailoverLoop() && maxConnectionTry > 0)) {
protocol = getNewProtocol(listener.getProxy(), globalInfo, listener.getUrlParser());
if (listener.isExplicitClosed()
|| (!listener.isSecondaryHostFailReconnect() && !listener.isMasterHostFailReconnect())) {
return;
}
maxConnectionTry--;
try {
HostAddress host = loopAddresses.pollFirst();
if (host == null) {
for (HostAddress hostAddress : listener.getUrlParser().getHostAddresses()) {
if (!hostAddress.equals(listener.getClusterHostAddress())) {
loopAddresses.add(hostAddress);
}
}
// Use cluster last as backup
if (listener.getClusterHostAddress() != null
&& (listener.getUrlParser().getHostAddresses().size() < 2
|| loopAddresses.isEmpty())) {
loopAddresses.add(listener.getClusterHostAddress());
}
host = loopAddresses.pollFirst();
}
protocol.setHostAddress(host);
protocol.connect();
if (listener.isExplicitClosed()) {
protocol.close();
return;
}
listener.removeFromBlacklist(protocol.getHostAddress());
if (listener.isMasterHostFailReconnect() && protocol.isMasterConnection()) {
// Look for secondary when only known endpoint is the cluster endpoint
if (searchFilter.isFineIfFoundOnlyMaster()
&& listener.getUrlParser().getHostAddresses().size() <= 1
&& protocol.getHostAddress().equals(listener.getClusterHostAddress())) {
listener.retrieveAllEndpointsAndSet(protocol);
if (listener.getUrlParser().getHostAddresses().size() > 1) {
// add newly discovered end-point to loop
loopAddresses.addAll(listener.getUrlParser().getHostAddresses());
// since there is more than one end point, reactivate connection to a read-only host
searchFilter = new SearchFilter(false);
}
}
if (foundMaster(listener, protocol, searchFilter)) {
return;
}
} else if (!protocol.isMasterConnection()) {
if (listener.isSecondaryHostFailReconnect()) {
// in case cluster DNS is currently pointing to a slave host
if (listener.getUrlParser().getHostAddresses().size() <= 1
&& protocol.getHostAddress().equals(listener.getClusterHostAddress())) {
listener.retrieveAllEndpointsAndSet(protocol);
if (listener.getUrlParser().getHostAddresses().size() > 1) {
// add newly discovered end-point to loop
loopAddresses.addAll(listener.getUrlParser().getHostAddresses());
// since there is more than one end point, reactivate connection to a read-only host
searchFilter = new SearchFilter(false);
}
} else {
if (foundSecondary(listener, protocol, searchFilter)) {
return;
}
}
} else {
try {
if (listener.isSecondaryHostFailReconnect()
|| (listener.isMasterHostFailReconnect() && probableMasterHost == null)) {
probableMasterHost =
listener.searchByStartName(
protocol, listener.getUrlParser().getHostAddresses());
if (probableMasterHost != null) {
loopAddresses.remove(probableMasterHost);
AuroraProtocol.searchProbableMaster(listener, globalInfo, probableMasterHost);
if (listener.isMasterHostFailReconnect()
&& searchFilter.isFineIfFoundOnlySlave()) {
return;
}
}
}
} finally {
protocol.close();
}
}
} else {
protocol.close();
}
} catch (SQLException e) {
lastQueryException = e;
listener.addToBlacklist(protocol.getHostAddress());
}
if (!listener.isMasterHostFailReconnect() && !listener.isSecondaryHostFailReconnect()) {
return;
}
// in case master not found but slave is , and allowing master down
if (loopAddresses.isEmpty()
&& (listener.isMasterHostFailReconnect()
&& listener.urlParser.getOptions().allowMasterDownConnection
&& !listener.isSecondaryHostFailReconnect())) {
return;
}
// on connection and all slaves have been tested, use master if on
if (loopAddresses.isEmpty()
&& searchFilter.isInitialConnection()
&& !listener.isMasterHostFailReconnect()) {
return;
}
// if server has try to connect to all host, and there is remaining master or slave that fail
// add all servers back to continue looping until maxConnectionTry is reached
if (loopAddresses.isEmpty() && !searchFilter.isFailoverLoop() && maxConnectionTry > 0) {
resetHostList(listener, loopAddresses);
if (firstLoop) {
firstLoop = false;
} else {
try {
// wait 250ms before looping through all connection another time
Thread.sleep(250);
} catch (InterruptedException interrupted) {
// interrupted, continue
}
}
}
// Try to connect to the cluster if no other connection is good
if (maxConnectionTry == 0
&& !loopAddresses.contains(listener.getClusterHostAddress())
&& listener.getClusterHostAddress() != null) {
loopAddresses.add(listener.getClusterHostAddress());
}
}
if (listener.isMasterHostFailReconnect() || listener.isSecondaryHostFailReconnect()) {
String error = "No active connection found for replica";
if (listener.isMasterHostFailReconnect()) {
error = "No active connection found for master";
}
if (lastQueryException != null) {
throw new SQLException(
error,
lastQueryException.getSQLState(),
lastQueryException.getErrorCode(),
lastQueryException);
}
throw new SQLException(error);
}
}