//文件:dbconnectiondefaultpool.java的第三部分
/**
* 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];
}
private void createconn(int i) throws sqlexception {
date now = new date();
try {
class.forname (dbdriver);
properties dbprop = new properties();
//log.println("creating…..");
dbprop.put("user", dblogin);
dbprop.put("password", dbpassword);
dbprop.put("characterencoding","gb2112");
//dbprop.put("useunicode", "true");
connpool[i] = drivermanager.getconnection
(dbserver,dbprop);
//log.println("created ok…");
connstatus[i]=0;
connid[i]=connpool[i].tostring();
connlocktime[i]=0;
conncreatedate[i] = now.gettime();
}
catch (classnotfoundexception e2) {}
log.println(now.tostring() + " opening connection " + string.valueof(i) +
" " + connpool[i].tostring() + ":");
}
/**
* 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()
}
/**
* 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 implements connection {
private connection connection;
private connectionpool connectionpool;
public connectionwrapper(connection connection, connectionpool connectionpool) {
this.connection = 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 statement createstatement() throws sqlexception {
return connection.createstatement();
}
public preparedstatement preparestatement(string sql) throws sqlexception {
return connection.preparestatement(sql);
}
public callablestatement preparecall(string sql) throws sqlexception {
return connection.preparecall(sql);
}
public string nativesql(string sql) throws sqlexception {
return connection.nativesql(sql);
}
public void setautocommit(boolean autocommit) throws sqlexception {
connection.setautocommit(autocommit);
}
public boolean getautocommit() throws sqlexception {
return connection.getautocommit();
}
public void commit() throws sqlexception {
connection.commit();
}
public void rollback() throws sqlexception {
connection.rollback();
}
public boolean isclosed() throws sqlexception {
return connection.isclosed();
}
public databasemetadata getmetadata() throws sqlexception {
return connection.getmetadata();
}
public void setreadonly(boolean readonly) throws sqlexception {
connection.setreadonly(readonly);
}
public boolean isreadonly() throws sqlexception {
return connection.isreadonly();
}
public void setcatalog(string catalog) throws sqlexception {
connection.setcatalog(catalog);
}
public string getcatalog() throws sqlexception {
return connection.getcatalog();
}
public void settransactionisolation(int level) throws sqlexception {
connection.settransactionisolation(level);
}
public int gettransactionisolation() throws sqlexception {
return connection.gettransactionisolation();
}
public sqlwarning getwarnings() throws sqlexception {
return connection.getwarnings();
}
public void clearwarnings() throws sqlexception {
connection.clearwarnings();
}
public statement createstatement(int resultsettype, int resultsetconcurrency)
throws sqlexception
{
return connection.createstatement(resultsettype, resultsetconcurrency);
}
public preparedstatement preparestatement(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return connection.preparestatement(sql, resultsettype, resultsetconcurrency);
}
public callablestatement preparecall(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return preparecall(sql, resultsettype, resultsetconcurrency);
}
public map gettypemap() throws sqlexception {
return connection.gettypemap();
}
public void settypemap(map map) throws sqlexception {
connection.settypemap(map);
}
}
}
