📄 simpledatasource.java
字号:
*/
public long getAverageRequestTime() {
synchronized (POOL_LOCK) {
return requestCount == 0 ? 0 : accumulatedRequestTime / requestCount;
}
}
/**
* Getter for the average time spent waiting for connections that were in use
* @return The average time
*/
public long getAverageWaitTime() {
synchronized (POOL_LOCK) {
return hadToWaitCount == 0 ? 0 : accumulatedWaitTime / hadToWaitCount;
}
}
/**
* Getter for the number of requests that had to wait for connections that were in use
* @return The number of requests that had to wait
*/
public long getHadToWaitCount() {
synchronized (POOL_LOCK) {
return hadToWaitCount;
}
}
/**
* Getter for the number of invalid connections that were found in the pool
* @return The number of invalid connections
*/
public long getBadConnectionCount() {
synchronized (POOL_LOCK) {
return badConnectionCount;
}
}
/**
* Getter for the number of connections that were claimed before they were returned
* @return The number of connections
*/
public long getClaimedOverdueConnectionCount() {
synchronized (POOL_LOCK) {
return claimedOverdueConnectionCount;
}
}
/**
* Getter for the average age of overdue connections
* @return The average age
*/
public long getAverageOverdueCheckoutTime() {
synchronized (POOL_LOCK) {
return claimedOverdueConnectionCount == 0 ? 0 : accumulatedCheckoutTimeOfOverdueConnections / claimedOverdueConnectionCount;
}
}
/**
* Getter for the average age of a connection checkout
* @return The average age
*/
public long getAverageCheckoutTime() {
synchronized (POOL_LOCK) {
return requestCount == 0 ? 0 : accumulatedCheckoutTime / requestCount;
}
}
/**
* Returns the status of the connection pool
* @return The status
*/
public String getStatus() {
StringBuffer buffer = new StringBuffer();
buffer.append("\n===============================================================");
buffer.append("\n jdbcDriver ").append(jdbcDriver);
buffer.append("\n jdbcUrl ").append(jdbcUrl);
buffer.append("\n jdbcUsername ").append(jdbcUsername);
buffer.append("\n jdbcPassword ").append((jdbcPassword == null ? "NULL" : "************"));
buffer.append("\n poolMaxActiveConnections ").append(poolMaximumActiveConnections);
buffer.append("\n poolMaxIdleConnections ").append(poolMaximumIdleConnections);
buffer.append("\n poolMaxCheckoutTime " + poolMaximumCheckoutTime);
buffer.append("\n poolTimeToWait " + poolTimeToWait);
buffer.append("\n poolPingEnabled " + poolPingEnabled);
buffer.append("\n poolPingQuery " + poolPingQuery);
buffer.append("\n poolPingConnectionsOlderThan " + poolPingConnectionsOlderThan);
buffer.append("\n poolPingConnectionsNotUsedFor " + poolPingConnectionsNotUsedFor);
buffer.append("\n --------------------------------------------------------------");
buffer.append("\n activeConnections " + activeConnections.size());
buffer.append("\n idleConnections " + idleConnections.size());
buffer.append("\n requestCount " + getRequestCount());
buffer.append("\n averageRequestTime " + getAverageRequestTime());
buffer.append("\n averageCheckoutTime " + getAverageCheckoutTime());
buffer.append("\n claimedOverdue " + getClaimedOverdueConnectionCount());
buffer.append("\n averageOverdueCheckoutTime " + getAverageOverdueCheckoutTime());
buffer.append("\n hadToWait " + getHadToWaitCount());
buffer.append("\n averageWaitTime " + getAverageWaitTime());
buffer.append("\n badConnectionCount " + getBadConnectionCount());
buffer.append("\n===============================================================");
return buffer.toString();
}
/**
* Closes all of the connections in the pool
*/
public void forceCloseAll() {
synchronized (POOL_LOCK) {
for (int i = activeConnections.size(); i > 0; i--) {
try {
SimplePooledConnection conn = (SimplePooledConnection) activeConnections.remove(i - 1);
conn.invalidate();
Connection realConn = conn.getRealConnection();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
realConn.close();
} catch (Exception e) {
// ignore
}
}
for (int i = idleConnections.size(); i > 0; i--) {
try {
SimplePooledConnection conn = (SimplePooledConnection) idleConnections.remove(i - 1);
conn.invalidate();
Connection realConn = conn.getRealConnection();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
realConn.close();
} catch (Exception e) {
// ignore
}
}
}
if (log.isDebugEnabled()) {
log.debug("SimpleDataSource forcefully closed/removed all connections.");
}
}
private void pushConnection(SimplePooledConnection conn)
throws SQLException {
synchronized (POOL_LOCK) {
activeConnections.remove(conn);
if (conn.isValid()) {
if (idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == getExpectedConnectionTypeCode()) {
accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
SimplePooledConnection newConn = new SimplePooledConnection(conn.getRealConnection(), this);
idleConnections.add(newConn);
newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
}
POOL_LOCK.notifyAll();
} else {
accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.getRealConnection().close();
if (log.isDebugEnabled()) {
log.debug("Closed connection " + conn.getRealHashCode() + ".");
}
conn.invalidate();
}
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
}
badConnectionCount++;
}
}
}
private SimplePooledConnection popConnection(String username, String password)
throws SQLException {
boolean countedWait = false;
SimplePooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
while (conn == null) {
synchronized (POOL_LOCK) {
if (idleConnections.size() > 0) {
// Pool has available connection
conn = (SimplePooledConnection) idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else {
// Pool does not have available connection
if (activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
if (useDriverProps) {
conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, driverProps), this);
} else {
conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword), this);
}
Connection realConn = conn.getRealConnection();
if (realConn.getAutoCommit() != jdbcDefaultAutoCommit) {
realConn.setAutoCommit(jdbcDefaultAutoCommit);
}
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
// Cannot create new connection
SimplePooledConnection oldestActiveConnection = (SimplePooledConnection) activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
claimedOverdueConnectionCount++;
accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
accumulatedCheckoutTime += longestCheckoutTime;
activeConnections.remove(oldestActiveConnection);
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
oldestActiveConnection.getRealConnection().rollback();
}
conn = new SimplePooledConnection(oldestActiveConnection.getRealConnection(), this);
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
// Must wait
try {
if (!countedWait) {
hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
POOL_LOCK.wait(poolTimeToWait);
accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
if (conn != null) {
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(assembleConnectionTypeCode(jdbcUrl, username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
activeConnections.add(conn);
requestCount++;
accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
if (log.isDebugEnabled()) {
log.debug("SimpleDataSource: Could not get a good connection to the database.");
}
throw new SQLException("SimpleDataSource: Could not get a good connection to the database.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
throw new SQLException("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
return conn;
}
/**
* Method to check to see if a connection is still usable
*
* @param conn - the connection to check
* @return True if the connection is still usable
*/
private boolean pingConnection(SimplePooledConnection conn) {
boolean result = true;
try {
result = !conn.getRealConnection().isClosed();
} catch (SQLException e) {
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
}
result = false;
}
if (result) {
if (poolPingEnabled) {
if ((poolPingConnectionsOlderThan > 0 && conn.getAge() > poolPingConnectionsOlderThan)
|| (poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor)) {
try {
if (log.isDebugEnabled()) {
log.debug("Testing connection " + conn.getRealHashCode() + " ...");
}
Connection realConn = conn.getRealConnection();
Statement statement = realConn.createStatement();
ResultSet rs = statement.executeQuery(poolPingQuery);
rs.close();
statement.close();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
result = true;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
}
} catch (Exception e) {
log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());
try {
conn.getRealConnection().close();
} catch (Exception e2) {
//ignore
}
result = false;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
}
}
}
}
}
return result;
}
/**
* Unwraps a pooled connection to get to the 'real' connection
*
* @param conn - the pooled connection to unwrap
* @return The 'real' connection
*/
public static Connection unwrapConnection(Connection conn) {
if (conn instanceof SimplePooledConnection) {
return ((SimplePooledConnection) conn).getRealConnection();
} else {
return conn;
}
}
protected void finalize() throws Throwable {
forceCloseAll();
}
/**
* ---------------------------------------------------------------------------------------
* SimplePooledConnection
* ---------------------------------------------------------------------------------------
*/
private static class SimplePooledConnection implements InvocationHandler {
private static final String CLOSE = "close";
private static final Class[] IFACES = new Class[]{Connection.class};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -