📄 defaultconnectionprovider.java
字号:
int roundRobin = connLast + 1;
if(roundRobin >= currConnections) roundRobin=0;
do {
synchronized(connStatus) {
if((connStatus[roundRobin] < 1) &&
(! connPool[roundRobin].isClosed()))
{
conn = connPool[roundRobin];
connStatus[roundRobin]=1;
connLockTime[roundRobin] =
System.currentTimeMillis();
connLast = roundRobin;
gotOne = true;
break;
}
else {
loop++;
roundRobin++;
if(roundRobin >= currConnections) roundRobin=0;
}
}
}
while((gotOne==false) && (loop < currConnections));
}
catch (SQLException e1) {}
if(gotOne) {
break;
}
else {
synchronized(this) { // Add new connections to the pool
if(currConnections < maxConns) {
try {
createConn(currConnections);
currConnections++;
}
catch(SQLException e) {
log.println("Unable to create new connection: " + e);
}
}
}
try { Thread.sleep(2000); }
catch(InterruptedException e) {}
log.println("-----> Connections Exhausted! Will wait and try " +
"again in loop " + String.valueOf(outerloop));
}
} // End of try 10 times loop
}
else {
log.println("Unsuccessful getConnection() request during destroy()");
} // End if(available)
return conn;
}
/**
* Returns the local JDBC ID for a connection.
*/
public int idOfConnection(Connection conn) {
int match;
String tag;
try {
tag = String.valueOf(this.getConnectionHash(conn));
//tag = conn.toString();
}
catch (NullPointerException e1) {
tag = "none";
}
match=-1;
for(int i=0; i< currConnections; i++) {
if(connID[i].equals(tag)) {
match = i;
break;
}
}
return match;
}
/**
* Frees a connection. Replaces connection back into the main pool for
* reuse.
*/
public void freeConnection(Connection conn) {
int thisconn = idOfConnection(conn);
if(thisconn >= 0) {
connStatus[thisconn]=0;
}
else {
log.println("----> Could not free connection!!!");
}
}
/**
* Returns the age of a connection -- the time since it was handed out to
* an application.
*/
public long getAge(Connection conn) { // Returns the age of the connection in millisec.
int thisconn = idOfConnection(conn);
return System.currentTimeMillis() - connLockTime[thisconn];
}
/**
* Returns the same hashcode for the given object as would be returned
* by the default method hashCode(), whether or not the given object's
* class overrides hashCode().
* The hashcode for the null reference is zero.
*/
private int getConnectionHash(Connection con) {
// Use of System.identifyHashCode() gets the base (java.lang.Object)
// version of the hashCode. If the Connection implementations has
// provided it's own hashCode method, it will not be used
return System.identityHashCode(con);
}
private void createConn(int i) throws SQLException {
Date now = new Date();
try {
Class.forName(dbDriver);
connPool[i] = DriverManager.getConnection(dbServer,dbLogin,dbPassword);
connStatus[i] = 0;
connID[i] = String.valueOf(getConnectionHash(connPool[i]));
connLockTime[i] = 0;
connCreateDate[i] = now.getTime();
log.println(now.toString() + " Opening connection " + String.valueOf(i) +
" " + connPool[i].toString() + ":");
}
catch (ClassNotFoundException e2) {
e2.printStackTrace();
throw new SQLException(e2.getMessage());
}
}
/**
* Shuts down the housekeeping thread and closes all connections
* in the pool. Call this method from the destroy() method of the servlet.
*/
/**
* Multi-phase shutdown. having following sequence:
* <OL>
* <LI><code>getConnection()</code> will refuse to return connections.
* <LI>The housekeeping thread is shut down.<br>
* Up to the time of <code>millis</code> milliseconds after shutdown of
* the housekeeping thread, <code>freeConnection()</code> can still be
* called to return used connections.
* <LI>After <code>millis</code> milliseconds after the shutdown of the
* housekeeping thread, all connections in the pool are closed.
* <LI>If any connections were in use while being closed then a
* <code>SQLException</code> is thrown.
* <LI>The log is closed.
* </OL><br>
* Call this method from a servlet destroy() method.
*
* @param millis the time to wait in milliseconds.
* @exception SQLException if connections were in use after
* <code>millis</code>.
*/
public void destroy(int millis) throws SQLException {
// Checking for invalid negative arguments is not necessary,
// Thread.join() does this already in runner.join().
// Stop issuing connections
available=false;
// Shut down the background housekeeping thread
runner.interrupt();
// Wait until the housekeeping thread has died.
try { runner.join(millis); }
catch(InterruptedException e){} // ignore
// The housekeeping thread could still be running
// (e.g. if millis is too small). This case is ignored.
// At worst, this method will throw an exception with the
// clear indication that the timeout was too short.
long startTime=System.currentTimeMillis();
// Wait for freeConnection() to return any connections
// that are still used at this time.
int useCount;
while((useCount=getUseCount())>0 && System.currentTimeMillis() -
startTime <= millis)
{
try { Thread.sleep(500); }
catch(InterruptedException e) {} // ignore
}
// Close all connections, whether safe or not
for(int i=0; i < currConnections; i++) {
try {
connPool[i].close();
}
catch (SQLException e1)
{
log.println("Cannot close connections on Destroy");
}
}
if(useCount > 0) {
//bt-test successful
String msg="Unsafe shutdown: Had to close "+useCount+
" active DB connections after "+millis+"ms";
log.println(msg);
// Close all open files
log.close();
// Throwing following Exception is essential because servlet authors
// are likely to have their own error logging requirements.
throw new SQLException(msg);
}
// Close all open files
log.close();
}//End destroy()
/**
* Less safe shutdown. Uses default timeout value.
* This method simply calls the <code>destroy()</code> method
* with a <code>millis</code>
* value of 10000 (10 seconds) and ignores <code>SQLException</code>
* thrown by that method.
* @see #destroy(int)
*/
public void destroy() {
try {
destroy(10000);
}
catch(SQLException e) {}
}
/**
* Returns the number of connections in use.
*/
// This method could be reduced to return a counter that is
// maintained by all methods that update connStatus.
// However, it is more efficient to do it this way because:
// Updating the counter would put an additional burden on the most
// frequently used methods; in comparison, this method is
// rarely used (although essential).
public int getUseCount() {
int useCount=0;
synchronized(connStatus) {
for(int i=0; i < currConnections; i++) {
if(connStatus[i] > 0) { // In use
useCount++;
}
}
}
return useCount;
}//End getUseCount()
/**
* Returns the number of connections in the dynamic pool.
*/
public int getSize() {
return currConnections;
}//End getSize()
} // End class
/**
* An implementation of the Connection interface that wraps an underlying
* Connection object. It releases the connection back to a connection pool
* when Connection.close() is called.
*/
public class ConnectionWrapper extends ConnectionAdapter {
private ConnectionPool connectionPool;
public ConnectionWrapper(Connection connection, ConnectionPool connectionPool) {
super(connection);
this.connectionPool = connectionPool;
}
/**
* Instead of closing the underlying connection, we simply release
* it back into the pool.
*/
public void close() throws SQLException {
connectionPool.freeConnection(this.connection);
//Release object references. Any further method calls on the
//connection will fail.
connection = null;
connectionPool = null;
}
public String toString() {
if (connection != null) {
return connection.toString();
}
else {
return "Jive Software Cnnection Wrapper";
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -