bug fixed

This commit is contained in:
wenshao
2013-04-29 01:58:20 +08:00
parent de80373003
commit 4a7ae77e0d
14 changed files with 573 additions and 139 deletions
@@ -53,6 +53,8 @@ public class MockConnection extends ConnectionBase implements Connection {
private final long createdTimeMillis = System.currentTimeMillis();
private long lastActiveTimeMillis = System.currentTimeMillis();
private SQLException error;
public MockConnection(){
this(null, null, null);
}
@@ -67,6 +69,14 @@ public class MockConnection extends ConnectionBase implements Connection {
}
}
public SQLException getError() {
return error;
}
public void setError(SQLException error) {
this.error = error;
}
public List<Savepoint> getSavepoints() {
return savepoints;
}
@@ -112,9 +122,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public Statement createStatement() throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockStatement();
}
@@ -128,53 +136,40 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockPreparedStatement(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockCallableStatement(sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return sql;
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
super.setAutoCommit(autoCommit);
}
@Override
public void commit() throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
}
@Override
public void rollback() throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
this.savepoints.clear();
}
@@ -201,9 +196,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockStatement stmt = createMockStatement();
@@ -216,9 +209,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockPreparedStatement stmt = createMockPreparedStatement(sql);
@@ -230,9 +221,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockCallableStatement stmt = createMockCallableStatement(sql);
@@ -254,9 +243,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public Savepoint setSavepoint() throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockSavepoint savepoint = new MockSavepoint();
savepoint.setSavepointId(this.savepointIdSeed++);
@@ -267,9 +254,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public Savepoint setSavepoint(String name) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockSavepoint savepoint = new MockSavepoint();
savepoint.setSavepointId(this.savepointIdSeed++);
@@ -279,12 +264,19 @@ public class MockConnection extends ConnectionBase implements Connection {
return savepoint;
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
public void checkState() throws SQLException {
if (error != null) {
throw error;
}
if (closed) {
throw new MockConnectionClosedException();
}
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
checkState();
int index = this.savepoints.indexOf(savepoint);
if (index == -1) {
@@ -297,9 +289,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
if (savepoint == null) {
throw new SQLException("argument is null");
@@ -315,9 +305,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockStatement stmt = createMockStatement();
@@ -331,9 +319,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockPreparedStatement stmt = createMockPreparedStatement(sql);
@@ -354,9 +340,7 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
MockCallableStatement stmt = createMockCallableStatement(sql);
@@ -376,27 +360,21 @@ public class MockConnection extends ConnectionBase implements Connection {
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockPreparedStatement(sql);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockPreparedStatement(sql);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
if (closed) {
throw new MockConnectionClosedException();
}
checkState();
return createMockPreparedStatement(sql);
}
@@ -30,14 +30,14 @@ import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.IOUtils;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
/**
* @author wenshao<szujobs@hotmail.com>
*/
public final class DruidConnectionHolder {
private final static Log LOG = LogFactory.getLog(DruidConnectionHolder.class);
private final static Log LOG = LogFactory.getLog(DruidConnectionHolder.class);
private final DruidAbstractDataSource dataSource;
private final Connection conn;
private final List<ConnectionEventListener> connectionEventListeners = new CopyOnWriteArrayList<ConnectionEventListener>();
@@ -60,6 +60,7 @@ public final class DruidConnectionHolder {
private int underlyingHoldability;
private int underlyingTransactionIsolation;
private boolean underlyingAutoCommit;
private boolean discard = false;
public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn) throws SQLException{
@@ -167,6 +168,17 @@ public final class DruidConnectionHolder {
return statementPool;
}
public PreparedStatementPool getStatementPoolDirect() {
return statementPool;
}
public void clearStatementCache() {
if (this.statementPool == null) {
return;
}
this.statementPool.clear();
}
public DruidAbstractDataSource getDataSource() {
return dataSource;
}
@@ -218,13 +230,21 @@ public final class DruidConnectionHolder {
for (Object item : statementTrace.toArray()) {
Statement stmt = (Statement) item;
JdbcUtils.close(stmt);
stmt.close();
}
statementTrace.clear();
conn.clearWarnings();
}
public boolean isDiscard() {
return discard;
}
public void setDiscard(boolean discard) {
this.discard = discard;
}
public String toString() {
StringBuilder buf = new StringBuilder();
@@ -575,7 +575,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (!(isTestOnBorrow() || isTestOnReturn() || isTestWhileIdle())) {
return;
}
if (this.validConnectionChecker != null) {
return;
}
@@ -900,6 +900,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
this.discardConnection(holder.getConnection());
holder.setDiscard(true);
pooledConnection.disable(t);
}
@@ -988,22 +989,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
lock.unlock();
}
} catch (Throwable e) {
JdbcUtils.close(physicalConnection);
holder.clearStatementCache();
try {
lock.lockInterruptibly();
} catch (InterruptedException interruptEx) {
throw new SQLException("interrupt", interruptEx);
if (!holder.isDiscard()) {
this.discardConnection(physicalConnection);
holder.setDiscard(true);
}
try {
activeCount--;
closeCount++;
} finally {
lock.unlock();
}
throw new SQLException("recyle error", e);
LOG.error("recyle error", e);
}
}
@@ -149,6 +149,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
try {
rawStatement.clearParameters();
} catch (SQLException ex) {
this.handleException(ex);
if (rawStatement.getConnection().isClosed()) {
return;
}
@@ -187,6 +188,10 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
}
public void disable(Throwable error) {
if (this.holder != null) {
this.holder.clearStatementCache();
}
this.traceEnable = false;
this.holder = null;
this.transactionInfo = null;
@@ -292,7 +297,8 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
}
if (!this.abandoned) {
holder.getDataSource().recycle(this);
DruidAbstractDataSource dataSource = holder.getDataSource();
dataSource.recycle(this);
}
this.holder = null;
@@ -163,26 +163,33 @@ public class DruidPooledPreparedStatement extends DruidPooledStatement implement
return;
}
boolean connectionClosed = this.conn.isClosed();
// Reset the defaults
if (defaultMaxFieldSize != currentMaxFieldSize) {
stmt.setMaxFieldSize(defaultMaxFieldSize);
currentMaxFieldSize = defaultMaxFieldSize;
}
if (defaultMaxRows != currentMaxRows) {
stmt.setMaxRows(defaultMaxRows);
currentMaxRows = defaultMaxRows;
}
if (defaultQueryTimeout != currentQueryTimeout) {
stmt.setQueryTimeout(defaultQueryTimeout);
currentQueryTimeout = defaultQueryTimeout;
}
if (defaultFetchDirection != currentFetchDirection) {
stmt.setFetchDirection(defaultFetchDirection);
currentFetchDirection = defaultFetchDirection;
}
if (defaultFetchSize != currentFetchSize) {
stmt.setFetchSize(defaultFetchSize);
currentFetchSize = defaultFetchSize;
if (!connectionClosed) {
try {
if (defaultMaxFieldSize != currentMaxFieldSize) {
stmt.setMaxFieldSize(defaultMaxFieldSize);
currentMaxFieldSize = defaultMaxFieldSize;
}
if (defaultMaxRows != currentMaxRows) {
stmt.setMaxRows(defaultMaxRows);
currentMaxRows = defaultMaxRows;
}
if (defaultQueryTimeout != currentQueryTimeout) {
stmt.setQueryTimeout(defaultQueryTimeout);
currentQueryTimeout = defaultQueryTimeout;
}
if (defaultFetchDirection != currentFetchDirection) {
stmt.setFetchDirection(defaultFetchDirection);
currentFetchDirection = defaultFetchDirection;
}
if (defaultFetchSize != currentFetchSize) {
stmt.setFetchSize(defaultFetchSize);
currentFetchSize = defaultFetchSize;
}
} catch (Exception e) {
this.conn.handleException(e);
}
}
conn.closePoolableStatement(this);
@@ -1034,16 +1041,16 @@ public class DruidPooledPreparedStatement extends DruidPooledStatement implement
}
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
if (iface == PreparedStatementHolder.class) {
return true;
}
return super.isWrapperFor(iface);
}
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface == PreparedStatementHolder.class) {
@@ -89,11 +89,11 @@ public class PreparedStatementPool {
PreparedStatementKey key = stmtHolder.getKey();
PreparedStatementHolder oldStmtHolder = map.put(key, stmtHolder);
if (oldStmtHolder == stmtHolder) {
return;
}
if (oldStmtHolder != null) {
oldStmtHolder.setPooling(false);
closeRemovedStatement(oldStmtHolder);
@@ -104,25 +104,27 @@ public class PreparedStatementPool {
}
stmtHolder.setPooling(true);
if (LOG.isDebugEnabled()) {
String message = null;
if (stmtHolder.getStatement() instanceof PreparedStatementProxy) {
PreparedStatementProxy stmtProxy = (PreparedStatementProxy) stmtHolder.getStatement();
if (stmtProxy instanceof CallableStatementProxy) {
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", cstmt-" + stmtProxy.getId() + "} enter cache";
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", cstmt-" + stmtProxy.getId()
+ "} enter cache";
} else {
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", pstmt-" + stmtProxy.getId() + "} enter cache";
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", pstmt-" + stmtProxy.getId()
+ "} enter cache";
}
} else {
message = "stmt enter cache";
}
LOG.debug(message);
}
}
public void clear() throws SQLException {
public void clear() {
Iterator<Entry<PreparedStatementKey, PreparedStatementHolder>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<PreparedStatementKey, PreparedStatementHolder> entry = iter.next();
@@ -133,30 +135,36 @@ public class PreparedStatementPool {
}
}
public void closeRemovedStatement(PreparedStatementHolder holder) throws SQLException {
public void closeRemovedStatement(PreparedStatementHolder holder) {
if (LOG.isDebugEnabled()) {
String message = null;
if (holder.getStatement() instanceof PreparedStatementProxy) {
PreparedStatementProxy stmtProxy = (PreparedStatementProxy) holder.getStatement();
if (stmtProxy instanceof CallableStatementProxy) {
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", cstmt-" + stmtProxy.getId() + "} exit cache";
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", cstmt-" + stmtProxy.getId()
+ "} exit cache";
} else {
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", pstmt-" + stmtProxy.getId() + "} exit cache";
message = "{conn-" + stmtProxy.getConnectionProxy().getId() + ", pstmt-" + stmtProxy.getId()
+ "} exit cache";
}
} else {
message = "stmt exit cache";
}
LOG.debug(message);
}
holder.setPooling(false);
if (holder.isInUse()) {
return;
}
if (holder.isEnterOracleImplicitCache()) {
OracleUtils.exitImplicitCacheToClose(holder.getStatement());
try {
OracleUtils.exitImplicitCacheToClose(holder.getStatement());
} catch (Exception ex) {
LOG.error("exitImplicitCacheToClose error", ex);
}
}
dataSource.closePreapredStatement(holder);
}
@@ -181,11 +189,7 @@ public class PreparedStatementPool {
boolean remove = (size() > dataSource.getMaxPoolPreparedStatementPerConnectionSize());
if (remove) {
try {
closeRemovedStatement(eldest.getValue());
} catch (SQLException e) {
LOG.error("closeStatement error", e);
}
closeRemovedStatement(eldest.getValue());
}
return remove;
@@ -121,4 +121,5 @@ public abstract class ConnectionBase implements Connection {
public boolean isReadOnly() throws SQLException {
return readOnly;
}
}
@@ -22,28 +22,29 @@ import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Statement;
import com.alibaba.druid.mock.MockConnection;
import com.alibaba.druid.mock.MockConnectionClosedException;
public abstract class StatementBase implements Statement {
private Connection connection;
private int fetchDirection;
private int fetchSize;
private int resultSetType;
private int resultSetConcurrency;
private int resultSetHoldability;
private int maxFieldSize;
private int maxRows;
private int queryTimeout;
private boolean escapeProcessing;
private String cursorName;
private SQLWarning warnings;
private int updateCount;
protected boolean closed = false;
private boolean poolable;
private Connection connection;
private int fetchDirection;
private int fetchSize;
private int resultSetType;
private int resultSetConcurrency;
private int resultSetHoldability;
private int maxFieldSize;
private int maxRows;
private int queryTimeout;
private boolean escapeProcessing;
private String cursorName;
private SQLWarning warnings;
private int updateCount;
protected boolean closed = false;
private boolean poolable;
protected ResultSet generatedKeys;
protected ResultSet resultSet;
protected ResultSet generatedKeys;
protected ResultSet resultSet;
public StatementBase(Connection connection){
super();
@@ -62,9 +63,13 @@ public abstract class StatementBase implements Statement {
if (closed) {
throw new SQLException();
}
if (this.connection != null && this.connection.isClosed()) {
throw new MockConnectionClosedException();
if (this.connection != null) {
if (this.connection instanceof MockConnection) {
((MockConnection) this.connection).checkState();
} else if (this.connection.isClosed()) {
throw new MockConnectionClosedException();
}
}
}