|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. |
| 2 | + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. |
3 | 3 | *
|
4 | 4 | * This program is free software; you can redistribute it and/or modify it under
|
5 | 5 | * the terms of the GNU General Public License, version 2.0, as published by the
|
@@ -12017,4 +12017,116 @@ public void handleSessionStateChanges(ServerSessionStateChanges changes) {
|
12017 | 12017 |
|
12018 | 12018 | }
|
12019 | 12019 |
|
| 12020 | + /** |
| 12021 | + * Test fix for Bug#23143279, CLIENT HANG WHEN LOADBALANCESTRATEGY IS BESTRESPONSETIME. |
| 12022 | + * |
| 12023 | + * @throws Exception |
| 12024 | + */ |
| 12025 | + @Test |
| 12026 | + public void testBug23143279() throws Exception { |
| 12027 | + testBug23143279RunTest("random"); |
| 12028 | + testBug23143279RunTest("bestResponseTime"); |
| 12029 | + testBug23143279RunTest("serverAffinity"); |
| 12030 | + testBug23143279RunTest(SequentialBalanceStrategy.class.getName()); |
| 12031 | + } |
| 12032 | + |
| 12033 | + private void testBug23143279RunTest(String lbStrategy) throws Exception { |
| 12034 | + final String defaultHost = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.HOST.getKeyName()); |
| 12035 | + final String defaultPort = getPropertiesFromTestsuiteUrl().getProperty(PropertyKey.PORT.getKeyName()); |
| 12036 | + |
| 12037 | + final String host1 = "first"; |
| 12038 | + final String host2 = "second"; |
| 12039 | + final String host3 = "third"; |
| 12040 | + final String host4 = "fourth"; |
| 12041 | + final String hostPort4 = host4 + ":" + defaultPort; |
| 12042 | + |
| 12043 | + final String uniqueId = String.valueOf(lbStrategy.substring(lbStrategy.lastIndexOf('.') + 1, lbStrategy.lastIndexOf('.') + 4)).toUpperCase(); |
| 12044 | + final String connGroupName = "testBug23143279" + uniqueId; |
| 12045 | + |
| 12046 | + final Properties props = new Properties(); |
| 12047 | + props.setProperty(PropertyKey.sslMode.getKeyName(), "DISABLED"); |
| 12048 | + props.setProperty(PropertyKey.loadBalanceHostRemovalGracePeriod.getKeyName(), "0"); |
| 12049 | + props.setProperty(PropertyKey.loadBalanceConnectionGroup.getKeyName(), connGroupName); |
| 12050 | + props.setProperty(PropertyKey.ha_loadBalanceStrategy.getKeyName(), lbStrategy); |
| 12051 | + |
| 12052 | + System.out.println("\n\nTEST: " + lbStrategy); |
| 12053 | + System.out.println("********************************************************************************"); |
| 12054 | + System.out.println("\tHosts group: " + connGroupName); |
| 12055 | + |
| 12056 | + final Connection testConn = getUnreliableLoadBalancedConnection(new String[] { host1, host2, host3 }, props, |
| 12057 | + new HashSet<>(Arrays.asList(host2, host3))); |
| 12058 | + UnreliableSocketFactory.mapHost(host4, defaultHost); |
| 12059 | + |
| 12060 | + System.out.println("\nStep 1: initial connection"); |
| 12061 | + System.out.println("********************************************************************************"); |
| 12062 | + System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName)); |
| 12063 | + System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName)); |
| 12064 | + System.out.println("\tConnected to: " + ((JdbcConnection) testConn).getHostPortPair()); |
| 12065 | + System.out.println("\tConnection id: " + ((MysqlConnection) testConn).getId()); |
| 12066 | + |
| 12067 | + assertEquals(host1 + ":" + defaultPort, ((JdbcConnection) testConn).getHostPortPair()); |
| 12068 | + |
| 12069 | + this.stmt.execute("KILL CONNECTION " + ((MysqlConnection) testConn).getId()); |
| 12070 | + assertThrows(SQLException.class, () -> testConn.createStatement().executeQuery("SELECT 1")); |
| 12071 | + |
| 12072 | + System.out.println("\nStep 2: after killing the active connection and having reconnected"); |
| 12073 | + System.out.println("********************************************************************************"); |
| 12074 | + System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName)); |
| 12075 | + System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName)); |
| 12076 | + System.out.println("\tConnected to: " + ((JdbcConnection) testConn).getHostPortPair()); |
| 12077 | + System.out.println("\tConnection id: " + ((MysqlConnection) testConn).getId()); |
| 12078 | + |
| 12079 | + assertEquals(host1 + ":" + defaultPort, ((JdbcConnection) testConn).getHostPortPair()); |
| 12080 | + |
| 12081 | + ConnectionGroupManager.addHost(connGroupName, hostPort4, true); |
| 12082 | + |
| 12083 | + System.out.println("\nStep 3: after adding a new host"); |
| 12084 | + System.out.println("********************************************************************************"); |
| 12085 | + System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName)); |
| 12086 | + System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName)); |
| 12087 | + System.out.println("\tConnected to: " + ((JdbcConnection) testConn).getHostPortPair()); |
| 12088 | + System.out.println("\tConnection id: " + ((MysqlConnection) testConn).getId()); |
| 12089 | + |
| 12090 | + this.stmt.execute("KILL CONNECTION " + ((MysqlConnection) testConn).getId()); |
| 12091 | + assertThrows(SQLException.class, () -> testConn.createStatement().executeQuery("SELECT 1")); |
| 12092 | + // Should be reconnected by now. |
| 12093 | + |
| 12094 | + boolean connectedToHost1 = ((JdbcConnection) testConn).getHostPortPair().startsWith(host1); |
| 12095 | + assertEquals((connectedToHost1 ? host1 : host4) + ":" + defaultPort, ((JdbcConnection) testConn).getHostPortPair()); |
| 12096 | + |
| 12097 | + System.out.println("\nStep 4: after killing the active connection and having reconnected"); |
| 12098 | + System.out.println("********************************************************************************"); |
| 12099 | + System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName)); |
| 12100 | + System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName)); |
| 12101 | + System.out.println("\tConnected to: " + ((JdbcConnection) testConn).getHostPortPair()); |
| 12102 | + System.out.println("\tConnection id: " + ((MysqlConnection) testConn).getId()); |
| 12103 | + |
| 12104 | + final String hostToRemove = ((JdbcConnection) testConn).getHostPortPair(); |
| 12105 | + ExecutorService executor = Executors.newSingleThreadExecutor(); |
| 12106 | + Future<?> future = executor.submit(() -> { |
| 12107 | + ConnectionGroupManager.removeHost(connGroupName, hostToRemove, true); |
| 12108 | + return null; |
| 12109 | + }); |
| 12110 | + |
| 12111 | + try { |
| 12112 | + future.get(10, TimeUnit.SECONDS); |
| 12113 | + } catch (TimeoutException e) { |
| 12114 | + executor.shutdownNow(); |
| 12115 | + fail("Failed to remove host and connect to a new one.\n" |
| 12116 | + + "WARNING: A ConcurrentModificationException on UnreliableSocketFactory can happen from now on."); |
| 12117 | + } |
| 12118 | + executor.shutdownNow(); |
| 12119 | + |
| 12120 | + System.out.println("\nStep 5: after removing the connected host [" + hostToRemove + "]"); |
| 12121 | + System.out.println("********************************************************************************"); |
| 12122 | + System.out.println("\tHosts count: " + ConnectionGroupManager.getActiveHostCount(connGroupName)); |
| 12123 | + System.out.println("\tHosts: " + ConnectionGroupManager.getActiveHostLists(connGroupName)); |
| 12124 | + System.out.println("\tConnected to: " + ((JdbcConnection) testConn).getHostPortPair()); |
| 12125 | + System.out.println("\tConnection id: " + ((MysqlConnection) testConn).getId()); |
| 12126 | + |
| 12127 | + assertEquals((connectedToHost1 ? host4 : host1) + ":" + defaultPort, ((JdbcConnection) testConn).getHostPortPair()); |
| 12128 | + |
| 12129 | + testConn.close(); |
| 12130 | + } |
| 12131 | + |
12020 | 12132 | }
|
0 commit comments