mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve dynamic config
This commit is contained in:
@@ -57,12 +57,18 @@ import com.alibaba.druid.proxy.jdbc.StatementProxy;
|
||||
/**
|
||||
* @author wenshao<szujobs@hotmail.com>
|
||||
*/
|
||||
public interface Filter {
|
||||
public interface Filter extends Wrapper {
|
||||
|
||||
void init(DataSourceProxy dataSource);
|
||||
|
||||
|
||||
void destory();
|
||||
|
||||
void configFromProperties(Properties properties);
|
||||
|
||||
boolean isWrapperFor(java.lang.Class<?> iface);
|
||||
|
||||
<T> T unwrap(java.lang.Class<T> iface);
|
||||
|
||||
ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException;
|
||||
|
||||
StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection) throws SQLException;
|
||||
@@ -1277,6 +1283,7 @@ public interface Filter {
|
||||
void clob_truncate(FilterChain chain, ClobProxy wrapper, long len) throws SQLException;
|
||||
|
||||
void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection connection) throws SQLException;
|
||||
|
||||
DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, long maxWaitMillis) throws SQLException;
|
||||
|
||||
DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, long maxWaitMillis)
|
||||
throws SQLException;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,23 @@ public abstract class FilterAdapter extends NotificationBroadcasterSupport imple
|
||||
public void destory() {
|
||||
|
||||
}
|
||||
|
||||
public void configFromProperties(Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) {
|
||||
return iface == this.getClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) {
|
||||
if (iface == this.getClass()) {
|
||||
return (T) this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array callableStatement_getArray(FilterChain chain, CallableStatementProxy statement, int parameterIndex)
|
||||
|
||||
@@ -412,7 +412,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM
|
||||
@Override
|
||||
protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {
|
||||
logExecutableSql(statement, sql);
|
||||
|
||||
|
||||
if (statementExecuteAfterLogEnable && isStatementLogEnabled()) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
double nanos = statement.getLastExecuteTimeNano();
|
||||
@@ -436,9 +436,9 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM
|
||||
} else {
|
||||
sql = statement.getBatchSql();
|
||||
}
|
||||
|
||||
|
||||
logExecutableSql(statement, sql);
|
||||
|
||||
|
||||
if (statementExecuteBatchAfterLogEnable && isStatementLogEnabled()) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
double nanos = statement.getLastExecuteTimeNano();
|
||||
@@ -460,7 +460,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM
|
||||
@Override
|
||||
protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {
|
||||
logExecutableSql(statement, sql);
|
||||
|
||||
|
||||
if (statementExecuteQueryAfterLogEnable && isStatementLogEnabled()) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
double nanos = statement.getLastExecuteTimeNano();
|
||||
@@ -810,4 +810,18 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM
|
||||
|
||||
chain.preparedStatement_clearParameters(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) {
|
||||
return iface == this.getClass() || iface == LogFilter.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> iface) {
|
||||
if (iface == this.getClass() || iface == LogFilter.class) {
|
||||
return (T) this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,21 @@
|
||||
package com.alibaba.druid.filter.stat;
|
||||
|
||||
public class MergeStatFilter extends StatFilter {
|
||||
public MergeStatFilter() {
|
||||
super.setMergeSql(true);
|
||||
}
|
||||
|
||||
public MergeStatFilter(){
|
||||
super.setMergeSql(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) {
|
||||
return iface == MergeStatFilter.class || iface == StatFilter.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) {
|
||||
if (iface == MergeStatFilter.class || iface == StatFilter.class) {
|
||||
return (T) this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +156,11 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
this.dbType = dataSource.getDbType();
|
||||
}
|
||||
|
||||
initFromProperties(dataSource.getConnectProperties());
|
||||
initFromProperties(System.getProperties());
|
||||
configFromProperties(dataSource.getConnectProperties());
|
||||
configFromProperties(System.getProperties());
|
||||
}
|
||||
|
||||
private void initFromProperties(Properties properties) {
|
||||
public void configFromProperties(Properties properties) {
|
||||
if (properties == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import javax.sql.ConnectionEventListener;
|
||||
import javax.sql.ConnectionPoolDataSource;
|
||||
import javax.sql.PooledConnection;
|
||||
|
||||
import com.alibaba.druid.Constants;
|
||||
import com.alibaba.druid.TransactionTimeoutException;
|
||||
import com.alibaba.druid.VERSION;
|
||||
import com.alibaba.druid.filter.AutoLoad;
|
||||
@@ -144,8 +145,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
public DruidDataSource(boolean fairLock){
|
||||
super(fairLock);
|
||||
|
||||
configFromPropety(System.getProperties());
|
||||
}
|
||||
|
||||
public void configFromPropety(Properties properties) {
|
||||
{
|
||||
String property = System.getProperty("druid.testWhileIdle");
|
||||
String property = properties.getProperty("druid.testWhileIdle");
|
||||
if ("true".equals(property)) {
|
||||
this.setTestWhileIdle(true);
|
||||
} else if ("false".equals(property)) {
|
||||
@@ -153,7 +158,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = System.getProperty("druid.testOnBorrow");
|
||||
String property = properties.getProperty("druid.testOnBorrow");
|
||||
if ("true".equals(property)) {
|
||||
this.setTestOnBorrow(true);
|
||||
} else if ("false".equals(property)) {
|
||||
@@ -161,13 +166,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = System.getProperty("druid.validationQuery");
|
||||
String property = properties.getProperty("druid.validationQuery");
|
||||
if (property != null && property.length() > 0) {
|
||||
this.setValidationQuery(property);
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = System.getProperty("druid.useGloalDataSourceStat");
|
||||
String property = properties.getProperty("druid.useGloalDataSourceStat");
|
||||
if ("true".equals(property)) {
|
||||
this.setUseGloalDataSourceStat(true);
|
||||
} else if ("false".equals(property)) {
|
||||
@@ -175,7 +180,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = System.getProperty("druid.filters");
|
||||
String property = properties.getProperty("druid.filters");
|
||||
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
@@ -186,7 +191,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = System.getProperty("druid.timeBetweenLogStatsMillis");
|
||||
String property = properties.getProperty("druid.timeBetweenLogStatsMillis");
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
long value = Long.parseLong(property);
|
||||
@@ -196,6 +201,19 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = properties.getProperty(Constants.DRUID_STAT_SQL_MAX_SIZE);
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
int value = Integer.parseInt(property);
|
||||
if (dataSourceStat != null) {
|
||||
dataSourceStat.setMaxSqlSize(value);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.error("illegal property '" + Constants.DRUID_STAT_SQL_MAX_SIZE + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUseGloalDataSourceStat() {
|
||||
@@ -371,15 +389,42 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setConnectProperties(Properties properties) {
|
||||
if (properties == null) {
|
||||
properties = new Properties();
|
||||
}
|
||||
|
||||
if (inited) {
|
||||
if (!this.connectProperties.equals(properties)) {
|
||||
boolean equals;
|
||||
if (properties.size() == this.connectProperties.size()) {
|
||||
equals = true;
|
||||
for (Map.Entry entry : properties.entrySet()) {
|
||||
Object value = this.connectProperties.get(entry.getKey());
|
||||
Object entryValue = entry.getValue();
|
||||
if (value == null && entryValue != null) {
|
||||
equals = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!value.equals(entry.getValue())) {
|
||||
equals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
equals = false;
|
||||
}
|
||||
|
||||
if (!equals) {
|
||||
if (inited && LOG.isInfoEnabled()) {
|
||||
LOG.info("connectProperties changed : " + this.connectProperties + " -> " + properties);
|
||||
}
|
||||
|
||||
configFromPropety(properties);
|
||||
|
||||
for (Filter filter : this.filters) {
|
||||
filter.configFromProperties(properties);
|
||||
}
|
||||
}
|
||||
|
||||
this.connectProperties = properties;
|
||||
@@ -499,7 +544,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
dataSourceStat.setDbType(this.getDbType());
|
||||
}
|
||||
} else {
|
||||
dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbType);
|
||||
dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbType, this.connectProperties);
|
||||
}
|
||||
|
||||
connections = new DruidConnectionHolder[maxActive];
|
||||
@@ -2188,4 +2233,26 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
public Lock getLock() {
|
||||
return lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) {
|
||||
for (Filter filter : this.filters) {
|
||||
if (filter.isWrapperFor(iface)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.isWrapperFor(iface);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) {
|
||||
for (Filter filter : this.filters) {
|
||||
if (filter.isWrapperFor(iface)) {
|
||||
return (T) filter;
|
||||
}
|
||||
}
|
||||
|
||||
return super.unwrap(iface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,12 +585,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
}
|
||||
}
|
||||
|
||||
String varName = x.getName();
|
||||
if (x.isGlobal()) {
|
||||
print("@@global.");
|
||||
} else {
|
||||
String varName = x.getName();
|
||||
if ((!varName.startsWith("@")) && (!varName.equals("?")) && (!varName.startsWith("#"))
|
||||
&& (!varName.startsWith("$"))) {
|
||||
if ((!varName.startsWith("@")) // /
|
||||
&& (!varName.equals("?")) //
|
||||
&& (!varName.startsWith("#")) //
|
||||
&& (!varName.startsWith("$")) //
|
||||
&& (!varName.startsWith(":"))
|
||||
) {
|
||||
print("@@");
|
||||
}
|
||||
}
|
||||
@@ -3006,7 +3010,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
print(' ');
|
||||
x.getValues().accept(this);
|
||||
}
|
||||
|
||||
|
||||
if (x.getDataDirectory() != null) {
|
||||
incrementIndent();
|
||||
println();
|
||||
@@ -3021,7 +3025,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
x.getIndexDirectory().accept(this);
|
||||
decrementIndent();
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ 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 {
|
||||
|
||||
@@ -53,11 +52,13 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat();
|
||||
private final JdbcStatementStat statementStat = new JdbcStatementStat();
|
||||
|
||||
private int maxSize = 1000 * 1;
|
||||
private int maxSqlSize = 1000 * 1;
|
||||
|
||||
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final LinkedHashMap<String, JdbcSqlStat> sqlStatMap;
|
||||
|
||||
private final AtomicLong skipSqlCount = new AtomicLong();
|
||||
|
||||
private final Histogram connectionHoldHistogram = new Histogram(new long[] { //
|
||||
//
|
||||
1, 10, 100, 1000, 10 * 1000, //
|
||||
@@ -100,6 +101,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
this(name, url, dbType, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public JdbcDataSourceStat(String name, String url, String dbType, Properties connectProperties){
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
@@ -114,14 +116,36 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
|
||||
if (arg != null) {
|
||||
try {
|
||||
maxSize = Integer.parseInt(arg.toString());
|
||||
maxSqlSize = Integer.parseInt(arg.toString());
|
||||
} catch (NumberFormatException ex) {
|
||||
LOG.error("maxSize parse error", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlStatMap = new LRUCache<String, JdbcSqlStat>(maxSize, 16, 0.75f, false);
|
||||
sqlStatMap = new LinkedHashMap<String, JdbcSqlStat>(16, 0.75f, false) {
|
||||
|
||||
protected boolean removeEldestEntry(Map.Entry<String, JdbcSqlStat> eldest) {
|
||||
boolean remove = (size() > maxSqlSize);
|
||||
|
||||
if (remove) {
|
||||
JdbcSqlStat sqlStat = eldest.getValue();
|
||||
if (sqlStat.getRunningCount() > 0 || sqlStat.getExecuteCount() > 0) {
|
||||
skipSqlCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
return remove;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int getMaxSqlSize() {
|
||||
return this.maxSqlSize;
|
||||
}
|
||||
|
||||
public void setMaxSqlSize(int value) {
|
||||
this.maxSqlSize = value;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
@@ -131,6 +155,14 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public long getSkipSqlCount() {
|
||||
return skipSqlCount.get();
|
||||
}
|
||||
|
||||
public long getSkipSqlCountAndReset() {
|
||||
return skipSqlCount.getAndSet(0);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
blobOpenCount.set(0);
|
||||
@@ -140,6 +172,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
statementStat.reset();
|
||||
resultSetStat.reset();
|
||||
connectionHoldHistogram.reset();
|
||||
skipSqlCount.set(0);
|
||||
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
@@ -286,7 +319,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
|
||||
|
||||
List<JdbcSqlStatValue> values = new ArrayList<JdbcSqlStatValue>(stats.size());
|
||||
for (int i = 0; i < stats.size(); ++i) {
|
||||
JdbcSqlStat stat = stats.get(i);
|
||||
@@ -375,7 +408,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
public long getClobOpenCount() {
|
||||
return clobOpenCount.get();
|
||||
}
|
||||
|
||||
|
||||
public long getClobOpenCountAndReset() {
|
||||
return clobOpenCount.getAndSet(0);
|
||||
}
|
||||
@@ -387,7 +420,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
|
||||
public long getBlobOpenCount() {
|
||||
return blobOpenCount.get();
|
||||
}
|
||||
|
||||
|
||||
public long getBlobOpenCountAndReset() {
|
||||
return blobOpenCount.getAndSet(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user