Conflicts:
	src/main/java/com/alibaba/druid/util/ReflectionUtils.java
This commit is contained in:
septer
2012-08-10 13:15:20 +08:00
15 changed files with 263 additions and 83 deletions
@@ -96,6 +96,10 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
this.dbType = dbType;
}
public long getSlowSqlMillis() {
return slowSqlMillis;
}
public boolean isConnectionStackTraceEnable() {
return connectionStackTraceEnable;
}
@@ -406,7 +410,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
}
}
private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult, int... updateCountArray) {
private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult,
int... updateCountArray) {
final JdbcStatementStat.Entry entry = getStatementInfo(statement);
@@ -0,0 +1,21 @@
package com.alibaba.druid.pool;
import java.sql.SQLException;
public class DataSourceClosedException extends SQLException {
private static final long serialVersionUID = 1L;
public DataSourceClosedException(){
super();
}
public DataSourceClosedException(String reason){
super(reason);
}
public DataSourceClosedException(Throwable cause){
super(cause);
}
}
@@ -72,7 +72,7 @@ import com.alibaba.druid.util.JdbcUtils;
*/
public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource {
public final static Log LOG = LogFactory.getLog(DruidDataSource.class);
private final static Log LOG = LogFactory.getLog(DruidDataSource.class);
private static final long serialVersionUID = 1L;
@@ -117,6 +117,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
private String initStackTrace;
private boolean closed = false;
private long closeTimeMillis = -1L;
private JdbcDataSourceStat dataSourceStat;
@@ -274,23 +275,23 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (this.driverClass != null) {
this.driverClass = driverClass.trim();
}
if (isTestOnBorrow() || isTestOnReturn() || isTestWhileIdle()) {
if (this.getValidationQuery() == null || this.getValidationQuery().length() == 0) {
String errorMessage = "";
if (isTestOnBorrow()) {
errorMessage += "testOnBorrow is true, ";
}
if (isTestOnReturn()) {
errorMessage += "testOnReturn is true, ";
}
if (isTestWhileIdle()) {
errorMessage += "testWhileIdle is true, ";
}
LOG.error(errorMessage + "validationQuery not set");
}
}
@@ -301,9 +302,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (jdbcUrl.startsWith(DruidDriver.DEFAULT_PREFIX)) {
DataSourceProxyConfig config = DruidDriver.parseConfig(jdbcUrl, null);
this.driverClass = config.getRawDriverClassName();
LOG.error("error url : '" + jdbcUrl + "', it should be : '" + config.getRawUrl() + "'");
this.jdbcUrl = config.getRawUrl();
if (this.name == null) {
this.name = config.getName();
@@ -366,7 +367,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
} else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) {
this.exceptionSorter = new MockExceptionSorter();
}
if (realDriverClassName.equals("com.mysql.jdbc.Driver")) {
if (this.isPoolPreparedStatements()) {
LOG.error("mysql should not use 'PoolPreparedStatements'");
@@ -554,6 +555,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
try {
if (closed) {
connectErrorCount.incrementAndGet();
throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
}
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
@@ -775,6 +781,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
notEmptySignalCount++;
this.closed = true;
this.closeTimeMillis = System.currentTimeMillis();
for (Filter filter : filters) {
filter.destory();
@@ -782,6 +789,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
} finally {
lock.unlock();
}
LOG.warn("dataSource " + this.getID() + " closed");
}
void incrementCreateCount() {
@@ -879,7 +888,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (createError != null) {
throw new GetConnectionTimeoutException(createError);
} else {
throw new GetConnectionTimeoutException("loopWaitCount " + i + ", wait millis " + (nanos - estimate)/(1000 * 1000));
throw new GetConnectionTimeoutException("loopWaitCount " + i + ", wait millis "
+ (nanos - estimate) / (1000 * 1000));
}
}
}
@@ -1105,11 +1115,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
for (; iter.hasNext();) {
Map.Entry<DruidPooledConnection, ActiveConnectionTraceInfo> entry = iter.next();
DruidPooledConnection pooledConnection = entry.getKey();
if (pooledConnection.isRunning()) {
continue;
}
ActiveConnectionTraceInfo activeInfo = entry.getValue();
long timeMillis = currentMillis - activeInfo.getConnectTime();
@@ -1447,15 +1457,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
PreparedStatementPool stmtPool = connHolder.getStatementPool();
for (PreparedStatementHolder stmtHolder : stmtPool.getMap().values()) {
Map<String, Object> stmtInfo = new LinkedHashMap<String, Object>();
stmtInfo.put("sql", stmtHolder.getKey().getSql());
stmtInfo.put("defaultRowPretch", stmtHolder.getDefaultRowPretch());
stmtInfo.put("rowPrefetch", stmtHolder.getRowPrefetch());
stmtInfo.put("hitCount", stmtHolder.getHitCount());
stmtCache.add(stmtInfo);
}
map.put("pscache", stmtCache);
}
@@ -3,12 +3,21 @@ package com.alibaba.druid.stat;
import java.util.List;
import java.util.Map;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.ReflectionUtils;
public class DruidDataSourceStatJNDIStatStrategy implements DruidDataSourceStatStrategy{
private final static Log LOG = LogFactory.getLog(DruidDataSourceStatJNDIStatStrategy.class);
private Object getStrategyB() {
return ReflectionUtils.getClassFromWebContainerOrCurrentClassLoader("com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy");
try {
Class<?> clazz = ReflectionUtils.getClassFromWebContainerOrCurrentClassLoader("com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy");
return clazz.newInstance();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
return null;
}
}
@SuppressWarnings("unchecked")
@@ -17,7 +17,7 @@ public class DruidStatManagerFacade {
private final static DruidStatManagerFacade instance = new DruidStatManagerFacade();
private static DruidDataSourceStatStrategyContext ctx = null;
private static DruidDataSourceStatStrategyContext ctx = null;
private static DruidDataSourceStatStrategy strategy = null;
@@ -490,10 +490,14 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean {
// 25 - 29
"Histogram", //
"LastSlowParameters", "ResultSetHoldTime", "ExecuteAndResultSetHoldTime", "FetchRowCountHistogram",
"LastSlowParameters", //
"ResultSetHoldTime", //
"ExecuteAndResultSetHoldTime", //
"FetchRowCountHistogram", //
// 30
"EffectedRowCountHistogram", "ExecuteAndResultHoldTimeHistogram"
"EffectedRowCountHistogram", //
"ExecuteAndResultHoldTimeHistogram"
//
};
@@ -4,24 +4,23 @@ import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.DruidStatManagerFacade;
import com.alibaba.druid.stat.JdbcSqlStat;
import com.alibaba.druid.support.JSONDruidStatService;
import com.alibaba.druid.util.IOUtils;
import com.alibaba.druid.util.StringUtils;
/**
* 注意:避免直接调用Druid相关对象例如DruidDataSource等,相关调用要到DruidStatManagerFacade里用反射实现
*
* @author sandzhang<sandzhangtoo@gmail.com>
*/
public class StatViewServlet extends HttpServlet {
@@ -77,19 +76,22 @@ public class StatViewServlet extends HttpServlet {
if (path.startsWith("/connectionInfo-") && path.endsWith(".html")) {
Integer id = StringUtils.subStringToInteger(path, "connectionInfo-", ".");
returnViewConnectionInfo(id, request, response);
DruidDataSource datasource = druidStatManager.getDruidDataSourceById(id);
returnViewConnectionInfo(datasource, request, response);
return;
}
if (path.startsWith("/activeConnectionStackTrace-") && path.endsWith(".html")) {
Integer id = StringUtils.subStringToInteger(path, "activeConnectionStackTrace-", ".");
returnViewActiveConnectionStackTrace(id, request, response);
DruidDataSource datasource = druidStatManager.getDruidDataSourceById(id);
returnViewActiveConnectionStackTrace(datasource, request, response);
return;
}
if (path.startsWith("/sql-") && path.endsWith(".html")) {
Integer id = StringUtils.subStringToInteger(path, "sql-", ".");
returnViewSqlStat(druidStatManager.getSqlStatData(id), response);
JdbcSqlStat sqlStat = druidStatManager.getSqlStatById(id);
returnViewSqlStat(sqlStat, response);
return;
}
@@ -97,61 +99,63 @@ public class StatViewServlet extends HttpServlet {
returnResourceFile(path, response);
}
private void returnViewActiveConnectionStackTrace(Integer id, HttpServletRequest request,
private void returnViewActiveConnectionStackTrace(DruidDataSource datasource, HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (datasource == null) return;
if (!datasource.isRemoveAbandoned()) {
response.getWriter().print(mergeTemplatePage("ERROR", "require set removeAbandoned=true"));
return;
}
String text = IOUtils.readFromResource(RESOURCE_PATH + "/activeConnectionStackTrace.html");
text = text.replaceAll("\\{datasourceId\\}", id.toString());
text = text.replaceAll("\\{datasourceId\\}", String.valueOf(System.identityHashCode(datasource)));
response.getWriter().print(text);
}
private void returnViewConnectionInfo(Integer id, HttpServletRequest request, HttpServletResponse response)
throws IOException {
private void returnViewConnectionInfo(DruidDataSource datasource, HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (datasource == null) return;
String text = IOUtils.readFromResource(RESOURCE_PATH + "/connectionInfo.html");
text = text.replaceAll("\\{datasourceId\\}", id.toString());
text = text.replaceAll("\\{datasourceId\\}", String.valueOf(System.identityHashCode(datasource)));
response.getWriter().print(text);
}
private void returnViewSqlStat(Map<String, Object> sqlStat, HttpServletResponse response) throws IOException {
private void returnViewSqlStat(JdbcSqlStat sqlStat, HttpServletResponse response) throws IOException {
if (sqlStat == null) return;
StringBuilder content = new StringBuilder();
content.append("<h2>FULL SQL</h2> <h4>" + sqlStat.get("SQL") + "</h4>");
content.append("<h2>FULL SQL</h2> <h4>" + sqlStat.getSql() + "</h4>");
content.append("<h2>Format View:</h2>");
content.append("<textarea style='width:99%;height:120px;;border:1px #A8C7CE solid;line-height:20px;font-size:12px;'>");
content.append(SQLUtils.format((String) sqlStat.get("SQL"), (String) sqlStat.get("DbType")));
content.append(SQLUtils.format(sqlStat.getSql(), sqlStat.getDbType()));
content.append("</textarea><br />");
content.append("<p>API:com.alibaba.druid.sql.SQLUtils.format(sql,DBType);</p>");
content.append("<br />");
<<<<<<< HEAD
List<SQLStatement> statementList = SQLUtils.parseStatements((String) sqlStat.get("SQL"),
(String) sqlStat.get("DbType"));
=======
if (sqlStat.getLastSlowParameters() != null && sqlStat.getLastSlowParameters().trim().length() > 0) {
content.append("<h2>LastSlow SQL View:</h2>");
content.append("<table cellpadding='5' cellspacing='1' width='99%'>");
content.append("<tr>");
content.append("<td class='td_lable' width='130'>MaxTimespanOccurTime</td>");
content.append("<td>" + format.format(sqlStat.getExecuteNanoSpanMaxOccurTime()) + "</td>");
content.append("</tr>");
content.append("<tr>");
content.append("<td class='td_lable' width='130'>LastSlowParameters</td>");
content.append("<td>" + sqlStat.getLastSlowParameters() + "</td>");
content.append("</tr>");
content.append("</table>");
content.append("<br />");
}
if (sqlStat.getLastSlowParameters() != null && sqlStat.getLastSlowParameters().trim().length() > 0) {
content.append("<h2>LastSlow SQL View:</h2>");
content.append("<table cellpadding='5' cellspacing='1' width='99%'>");
content.append("<tr>");
content.append("<td class='td_lable' width='130'>MaxTimespanOccurTime</td>");
content.append("<td>" + format.format(sqlStat.getExecuteNanoSpanMaxOccurTime()) + "</td>");
content.append("</tr>");
content.append("<tr>");
content.append("<td class='td_lable' width='130'>LastSlowParameters</td>");
content.append("<td>" + sqlStat.getLastSlowParameters() + "</td>");
content.append("</tr>");
content.append("</table>");
content.append("<br />");
}
List<SQLStatement> statementList = SQLUtils.parseStatements(sqlStat.getSql(), sqlStat.getDbType());
>>>>>>> e5365eae94e50a7b51cd1d1ab2ed0cd029738eb4
if (!statementList.isEmpty()) {
content.append("<h2>Parse View:</h2>");
SQLStatement statemen = statementList.get(0);
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(statementList, (String) sqlStat.get("DbType"));
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(statementList, sqlStat.getDbType());
statemen.accept(visitor);
content.append("<table cellpadding='5' cellspacing='1' width='99%'>");
content.append("<tr>");
@@ -210,3 +214,4 @@ public class StatViewServlet extends HttpServlet {
return templatePage.replaceAll("\\{title\\}", title).replaceAll("\\{content\\}", content);
}
}
@@ -1,6 +1,5 @@
package com.alibaba.druid.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
@@ -20,50 +19,47 @@ public class ReflectionUtils {
try {
result = HttpServletRequest.class.getClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
if (LOG.isDebugEnabled()) LOG.debug(e.getMessage(), e);
if (LOG.isDebugEnabled()) LOG.debug("can'r find class in web container classLoader ", e);
}
if (result == null) {
try {
result = Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
LOG.warn(e.getMessage(), e);
LOG.error("can'r find class in current thread context classLoader ", e);
}
}
return result;
}
public static Object callStaticMethod(Class<?> classObject, String methodName) {
try {
Method m = classObject.getMethod(methodName);
return m.invoke(classObject);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
LOG.warn("callStaticMethod fail:class=" + classObject.getName() + " method=" + methodName, e);
return null;
}
return null;
}
public static Object callObjectMethod(Object obj, String methodName) {
try {
Constructor<?> ctor = ((Class<?>) obj).getConstructor();
Object instance = ctor.newInstance();
Method m = ((Class<?>) obj).getMethod(methodName); // 获取方法
return m.invoke(instance);
Method m = obj.getClass().getMethod(methodName);
return m.invoke(obj);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
LOG.warn("callObjectMethod fail:class=" + obj.getClass().getName() + " method=" + methodName, e);
return null;
}
return null;
}
public static Object callObjectMethod(Object obj, String methodName, Object methodParam) {
public static Object callObjectMethod(Object obj, String methodName, Integer id) {
try {
Constructor<?> ctor = ((Class<?>) obj).getConstructor();
Object instance = ctor.newInstance();
Method m = ((Class<?>) obj).getMethod(methodName, methodParam.getClass()); // 获取方法
return m.invoke(instance);
Method m = obj.getClass().getMethod(methodName, Integer.class);
return m.invoke(obj, id);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
LOG.warn("callObjectMethod fail:class=" + obj.getClass().getName() + " method=" + methodName, e);
return null;
}
return null;
}
public void getTest() {
@@ -3,6 +3,8 @@ package com.alibaba.druid.util;
import java.util.LinkedHashMap;
import java.util.Map;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.fastjson.JSON;
/**
@@ -10,6 +12,8 @@ import com.alibaba.fastjson.JSON;
*/
public class StringUtils {
private final static Log LOG = LogFactory.getLog(StringUtils.class);
/**
* Example: subString("12345","1","4")=23
*
@@ -52,6 +56,7 @@ public class StringUtils {
try {
return Integer.parseInt(in);
} catch (NumberFormatException e) {
LOG.warn("stringToInteger fail,string=" + in, e);
return null;
}
}
@@ -67,6 +72,7 @@ public class StringUtils {
try {
return Long.parseLong(in);
} catch (NumberFormatException e) {
LOG.warn("stringToLong fail,string=" + in, e);
return null;
}
}
@@ -0,0 +1,32 @@
package com.alibaba.druid.bvt.pool;
import java.sql.Connection;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.pool.DataSourceClosedException;
import com.alibaba.druid.pool.DruidDataSource;
public class ClosedTest extends TestCase {
public void test_close() throws Exception {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
Connection conn = dataSource.getConnection();
conn.close();
dataSource.close();
DataSourceClosedException error = null;
try {
dataSource.getConnection();
} catch (DataSourceClosedException ex) {
error = ex;
}
Assert.assertNotNull(error);
}
}
@@ -1,11 +1,13 @@
package com.alibaba.druid.bvt.pool;
import java.lang.reflect.Field;
import java.sql.Connection;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.logging.Log;
public class ConfigErrorTest extends TestCase {
@@ -22,12 +24,17 @@ public class ConfigErrorTest extends TestCase {
}
public void test_connect() throws Exception {
DruidDataSource.LOG.resetStat();
Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount());
Field field = DruidDataSource.class.getDeclaredField("LOG");
field.setAccessible(true);
Log LOG = (Log) field.get(null);
LOG.resetStat();
Assert.assertEquals(0, LOG.getErrorCount());
Connection conn = dataSource.getConnection();
conn.close();
Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount());
Assert.assertEquals(1, LOG.getErrorCount());
}
}
@@ -1,11 +1,13 @@
package com.alibaba.druid.bvt.pool;
import java.lang.reflect.Field;
import java.sql.Connection;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.logging.Log;
public class ConfigErrorTest2 extends TestCase {
@@ -24,12 +26,17 @@ public class ConfigErrorTest2 extends TestCase {
}
public void test_connect() throws Exception {
DruidDataSource.LOG.resetStat();
Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount());
Field field = DruidDataSource.class.getDeclaredField("LOG");
field.setAccessible(true);
Log LOG = (Log) field.get(null);
LOG.resetStat();
Assert.assertEquals(0, LOG.getErrorCount());
Connection conn = dataSource.getConnection();
conn.close();
Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount());
Assert.assertEquals(1, LOG.getErrorCount());
}
}
@@ -1,9 +1,12 @@
package com.alibaba.druid.bvt.pool;
import java.lang.reflect.Field;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.logging.Log;
public class ConfigErrorTest3 extends TestCase {
@@ -24,9 +27,14 @@ public class ConfigErrorTest3 extends TestCase {
}
public void test_connect() throws Exception {
DruidDataSource.LOG.resetStat();
Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount());
Field field = DruidDataSource.class.getDeclaredField("LOG");
field.setAccessible(true);
Log LOG = (Log) field.get(null);
LOG.resetStat();
Assert.assertEquals(0, LOG.getErrorCount());
dataSource.init();
Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount());
Assert.assertEquals(1, LOG.getErrorCount());
}
}
@@ -0,0 +1,32 @@
package com.alibaba.druid.bvt.pool;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
public class SlowSqlMillisTest extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setTestWhileIdle(false);
dataSource.setConnectionProperties("druid.stat.slowSqlMillis=500");
dataSource.setFilters("stat");
dataSource.init();
}
protected void tearDown() throws Exception {
dataSource.close();
}
public void test_connect() throws Exception {
StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);
Assert.assertEquals(500, filter.getSlowSqlMillis());
}
}
@@ -0,0 +1,38 @@
package com.alibaba.druid.bvt.pool;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
public class SlowSqlMillisTest2 extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setTestWhileIdle(false);
System.setProperty("druid.stat.slowSqlMillis", "500");
dataSource.setFilters("stat");
{
StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);
Assert.assertEquals(3000, filter.getSlowSqlMillis());
}
dataSource.init();
}
protected void tearDown() throws Exception {
System.clearProperty("druid.stat.slowSqlMillis");
dataSource.close();
}
public void test_connect() throws Exception {
StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);
Assert.assertEquals(500, filter.getSlowSqlMillis());
}
}