Search in sources :

Example 1 with ConnectionImpl

use of com.mysql.cj.jdbc.ConnectionImpl in project cloudstack by apache.

the class StaticStrategy method pickConnection.

@Override
public JdbcConnection pickConnection(InvocationHandler proxy, List<String> configuredHosts, Map<String, JdbcConnection> liveConnections, long[] responseTimes, int numRetries) throws SQLException {
    int numHosts = configuredHosts.size();
    SQLException ex = null;
    List<String> allowList = new ArrayList<String>(numHosts);
    allowList.addAll(configuredHosts);
    Map<String, Long> denylist = ((LoadBalancedConnectionProxy) proxy).getGlobalBlacklist();
    allowList.removeAll(denylist.keySet());
    Map<String, Integer> allowListMap = this.getArrayIndexMap(allowList);
    for (int attempts = 0; attempts < numRetries; ) {
        if (allowList.size() == 0) {
            throw SQLError.createSQLException("No hosts configured", null);
        }
        // Always take the first host
        String hostPortSpec = allowList.get(0);
        ConnectionImpl conn = (ConnectionImpl) liveConnections.get(hostPortSpec);
        if (conn == null) {
            try {
                conn = ((LoadBalancedConnectionProxy) proxy).createConnectionForHost(hostPortSpec);
            } catch (SQLException sqlEx) {
                ex = sqlEx;
                if (((LoadBalancedConnectionProxy) proxy).shouldExceptionTriggerFailover(sqlEx)) {
                    Integer allowListIndex = allowListMap.get(hostPortSpec);
                    // exclude this host from being picked again
                    if (allowListIndex != null) {
                        allowList.remove(allowListIndex.intValue());
                        allowListMap = this.getArrayIndexMap(allowList);
                    }
                    ((LoadBalancedConnectionProxy) proxy).addToGlobalBlacklist(hostPortSpec);
                    if (allowList.size() == 0) {
                        attempts++;
                        try {
                            Thread.sleep(250);
                        } catch (InterruptedException e) {
                            s_logger.debug("[ignored] interupted while fail over in progres.");
                        }
                        // start fresh
                        allowListMap = new HashMap<String, Integer>(numHosts);
                        allowList.addAll(configuredHosts);
                        denylist = ((LoadBalancedConnectionProxy) proxy).getGlobalBlacklist();
                        allowList.removeAll(denylist.keySet());
                        allowListMap = this.getArrayIndexMap(allowList);
                    }
                    continue;
                }
                throw sqlEx;
            }
        }
        return conn;
    }
    if (ex != null) {
        throw ex;
    }
    // we won't get here, compiler can't tell
    return null;
}
Also used : LoadBalancedConnectionProxy(com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy) SQLException(java.sql.SQLException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl)

Example 2 with ConnectionImpl

use of com.mysql.cj.jdbc.ConnectionImpl in project ABC by RuiPinto96274.

the class RandomBalanceStrategy method pickConnection.

@Override
public ConnectionImpl pickConnection(InvocationHandler proxy, List<String> configuredHosts, Map<String, JdbcConnection> liveConnections, long[] responseTimes, int numRetries) throws SQLException {
    int numHosts = configuredHosts.size();
    SQLException ex = null;
    List<String> allowList = new ArrayList<>(numHosts);
    allowList.addAll(configuredHosts);
    Map<String, Long> blockList = ((LoadBalancedConnectionProxy) proxy).getGlobalBlocklist();
    allowList.removeAll(blockList.keySet());
    Map<String, Integer> allowListMap = this.getArrayIndexMap(allowList);
    for (int attempts = 0; attempts < numRetries; ) {
        int random = (int) Math.floor((Math.random() * allowList.size()));
        if (allowList.size() == 0) {
            throw SQLError.createSQLException(Messages.getString("RandomBalanceStrategy.0"), null);
        }
        String hostPortSpec = allowList.get(random);
        ConnectionImpl conn = (ConnectionImpl) liveConnections.get(hostPortSpec);
        if (conn == null) {
            try {
                conn = ((LoadBalancedConnectionProxy) proxy).createConnectionForHost(hostPortSpec);
            } catch (SQLException sqlEx) {
                ex = sqlEx;
                if (((LoadBalancedConnectionProxy) proxy).shouldExceptionTriggerConnectionSwitch(sqlEx)) {
                    Integer allowListIndex = allowListMap.get(hostPortSpec);
                    // exclude this host from being picked again
                    if (allowListIndex != null) {
                        allowList.remove(allowListIndex.intValue());
                        allowListMap = this.getArrayIndexMap(allowList);
                    }
                    ((LoadBalancedConnectionProxy) proxy).addToGlobalBlocklist(hostPortSpec);
                    if (allowList.size() == 0) {
                        attempts++;
                        try {
                            Thread.sleep(250);
                        } catch (InterruptedException e) {
                        }
                        // start fresh
                        allowListMap = new HashMap<>(numHosts);
                        allowList.addAll(configuredHosts);
                        blockList = ((LoadBalancedConnectionProxy) proxy).getGlobalBlocklist();
                        allowList.removeAll(blockList.keySet());
                        allowListMap = this.getArrayIndexMap(allowList);
                    }
                    continue;
                }
                throw sqlEx;
            }
        }
        return conn;
    }
    if (ex != null) {
        throw ex;
    }
    // we won't get here, compiler can't tell
    return null;
}
Also used : SQLException(java.sql.SQLException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl)

Example 3 with ConnectionImpl

use of com.mysql.cj.jdbc.ConnectionImpl in project ABC by RuiPinto96274.

the class LoadBalancedConnectionProxy method pickNewConnection.

/**
 * Picks the "best" connection to use for the next transaction based on the BalanceStrategy in use.
 *
 * @throws SQLException
 *             if an error occurs
 */
@Override
public synchronized void pickNewConnection() throws SQLException {
    if (this.isClosed && this.closedExplicitly) {
        return;
    }
    List<String> hostPortList = Collections.unmodifiableList(this.hostsList.stream().map(hi -> hi.getHostPortPair()).collect(Collectors.toList()));
    if (this.currentConnection == null) {
        // startup
        this.currentConnection = this.balancer.pickConnection(this, hostPortList, Collections.unmodifiableMap(this.liveConnections), this.responseTimes.clone(), this.retriesAllDown);
        return;
    }
    if (this.currentConnection.isClosed()) {
        invalidateCurrentConnection();
    }
    int pingTimeout = this.currentConnection.getPropertySet().getIntegerProperty(PropertyKey.loadBalancePingTimeout).getValue();
    boolean pingBeforeReturn = this.currentConnection.getPropertySet().getBooleanProperty(PropertyKey.loadBalanceValidateConnectionOnSwapServer).getValue();
    for (int hostsTried = 0, hostsToTry = this.hostsList.size(); hostsTried < hostsToTry; hostsTried++) {
        ConnectionImpl newConn = null;
        try {
            newConn = (ConnectionImpl) this.balancer.pickConnection(this, hostPortList, Collections.unmodifiableMap(this.liveConnections), this.responseTimes.clone(), this.retriesAllDown);
            if (this.currentConnection != null) {
                if (pingBeforeReturn) {
                    newConn.pingInternal(true, pingTimeout);
                }
                syncSessionState(this.currentConnection, newConn);
            }
            this.currentConnection = newConn;
            return;
        } catch (SQLException e) {
            if (shouldExceptionTriggerConnectionSwitch(e) && newConn != null) {
                // connection error, close up shop on current connection
                invalidateConnection(newConn);
            }
        }
    }
    // no hosts available to swap connection to, close up.
    this.isClosed = true;
    this.closedReason = "Connection closed after inability to pick valid new connection during load-balance.";
}
Also used : SQLException(java.sql.SQLException) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl)

Example 4 with ConnectionImpl

use of com.mysql.cj.jdbc.ConnectionImpl in project ABC by RuiPinto96274.

the class LoadBalancedConnectionProxy method doPing.

/**
 * Pings live connections.
 *
 * @throws SQLException
 *             if an error occurs
 */
@Override
public synchronized void doPing() throws SQLException {
    SQLException se = null;
    boolean foundHost = false;
    int pingTimeout = this.currentConnection.getPropertySet().getIntegerProperty(PropertyKey.loadBalancePingTimeout).getValue();
    synchronized (this) {
        for (HostInfo hi : this.hostsList) {
            String host = hi.getHostPortPair();
            ConnectionImpl conn = this.liveConnections.get(host);
            if (conn == null) {
                continue;
            }
            try {
                if (pingTimeout == 0) {
                    conn.ping();
                } else {
                    conn.pingInternal(true, pingTimeout);
                }
                foundHost = true;
            } catch (SQLException e) {
                // give up if it is the current connection, otherwise NPE faking resultset later.
                if (host.equals(this.connectionsToHostsMap.get(this.currentConnection))) {
                    // clean up underlying connections, since connection pool won't do it
                    closeAllConnections();
                    this.isClosed = true;
                    this.closedReason = "Connection closed because ping of current connection failed.";
                    throw e;
                }
                // if the Exception is caused by ping connection lifetime checks, don't add to blocklist
                if (e.getMessage().equals(Messages.getString("Connection.exceededConnectionLifetime"))) {
                    // only set the return Exception if it's null
                    if (se == null) {
                        se = e;
                    }
                } else {
                    // overwrite the return Exception no matter what
                    se = e;
                    if (isGlobalBlocklistEnabled()) {
                        addToGlobalBlocklist(host);
                    }
                }
                // take the connection out of the liveConnections Map
                this.liveConnections.remove(this.connectionsToHostsMap.get(conn));
            }
        }
    }
    // if there were no successful pings
    if (!foundHost) {
        closeAllConnections();
        this.isClosed = true;
        this.closedReason = "Connection closed due to inability to ping any active connections.";
        // throw the stored Exception, if exists
        if (se != null) {
            throw se;
        }
        // or create a new SQLException and throw it, must be no liveConnections
        ((ConnectionImpl) this.currentConnection).throwConnectionClosedException();
    }
}
Also used : SQLException(java.sql.SQLException) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl) HostInfo(com.mysql.cj.conf.HostInfo)

Example 5 with ConnectionImpl

use of com.mysql.cj.jdbc.ConnectionImpl in project JavaSegundasQuintas by ecteruel.

the class LoadBalancedConnectionProxy method doPing.

/**
 * Pings live connections.
 *
 * @throws SQLException
 *             if an error occurs
 */
@Override
public synchronized void doPing() throws SQLException {
    SQLException se = null;
    boolean foundHost = false;
    int pingTimeout = this.currentConnection.getPropertySet().getIntegerProperty(PropertyKey.loadBalancePingTimeout).getValue();
    synchronized (this) {
        for (HostInfo hi : this.hostsList) {
            String host = hi.getHostPortPair();
            ConnectionImpl conn = this.liveConnections.get(host);
            if (conn == null) {
                continue;
            }
            try {
                if (pingTimeout == 0) {
                    conn.ping();
                } else {
                    conn.pingInternal(true, pingTimeout);
                }
                foundHost = true;
            } catch (SQLException e) {
                // give up if it is the current connection, otherwise NPE faking resultset later.
                if (host.equals(this.connectionsToHostsMap.get(this.currentConnection))) {
                    // clean up underlying connections, since connection pool won't do it
                    closeAllConnections();
                    this.isClosed = true;
                    this.closedReason = "Connection closed because ping of current connection failed.";
                    throw e;
                }
                // if the Exception is caused by ping connection lifetime checks, don't add to blocklist
                if (e.getMessage().equals(Messages.getString("Connection.exceededConnectionLifetime"))) {
                    // only set the return Exception if it's null
                    if (se == null) {
                        se = e;
                    }
                } else {
                    // overwrite the return Exception no matter what
                    se = e;
                    if (isGlobalBlocklistEnabled()) {
                        addToGlobalBlocklist(host);
                    }
                }
                // take the connection out of the liveConnections Map
                this.liveConnections.remove(this.connectionsToHostsMap.get(conn));
            }
        }
    }
    // if there were no successful pings
    if (!foundHost) {
        closeAllConnections();
        this.isClosed = true;
        this.closedReason = "Connection closed due to inability to ping any active connections.";
        // throw the stored Exception, if exists
        if (se != null) {
            throw se;
        }
        // or create a new SQLException and throw it, must be no liveConnections
        ((ConnectionImpl) this.currentConnection).throwConnectionClosedException();
    }
}
Also used : SQLException(java.sql.SQLException) ConnectionImpl(com.mysql.cj.jdbc.ConnectionImpl) HostInfo(com.mysql.cj.conf.HostInfo)

Aggregations

ConnectionImpl (com.mysql.cj.jdbc.ConnectionImpl)41 SQLException (java.sql.SQLException)27 HostInfo (com.mysql.cj.conf.HostInfo)17 ArrayList (java.util.ArrayList)17 Test (org.junit.jupiter.api.Test)17 HashMap (java.util.HashMap)12 IConnectionProvider (com.mysql.cj.jdbc.ha.plugins.IConnectionProvider)11 JdbcConnection (com.mysql.cj.jdbc.JdbcConnection)10 Log (com.mysql.cj.log.Log)8 List (java.util.List)8 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)8 Assertions.assertFalse (org.junit.jupiter.api.Assertions.assertFalse)8 Assertions.assertSame (org.junit.jupiter.api.Assertions.assertSame)8 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)8 ArgumentMatchers.any (org.mockito.ArgumentMatchers.any)8 ArgumentMatchers.refEq (org.mockito.ArgumentMatchers.refEq)8 Mockito (org.mockito.Mockito)8 Mockito.atLeastOnce (org.mockito.Mockito.atLeastOnce)8 Mockito.times (org.mockito.Mockito.times)8 Mockito.verify (org.mockito.Mockito.verify)8