Skip to content

Commit

Permalink
[CONJ-555] failover implementation correction when issue is due to ti…
Browse files Browse the repository at this point in the history
…meout client side.
  • Loading branch information
rusher committed Dec 12, 2017
1 parent be7de9a commit e29fa94
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,7 @@ public HandleErrorResult primaryFail(Method method, Object[] args, boolean killC
boolean alreadyClosed = !currentProtocol.isConnected();
boolean inTransaction = currentProtocol != null && currentProtocol.inTransaction();

proxy.lock.lock();
try {
if (currentProtocol != null && currentProtocol.isConnected() && currentProtocol.isValid(0)) {
//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 (SQLException e) {
currentProtocol.close();
if (setMasterHostFail()) {
addToBlacklist(currentProtocol.getHostAddress());
}
} finally {
proxy.lock.unlock();
}
if (currentProtocol.isConnected()) currentProtocol.close();

try {
reconnectFailedConnection(new SearchFilter(true, false));
Expand All @@ -170,6 +152,11 @@ public HandleErrorResult primaryFail(Method method, Object[] args, boolean killC
return new HandleErrorResult(true);
} catch (Exception e) {
//we will throw a Connection exception that will close connection
if (e.getCause() != null
&& proxy.hasToHandleFailover((SQLException) e.getCause())
&& currentProtocol.isConnected()) {
currentProtocol.noLockClose();
}
FailoverLoop.removeListener(this);
return new HandleErrorResult();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,25 +539,8 @@ public HandleErrorResult primaryFail(Method method, Object[] args, boolean killC
boolean alreadyClosed = !masterProtocol.isConnected();
boolean inTransaction = masterProtocol != null && masterProtocol.inTransaction();

//try to reconnect automatically only time before looping
proxy.lock.lock();
try {
if (masterProtocol != null && masterProtocol.isConnected() && masterProtocol.isValid(0)) {
if (inTransaction) {
masterProtocol.rollback();
return new HandleErrorResult(true);
}
return relaunchOperation(method, args);
}
} catch (SQLException e) {
masterProtocol.close();

if (setMasterHostFail()) {
addToBlacklist(masterProtocol.getHostAddress());
}
} finally {
proxy.lock.unlock();
}
//in case of SocketTimeoutException due to having set socketTimeout, must force connection close
if (masterProtocol.isConnected()) masterProtocol.close();

//fail on slave if parameter permit so
if (urlParser.getOptions().failOnReadOnly && !isSecondaryHostFail()) {
Expand Down Expand Up @@ -606,6 +589,11 @@ public HandleErrorResult primaryFail(Method method, Object[] args, boolean killC
return new HandleErrorResult(true);
} catch (Exception e) {
//we will throw a Connection exception that will close connection
if (e.getCause() != null
&& proxy.hasToHandleFailover((SQLException) e.getCause())
&& currentProtocol.isConnected()) {
currentProtocol.noLockClose();
}
setMasterHostFail();
FailoverLoop.removeListener(this);
return new HandleErrorResult();
Expand Down Expand Up @@ -677,15 +665,9 @@ private boolean pingSecondaryProtocol(Protocol protocol) {
* @throws Throwable if failover has not catch error
*/
public HandleErrorResult secondaryFail(Method method, Object[] args, boolean killCmd) throws Throwable {
proxy.lock.lock();
try {
if (pingSecondaryProtocol(this.secondaryProtocol)) {
return relaunchOperation(method, args);
}
} finally {
proxy.lock.unlock();
}

//in case of SocketTimeoutException due to having set socketTimeout, must force connection close
if (secondaryProtocol.isConnected()) secondaryProtocol.close();

if (!isMasterHostFail()) {
try {
Expand All @@ -706,9 +688,7 @@ public HandleErrorResult secondaryFail(Method method, Object[] args, boolean kil
}
} catch (Exception e) {
//ping fail on master
if (setMasterHostFail()) {
blackListAndCloseConnection(masterProtocol);
}
if (setMasterHostFail()) blackListAndCloseConnection(masterProtocol);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1083,12 +1083,12 @@ public boolean isValid(int timeout) throws SQLException {
//this is a galera node.
//checking not only that node is responding, but that this node is in primary mode too.
Results results = new Results();
executeQuery(true, results, "SELECT @@wsrep_cluster_status");
executeQuery(true, results, "show status like 'wsrep_cluster_status'");
results.commandEnd();
ResultSet rs = results.getResultSet();

//return true if connected to a galera node that is primary
return (rs != null && (!rs.next() || "PRIMARY".equalsIgnoreCase(rs.getString(1))));
return (rs != null && (!rs.next() || "PRIMARY".equalsIgnoreCase(rs.getString(2))));
}

return ping();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public static SQLException getFeatureNotSupportedException(String message) {
}

/**
* Mapp code to State.
* Map code to State.
*
* @param code code
* @return String
Expand Down
30 changes: 30 additions & 0 deletions src/test/java/org/mariadb/jdbc/BasicFailover.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.mariadb.jdbc;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLNonTransientConnectionException;
import java.sql.Statement;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class BasicFailover extends BaseTest {

@Test
public void failoverRetry() throws Throwable {
try (Connection connection = DriverManager.getConnection("jdbc:mariadb:failover//" + ((hostname != null) ? hostname : "localhost")
+ ":" + port + "/" + database + "?user=" + username
+ ((password != null) ? "&password=" + password : "") + "&socketTimeout=1000")) {
try (Statement stmt = connection.createStatement()) {
stmt.execute("SELECT SLEEP(10)");
fail();
} catch (SQLNonTransientConnectionException e) {
//normal error : fail to reconnect, since second execution fail too
}
assertTrue(connection.isClosed());
}
}

}

0 comments on commit e29fa94

Please sign in to comment.