package org.opensource.clearpool.datasource.proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.Map;
import java.util.WeakHashMap;
import javax.sql.XAConnection;
import org.opensource.clearpool.configuration.ConfigurationVO;
import org.opensource.clearpool.core.ConnectionPoolManager;
import org.opensource.clearpool.datasource.connection.CommonConnection;
import org.opensource.clearpool.exception.ConnectionPoolException;
import org.opensource.clearpool.logging.PoolLogger;
import org.opensource.clearpool.logging.PoolLoggerFactory;
/**
* This class is the proxy of connection.
*
* @author xionghui
* @date 26.07.2014
* @version 1.0
*/
public class ConnectionProxy implements Comparable<ConnectionProxy> {
private static final PoolLogger LOGGER = PoolLoggerFactory.getLogger(ConnectionProxy.class);
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
private final ConnectionPoolManager pool;
private final Connection connection;
private final XAConnection xaConnection;
private Map<String, Object> sqlMap = new WeakHashMap<String, Object>();
private int sqlCount;
boolean autoCommit;
String catalog;
int holdability;
boolean readOnly;
int transactionIsolation;
boolean newAutoCommit;
String newCatalog;
int newHoldability;
boolean newReadOnly;
int newTransactionIsolation;
Savepoint savepoint;
public ConnectionProxy(ConnectionPoolManager pool, CommonConnection cmnCon) {
this.pool = pool;
connection = cmnCon.getConnection();
xaConnection = cmnCon.getXAConnection();
this.saveValue();
}
/**
* Save the value which may changed after using.
*/
private void saveValue() {
try {
newAutoCommit = autoCommit = connection.getAutoCommit();
newCatalog = catalog = connection.getCatalog();
newHoldability = holdability = connection.getHoldability();
newReadOnly = readOnly = connection.isReadOnly();
newTransactionIsolation = transactionIsolation = connection.getTransactionIsolation();
} catch (SQLException e) {
LOGGER.error("it calls a exception when we saveValue: ", e);
throw new ConnectionPoolException(e);
}
}
/**
* Reset the value which had been changed.
*/
void reset() throws SQLException {
boolean autoCommit = connection.getAutoCommit();
if (!autoCommit) {
// we have to roll back commit before we return connection to
// the pool
connection.rollback();
}
if (newAutoCommit != this.autoCommit) {
connection.setAutoCommit(this.autoCommit);
}
if (newCatalog != catalog) {
connection.setCatalog(catalog);
}
if (newHoldability != holdability) {
connection.setHoldability(holdability);
}
if (newReadOnly != readOnly) {
connection.setReadOnly(readOnly);
}
if (newTransactionIsolation != transactionIsolation) {
connection.setTransactionIsolation(transactionIsolation);
}
if (savepoint != null) {
connection.releaseSavepoint(savepoint);
}
// clear warnings before return connection to pool
connection.clearWarnings();
}
public Connection getConnection() {
return connection;
}
public XAConnection getXaConnection() {
return xaConnection;
}
/**
* Return connection to the pool.
*/
public void close() {
try {
// reset it
this.reset();
} catch (SQLException e) {
LOGGER.error("it calls a exception when we reset the connection: ", e);
this.reallyClose();
return;
}
pool.entryPool(this);
}
/**
* Really close the connection.
*/
private void reallyClose() {
// close connection
pool.closeConnection(this);
pool.decrementPoolSize();
pool.incrementOneConnection();
}
public ConfigurationVO getCfgVO() {
return pool.getCfgVO();
}
/**
* deal if we need to increment {@link #sqlCount};
*
* @param sql
*/
public void dealSqlCount(String sql) {
if (sqlMap.put(sql, PRESENT) == null) {
int count = sqlCount;
count++;
// in case sqlCount be negative
if (count > 0) {
sqlCount = count;
}
}
}
@Override
public int compareTo(ConnectionProxy anoConnProxy) {
int x = sqlCount;
int y = anoConnProxy.sqlCount;
return x < y ? -1 : x == y ? 0 : 1;
}
}