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.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);
    }
  }
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 ) ; } } if ( listener . getClusterHostAddress ( ) != null && listener . getUrlParser ( ) . getHostAddresses ( ) . size ( ) < 2 ) { 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 ( ) ) { if ( searchFilter . isFineIfFoundOnlyMaster ( ) && listener . getUrlParser ( ) . getHostAddresses ( ) . size ( ) <= 1 && protocol . getHostAddress ( ) . equals ( listener . getClusterHostAddress ( ) ) ) { listener . retrieveAllEndpointsAndSet ( protocol ) ; if ( listener . getUrlParser ( ) . getHostAddresses ( ) . size ( ) > 1 ) { loopAddresses . addAll ( listener . getUrlParser ( ) . getHostAddresses ( ) ) ; searchFilter = new SearchFilter ( false ) ; } } if ( foundMaster ( listener , protocol , searchFilter ) ) { return ; } } else if ( ! protocol . isMasterConnection ( ) ) { if ( listener . isSecondaryHostFailReconnect ( ) ) { if ( listener . getUrlParser ( ) . getHostAddresses ( ) . size ( ) <= 1 && protocol . getHostAddress ( ) . equals ( listener . getClusterHostAddress ( ) ) ) { listener . retrieveAllEndpointsAndSet ( protocol ) ; if ( listener . getUrlParser ( ) . getHostAddresses ( ) . size ( ) > 1 ) { loopAddresses . addAll ( listener . getUrlParser ( ) . getHostAddresses ( ) ) ; 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 ; } if ( loopAddresses . isEmpty ( ) && ( listener . isMasterHostFailReconnect ( ) && listener . urlParser . getOptions ( ) . allowMasterDownConnection && ! listener . isSecondaryHostFailReconnect ( ) ) ) { return ; } if ( loopAddresses . isEmpty ( ) && searchFilter . isInitialConnection ( ) && ! listener . isMasterHostFailReconnect ( ) ) { return ; } if ( loopAddresses . isEmpty ( ) && ! searchFilter . isFailoverLoop ( ) && maxConnectionTry > 0 ) { resetHostList ( listener , loopAddresses ) ; if ( firstLoop ) { firstLoop = false ; } else { try { Thread . sleep ( 250 ) ; } catch ( InterruptedException interrupted ) { } } } 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 ) ; } }
loop until found the failed connection.

@param listener            current failover
@param globalInfo          server global variables information
@param addresses           list of HostAddress to loop
@param initialSearchFilter search parameter
@throws SQLException if not found