mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved DruidDataSource for profile
This commit is contained in:
@@ -1393,7 +1393,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
return conn;
|
||||
}
|
||||
|
||||
public Connection createPhysicalConnection() throws SQLException {
|
||||
public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
|
||||
String url = this.getUrl();
|
||||
Properties connectProperties = getConnectProperties();
|
||||
|
||||
@@ -1436,18 +1436,22 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
|
||||
Connection conn;
|
||||
|
||||
long startNano = System.nanoTime();
|
||||
|
||||
long connectStartNanos = System.nanoTime();
|
||||
long connectedNanos, initedNanos, validatedNanos;
|
||||
try {
|
||||
conn = createPhysicalConnection(url, physicalConnectProperties);
|
||||
connectedNanos = System.nanoTime();
|
||||
|
||||
if (conn == null) {
|
||||
throw new SQLException("connect error, url " + url + ", driverClass " + this.driverClass);
|
||||
}
|
||||
|
||||
initPhysicalConnection(conn);
|
||||
initedNanos = System.nanoTime();
|
||||
|
||||
validateConnection(conn);
|
||||
validatedNanos = System.nanoTime();
|
||||
|
||||
createError = null;
|
||||
} catch (SQLException ex) {
|
||||
createErrorCount.incrementAndGet();
|
||||
@@ -1465,11 +1469,11 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
createErrorCount.incrementAndGet();
|
||||
throw ex;
|
||||
} finally {
|
||||
long nano = System.nanoTime() - startNano;
|
||||
long nano = System.nanoTime() - connectStartNanos;
|
||||
createTimespan += nano;
|
||||
}
|
||||
|
||||
return conn;
|
||||
return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos);
|
||||
}
|
||||
|
||||
public void initPhysicalConnection(Connection conn) throws SQLException {
|
||||
@@ -1753,4 +1757,49 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
|
||||
this.maxCreateTaskCount = maxCreateTaskCount;
|
||||
}
|
||||
|
||||
static class PhysicalConnectionInfo {
|
||||
private Connection connection;
|
||||
private long connectStartNanos;
|
||||
private long connectedNanos;
|
||||
private long initedNanos;
|
||||
private long validatedNanos;
|
||||
|
||||
public PhysicalConnectionInfo(Connection connection //
|
||||
, long connectStartNanos //
|
||||
, long connectedNanos //
|
||||
, long initedNanos //
|
||||
, long validatedNanos) {
|
||||
this.connection = connection;
|
||||
|
||||
this.connectStartNanos = connectStartNanos;
|
||||
this.connectedNanos = connectedNanos;
|
||||
this.initedNanos = initedNanos;
|
||||
this.validatedNanos = validatedNanos;
|
||||
}
|
||||
|
||||
public Connection getPhysicalConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public long getConnectStartNanos() {
|
||||
return connectStartNanos;
|
||||
}
|
||||
|
||||
public long getConnectedNanos() {
|
||||
return connectedNanos;
|
||||
}
|
||||
|
||||
public long getInitedNanos() {
|
||||
return initedNanos;
|
||||
}
|
||||
|
||||
public long getValidatedNanos() {
|
||||
return validatedNanos;
|
||||
}
|
||||
|
||||
public long getConnectNanoSpan() {
|
||||
return connectedNanos - connectStartNanos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.alibaba.druid.pool;
|
||||
|
||||
import com.alibaba.druid.pool.DruidAbstractDataSource.PhysicalConnectionInfo;
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
@@ -47,6 +48,10 @@ public final class DruidConnectionHolder {
|
||||
private final long connectTimeMillis;
|
||||
private transient long lastActiveTimeMillis;
|
||||
private long useCount = 0;
|
||||
|
||||
private long lastNotEmptyWaitNanos;
|
||||
|
||||
private final long createNanoSpan;
|
||||
|
||||
private PreparedStatementPool statementPool;
|
||||
|
||||
@@ -65,11 +70,16 @@ public final class DruidConnectionHolder {
|
||||
private boolean discard = false;
|
||||
|
||||
public static boolean holdabilityUnsupported = false;
|
||||
|
||||
public DruidConnectionHolder(DruidAbstractDataSource dataSource, PhysicalConnectionInfo pyConnectInfo) throws SQLException {
|
||||
this(dataSource, pyConnectInfo.getPhysicalConnection(), pyConnectInfo.getConnectNanoSpan());
|
||||
}
|
||||
|
||||
public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn) throws SQLException{
|
||||
public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn, long connectNanoSpan) throws SQLException{
|
||||
|
||||
this.dataSource = dataSource;
|
||||
this.conn = conn;
|
||||
this.createNanoSpan = connectNanoSpan;
|
||||
this.connectTimeMillis = System.currentTimeMillis();
|
||||
this.lastActiveTimeMillis = connectTimeMillis;
|
||||
|
||||
@@ -256,6 +266,20 @@ public final class DruidConnectionHolder {
|
||||
public void setDiscard(boolean discard) {
|
||||
this.discard = discard;
|
||||
}
|
||||
|
||||
|
||||
public long getCreateNanoSpan() {
|
||||
return createNanoSpan;
|
||||
}
|
||||
|
||||
|
||||
public long getLastNotEmptyWaitNanos() {
|
||||
return lastNotEmptyWaitNanos;
|
||||
}
|
||||
|
||||
protected void setLastNotEmptyWaitNanos(long lastNotEmptyWaitNanos) {
|
||||
this.lastNotEmptyWaitNanos = lastNotEmptyWaitNanos;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
@@ -166,7 +166,7 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
public static ThreadLocal<Long> waitNanosLocal = new ThreadLocal<Long>();
|
||||
|
||||
private boolean logDifferentThread = true;
|
||||
|
||||
|
||||
public DruidDataSource(){
|
||||
this(false);
|
||||
}
|
||||
@@ -640,8 +640,8 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
try {
|
||||
// init connections
|
||||
for (int i = 0, size = getInitialSize(); i < size; ++i) {
|
||||
Connection conn = createPhysicalConnection();
|
||||
DruidConnectionHolder holder = new DruidConnectionHolder(this, conn);
|
||||
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
|
||||
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
|
||||
connections[poolingCount] = holder;
|
||||
incrementPoolingCount();
|
||||
}
|
||||
@@ -1530,6 +1530,9 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
decrementPoolingCount();
|
||||
DruidConnectionHolder last = connections[poolingCount];
|
||||
connections[poolingCount] = null;
|
||||
|
||||
long waitNanos = nanos - estimate;
|
||||
last.setLastNotEmptyWaitNanos(waitNanos);
|
||||
|
||||
return last;
|
||||
}
|
||||
@@ -1726,10 +1729,10 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
return removeAbandonedCount;
|
||||
}
|
||||
|
||||
protected void put(Connection connection) {
|
||||
protected void put(PhysicalConnectionInfo physicalConnectionInfo) {
|
||||
DruidConnectionHolder holder = null;
|
||||
try {
|
||||
holder = new DruidConnectionHolder(DruidDataSource.this, connection);
|
||||
holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo);
|
||||
} catch (SQLException ex) {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -1799,10 +1802,10 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
Connection connection = null;
|
||||
PhysicalConnectionInfo physicalConnection = null;
|
||||
|
||||
try {
|
||||
connection = createPhysicalConnection();
|
||||
physicalConnection = createPhysicalConnection();
|
||||
} catch (SQLException e) {
|
||||
LOG.error("create connection error, url: " + jdbcUrl, e);
|
||||
|
||||
@@ -1837,11 +1840,11 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
break;
|
||||
}
|
||||
|
||||
if (connection == null) {
|
||||
if (physicalConnection == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
put(connection);
|
||||
put(physicalConnection);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1886,7 +1889,7 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
Connection connection = null;
|
||||
PhysicalConnectionInfo connection = null;
|
||||
|
||||
try {
|
||||
connection = createPhysicalConnection();
|
||||
@@ -2704,8 +2707,8 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
|
||||
DruidConnectionHolder holder;
|
||||
try {
|
||||
Connection conn = createPhysicalConnection();
|
||||
holder = new DruidConnectionHolder(this, conn);
|
||||
PhysicalConnectionInfo pyConnInfo = createPhysicalConnection();
|
||||
holder = new DruidConnectionHolder(this, pyConnInfo);
|
||||
} catch (SQLException e) {
|
||||
LOG.error("fill connection error, url: " + this.jdbcUrl, e);
|
||||
connectErrorCount.incrementAndGet();
|
||||
@@ -2774,7 +2777,7 @@ public class DruidDataSource extends DruidAbstractDataSource
|
||||
CreateConnectionTask task = new CreateConnectionTask();
|
||||
createScheduler.submit(task);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
|
||||
//do nothing
|
||||
|
||||
@@ -1182,4 +1182,16 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
public void abandond() {
|
||||
this.abandoned = true;
|
||||
}
|
||||
|
||||
public long getPhysicalConnectNanoSpan() {
|
||||
return this.holder.getCreateNanoSpan();
|
||||
}
|
||||
|
||||
public long getPhysicalConnectionUsedCount() {
|
||||
return this.holder.getUseCount();
|
||||
}
|
||||
|
||||
public long getConnectNotEmptyWaitNanos() {
|
||||
return this.holder.getLastNotEmptyWaitNanos();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PoolableCallableStatementTest extends TestCase {
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
MockConnection mockConn = new MockConnection();
|
||||
DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn);
|
||||
DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0);
|
||||
conn = new DruidPooledConnection(connHolder);
|
||||
raw = new MockCallableStatement(null, null);
|
||||
stmt = new DruidPooledCallableStatement(conn, new PreparedStatementHolder(new PreparedStatementKey("", null,
|
||||
|
||||
@@ -45,7 +45,7 @@ public class PoolablePreparedStatementTest extends TestCase {
|
||||
protected void setUp() throws Exception {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
MockConnection mockConn = new MockConnection();
|
||||
DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn);
|
||||
DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0);
|
||||
DruidPooledConnection conn = new DruidPooledConnection(connHolder);
|
||||
|
||||
raw = new MockPreparedStatement(null, null);
|
||||
|
||||
@@ -162,7 +162,7 @@ public class PreparedStatementKeyTest extends TestCase {
|
||||
MockConnection conn = new MockConnection();
|
||||
PreparedStatementKey k1 = new PreparedStatementKey("x1", "c1", MethodType.M1);
|
||||
|
||||
PreparedStatementPool pool = new PreparedStatementPool(new DruidConnectionHolder(dataSource, conn));
|
||||
PreparedStatementPool pool = new PreparedStatementPool(new DruidConnectionHolder(dataSource, conn, 0));
|
||||
MockPreparedStatement raw = new MockPreparedStatement(null, null);
|
||||
pool.put(new PreparedStatementHolder(k1, raw));
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.alibaba.druid.bvt.pool.profile;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.DruidPooledConnection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ProfileEnableTest extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:mock:xxx");
|
||||
dataSource.setMaxWait(1000);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
public void testDefault() throws Exception {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
DruidPooledConnection conn = dataSource.getConnection();
|
||||
System.out.println("physicalConnectNanoSpan : " + conn.getPhysicalConnectNanoSpan());
|
||||
System.out.println("physicalConnectionUsedCount : " + conn.getPhysicalConnectionUsedCount());
|
||||
System.out.println("connectNotEmptyWaitNanos : " + conn.getConnectNotEmptyWaitNanos());
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user