From b45031a78773355f4971879623774cc700dc443c Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 30 Apr 2013 01:03:57 +0800 Subject: [PATCH 1/2] change pool create & destory thread name --- src/main/java/com/alibaba/druid/pool/DruidDataSource.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 3028f22a27..28f07af672 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -486,12 +486,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } private void createAndStartDestroyThread() { - destoryConnectionThread = new DestroyConnectionThread("Druid-ConnectionPool-Destory"); + String threadName = "Druid-ConnectionPool-Destory-" + System.identityHashCode(this); + destoryConnectionThread = new DestroyConnectionThread(threadName); destoryConnectionThread.start(); } protected void createAndStartCreatorThread() { - createConnectionThread = new CreateConnectionThread("Druid-ConnectionPool-Create"); + String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this); + createConnectionThread = new CreateConnectionThread(threadName); createConnectionThread.start(); } From 1b2ffe9d8049b56cb4cf297f6b6514d9774916ba Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 30 Apr 2013 02:34:59 +0800 Subject: [PATCH 2/2] StatFilter mergeSql support tddl --- .../alibaba/druid/pool/DruidDataSource.java | 24 ++++++- .../MySqlParameterizedOutputVisitor.java | 29 +++++++- .../sql/visitor/SQLASTOutputVisitor.java | 4 +- .../druid/stat/JdbcDataSourceStat.java | 12 ++++ .../alibaba/druid/stat/JdbcStatManager.java | 52 ++++++++++---- .../druid/bvt/filter/ReuseStatFilterTest.java | 38 +++++++++++ .../bvt/proxy/filter/GlobalStatTest0.java | 68 +++++++++++++++++++ .../filter/MergeStatFilterTest_tddl.java} | 40 +++++------ 8 files changed, 230 insertions(+), 37 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/ReuseStatFilterTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest0.java rename src/test/java/com/alibaba/druid/bvt/{filter/PoolStatFilterTest.java => proxy/filter/MergeStatFilterTest_tddl.java} (54%) diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 28f07af672..b07df712c3 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -130,6 +130,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private JdbcDataSourceStat dataSourceStat; + private boolean useGloalDataSourceStat = false; + public DruidDataSource(){ this(false); } @@ -149,6 +151,22 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.setValidationQuery(property); } } + { + String property = System.getProperty("druid.useGloalDataSourceStat"); + if ("true".equals(property)) { + this.setUseGloalDataSourceStat(true); + } else if ("false".equals(property)) { + this.setUseGloalDataSourceStat(false); + } + } + } + + public boolean isUseGloalDataSourceStat() { + return useGloalDataSourceStat; + } + + public void setUseGloalDataSourceStat(boolean useGloalDataSourceStat) { + this.useGloalDataSourceStat = useGloalDataSourceStat; } public String getInitStackTrace() { @@ -435,7 +453,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } - dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbType); + if (useGloalDataSourceStat) { + dataSourceStat = JdbcDataSourceStat.getGlobal(); + } else { + dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbType); + } connections = new DruidConnectionHolder[maxActive]; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index 8cf5137bca..cd7316d2e0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -17,17 +17,20 @@ package com.alibaba.druid.sql.dialect.mysql.visitor; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; import com.alibaba.druid.sql.ast.expr.SQLNullExpr; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { - public MySqlParameterizedOutputVisitor() { + public MySqlParameterizedOutputVisitor(){ this(new StringBuilder()); } @@ -39,6 +42,30 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { return ParameterizedOutputVisitorUtils.visit(this, x); } + public boolean visit(SQLIdentifierExpr x) { + String name = x.getName(); + if (x.getParent() instanceof SQLExprTableSource || x.getParent() instanceof SQLPropertyExpr) { + int pos = name.lastIndexOf('_'); + if (pos != -1 && pos != name.length()) { + boolean isNumber = true; + for (int i = pos + 1; i < name.length(); ++i) { + char ch = name.charAt(i); + if (ch < '0' || ch > '9') { + isNumber = false; + break; + } + } + if (isNumber) { + String realName = name.substring(0, pos); + print(realName); + return false; + } + } + } + print(name); + return false; + } + public boolean visit(SQLBinaryOpExpr x) { x = ParameterizedOutputVisitorUtils.merge(x); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index ada5726635..5f770d3aba 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -458,8 +458,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { return false; } - public boolean visit(SQLIdentifierExpr astNode) { - print(astNode.getName()); + public boolean visit(SQLIdentifierExpr x) { + print(x.getName()); return false; } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java index 3c95692c58..2b0f07d348 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java @@ -70,6 +70,18 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { private final AtomicLong blobOpenCount = new AtomicLong(); + private static JdbcDataSourceStat global = new JdbcDataSourceStat( + "global", + "global"); + + public static JdbcDataSourceStat getGlobal() { + return global; + } + + public static void setGlobal(JdbcDataSourceStat value) { + global = value; + } + public JdbcDataSourceStat(String name, String url){ this(name, url, null); } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java b/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java index 6cd73b3653..6fb0730fdf 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java @@ -36,17 +36,17 @@ import com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl; public final class JdbcStatManager implements JdbcStatManagerMBean { - private final AtomicLong sqlIdSeed = new AtomicLong(1000); + private final AtomicLong sqlIdSeed = new AtomicLong(1000); - private final static JdbcStatManager instance = new JdbcStatManager(); + private final static JdbcStatManager instance = new JdbcStatManager(); - private final JdbcConnectionStat connectionStat = new JdbcConnectionStat(); - private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat(); - private final JdbcStatementStat statementStat = new JdbcStatementStat(); + private final JdbcConnectionStat connectionStat = new JdbcConnectionStat(); + private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat(); + private final JdbcStatementStat statementStat = new JdbcStatementStat(); - private final AtomicLong resetCount = new AtomicLong(); + private final AtomicLong resetCount = new AtomicLong(); - public final ThreadLocal contextLocal = new ThreadLocal(); + public final ThreadLocal contextLocal = new ThreadLocal(); private JdbcStatManager(){ @@ -296,26 +296,52 @@ public final class JdbcStatManager implements JdbcStatManagerMBean { TabularType tabularType = new TabularType("SqlListStatistic", "SqlListStatistic", rowType, indexNames); TabularData data = new TabularDataSupport(tabularType); - for (DataSourceProxyImpl dataSource : DruidDriver.getProxyDataSources().values()) { - Map statMap = dataSource.getDataSourceStat().getSqlStatMap(); + JdbcDataSourceStat globalStat = JdbcDataSourceStat.getGlobal(); + { + Map statMap = globalStat.getSqlStatMap(); for (Map.Entry entry : statMap.entrySet()) { if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) { continue; } - + + Map map = entry.getValue().getData(); + map.put("URL", globalStat.getUrl()); + data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map)); + } + } + + for (DataSourceProxyImpl dataSource : DruidDriver.getProxyDataSources().values()) { + JdbcDataSourceStat druidDataSourceStat = dataSource.getDataSourceStat(); + + if (druidDataSourceStat == globalStat) { + continue; + } + + Map statMap = druidDataSourceStat.getSqlStatMap(); + for (Map.Entry entry : statMap.entrySet()) { + if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) { + continue; + } + Map map = entry.getValue().getData(); map.put("URL", dataSource.getUrl()); data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map)); } } - + for (DruidDataSource dataSource : DruidDataSourceStatManager.getDruidDataSourceInstances()) { - Map statMap = dataSource.getDataSourceStat().getSqlStatMap(); + JdbcDataSourceStat druidDataSourceStat = dataSource.getDataSourceStat(); + + if (druidDataSourceStat == globalStat) { + continue; + } + + Map statMap = druidDataSourceStat.getSqlStatMap(); for (Map.Entry entry : statMap.entrySet()) { if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) { continue; } - + Map map = entry.getValue().getData(); map.put("URL", dataSource.getUrl()); data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map)); diff --git a/src/test/java/com/alibaba/druid/bvt/filter/ReuseStatFilterTest.java b/src/test/java/com/alibaba/druid/bvt/filter/ReuseStatFilterTest.java new file mode 100644 index 0000000000..ad35afedd8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/ReuseStatFilterTest.java @@ -0,0 +1,38 @@ +package com.alibaba.druid.bvt.filter; + +import junit.framework.TestCase; + +import com.alibaba.druid.filter.stat.StatFilter; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.util.JdbcUtils; + +public class ReuseStatFilterTest extends TestCase { + + private DruidDataSource dataSourceA; + private DruidDataSource dataSourceB; + + protected void setUp() throws Exception { + dataSourceA = new DruidDataSource(); + dataSourceB = new DruidDataSource(); + + dataSourceA.setUrl("jdbc:mock:xxx_A"); + dataSourceB.setUrl("jdbc:mock:xxx_B"); + + StatFilter filter = new StatFilter(); + + dataSourceA.getProxyFilters().add(filter); + dataSourceB.getProxyFilters().add(filter); + + dataSourceA.init(); + dataSourceB.init(); + } + + public void test_execute() throws Exception { + + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSourceA); + JdbcUtils.close(dataSourceB); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest0.java b/src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest0.java new file mode 100644 index 0000000000..83c2f49826 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest0.java @@ -0,0 +1,68 @@ +package com.alibaba.druid.bvt.proxy.filter; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +import org.junit.Assert; + +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.stat.JdbcDataSourceStat; +import com.alibaba.druid.stat.JdbcStatManager; +import com.alibaba.druid.util.JdbcUtils; + +public class GlobalStatTest0 extends TestCase { + + private DruidDataSource dataSourceA; + private DruidDataSource dataSourceB; + + protected void setUp() throws Exception { + dataSourceA = new DruidDataSource(); + dataSourceA.setUrl("jdbc:mock:xx_A"); + dataSourceA.setFilters("stat"); + dataSourceA.setUseGloalDataSourceStat(true); + + dataSourceB = new DruidDataSource(); + dataSourceB.setUrl("jdbc:mock:xx_A"); + dataSourceB.setFilters("stat"); + dataSourceB.setUseGloalDataSourceStat(true); + } + + public void test_execute() throws Exception { + { + Connection conn = dataSourceA.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT 1"); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + + } + rs.close(); + stmt.close(); + conn.close(); + } + { + Connection conn = dataSourceB.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT 1"); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + + } + rs.close(); + stmt.close(); + conn.close(); + } + + Assert.assertSame(JdbcDataSourceStat.getGlobal(), dataSourceA.getDataSourceStat()); + Assert.assertSame(JdbcDataSourceStat.getGlobal(), dataSourceB.getDataSourceStat()); + + Assert.assertEquals(1, JdbcStatManager.getInstance().getSqlList().size()); + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSourceA); + JdbcUtils.close(dataSourceB); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/PoolStatFilterTest.java b/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl.java similarity index 54% rename from src/test/java/com/alibaba/druid/bvt/filter/PoolStatFilterTest.java rename to src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl.java index a5fa1a11bb..cf518c09c2 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/PoolStatFilterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl.java @@ -13,46 +13,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.bvt.filter; +package com.alibaba.druid.bvt.proxy.filter; import java.sql.Connection; +import java.sql.Statement; import junit.framework.Assert; import junit.framework.TestCase; import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.util.Histogram; -import com.alibaba.druid.util.JdbcUtils; -public class PoolStatFilterTest extends TestCase { +public class MergeStatFilterTest_tddl extends TestCase { private DruidDataSource dataSource; protected void setUp() throws Exception { dataSource = new DruidDataSource(); - - dataSource.setUrl("jdbc:mock:xxx"); - dataSource.setFilters("stat"); - - dataSource.init(); + dataSource.setUrl("jdbc:mock:xx"); + dataSource.setFilters("mergeStat"); + dataSource.setDbType("mysql"); } protected void tearDown() throws Exception { - JdbcUtils.close(dataSource); + dataSource.close(); } - public void test_stat() throws Exception { - - Assert.assertTrue(dataSource.isInited()); - - Histogram histogram = dataSource.getDataSourceStat().getConnectionHoldHistogram(); - - Assert.assertEquals(0, histogram.getValue(0)); + public void test_merge() throws Exception { + for (int i = 0; i < 100; ++i) { + String tableName = "t_" + i; + String sql = "select * from " + tableName + " where " + tableName + ".id = " + i; + Connection conn = dataSource.getConnection(); - Connection conn = dataSource.getConnection(); + Statement stmt = conn.createStatement(); + stmt.execute(sql); + stmt.close(); - conn.close(); + conn.close(); + } + + Assert.assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size()); - Assert.assertEquals(1, histogram.getValue(0)); } + }