use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.
the class DefaultConnectionPlugin method openInitialConnection.
@Override
public void openInitialConnection(ConnectionUrl connectionUrl) throws SQLException {
if (this.currentConnectionProvider.getCurrentConnection() != null) {
return;
}
HostInfo mainHostInfo = connectionUrl.getMainHost();
JdbcConnection connection = this.connectionProvider.connect(mainHostInfo);
this.currentConnectionProvider.setCurrentConnection(connection, mainHostInfo);
}
use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.
the class StatementsTest method testServerPreparedStatementsCaching.
/**
* WL#11101 - Remove de-cache and close of SSPSs on double call to close()
*
* @throws Exception
*/
@Test
public void testServerPreparedStatementsCaching() throws Exception {
// Non prepared statements must be non-poolable by default.
assertFalse(this.stmt.isPoolable());
Field stmtsCacheField = ConnectionImpl.class.getDeclaredField("serverSideStatementCache");
stmtsCacheField.setAccessible(true);
ToIntFunction<Connection> getStmtsCacheSize = (c) -> {
try {
LRUCache<?, ?> stmtsCacheObj = (LRUCache<?, ?>) stmtsCacheField.get(c);
return stmtsCacheObj == null ? -1 : stmtsCacheObj.size();
} catch (IllegalArgumentException | IllegalAccessException e) {
fail("Fail getting the statemets cache size.");
return -1;
}
};
Function<Connection, ServerPreparedStatement> getStmtsCacheSingleElem = (c) -> {
try {
@SuppressWarnings("unchecked") LRUCache<?, ServerPreparedStatement> stmtsCacheObj = (LRUCache<?, ServerPreparedStatement>) stmtsCacheField.get(c);
return stmtsCacheObj.get(stmtsCacheObj.keySet().iterator().next());
} catch (IllegalArgumentException | IllegalAccessException e) {
fail("Fail getting the statemets cache element.");
return null;
}
};
final String sql1 = "SELECT 1, ?";
final String sql2 = "SELECT 2, ?";
boolean useSPS = false;
boolean cachePS = false;
do {
Properties props = new Properties();
props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), Boolean.toString(useSPS));
props.setProperty(PropertyKey.cachePrepStmts.getKeyName(), Boolean.toString(cachePS));
props.setProperty(PropertyKey.prepStmtCacheSize.getKeyName(), "5");
boolean cachedSPS = useSPS && cachePS;
/*
* Cache the prepared statement and de-cache it later.
* (*) if server prepared statement and caching is enabled.
*/
{
JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
PreparedStatement testPstmt = testConn.prepareStatement(sql1);
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertTrue(testPstmt.isPoolable());
// Caches this PS (*).
testPstmt.close();
assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
// No-op.
testPstmt.close();
assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
if (cachedSPS) {
assertTrue(testPstmt.isPoolable());
// De-caches this PS; it gets automatically closed (*).
testPstmt.setPoolable(false);
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(0, getStmtsCacheSize.applyAsInt(testConn));
}
// No-op.
testPstmt.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
testPstmt.setPoolable(false);
return null;
});
assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
testPstmt.isPoolable();
return null;
});
testConn.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
/*
* Set not to cache the prepared statement.
* (*) if server prepared statement and caching is enabled.
*/
{
JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
PreparedStatement testPstmt = testConn.prepareStatement(sql1);
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertTrue(testPstmt.isPoolable());
// Don't cache this PS (*).
testPstmt.setPoolable(false);
assertFalse(testPstmt.isPoolable());
// Doesn't cache this PS (*).
testPstmt.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
// No-op.
testPstmt.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
testPstmt.setPoolable(true);
return null;
});
assertThrows(SQLException.class, "No operations allowed after statement closed\\.", () -> {
testPstmt.isPoolable();
return null;
});
testConn.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
/*
* Set not to cache the prepared statement but change mind before closing it.
* Reuse the cached prepared statement and don't re-cache it.
* (*) if server prepared statement and caching is enabled.
*/
{
JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
PreparedStatement testPstmt = testConn.prepareStatement(sql1);
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
// Don't cache this PS (*).
testPstmt.setPoolable(false);
assertFalse(testPstmt.isPoolable());
testPstmt.setPoolable(true);
// Changed my mind, let it be cached (*).
assertTrue(testPstmt.isPoolable());
// Caches this PS (*).
testPstmt.close();
assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
// No-op.
testPstmt.close();
assertEquals(cachedSPS ? 1 : 0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
PreparedStatement testPstmtOld = testPstmt;
// Takes the cached statement (*), or creates a fresh one.
testPstmt = testConn.prepareStatement(sql1);
if (cachedSPS) {
assertSame(testPstmtOld, testPstmt);
} else {
assertNotSame(testPstmtOld, testPstmt);
}
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertTrue(testPstmt.isPoolable());
// Don't cache this PS (*).
testPstmt.setPoolable(false);
assertFalse(testPstmt.isPoolable());
// Doesn't cache this PS (*).
testPstmt.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
testPstmtOld = testPstmt;
// Creates a fresh prepared statement.
testPstmt = testConn.prepareStatement(sql1);
assertNotSame(testPstmtOld, testPstmt);
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertTrue(testPstmt.isPoolable());
testConn.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
/*
* Caching of multiple copies of same prepared statement.
* (*) if server prepared statement and caching is enabled.
*/
{
int psCount = 5;
JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
PreparedStatement[] testPstmts = new PreparedStatement[psCount];
for (int i = 0; i < psCount; i++) {
testPstmts[i] = testConn.prepareStatement(sql1);
}
assertEquals(5, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
for (int i = 0; i < psCount; i++) {
assertTrue(testPstmts[i].isPoolable());
// Caches this PS and replaces existing if same (*).
testPstmts[i].close();
assertEquals(cachedSPS ? psCount - i : psCount - i - 1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
if (cachedSPS) {
assertSame(testPstmts[i], getStmtsCacheSingleElem.apply(testConn));
}
}
PreparedStatement testPstmt = testConn.prepareStatement(sql1);
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
for (int i = 0; i < psCount; i++) {
if (cachedSPS && i == psCount - 1) {
assertSame(testPstmts[i], testPstmt);
} else {
assertNotSame(testPstmts[i], testPstmt);
}
}
// Don't cache this PS (*).
testPstmt.setPoolable(false);
// Doesn't cache this PS (*).
testPstmt.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
testConn.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
/*
* Combine caching different prepared statements.
* (*) if server prepared statement and caching is enabled.
*/
{
int psCount = 5;
JdbcConnection testConn = (JdbcConnection) getConnectionWithProps(props);
PreparedStatement[] testPstmts1 = new PreparedStatement[psCount];
for (int i = 0; i < psCount; i++) {
testPstmts1[i] = testConn.prepareStatement(sql1);
}
PreparedStatement testPstmt = testConn.prepareStatement(sql2);
assertEquals(6, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
assertTrue(testPstmt.isPoolable());
// Caches this PS (*).
testPstmt.close();
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
for (int i = 0; i < psCount; i++) {
assertTrue(testPstmts1[i].isPoolable());
// Caches this PS and replaces existing if same (*).
testPstmts1[i].close();
assertEquals(cachedSPS ? psCount - i + 1 : psCount - i - 1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 2 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
PreparedStatement testPstmt1 = testConn.prepareStatement(sql1);
assertEquals(cachedSPS ? 2 : 1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 1 : -1, getStmtsCacheSize.applyAsInt(testConn));
for (int i = 0; i < psCount; i++) {
if (cachedSPS && i == psCount - 1) {
assertSame(testPstmts1[i], testPstmt1);
} else {
assertNotSame(testPstmts1[i], testPstmt1);
}
}
PreparedStatement testPstmt2 = testConn.prepareStatement(sql2);
assertEquals(2, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
if (cachedSPS) {
assertSame(testPstmt, testPstmt2);
} else {
assertNotSame(testPstmt, testPstmt2);
}
// Don't cache this PS (*).
testPstmt1.setPoolable(false);
// Doesn't cache this PS (*).
testPstmt1.close();
assertEquals(1, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
// Don't cache this PS (*).
testPstmt2.setPoolable(false);
// Doesn't cache this PS (*).
testPstmt2.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
testConn.close();
assertEquals(0, testConn.getActiveStatementCount());
assertEquals(cachedSPS ? 0 : -1, getStmtsCacheSize.applyAsInt(testConn));
}
} while ((useSPS = !useSPS) || (cachePS = !cachePS));
}
use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.
the class ConnectionProxy method autodetectClusterAndCreateProxyInstance.
/**
* Checks if connection is associated with Aurora cluster and instantiates a new
* AuroraConnectionProxy if needed. Otherwise it returns a single-host connection.
*
* @param connectionUrl {@link ConnectionUrl} instance containing the lists of hosts available to
* switch on.
* @throws SQLException if an error occurs
*/
public static JdbcConnection autodetectClusterAndCreateProxyInstance(ConnectionUrl connectionUrl) throws SQLException {
boolean pluginsEnabled = Boolean.parseBoolean(connectionUrl.getConnectionArgumentsAsProperties().getProperty(PropertyKey.useConnectionPlugins.getKeyName(), Boolean.toString(true)));
if (pluginsEnabled) {
final ConnectionProxy connProxy = new ConnectionProxy(connectionUrl);
return (JdbcConnection) java.lang.reflect.Proxy.newProxyInstance(JdbcConnection.class.getClassLoader(), new Class<?>[] { JdbcConnection.class }, connProxy);
}
final IConnectionProvider connectionProvider = new BasicConnectionProvider();
return connectionProvider.connect(connectionUrl.getMainHost());
}
use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.
the class ConnectionRegressionTest method testExpiredPassword.
@Test
public void testExpiredPassword() throws Exception {
assumeTrue(versionMeetsMinimum(5, 6, 10), "MySQL 5.6.10+ is required to run this test.");
Connection testConn = null;
Statement testSt = null;
ResultSet testRs = null;
Properties urlProps = getPropertiesFromTestsuiteUrl();
String dbname = urlProps.getProperty(PropertyKey.DBNAME.getKeyName());
try {
createUser("'must_change1'@'%'", "IDENTIFIED BY 'aha'");
this.stmt.executeUpdate("grant all on `" + dbname + "`.* to 'must_change1'@'%'");
createUser("'must_change2'@'%'", "IDENTIFIED BY 'aha'");
this.stmt.executeUpdate("grant all on `" + dbname + "`.* to 'must_change2'@'%'");
// workaround for Bug#77732
if (versionMeetsMinimum(5, 7, 6) && !versionMeetsMinimum(8, 0, 5)) {
this.stmt.executeUpdate("GRANT SELECT ON `performance_schema`.`session_variables` TO 'must_change1'@'%'");
this.stmt.executeUpdate("GRANT SELECT ON `performance_schema`.`session_variables` TO 'must_change2'@'%'");
}
this.stmt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'must_change1'@'%', 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
Properties props = new Properties();
props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
// ALTER USER can be prepared as of 5.6.8 (BUG#14646014)
if (versionMeetsMinimum(5, 6, 8)) {
props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), "true");
testConn = getConnectionWithProps(props);
this.pstmt = testConn.prepareStatement(versionMeetsMinimum(5, 7, 6) ? "ALTER USER 'must_change1'@'%', 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER 'must_change1'@'%' PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
this.pstmt.executeUpdate();
this.pstmt.close();
this.pstmt = testConn.prepareStatement(versionMeetsMinimum(5, 7, 6) ? "ALTER USER ?, 'must_change2'@'%' PASSWORD EXPIRE" : "ALTER USER ? PASSWORD EXPIRE, 'must_change2'@'%' PASSWORD EXPIRE");
this.pstmt.setString(1, "must_change1");
this.pstmt.executeUpdate();
this.pstmt.close();
testConn.close();
}
props.setProperty(PropertyKey.USER.getKeyName(), "must_change1");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "aha");
try {
testConn = getConnectionWithProps(props);
fail("SQLException expected due to password expired");
} catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e1) {
if ((e1 instanceof SQLException && (((SQLException) e1).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || ((SQLException) e1).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN)) || e1 instanceof PasswordExpiredException || e1 instanceof ClosedOnExpiredPasswordException) {
props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "false");
try {
testConn = getConnectionWithProps(props);
testSt = testConn.createStatement();
testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
testRs.close();
fail("SQLException expected due to password expired");
} catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e3) {
if (e3 instanceof SQLException && (((SQLException) e3).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) || e3 instanceof ClosedOnExpiredPasswordException) {
testSt.close();
testConn = getConnectionWithProps(props);
testSt = testConn.createStatement();
}
if (testSt == null) {
testSt = testConn.createStatement();
}
testSt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER USER() IDENTIFIED BY 'newpwd'" : "SET PASSWORD = PASSWORD('newpwd')");
testConn.close();
props.setProperty(PropertyKey.USER.getKeyName(), "must_change1");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "newpwd");
props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "true");
testConn = getConnectionWithProps(props);
testSt = testConn.createStatement();
testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
assertTrue(testRs.next());
// change user
try {
((JdbcConnection) testConn).changeUser("must_change2", "aha");
fail("SQLException expected due to password expired");
} catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e4) {
if (e4 instanceof SQLException && (((SQLException) e4).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || ((SQLException) e4).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN) || e4 instanceof PasswordExpiredException || e4 instanceof ClosedOnExpiredPasswordException) {
props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "false");
testConn = getConnectionWithProps(props);
try {
((JdbcConnection) testConn).changeUser("must_change2", "aha");
testSt = testConn.createStatement();
testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
fail("SQLException expected due to password expired");
} catch (PasswordExpiredException | ClosedOnExpiredPasswordException | SQLException e5) {
if (e5 instanceof SQLException && ((SQLException) e5).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD_LOGIN || e5 instanceof ClosedOnExpiredPasswordException) {
testConn = getConnectionWithProps(props);
testSt = testConn.createStatement();
}
testSt = testConn.createStatement();
testSt.executeUpdate(versionMeetsMinimum(5, 7, 6) ? "ALTER USER USER() IDENTIFIED BY 'newpwd'" : "SET PASSWORD = PASSWORD('newpwd')");
testConn.close();
props.setProperty(PropertyKey.USER.getKeyName(), "must_change2");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "newpwd");
props.setProperty(PropertyKey.disconnectOnExpiredPasswords.getKeyName(), "true");
testConn = getConnectionWithProps(props);
testSt = testConn.createStatement();
testRs = testSt.executeQuery("SHOW VARIABLES LIKE 'disconnect_on_expired_password'");
assertTrue(testRs.next());
}
} else {
throw e4;
}
}
}
} else {
throw e1;
}
}
} finally {
if (testRs != null) {
testRs.close();
}
if (testSt != null) {
testSt.close();
}
if (testConn != null) {
testConn.close();
}
}
}
use of com.mysql.cj.jdbc.JdbcConnection in project aws-mysql-jdbc by awslabs.
the class ConnectionRegressionTest method subTestBug22848249D.
/*
* Tests adding hosts from the connection group without affecting current active connections.
*/
private void subTestBug22848249D() throws Exception {
final String defaultHost = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.HOST.getKeyName());
final String defaultPort = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.PORT.getKeyName());
final String host1 = "first";
final String host2 = "second";
final String host3 = "third";
final String host4 = "fourth";
final String hostPort1 = host1 + ":" + defaultPort;
final String hostPort2 = host2 + ":" + defaultPort;
final String hostPort3 = host3 + ":" + defaultPort;
final String hostPort4 = host4 + ":" + defaultPort;
final String lbConnGroup = "Bug22848249D";
System.out.println("testBug22848249D:");
System.out.println("********************************************************************************");
/*
* Initial connection will be able to use only the hosts available when it was initialized, even after adding new ones to the connection group.
*/
Properties props = new Properties();
props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
props.setProperty(PropertyKey.loadBalanceHostRemovalGracePeriod.getKeyName(), "0");
props.setProperty(PropertyKey.loadBalanceConnectionGroup.getKeyName(), lbConnGroup);
Connection testConn = getUnreliableLoadBalancedConnection(new String[] { host1, host2 }, props);
testConn.setAutoCommit(false);
String connectedHost = ((JdbcConnection) testConn).getHost();
assertConnectionsHistory(UnreliableSocketFactory.getHostConnectedStatus(connectedHost));
assertEquals(2, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
// Add two hosts.
UnreliableSocketFactory.mapHost(host3, defaultHost);
ConnectionGroupManager.addHost(lbConnGroup, hostPort3, false);
UnreliableSocketFactory.mapHost(host4, defaultHost);
ConnectionGroupManager.addHost(lbConnGroup, hostPort4, false);
assertEquals(4, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort3));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort4));
// Force some transaction boundaries and check that the new hosts aren't used.
int connectionSwaps = 0;
for (int i = 0; i < 100; i++) {
testConn.rollback();
String newConnectedHost = ((JdbcConnection) testConn).getHost();
assertFalse(newConnectedHost.equals(host3));
assertFalse(newConnectedHost.equals(host4));
if (!connectedHost.equals(newConnectedHost)) {
connectedHost = newConnectedHost;
connectionSwaps++;
}
}
System.out.println("\t1. Swapped connections " + connectionSwaps + " times out of 100, without hitting the newly added host(s).");
// Non-deterministic, but something must be wrong if there are no swaps after 100 transaction boundaries.
assertTrue(connectionSwaps > 0);
// Make sure the connection is working fine.
this.rs = testConn.createStatement().executeQuery("SELECT 'testBug22848249'");
assertTrue(this.rs.next());
assertEquals("testBug22848249", this.rs.getString(1));
testConn.close();
/*
* New connection will be able to use all hosts.
*/
testConn = getUnreliableLoadBalancedConnection(new String[] { host1, host2, host3, host4 }, props);
testConn.setAutoCommit(false);
connectedHost = ((JdbcConnection) testConn).getHost();
assertConnectionsHistory(UnreliableSocketFactory.getHostConnectedStatus(connectedHost));
assertEquals(4, ConnectionGroupManager.getActiveHostCount(lbConnGroup));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort1));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort2));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort3));
assertTrue(ConnectionGroupManager.getActiveHostLists(lbConnGroup).contains(hostPort4));
// Force some transaction boundaries while checking that the removed hosts are never used.
connectionSwaps = 0;
Set<String> hostsUsed = new HashSet<>();
for (int i = 0; i < 100 && hostsUsed.size() < 4; i++) {
testConn.rollback();
String newConnectedHost = ((JdbcConnection) testConn).getHost();
if (!connectedHost.equals(newConnectedHost)) {
hostsUsed.add(newConnectedHost);
connectedHost = newConnectedHost;
connectionSwaps++;
}
}
System.out.println("\t2. Swapped connections " + connectionSwaps + " times out of 100 or before using all hosts.");
// Non-deterministic, but something must be wrong if there are no swaps after 100 transaction boundaries.
assertTrue(connectionSwaps > 0);
assertEquals(4, hostsUsed.size());
// Make sure the connection is working fine.
this.rs = testConn.createStatement().executeQuery("SELECT 'testBug22848249'");
assertTrue(this.rs.next());
assertEquals("testBug22848249", this.rs.getString(1));
testConn.close();
}
Aggregations