diff --git a/src/main/java/com/alibaba/druid/Constants.java b/src/main/java/com/alibaba/druid/Constants.java new file mode 100644 index 0000000000..1334e9508f --- /dev/null +++ b/src/main/java/com/alibaba/druid/Constants.java @@ -0,0 +1,6 @@ +package com.alibaba.druid; + +public interface Constants { + + public final static String DRUID_STAT_SQL_MAX_SIZE = "druid.stat.sql.MaxSize"; +} diff --git a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java index 4949e7ac3a..4665f2cd41 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -29,13 +30,19 @@ import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; +import com.alibaba.druid.Constants; import com.alibaba.druid.filter.Filter; import com.alibaba.druid.filter.stat.StatFilter; import com.alibaba.druid.proxy.jdbc.DataSourceProxy; +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.util.Histogram; +import com.alibaba.druid.util.LRUCache; public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { + private final static Log LOG = LogFactory.getLog(JdbcDataSourceStat.class); + private final String name; private final String url; private String dbType; @@ -47,10 +54,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { private int maxSize = 1000 * 1; private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - private final LinkedHashMap sqlStatMap = new LinkedHashMap( - maxSize, - 0.75f, - false); + private final LinkedHashMap sqlStatMap; private final Histogram connectionHoldHistogram = new Histogram(new long[] { // // @@ -66,11 +70,33 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { public JdbcDataSourceStat(String name, String url){ this(name, url, null); } - + public JdbcDataSourceStat(String name, String url, String dbType){ + this(name, url, dbType, null); + } + + public JdbcDataSourceStat(String name, String url, String dbType, Properties connectProperties){ this.name = name; this.url = url; this.dbType = dbType; + + if (connectProperties != null) { + Object arg = connectProperties.get(Constants.DRUID_STAT_SQL_MAX_SIZE); + + if (arg == null) { + arg = System.getProperty(Constants.DRUID_STAT_SQL_MAX_SIZE); + } + + if (arg != null) { + try { + maxSize = Integer.parseInt(arg.toString()); + } catch (NumberFormatException ex) { + LOG.error("maxSize parse error", ex); + } + } + } + + sqlStatMap = new LRUCache(maxSize, 16, 0.75f, false); } public void reset() { diff --git a/src/main/java/com/alibaba/druid/util/LRUCache.java b/src/main/java/com/alibaba/druid/util/LRUCache.java new file mode 100644 index 0000000000..bedf7443d1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/util/LRUCache.java @@ -0,0 +1,19 @@ +package com.alibaba.druid.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class LRUCache extends LinkedHashMap { + + private static final long serialVersionUID = 1L; + private final int maxSize; + + public LRUCache(int maxSize, int initialCapacity, float loadFactor, boolean accessOrder){ + super(initialCapacity, loadFactor, accessOrder); + this.maxSize = maxSize; + } + + protected boolean removeEldestEntry(Map.Entry eldest) { + return this.size() > this.maxSize; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/JdbcDataSourceStatTest.java b/src/test/java/com/alibaba/druid/bvt/pool/JdbcDataSourceStatTest.java new file mode 100644 index 0000000000..48205f0e53 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/JdbcDataSourceStatTest.java @@ -0,0 +1,46 @@ +package com.alibaba.druid.bvt.pool; + +import java.util.Properties; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.Constants; +import com.alibaba.druid.stat.JdbcDataSourceStat; + +public class JdbcDataSourceStatTest extends TestCase { + + public void test_max() throws Exception { + JdbcDataSourceStat stat = new JdbcDataSourceStat("", ""); + + for (int i = 0; i < 1000 * 10; ++i) { + stat.createSqlStat("select " + i); + } + + Assert.assertEquals(1000, stat.getSqlStatMap().size()); + } + + public void test_max_10() throws Exception { + Properties connectProperties = new Properties(); + connectProperties.put(Constants.DRUID_STAT_SQL_MAX_SIZE, 10); + JdbcDataSourceStat stat = new JdbcDataSourceStat("", "", "mysql", connectProperties); + + for (int i = 0; i < 1000 * 1; ++i) { + stat.createSqlStat("select " + i); + } + + Assert.assertEquals(10, stat.getSqlStatMap().size()); + } + + public void test_max_10_str() throws Exception { + Properties connectProperties = new Properties(); + connectProperties.put(Constants.DRUID_STAT_SQL_MAX_SIZE, "10"); + JdbcDataSourceStat stat = new JdbcDataSourceStat("", "", "mysql", connectProperties); + + for (int i = 0; i < 1000 * 1; ++i) { + stat.createSqlStat("select " + i); + } + + Assert.assertEquals(10, stat.getSqlStatMap().size()); + } +}