Merge remote-tracking branch 'upstream/master'

This commit is contained in:
xiaoyu830411
2012-08-27 16:49:37 +08:00
13 changed files with 232 additions and 77 deletions
@@ -113,13 +113,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
private final CountDownLatch initedLatch = new CountDownLatch(2);
private boolean enable = true;
private volatile boolean enable = true;
private boolean resetStatEnable = true;
private String initStackTrace;
private boolean closed = false;
private volatile boolean closed = false;
private long closeTimeMillis = -1L;
private JdbcDataSourceStat dataSourceStat;
@@ -320,11 +320,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
throw new SQLException("interrupt", e);
}
boolean init = false;
try {
if (inited) {
return;
}
init = true;
initStackTrace = IOUtils.toString(Thread.currentThread().getStackTrace());
this.id = DruidDriver.createDataSourceId();
@@ -343,10 +346,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
throw new IllegalArgumentException("illegal maxActive " + maxActive);
}
if (maxIdle <= 0 || maxIdle < minIdle) {
throw new IllegalArgumentException("illegal maxPoolSize");
}
if (getInitialSize() > maxActive) {
throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActieve "
+ maxActive);
@@ -437,7 +436,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
inited = true;
lock.unlock();
if (LOG.isInfoEnabled()) {
if (init && LOG.isInfoEnabled()) {
LOG.info("{dataSource-" + this.getID() + "} inited");
}
}
@@ -669,8 +668,20 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
DruidPooledConnection poolalbeConnection;
if (closed) {
connectErrorCount.incrementAndGet();
throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
}
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
}
final long nanos = TimeUnit.MILLISECONDS.toNanos(maxWait);
final int maxWaitThreadCount = getMaxWaitThreadCount();
DruidConnectionHolder holder;
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
@@ -679,17 +690,6 @@ 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();
}
final int maxWaitThreadCount = getMaxWaitThreadCount();
if (maxWaitThreadCount > 0) {
if (notEmptyWaitThreadCount >= maxWaitThreadCount) {
connectErrorCount.incrementAndGet();
@@ -700,26 +700,18 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
connectCount++;
DruidConnectionHolder holder;
if (maxWait > 0) {
holder = pollLast(maxWait, TimeUnit.MILLISECONDS);
holder = pollLast(nanos);
} else {
holder = takeLast();
}
if (holder == null) {
throw new SQLException("can not get connection");
}
holder.incrementUseCount();
activeCount++;
if (activeCount > activePeak) {
activePeak = activeCount;
activePeakTime = System.currentTimeMillis();
}
poolalbeConnection = new DruidPooledConnection(holder);
} catch (InterruptedException e) {
connectErrorCount.incrementAndGet();
throw new SQLException(e.getMessage(), e);
@@ -729,6 +721,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
} finally {
lock.unlock();
}
holder.incrementUseCount();
DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);
return poolalbeConnection;
}
@@ -815,12 +811,18 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
if (!enable) {
discardConnection(holder.getConnection());
return;
}
final long lastActiveTimeMillis = System.currentTimeMillis();
lock.lockInterruptibly();
try {
activeCount--;
closeCount++;
putLast(holder);
putLast(holder, lastActiveTimeMillis);
recycleCount++;
} finally {
lock.unlock();
@@ -918,18 +920,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
void putLast(DruidConnectionHolder e) throws SQLException {
if (!enable) {
discardConnection(e.getConnection());
return;
}
e.setLastActiveTimeMillis(System.currentTimeMillis());
void putLast(DruidConnectionHolder e, long lastActiveTimeMillis) throws SQLException {
e.setLastActiveTimeMillis(lastActiveTimeMillis);
connections[poolingCount++] = e;
if (poolingCount > poolingPeak) {
poolingPeak = poolingCount;
poolingPeakTime = System.currentTimeMillis();
poolingPeakTime = lastActiveTimeMillis;
}
notEmpty.signal();
@@ -950,7 +947,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
notEmptyWaitThreadCount--;
}
notEmptyWaitCount++;
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
@@ -969,8 +966,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
return last;
}
DruidConnectionHolder pollLast(long timeout, TimeUnit unit) throws InterruptedException, SQLException {
final long nanos = unit.toNanos(timeout);
DruidConnectionHolder pollLast(long nanos) throws InterruptedException, SQLException {
long estimate = nanos;
for (int i = 0;; ++i) {
@@ -993,7 +989,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
// creator
notEmptyWaitCount++;
notEmptyWaitNanos += (startEstimate - estimate);
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
@@ -1540,7 +1536,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
buf.append(entry.getKey().getSql());
buf.append("\"");
buf.append("\t}");
entryIndex++;
}
} catch (ConcurrentModificationException e) {
@@ -15,10 +15,11 @@
*/
package com.alibaba.druid.stat;
import com.alibaba.druid.pool.DruidDataSource;
import java.lang.management.ManagementFactory;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
@@ -27,6 +28,7 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import com.alibaba.druid.VERSION;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.stat.WebAppStatManager;
import com.alibaba.druid.support.spring.stat.SpringStatManager;
import com.alibaba.druid.util.DruidDataSourceUtils;
@@ -188,6 +190,10 @@ public class DruidStatManagerFacade {
dataMap.put("Drivers", getDriversData());
dataMap.put("ResetEnable", isResetEnable());
dataMap.put("ResetCount", getResetCount());
dataMap.put("JavaVMName", System.getProperty("java.vm.name"));
dataMap.put("JavaVersion", System.getProperty("java.version"));
dataMap.put("JavaClassPath", System.getProperty("java.class.path"));
dataMap.put("StartTime", new Date(ManagementFactory.getRuntimeMXBean().getStartTime()));
return dataMap;
}
@@ -25,6 +25,7 @@ public class Option {
private PrintStyle style = PrintStyle.HORIZONTAL;
private int printDataType = 0;
private int vmid = -1;
private int id = -1;
public void addPrintDataType(int newValue) {
this.printDataType= this.printDataType | newValue;
@@ -33,7 +34,7 @@ public class Option {
public static boolean isPrintHelp(String[] args) {
if (args == null ) return true;
for (String arg: args) {
if (arg.equals("-h") || arg.equals("--help")) {
if (arg.equals("-help") ) {
return true;
}
}
@@ -112,6 +113,13 @@ public class Option {
option.setStyle(PrintStyle.HORIZONTAL);
} else if (args[i].equals("-s2")) {
option.setStyle(PrintStyle.VERTICAL);
} else if (args[i].equals("-id")) {
try {
int id = Integer.parseInt(args[i+1]);
option.setId(id);
} catch (NumberFormatException e) {
throw new OptionParseException("vmid argument is not a integer!");
}
}
i++;
}
@@ -122,7 +130,7 @@ public class Option {
}
public static void printHelp() {
System.out.println("Usage: druidStat -help | -sql -ds -act -s1 -s2 vmid");
System.out.println("Usage: druidStat -help | -sql -ds -act -s1 -s2 -id vmid");
System.out.println();
System.out.println("arguments: ");
System.out.println(" vmid the process id of jvm that running druid");
@@ -131,8 +139,17 @@ public class Option {
System.out.println(" -act print active connection stacktrace data");
System.out.println(" -s1 print field name in first row");
System.out.println(" -s2 print field name in first column");
System.out.println(" -id only print the sql data matched with id, use this with -sql argument" );
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
@@ -19,11 +19,26 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.druid.sql.SQLUtils;
public class TabledDataPrinter {
private static final int SQL_MAX_LEN = 32;
private static final String[] sqlFields = new String[] {
private static final int MAX_COL = 4;
private static final String[] sqlRowTitle = new String[] {
"ID", "SQL", "ExecCount", "ExecTime",
"ExecMax","Txn", "Error","Update","FetchRow","Running","Concurrent",
"ExecHisto", "ExecRsHisto","FetchRowHisto","UpdateHisto" };
private static final String[] sqlRowField = new String[] {
"ID", "SQL", "ExecuteCount", "TotalTime", "MaxTimespan",
"InTransactionCount", "ErrorCount", "EffectedRowCount", "FetchRowCount",
"RunningCount","ConcurrentMax","Histogram","ExecuteAndResultHoldTimeHistogram",
"FetchRowCountHistogram","EffectedRowCountHistogram" };
private static final String[] sqlColField = new String[] {
"ID", "DataSource", "SQL", "ExecuteCount", "ErrorCount",
"TotalTime", "LastTime", "MaxTimespan", "LastError", "EffectedRowCount",
"FetchRowCount", "MaxTimespanOccurTime", "BatchSizeMax", "BatchSizeTotal", "ConcurrentMax",
@@ -33,7 +48,21 @@ public class TabledDataPrinter {
"Histogram", "LastSlowParameters", "ResultSetHoldTime", "ExecuteAndResultSetHoldTime", "FetchRowCountHistogram",
"EffectedRowCountHistogram", "ExecuteAndResultHoldTimeHistogram", "EffectedRowCountMax", "FetchRowCountMax", "ClobOpenCount" };
private static final String[] dsFields = new String[] {
private static final String[] dsRowTitle = new String[] {
"Name", "DbType",
"PoolingCount", "PoolingPeak", "PoolingPeakTime",
"ActiveCount", "ActivePeak", "ActivePeakTime",
"ExecuteCount", "ErrorCount", "CommitCount", "RollbackCount" };
private static final String[] dsRowField = new String[] {
"Name", "DbType",
"PoolingCount", "PoolingPeak", "PoolingPeakTime",
"ActiveCount", "ActivePeak", "ActivePeakTime",
"ExecuteCount", "ErrorCount", "CommitCount", "RollbackCount" };
private static final String[] dsColField = new String[] {
"Identity", "Name", "DbType", "DriverClassName", "URL", "UserName", "FilterClassNames",
"WaitThreadCount", "NotEmptyWaitCount", "NotEmptyWaitMillis",
"PoolingCount", "PoolingPeak", "PoolingPeakTime",
@@ -60,29 +89,48 @@ public class TabledDataPrinter {
public static void printDataSourceData(List<Map<String, Object>> content,Option opt) {
if (opt.getStyle() == Option.PrintStyle.HORIZONTAL) {
System.out.println(getFormattedOutput(content, dsFields));
System.out.println(getFormattedOutput(content, dsRowTitle, dsRowField));
} else {
System.out.println(getVerticalFormattedOutput(content, dsFields));
System.out.println(getVerticalFormattedOutput(content, dsColField));
}
}
public static void printSqlData(List<Map<String, Object>> content, Option opt) {
if (opt.getId() != -1) {
List<Map<String,Object>> matchedContent = new ArrayList<Map<String,Object>>();
for (Map<String, Object> sqlStat : content) {
Integer idStr = (Integer)sqlStat.get("ID");
if (idStr.intValue() == opt.getId()) {
matchedContent.add(sqlStat);
String dbType = (String) sqlStat.get("DbType");
String sql = (String) sqlStat.get("SQL");
System.out.println(SQLUtils.format(sql, dbType));
System.out.println("===============================\n");
break;
}
}
content = matchedContent;
}
if (opt.getStyle() == Option.PrintStyle.HORIZONTAL) {
System.out.println(getFormattedOutput(content, sqlFields));
System.out.println(getFormattedOutput(content, sqlRowTitle, sqlRowField));
} else {
System.out.println(getVerticalFormattedOutput(content, sqlFields));
System.out.println(getVerticalFormattedOutput(content, sqlColField));
}
}
public static String getFormattedOutput(List<Map<String, Object>> content, String[] titleFields) {
public static String getFormattedOutput(List<Map<String, Object>> content,
String[] title , String[] rowField) {
List<String[]> printContents = new ArrayList<String[]>();
printContents.add(titleFields);
printContents.add(title);
for (Map<String, Object> sqlStat : content) {
String[] row = new String[titleFields.length];
for (int i = 0; i < titleFields.length; ++i) {
Object value = sqlStat.get(titleFields[i]);
row[i] = handleAndConvert(value,titleFields[i]);
String[] row = new String[rowField.length];
for (int i = 0; i < rowField.length; ++i) {
Object value = sqlStat.get(rowField[i]);
row[i] = handleAndConvert(value,rowField[i]);
}
printContents.add(row);
}
@@ -94,10 +142,12 @@ public class TabledDataPrinter {
public static String getVerticalFormattedOutput(List<Map<String, Object>> content, String[] titleFields) {
List<String[]> printContents = new ArrayList<String[]>();
int maxCol = content.size() > MAX_COL ? MAX_COL: content.size();
for (int i = 0; i < titleFields.length; ++i) {
String[] row = new String[content.size()+1];
String[] row = new String[maxCol+1];
row[0] = titleFields[i];
for (int j=0; j<content.size(); j++) {
for (int j=0; j< maxCol ; j++) {
Map<String,Object> sqlStat = content.get(j);
Object value = sqlStat.get(titleFields[i]);
row[j+1] = handleAndConvert(value, titleFields[i]);
@@ -112,6 +162,8 @@ public class TabledDataPrinter {
if (value == null) value = "";
if (fieldName.equals("SQL")) {
String sql = (String)value;
sql = sql.replace("\n", " ");
sql = sql.replace("\t", " ");
if (sql.length() > SQL_MAX_LEN) {
sql = sql.substring(0,SQL_MAX_LEN-3) + "...";
}
@@ -212,7 +212,8 @@ public class StatViewServlet extends HttpServlet {
return;
}
if (isRequireAuth() && session.getAttribute(SESSION_USER_KEY) == null
if (isRequireAuth()
&& session.getAttribute(SESSION_USER_KEY) == null
&& !("/login.html".equals(path) || path.startsWith("/css") || path.startsWith("/js") || path.startsWith("/img"))) {
if (contextPath == null || contextPath.equals("") || contextPath.equals("/")) {
response.sendRedirect("/login.html");
@@ -251,6 +252,15 @@ public class StatViewServlet extends HttpServlet {
private void returnResourceFile(String fileName, String uri, HttpServletResponse response) throws ServletException,
IOException {
if (fileName.endsWith(".jpg")) {
byte[] bytes = IOUtils.readByteArrayFromResource(RESOURCE_PATH + fileName);
if (bytes != null) {
response.getOutputStream().write(bytes);
}
return;
}
String text = IOUtils.readFromResource(RESOURCE_PATH + fileName);
if (text == null) {
response.sendRedirect(uri + "/index.html");
@@ -15,9 +15,11 @@
*/
package com.alibaba.druid.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
@@ -52,6 +54,37 @@ public class IOUtils {
JdbcUtils.close(in);
}
}
public static byte[] readByteArrayFromResource(String resource) throws IOException {
InputStream in = null;
try {
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
if (in == null) {
return null;
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(in, output);
return output.toByteArray();
} finally {
JdbcUtils.close(in);
}
}
public static long copy(InputStream input, OutputStream output)
throws IOException {
final int EOF = -1;
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
public static String read(Reader reader) {
try {