bug fixed for testWhileIdle.

This commit is contained in:
wenshao
2017-11-02 15:45:41 +08:00
parent b301168031
commit d51431252c
6 changed files with 123 additions and 72 deletions
@@ -1295,6 +1295,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
Exception error = null;
try {
result = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
} catch (SQLException ex) {
throw ex;
} catch (Exception ex) {
error = ex;
}
@@ -1327,7 +1329,14 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
}
}
/**
* @deprecated
*/
protected boolean testConnectionInternal(Connection conn) {
return testConnectionInternal(null, conn);
}
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
String sqlFile = JdbcSqlStat.getContextSqlFile();
String sqlName = JdbcSqlStat.getContextSqlName();
@@ -1339,7 +1348,28 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
}
try {
if (validConnectionChecker != null) {
return validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
long currentTimeMillis = System.currentTimeMillis();
if (holder != null) {
holder.lastValidTimeMillis = currentTimeMillis;
}
if (valid && JdbcConstants.MYSQL_DRIVER.equals(driverClass)) { // unexcepted branch
long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
if (lastPacketReceivedTimeMs > 0 //
&& mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
discardConnection(conn);
String errorMsg = "discard long time none received connection. "
+ ", jdbcUrl : " + jdbcUrl
+ ", jdbcUrl : " + jdbcUrl
+ ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
LOG.error(errorMsg);
return false;
}
}
return valid;
}
if (conn.isClosed()) {
@@ -1367,7 +1397,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
}
return true;
} catch (Exception ex) {
} catch (Throwable ex) {
// skip
return false;
} finally {
@@ -51,6 +51,7 @@ public final class DruidConnectionHolder {
protected final List<StatementEventListener> statementEventListeners = new CopyOnWriteArrayList<StatementEventListener>();
protected final long connectTimeMillis;
protected volatile long lastActiveTimeMillis;
protected volatile long lastValidTimeMillis;
private long useCount = 0;
private long keepAliveCheckCount = 0;
private long lastNotEmptyWaitNanos;
@@ -23,17 +23,7 @@ import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
@@ -461,6 +451,17 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
}
{
String property = properties.getProperty("druid.initConnectionSqls");
if (property != null && property.length() > 0) {
try {
StringTokenizer tokenizer = new StringTokenizer(property, ";");
setConnectionInitSqls(Collections.list(tokenizer));
} catch (NumberFormatException e) {
LOG.error("illegal property 'druid.initConnectionSqls'", e);
}
}
}
}
public boolean isKillWhenSocketReadTimeout() {
@@ -1175,27 +1176,39 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
return;
}
String realDriverClassName = driver.getClass().getName();
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
this.exceptionSorter = new MySqlExceptionSorter();
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
this.exceptionSorter = new OracleExceptionSorter();
} else if (realDriverClassName.equals("com.informix.jdbc.IfxDriver")) {
this.exceptionSorter = new InformixExceptionSorter();
} else if (realDriverClassName.equals("com.sybase.jdbc2.jdbc.SybDriver")) {
this.exceptionSorter = new SybaseExceptionSorter();
for (Class<?> driverClass = driver.getClass();;) {
String realDriverClassName = driverClass.getName();
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
this.exceptionSorter = new MySqlExceptionSorter();
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
this.exceptionSorter = new OracleExceptionSorter();
} else if (realDriverClassName.equals("com.informix.jdbc.IfxDriver")) {
this.exceptionSorter = new InformixExceptionSorter();
} else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)) {
this.exceptionSorter = new PGExceptionSorter();
} else if (realDriverClassName.equals("com.sybase.jdbc2.jdbc.SybDriver")) {
this.exceptionSorter = new SybaseExceptionSorter();
} else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) {
this.exceptionSorter = new MockExceptionSorter();
} else if (realDriverClassName.contains("DB2")) {
this.exceptionSorter = new DB2ExceptionSorter();
} else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)) {
this.exceptionSorter = new PGExceptionSorter();
} else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) {
this.exceptionSorter = new MockExceptionSorter();
} else if (realDriverClassName.contains("DB2")) {
this.exceptionSorter = new DB2ExceptionSorter();
} else {
Class<?> superClass = driverClass.getSuperclass();
if (superClass != null && superClass != Object.class) {
driverClass = superClass;
continue;
}
}
break;
}
}
@@ -1244,7 +1257,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
if (testOnBorrow) {
boolean validate = testConnectionInternal(poolableConnection.conn);
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
@@ -1275,25 +1288,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (idleMillis >= timeBetweenEvictionRunsMillis
|| idleMillis < 0 // unexcepted branch
) {
boolean validate = testConnectionInternal(poolableConnection.conn);
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
discardConnection(realConnection);
continue;
}
if (JdbcConstants.MYSQL_DRIVER.equals(driverClass)) { // unexcepted branch
long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(realConnection);
long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
if (lastPacketReceivedTimeMs > 0 //
&& mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
discardConnection(realConnection);
LOG.warn("discard long time none received connection. millis : " + mysqlIdleMillis);
continue;
}
continue;
}
}
}
@@ -1567,7 +1569,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
if (testOnReturn) {
boolean validate = testConnectionInternal(physicalConnection);
boolean validate = testConnectionInternal(holder, physicalConnection);
if (!validate) {
JdbcUtils.close(physicalConnection);
@@ -54,28 +54,23 @@ import com.alibaba.druid.support.logging.LogFactory;
* @author wenshao [szujobs@hotmail.com]
*/
public class DruidPooledConnection extends PoolableWrapper implements javax.sql.PooledConnection, Connection {
private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class);
public static final int MAX_RECORD_SQL_COUNT = 10;
protected Connection conn;
protected volatile DruidConnectionHolder holder;
protected TransactionInfo transactionInfo;
private final boolean dupCloseLogEnable;
protected volatile boolean traceEnable = false;
private boolean disable = false;
private boolean closed = false;
protected final Thread ownerThread;
private long connectedTimeMillis;
private long connectedTimeNano;
private volatile boolean running = false;
private volatile boolean abandoned = false;
protected StackTraceElement[] connectStackTrace;
protected Throwable disableError = null;
public ReentrantLock lock = new ReentrantLock();
private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class);
public static final int MAX_RECORD_SQL_COUNT = 10;
protected Connection conn;
protected volatile DruidConnectionHolder holder;
protected TransactionInfo transactionInfo;
private final boolean dupCloseLogEnable;
protected volatile boolean traceEnable = false;
private boolean disable = false;
private boolean closed = false;
protected final Thread ownerThread;
private long connectedTimeMillis;
private long connectedTimeNano;
private volatile boolean running = false;
private volatile boolean abandoned = false;
protected StackTraceElement[] connectStackTrace;
protected Throwable disableError = null;
public ReentrantLock lock = new ReentrantLock();
public DruidPooledConnection(DruidConnectionHolder holder){
super(holder.getConnection());
@@ -262,13 +262,26 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
DruidConnectionHolder holder = conn.holder;
DruidAbstractDataSource dataSource = holder.dataSource;
long currentTimeMillis = System.currentTimeMillis();
long lastActiveTimeMillis = holder.lastActiveTimeMillis;
long idleMillis = System.currentTimeMillis() - lastActiveTimeMillis;
long idleMillis = currentTimeMillis - lastActiveTimeMillis;
long lastValidIdleMillis = currentTimeMillis - holder.lastActiveTimeMillis;
LOG.error("CommunicationsException, druid version " + VERSION.getVersionNumber()
String errorMsg = "CommunicationsException, druid version " + VERSION.getVersionNumber()
+ ", jdbcUrl : " + dataSource.jdbcUrl
+ ", testWhileIdle " + dataSource.testWhileIdle
+ ", idle millis " + idleMillis);
+ ", idle millis " + idleMillis
+ ", minIdle " + dataSource.minIdle
+ ", poolingCount " + dataSource.getPoolingCount()
+ ", timeBetweenEvictionRunsMillis " + dataSource.timeBetweenEvictionRunsMillis
+ ", lastValidIdleMillis " + lastValidIdleMillis
+ ", driver " + dataSource.driver.getClass().getName();
if (dataSource.exceptionSorter != null) {
errorMsg += ", exceptionSorter " + dataSource.exceptionSorter.getClass().getName();
}
LOG.error(errorMsg);
}
}
@@ -16,9 +16,11 @@
package com.alibaba.druid.pool.vendor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
@@ -101,7 +103,15 @@ public class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter i
validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
}
ping.invoke(conn, true, validationQueryTimeout * 1000);
try {
ping.invoke(conn, true, validationQueryTimeout * 1000);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof SQLException) {
throw (SQLException) cause;
}
throw e;
}
return true;
}
}