package org.mariadb.jdbc.failover;
import org.junit.*;
import org.mariadb.jdbc.HostAddress;
import org.mariadb.jdbc.UrlParser;
import org.mariadb.jdbc.internal.protocol.Protocol;
import org.mariadb.jdbc.internal.util.constant.HaMode;
import org.threadly.test.concurrent.TestableScheduler;
import java.sql.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
/**
* Test for sequential connection
* exemple mvn test -DdefaultGaleraUrl=jdbc:mariadb:sequential//localhost:3306,localhost:3307/test?user=root.
*/
public class SequentialFailoverTest extends BaseMultiHostTest {
/**
* Initialisation.
*
* @throws SQLException exception
*/
@BeforeClass()
public static void beforeClass2() throws SQLException {
proxyUrl = proxySequentialUrl;
Assume.assumeTrue(initialGaleraUrl != null);
}
/**
* Initialisation.
*
* @throws SQLException exception
*/
@Before
public void init() throws SQLException {
defaultUrl = initialGaleraUrl;
currentType = HaMode.SEQUENTIAL;
}
@Test
public void connectionOrder() throws Throwable {
Assume.assumeTrue(!initialGaleraUrl.contains("failover"));
UrlParser urlParser = UrlParser.parse(initialGaleraUrl);
for (int i = 0; i < urlParser.getHostAddresses().size(); i++) {
int serverNb;
try (Connection connection = getNewConnection(true)) {
serverNb = getServerId(connection);
assertTrue(serverNb == i + 1);
}
stopProxy(serverNb);
}
}
@Test
public void checkStaticBlacklist() throws Throwable {
assureProxy();
try (Connection connection = getNewConnection("&loadBalanceBlacklistTimeout=500", true)) {
Statement st = connection.createStatement();
int firstServerId = getServerId(connection);
stopProxy(firstServerId);
try {
st.execute("SELECT 1");
fail();
} catch (SQLException e) {
//normal exception that permit to blacklist the failing connection.
}
//check blacklist size
try {
Protocol protocol = getProtocolFromConnection(connection);
assertTrue(protocol.getProxy().getListener().getBlacklistKeys().size() == 1);
//replace proxified HostAddress by normal one
UrlParser urlParser = UrlParser.parse(defaultUrl);
protocol.getProxy().getListener().addToBlacklist(urlParser.getHostAddresses().get(firstServerId - 1));
} catch (Throwable e) {
e.printStackTrace();
fail();
}
//add first Host to blacklist
Protocol protocol = getProtocolFromConnection(connection);
TestableScheduler scheduler = new TestableScheduler();
//check blacklist shared
scheduler.execute(new CheckBlacklist(firstServerId, protocol.getProxy().getListener().getBlacklistKeys()));
scheduler.execute(new CheckBlacklist(firstServerId, protocol.getProxy().getListener().getBlacklistKeys()));
// deterministically execute CheckBlacklists
scheduler.tick();
}
}
@Test
public void testMultiHostWriteOnMaster() throws Throwable {
Assume.assumeTrue(initialGaleraUrl != null);
try (Connection connection = getNewConnection()) {
Statement stmt = connection.createStatement();
stmt.execute("drop table if exists multinode");
stmt.execute("create table multinode (id int not null primary key auto_increment, test VARCHAR(10))");
} catch (SQLException sqle) {
fail("must have worked");
}
}
@Test
public void pingReconnectAfterRestart() throws Throwable {
try (Connection connection = getNewConnection("&retriesAllDown=6", true)) {
Statement st = connection.createStatement();
int masterServerId = getServerId(connection);
stopProxy(masterServerId);
try {
st.execute("SELECT 1");
} catch (SQLException e) {
//eat exception
}
restartProxy(masterServerId);
long restartTime = System.nanoTime();
boolean loop = true;
while (loop) {
if (!connection.isClosed()) {
loop = false;
}
long duration = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - restartTime);
if (duration > 15 * 1000) {
fail();
}
Thread.sleep(250);
}
}
}
protected class CheckBlacklist implements Runnable {
private int firstServerId;
private Set<HostAddress> blacklistKeys;
public CheckBlacklist(int firstServerId, Set<HostAddress> blacklistKeys) {
this.firstServerId = firstServerId;
this.blacklistKeys = blacklistKeys;
}
public void run() {
try (Connection connection2 = getNewConnection()) {
int otherServerId = getServerId(connection2);
assertTrue(otherServerId != firstServerId);
Protocol protocol = getProtocolFromConnection(connection2);
assertTrue(blacklistKeys.toArray()[0].equals(protocol.getProxy().getListener()
.getBlacklistKeys().toArray()[0]));
} catch (Throwable e) {
e.printStackTrace();
fail();
}
}
}
class MutableInt {
int value = 1; // note that we start at 1 since we're counting
public void increment() {
++value;
}
public int get() {
return value;
}
}
}