From 8bd297894d7ed6a9596453ef885e094c14e59f37 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 26 May 2013 19:32:32 +0800 Subject: [PATCH] improve dynamic config --- .../alibaba/druid/pool/DruidDataSource.java | 1 + .../pool/DruidDataSourceStatLoggerImpl.java | 20 ++++ .../druid/pool/DruidDataSourceStatValue.java | 106 ++--------------- .../druid/stat/JdbcDataSourceStat.java | 39 +++++-- .../bvt/pool/dynamic/SqlSkipCountTest.java | 107 ++++++++++++++++++ 5 files changed, 170 insertions(+), 103 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/dynamic/SqlSkipCountTest.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 4dc28b7f06..d61eeee8ed 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1478,6 +1478,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat value.clobOpenCount = this.getDataSourceStat().getClobOpenCountAndReset(); value.blobOpenCount = this.getDataSourceStat().getBlobOpenCountAndReset(); + value.sqlSkipCount = this.getDataSourceStat().getSkipSqlCountAndReset(); value.sqlList = this.getDataSourceStat().getSqlStatMapAndReset(); return value; diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java index d58829e0cf..fbd6644606 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java @@ -55,55 +55,75 @@ public class DruidDataSourceStatLoggerImpl implements DruidDataSourceStatLogger if (statValue.getWaitThreadCount() > 0) { map.put("waitThreadCount", statValue.getWaitThreadCount()); } + if (statValue.getNotEmptyWaitCount() > 0) { map.put("notEmptyWaitCount", statValue.getNotEmptyWaitCount()); } + if (statValue.getNotEmptyWaitMillis() > 0) { map.put("notEmptyWaitMillis", statValue.getNotEmptyWaitMillis()); } + if (statValue.getLogicConnectErrorCount() > 0) { map.put("logicConnectErrorCount", statValue.getLogicConnectErrorCount()); } + if (statValue.getPhysicalConnectCount() > 0) { map.put("physicalConnectCount", statValue.getPhysicalConnectCount()); } + if (statValue.getPhysicalCloseCount() > 0) { map.put("physicalCloseCount", statValue.getPhysicalCloseCount()); } + if (statValue.getPhysicalConnectErrorCount() > 0) { map.put("physicalConnectErrorCount", statValue.getPhysicalConnectErrorCount()); } + if (statValue.getExecuteCount() > 0) { map.put("executeCount", statValue.getExecuteCount()); } + if (statValue.getErrorCount() > 0) { map.put("errorCount", statValue.getErrorCount()); } + if (statValue.getCommitCount() > 0) { map.put("commitCount", statValue.getCommitCount()); } + if (statValue.getRollbackCount() > 0) { map.put("rollbackCount", statValue.getRollbackCount()); } + if (statValue.getPstmtCacheHitCount() > 0) { map.put("pstmtCacheHitCount", statValue.getPstmtCacheHitCount()); } + if (statValue.getPstmtCacheMissCount() > 0) { map.put("pstmtCacheMissCount", statValue.getPstmtCacheMissCount()); } + if (statValue.getStartTransactionCount() > 0) { map.put("startTransactionCount", statValue.getStartTransactionCount()); map.put("transactionHistogram", rtrim(statValue.getTransactionHistogram())); } + if (statValue.getConnectCount() > 0) { map.put("connectionHoldTimeHistogram", rtrim(statValue.getConnectionHoldTimeHistogram())); } + if (statValue.getClobOpenCount() > 0) { map.put("clobOpenCount", statValue.getClobOpenCount()); } + if (statValue.getBlobOpenCount() > 0) { map.put("blobOpenCount", statValue.getBlobOpenCount()); } + + if (statValue.getSqlSkipCount() > 0) { + map.put("sqlSkipCount", statValue.getSqlSkipCount()); + } ArrayList> sqlList = new ArrayList>(); if (statValue.sqlList.size() > 0) { diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java index 58e092371e..80e1be264c 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java @@ -75,6 +75,7 @@ public class DruidDataSourceStatValue { protected long clobOpenCount; protected long blobOpenCount; + protected long sqlSkipCount; protected List sqlList; @@ -86,6 +87,14 @@ public class DruidDataSourceStatValue { return new Date(poolingPeakTime); } + public long getSqlSkipCount() { + return sqlSkipCount; + } + + public void setSqlSkipCount(long sqlSkipCount) { + this.sqlSkipCount = sqlSkipCount; + } + public Date getActivePeakTime() { if (activePeakTime <= 0) { return null; @@ -98,475 +107,380 @@ public class DruidDataSourceStatValue { return notEmptyWaitNanos / (1000 * 1000); } - public String getName() { return name; } - public void setName(String name) { this.name = name; } - public String getDbType() { return dbType; } - public void setDbType(String dbType) { this.dbType = dbType; } - public String getDriverClassName() { return driverClassName; } - public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } - public String getUrl() { return url; } - public void setUrl(String url) { this.url = url; } - public String getUserName() { return userName; } - public void setUserName(String userName) { this.userName = userName; } - public List getFilterClassNames() { return filterClassNames; } - public void setFilterClassNames(List filterClassNames) { this.filterClassNames = filterClassNames; } - public boolean isRemoveAbandoned() { return removeAbandoned; } - public void setRemoveAbandoned(boolean removeAbandoned) { this.removeAbandoned = removeAbandoned; } - public int getInitialSize() { return initialSize; } - public void setInitialSize(int initialSize) { this.initialSize = initialSize; } - public int getMinIdle() { return minIdle; } - public void setMinIdle(int minIdle) { this.minIdle = minIdle; } - public int getMaxActive() { return maxActive; } - public void setMaxActive(int maxActive) { this.maxActive = maxActive; } - public int getQueryTimeout() { return queryTimeout; } - public void setQueryTimeout(int queryTimeout) { this.queryTimeout = queryTimeout; } - public int getTransactionQueryTimeout() { return transactionQueryTimeout; } - public void setTransactionQueryTimeout(int transactionQueryTimeout) { this.transactionQueryTimeout = transactionQueryTimeout; } - public int getLoginTimeout() { return loginTimeout; } - public void setLoginTimeout(int loginTimeout) { this.loginTimeout = loginTimeout; } - public String getValidConnectionCheckerClassName() { return validConnectionCheckerClassName; } - public void setValidConnectionCheckerClassName(String validConnectionCheckerClassName) { this.validConnectionCheckerClassName = validConnectionCheckerClassName; } - public String getExceptionSorterClassName() { return exceptionSorterClassName; } - public void setExceptionSorterClassName(String exceptionSorterClassName) { this.exceptionSorterClassName = exceptionSorterClassName; } - public boolean isTestOnBorrow() { return testOnBorrow; } - public void setTestOnBorrow(boolean testOnBorrow) { this.testOnBorrow = testOnBorrow; } - public boolean isTestOnReturn() { return testOnReturn; } - public void setTestOnReturn(boolean testOnReturn) { this.testOnReturn = testOnReturn; } - public boolean isTestWhileIdle() { return testWhileIdle; } - public void setTestWhileIdle(boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } - public boolean isDefaultAutoCommit() { return defaultAutoCommit; } - public void setDefaultAutoCommit(boolean defaultAutoCommit) { this.defaultAutoCommit = defaultAutoCommit; } - public boolean isDefaultReadOnly() { return defaultReadOnly; } - public void setDefaultReadOnly(boolean defaultReadOnly) { this.defaultReadOnly = defaultReadOnly; } - public Integer getDefaultTransactionIsolation() { return defaultTransactionIsolation; } - public void setDefaultTransactionIsolation(Integer defaultTransactionIsolation) { this.defaultTransactionIsolation = defaultTransactionIsolation; } - public int getActiveCount() { return activeCount; } - public void setActiveCount(int activeCount) { this.activeCount = activeCount; } - public int getActivePeak() { return activePeak; } - public void setActivePeak(int activePeak) { this.activePeak = activePeak; } - public int getPoolingCount() { return poolingCount; } - public void setPoolingCount(int poolingCount) { this.poolingCount = poolingCount; } - public int getPoolingPeak() { return poolingPeak; } - public void setPoolingPeak(int poolingPeak) { this.poolingPeak = poolingPeak; } - public long getConnectCount() { return connectCount; } - public void setConnectCount(long connectCount) { this.connectCount = connectCount; } - public long getCloseCount() { return closeCount; } - public void setCloseCount(long closeCount) { this.closeCount = closeCount; } - public long getWaitThreadCount() { return waitThreadCount; } - public void setWaitThreadCount(long waitThreadCount) { this.waitThreadCount = waitThreadCount; } - public long getNotEmptyWaitCount() { return notEmptyWaitCount; } - public void setNotEmptyWaitCount(long notEmptyWaitCount) { this.notEmptyWaitCount = notEmptyWaitCount; } - public long getNotEmptyWaitNanos() { return notEmptyWaitNanos; } - public void setNotEmptyWaitNanos(long notEmptyWaitNanos) { this.notEmptyWaitNanos = notEmptyWaitNanos; } - public long getLogicConnectErrorCount() { return logicConnectErrorCount; } - public void setLogicConnectErrorCount(long logicConnectErrorCount) { this.logicConnectErrorCount = logicConnectErrorCount; } - public long getPhysicalConnectCount() { return physicalConnectCount; } - public void setPhysicalConnectCount(long physicalConnectCount) { this.physicalConnectCount = physicalConnectCount; } - public long getPhysicalCloseCount() { return physicalCloseCount; } - public void setPhysicalCloseCount(long physicalCloseCount) { this.physicalCloseCount = physicalCloseCount; } - public long getPhysicalConnectErrorCount() { return physicalConnectErrorCount; } - public void setPhysicalConnectErrorCount(long physicalConnectErrorCount) { this.physicalConnectErrorCount = physicalConnectErrorCount; } - public long getExecuteCount() { return executeCount; } - public void setExecuteCount(long executeCount) { this.executeCount = executeCount; } - public long getErrorCount() { return errorCount; } - public void setErrorCount(long errorCount) { this.errorCount = errorCount; } - public long getCommitCount() { return commitCount; } - public void setCommitCount(long commitCount) { this.commitCount = commitCount; } - public long getRollbackCount() { return rollbackCount; } - public void setRollbackCount(long rollbackCount) { this.rollbackCount = rollbackCount; } - public long getPstmtCacheHitCount() { return pstmtCacheHitCount; } - public void setPstmtCacheHitCount(long pstmtCacheHitCount) { this.pstmtCacheHitCount = pstmtCacheHitCount; } - public long getPstmtCacheMissCount() { return pstmtCacheMissCount; } - public void setPstmtCacheMissCount(long pstmtCacheMissCount) { this.pstmtCacheMissCount = pstmtCacheMissCount; } - public long getStartTransactionCount() { return startTransactionCount; } - public void setStartTransactionCount(long startTransactionCount) { this.startTransactionCount = startTransactionCount; } - public long[] getTransactionHistogram() { return transactionHistogram; } - public void setTransactionHistogram(long[] transactionHistogram) { this.transactionHistogram = transactionHistogram; } - public long[] getConnectionHoldTimeHistogram() { return connectionHoldTimeHistogram; } - public void setConnectionHoldTimeHistogram(long[] connectionHoldTimeHistogram) { this.connectionHoldTimeHistogram = connectionHoldTimeHistogram; } - public long getClobOpenCount() { return clobOpenCount; } - public void setClobOpenCount(long clobOpenCount) { this.clobOpenCount = clobOpenCount; } - public long getBlobOpenCount() { return blobOpenCount; } - public void setBlobOpenCount(long blobOpenCount) { this.blobOpenCount = blobOpenCount; } - public List getSqlList() { return sqlList; } - public void setSqlList(List sqlList) { this.sqlList = sqlList; } - public void setActivePeakTime(long activePeakTime) { this.activePeakTime = activePeakTime; } - public void setPoolingPeakTime(long poolingPeakTime) { this.poolingPeakTime = poolingPeakTime; } - - + } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java index e4df1ffa3c..65a35b1782 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java @@ -52,7 +52,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat(); private final JdbcStatementStat statementStat = new JdbcStatementStat(); - private int maxSqlSize = 1000 * 1; + private int maxSqlSize = 1000 * 1; private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final LinkedHashMap sqlStatMap; @@ -139,13 +139,35 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { } }; } - + public int getMaxSqlSize() { return this.maxSqlSize; } - + public void setMaxSqlSize(int value) { - this.maxSqlSize = value; + if (value == this.maxSqlSize) { + return; + } + + lock.writeLock().lock(); + try { + if (value < this.maxSqlSize) { + int removeCount = this.maxSqlSize - value; + Iterator> iter = sqlStatMap.entrySet().iterator(); + while (iter.hasNext()) { + iter.next(); + if (removeCount > 0) { + iter.remove(); + removeCount--; + } else { + break; + } + } + } + this.maxSqlSize = value; + } finally { + lock.writeLock().unlock(); + } } public String getDbType() { @@ -155,11 +177,11 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { public void setDbType(String dbType) { this.dbType = dbType; } - + public long getSkipSqlCount() { return skipSqlCount.get(); } - + public long getSkipSqlCountAndReset() { return skipSqlCount.getAndSet(0); } @@ -300,7 +322,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { } return map; } - + public List getSqlStatMapAndReset() { List stats = new ArrayList(sqlStatMap.size()); lock.writeLock().lock(); @@ -324,6 +346,9 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { for (int i = 0; i < stats.size(); ++i) { JdbcSqlStat stat = stats.get(i); JdbcSqlStatValue value = stat.getValueAndReset(); + if (value.getExecuteCount() == 0 && value.getRunningCount() == 0) { + continue; + } values.add(value); } return values; diff --git a/src/test/java/com/alibaba/druid/bvt/pool/dynamic/SqlSkipCountTest.java b/src/test/java/com/alibaba/druid/bvt/pool/dynamic/SqlSkipCountTest.java new file mode 100644 index 0000000000..de22e0c82c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/dynamic/SqlSkipCountTest.java @@ -0,0 +1,107 @@ +package com.alibaba.druid.bvt.pool.dynamic; + +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.PreparedStatement; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.DruidDataSourceStatValue; +import com.alibaba.druid.support.logging.Log; + +public class SqlSkipCountTest extends TestCase { + + private DruidDataSource dataSource; + + private Log dataSourceLog; + + protected void setUp() throws Exception { + Field logField = DruidDataSource.class.getDeclaredField("LOG"); + logField.setAccessible(true); + dataSourceLog = (Log) logField.get(null); + + dataSourceLog.resetStat(); + + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setFilters("stat"); + dataSource.init(); + + Assert.assertEquals(1, dataSourceLog.getInfoCount()); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_connectPropertiesChange() throws Exception { + for (int i = 0; i < 2000; ++i) { + Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement("select " + i); + stmt.execute(); + stmt.close(); + conn.close(); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(1000, statValue.getSqlList().size()); + Assert.assertEquals(1000, statValue.getSqlSkipCount()); + } + + dataSource.setConnectionProperties("druid.stat.sql.MaxSize=2000"); + for (int i = 0; i < 2000; ++i) { + Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement("select " + i); + stmt.execute(); + stmt.close(); + conn.close(); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(2000, statValue.getSqlList().size()); + Assert.assertEquals(0, statValue.getSqlSkipCount()); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(0, statValue.getSqlList().size()); + Assert.assertEquals(0, statValue.getSqlSkipCount()); + } + + dataSource.setConnectionProperties("druid.stat.sql.MaxSize=2000"); + for (int i = 0; i < 2000; ++i) { + Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement("select " + i); + stmt.execute(); + stmt.close(); + conn.close(); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(2000, statValue.getSqlList().size()); + Assert.assertEquals(0, statValue.getSqlSkipCount()); + } + + dataSource.setConnectionProperties("druid.stat.sql.MaxSize=100"); + for (int i = 0; i < 2000; ++i) { + Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement("select " + i); + stmt.execute(); + stmt.close(); + conn.close(); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(100, statValue.getSqlList().size()); + Assert.assertEquals(1900, statValue.getSqlSkipCount()); + } + { + DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset(); + Assert.assertEquals(0, statValue.getSqlList().size()); + Assert.assertEquals(0, statValue.getSqlSkipCount()); + } + } +}