package core.framework.internal.db; import core.framework.internal.resource.PoolItem; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLTimeoutException; /** * @author neo */ final class Connections { static void checkConnectionState(PoolItem<Connection> connection, SQLException e) { String state = e.getSQLState(); // for state starts with "08" // refer to com.mysql.jdbc.integration.c3p0.MysqlConnectionTester, and standard sql state list: // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-error-sqlstates.html // // for state: S1009 // refer to com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException() and com.mysql.cj.exceptions.MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT // MySQL jdbc connector will translate "statement is closed" and other errors to "S1009" if (state != null && (state.startsWith("08") || "S1009".equals(state))) { connection.broken = true; } // if query timeout, com.mysql.cj.CancelQueryTaskImpl sends "KILL QUERY" to mysql server in cancel task thread // and as result, in current thread it triggers com.mysql.cj.jdbc.ConnectionImpl.handleCleanup with whyCleanedUp = com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure, The last packet successfully received from the server was x milliseconds ago. // so for query timeout, the connection needs to be marked as broken and close, // otherwise when other thread retrieves this connection, will encounter "statement is already closed" exception if (e instanceof SQLTimeoutException) { connection.broken = true; } } }