/** * Add listener to FailoverLoop if master connection is not active, so a reconnection will be * done. (the reconnection will be done by failover or if append before by the next query/method * that will use the failed connection) Remove listener from FailoverLoop is master connection is * active. */ public void handleFailLoop() { if (isMasterHostFail()) { if (!isExplicitClosed()) { FailoverLoop.addListener(this); } } else { FailoverLoop.removeListener(this); } }
/** * method called when a new Master connection is found after a fallback. * * @param protocol the new active connection */ @Override public void foundActiveMaster(Protocol protocol) throws QueryException { if (isExplicitClosed()) { proxy.lock.lock(); try { protocol.close(); } finally { proxy.lock.unlock(); } return; } syncConnection(this.currentProtocol, protocol); proxy.lock.lock(); try { if (currentProtocol != null && !currentProtocol.isClosed()) { currentProtocol.close(); } currentProtocol = protocol; } finally { proxy.lock.unlock(); } resetMasterFailoverData(); FailoverLoop.removeListener(this); }
/** * Loop to connect failed hosts. * * @param searchFilter search parameters. * @throws QueryException if there is any error during reconnection */ @Override public void reconnectFailedConnection(SearchFilter searchFilter) throws QueryException { proxy.lock.lock(); try { if (!searchFilter.isInitialConnection() && (isExplicitClosed() || !isMasterHostFail())) { return; } currentConnectionAttempts.incrementAndGet(); resetOldsBlackListHosts(); List<HostAddress> loopAddress = new LinkedList<>(urlParser.getHostAddresses()); if (HaMode.FAILOVER.equals(mode)) { // put the list in the following order // - random order not connected host // - random order blacklist host // - random order connected host loopAddress.removeAll(getBlacklistKeys()); Collections.shuffle(loopAddress); List<HostAddress> blacklistShuffle = new LinkedList<>(getBlacklistKeys()); Collections.shuffle(blacklistShuffle); loopAddress.addAll(blacklistShuffle); } else { // order in sequence loopAddress.removeAll(getBlacklistKeys()); loopAddress.addAll(getBlacklistKeys()); } // put connected at end if (currentProtocol != null && !isMasterHostFail()) { loopAddress.remove(currentProtocol.getHostAddress()); // loopAddress.add(currentProtocol.getHostAddress()); } MasterProtocol.loop(this, loopAddress, searchFilter); // close loop if all connection are retrieved if (!isMasterHostFail()) { FailoverLoop.removeListener(this); } // if no error, reset failover variables resetMasterFailoverData(); } finally { proxy.lock.unlock(); } }
@Override public HandleErrorResult primaryFail(Method method, Object[] args) throws Throwable { boolean alreadyClosed = !currentProtocol.isConnected(); boolean inTransaction = currentProtocol != null && currentProtocol.inTransaction(); try { if (currentProtocol != null && currentProtocol.isConnected() && currentProtocol.ping()) { // connection re-established // if in transaction cannot be sure that the last query has been received by server of not, // so rollback.and throw exception if (currentProtocol.inTransaction()) { currentProtocol.rollback(); } return new HandleErrorResult(true); } } catch (QueryException e) { proxy.lock.lock(); try { currentProtocol.close(); } finally { proxy.lock.unlock(); } if (setMasterHostFail()) { addToBlacklist(currentProtocol.getHostAddress()); } } try { reconnectFailedConnection(new SearchFilter(true, false)); handleFailLoop(); if (alreadyClosed || (!alreadyClosed && !inTransaction && isQueryRelaunchable(method, args))) { return relaunchOperation(method, args); } return new HandleErrorResult(true); } catch (Exception e) { // we will throw a Connection exception that will close connection FailoverLoop.removeListener(this); return new HandleErrorResult(); } }