//文件:dbconnectiondefaultpool.java的第二部分
/**
* housekeeping thread. runs in the background with low cpu overhead.
* connections are checked for warnings and closure and are periodically
* restarted.
* this thread is a catchall for corrupted
* connections and prevents the buildup of open cursors. (open cursors
* result when the application fails to close a statement).
* this method acts as fault tolerance for bad connection/statement programming.
*/
public void run() {
boolean forever = true;
statement stmt=null;
string currcatalog=null;
while(forever) {
// make sure the log file is the one this instance opened
// if not, clean it up!
try {
bufferedreader in = new bufferedreader(new
filereader(logfilestring + "pid"));
string curr_pid = in.readline();
if(curr_pid.equals(pid)) {
//log.println("they match = " + curr_pid);
}
else {
//log.println("no match = " + curr_pid);
log.close();
// close all connections silently – they are definitely dead.
for(int i=0; i < currconnections; i++) {
try {
connpool[i].close();
}
catch (sqlexception e1) {} // ignore
}
// returning from the run() method kills the thread
return;
}
in.close();
}
catch (ioexception e1) {
log.println("cant read the file for pid info: " +
logfilestring + "pid");
}
// get any warnings on connections and print to event file
for(int i=0; i < currconnections; i++) {
try {
currsqlwarning = connpool[i].getwarnings();
if(currsqlwarning != null) {
log.println("warnings on connection " +
string.valueof(i) + " " + currsqlwarning);
connpool[i].clearwarnings();
}
}
catch(sqlexception e) {
log.println("cannot access warnings: " + e);
}
}
for(int i=0; i < currconnections; i++) { // do for each connection
long age = system.currenttimemillis() – conncreatedate[i];
synchronized(connstatus) {
if(connstatus[i] > 0) { // in use, catch it next time!
continue;
}
connstatus[i] = 2; // take offline (2 indicates housekeeping lock)
}
try { // test the connection with createstatement call
if(age > maxconnmsec) { // force a reset at the max conn time
throw new sqlexception();
}
stmt = connpool[i].createstatement();
connstatus[i] = 0; // connection is o.k.
//log.println("connection confirmed for conn = " +
// string.valueof(i));
// some dbs return an object even if db is shut down
if(connpool[i].isclosed()) {
throw new sqlexception();
}
// connection has a problem, restart it
}
catch(sqlexception e) {
try {
log.println(new date().tostring() +
" ***** recycling connection " +
string.valueof(i) + ":");
connpool[i].close();
createconn(i);
}
catch(sqlexception e1) {
log.println("failed: " + e1);
connstatus[i] = 0; // cant open, try again next time
}
}
finally {
try {
if(stmt != null) {
stmt.close();
}
}
catch(sqlexception e1){};
}
}
try {
thread.sleep(20000);
} // wait 20 seconds for next cycle
catch(interruptedexception e) {
// returning from the run method sets the internal
// flag referenced by thread.isalive() to false.
// this is required because we dont use stop() to
// shutdown this thread.
return;
}
}
} // end run
/**
* this method hands out the connections in round-robin order.
* this prevents a faulty connection from locking
* up an application entirely. a browser refresh will
* get the next connection while the faulty
* connection is cleaned up by the housekeeping thread.
*
* if the min number of threads are ever exhausted, new
* threads are added up the the max thread count.
* finally, if all threads are in use, this method waits
* 2 seconds and tries again, up to ten times. after that, it
* returns a null.
*/
public connection getconnection() {
connection conn=null;
if(available){
boolean gotone = false;
for(int outerloop=1; outerloop<=10; outerloop++) {
try {
int loop=0;
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 = 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 string freeconnection(connection conn) {
string res="";
int thisconn = idofconnection(conn);
if(thisconn >= 0) {
connstatus[thisconn]=0;
res = "freed " + conn.tostring();
//log.println("freed connection " + string.valueof(thisconn) +
// " normal exit: ");
}
else {
log.println("—-> could not free connection!!!");
}
return res;
}
