mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user