danny 2002/06/20 15:04:14
Modified: src/java/org/apache/james/util/mordred JdbcDataSource.java
Log:
and now with pretty printing...
Revision Changes Path
1.8 +297 -338
jakarta-james/src/java/org/apache/james/util/mordred/JdbcDataSource.java
Index: JdbcDataSource.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/util/mordred/JdbcDataSource.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- JdbcDataSource.java 20 Jun 2002 21:55:17 -0000 1.7
+++ JdbcDataSource.java 20 Jun 2002 22:04:14 -0000 1.8
@@ -7,6 +7,14 @@
*/
package org.apache.james.util.mordred;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import java.util.Vector;
+
import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.configuration.Configurable;
@@ -14,20 +22,17 @@
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Vector;
/**
- * <p>This is a <b>reliable</b> DataSource implementation, based on the pooling
- * logic written for <a href="http://share.whichever.com/">Town</a> and the
- * configuration found in Avalon's excalibur code.
+ * <p>
+ * This is a <b>reliable</b> DataSource implementation, based on the pooling logic
written for <a
+ * href="http://share.whichever.com/">Town</a> and the configuration found in
Avalon's excalibur
+ * code.
* </p>
- * <p>This uses the normal <code>java.sql.Connection</code> object and
- * <code>java.sql.DriverManager</code>. The Configuration is like this:
*
+ * <p>
+ * This uses the normal <code>java.sql.Connection</code> object and
+ * <code>java.sql.DriverManager</code>. The Configuration is like this:
* <pre>
* <jdbc>
* <pool-controller min="<i>5</i>" max="<i>10</i>"
connection-class="<i>my.overrided.ConnectionClass</i>">
@@ -39,232 +44,246 @@
* <password><i>password</i></password>
* </jdbc>
* </pre>
+ * </p>
*
- * @author <a href="mailto:[EMAIL PROTECTED]">Serge Knystautas</a>
* @version CVS $Revision$ $Date$
+ * @author <a href="mailto:[EMAIL PROTECTED]">Serge Knystautas</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Danny Angus</a>
* @since 4.0
*/
-public class JdbcDataSource
- extends AbstractLogEnabled implements Configurable, Runnable, Disposable,
DataSourceComponent
-{
- private static final boolean DEEP_DEBUG = false;
+public class JdbcDataSource extends AbstractLogEnabled
+ implements Configurable,
+ Runnable,
+ Disposable,
+ DataSourceComponent {
+ // The limit that an active connection can be running
+ public static final long ACTIVE_CONN_TIME_LIMIT = 60000; // (one minute)
+ // How long before you kill off a connection due to inactivity
+ public static final long CONN_IDLE_LIMIT = 600000; // (10 minutes)
+ private static final boolean DEEP_DEBUG = false;
+ private static int total_served = 0;
+ // This is a temporary variable used to track how many active threads
+ // are in createConnection(). This is to prevent to many connections
+ // from being opened at once.
+ private int connCreationsInProgress = 0;
+ // The error message is the conn pooler cannot serve connections for whatever
reason
+ private String connErrorMessage = null;
+ // the last time a connection was created...
+ private long connLastCreated = 0;
+ // connection number for like of this broker
+ private int connectionCount;
+ // Driver class
+ private String jdbcDriver;
+ // Password to login to database
+ private String jdbcPassword;
+ // Server to connect to database (this really is the jdbc URL)
+ private String jdbcURL;
+ // Username to login to database
+ private String jdbcUsername;
+ // Maximum number of connections to have open at any point
+ private int maxConn = 0;
+ // collection of connection objects
+ private Vector pool;
+ // Thread that checks for dead/aged connections and removes them from pool
+ private Thread reaper;
+ // Flag to indicate whether reaper thread should run
+ private boolean reaperActive = false;
+ // a SQL command to execute to see if the connection is still ok
+ private String verifyConnSQL;
+
/**
- * Configure and set up DB connection. Here we set the connection
- * information needed to create the Connection objects.
+ * Implements the ConnDefinition behavior when a connection is needed. Checks
the pool of
+ * connections to see if there is one available. If there is not and we are
below the max
+ * number of connections limit, it tries to create another connection. It
retries this 10
+ * times until a connection is available or can be created
*
- * @param conf The Configuration object needed to describe the
- * connection.
+ * @return java.sql.Connection
+ * @throws SQLException Document throws!
+ */
+ public Connection getConnection() throws SQLException {
+ //If the conn definition has a fatal connection problem, need to return
that error
+ if(connErrorMessage != null) {
+ throw new SQLException(connErrorMessage);
+ }
+ //Look through our list of open connections right now, starting from
beginning.
+ //If we find one, book it.
+ int count = total_served++;
+ if(DEEP_DEBUG) {
+ System.out.println(new java.util.Date() + " trying to get a connection
(" + count +
+ ")");
+ }
+ for(int attempts = 1; attempts <= 100; attempts++) {
+ synchronized(pool) {
+ for(int i = 0; i < pool.size(); i++) {
+ PoolConnEntry entry = (PoolConnEntry)pool.elementAt(i);
+ //Set the appropriate flags to make this connection
+ //marked as in use
+ try {
+ if(entry.lock()) {
+ if(DEEP_DEBUG) {
+ System.out.println(
+ new java.util.Date() + " return a
connection (" + count +
+ ")");
+ }
+ return entry;
+ }
+ } catch(SQLException se) {
+ //Somehow a closed connection appeared in our pool.
+ //Remove it immediately.
+ finalizeEntry(entry);
+ continue;
+ }
+ //we were unable to get a lock on this entry.. so continue
through list
+ } //loop through existing connections
+ }
+ //If we have 0, create another
+ if(DEEP_DEBUG) {
+ System.out.println(pool.size());
+ }
+ try {
+ if(pool.size() == 0) {
+ //create a connection
+ PoolConnEntry entry = createConn();
+ if(entry != null) {
+ if(DEEP_DEBUG) {
+ System.out.println(
+ new java.util.Date() + " returning new
connection (" + count +
+ ")");
+ }
+ return entry;
+ }
+ //looks like a connection was already created
+ } else {
+ //Since we didn't find one, and we have < max connections, then
consider whether
+ // we create another
+ //if we've hit the 3rd attempt without getting a connection,
+ // let's create another to anticipate a slow down
+ if((attempts == 2) && (pool.size() < maxConn || maxConn == 0)) {
+ PoolConnEntry entry = createConn();
+ if(entry != null) {
+ if(DEEP_DEBUG) {
+ System.out.println(" returning new connection (" +
count + "(");
+ }
+ return entry;
+ } else {
+ attempts = 1;
+ }
+ }
+ }
+ } catch(SQLException sqle) {
+ //Ignore... error creating the connection
+ StringWriter sout = new StringWriter();
+ PrintWriter pout = new PrintWriter(sout, true);
+ pout.println("Error creating connection: ");
+ sqle.printStackTrace(pout);
+ getLogger().error(sout.toString());
+ }
+ //otherwise sleep 50ms 10 times, then create a connection
+ try {
+ Thread.currentThread().sleep(50);
+ } catch(InterruptedException ie) {
+ }
+ }
+ // Give up... no connections available
+ throw new SQLException("Giving up... no connections available.");
+ }
+
+ /**
+ * Configure and set up DB connection. Here we set the connection information
needed to create
+ * the Connection objects.
*
+ * @param configuration The Configuration object needed to describe the
connection.
* @throws ConfigurationException
*/
- public void configure( final Configuration configuration )
- throws ConfigurationException
- {
+ public void configure(final Configuration configuration)
+ throws ConfigurationException {
try {
- jdbcDriver = configuration.getChild("driver").getValue(null);
- jdbcURL = configuration.getChild("dburl").getValue(null);
- jdbcUsername = configuration.getChild("user").getValue(null);
- jdbcPassword = configuration.getChild("password").getValue(null);
-
- maxConn = configuration.getChild("max").getValueAsInteger(2);
+ jdbcDriver = configuration.getChild("driver").getValue(null);
+ jdbcURL = configuration.getChild("dburl").getValue(null);
+ jdbcUsername = configuration.getChild("user").getValue(null);
+ jdbcPassword = configuration.getChild("password").getValue(null);
+ maxConn = configuration.getChild("max").getValueAsInteger(2);
//logfilename?
verifyConnSQL = configuration.getChild("keep-alive").getValue(null);
-
//Not support from Town: logfilename
-
//Not supporting from Excalibur: pool-controller, min, auto-commit,
oradb, connection-class
-
- if (jdbcDriver == null) {
+ if(jdbcDriver == null) {
throw new ConfigurationException("You need to specify a valid
driver, e.g., <driver>my.class</driver>");
}
-
try {
getLogger().debug("Loading new driver: " + jdbcDriver);
Class.forName(jdbcDriver, true,
Thread.currentThread().getContextClassLoader());
- } catch (ClassNotFoundException cnfe) {
- throw new ConfigurationException("'" + jdbcDriver + "' could not be
found in classloader. Please specify a valid JDBC driver");
+ } catch(ClassNotFoundException cnfe) {
+ throw new ConfigurationException("'" + jdbcDriver +
+ "' could not be found in
classloader. Please specify a valid JDBC driver");
}
-
- if (jdbcURL == null) {
+ if(jdbcURL == null) {
throw new ConfigurationException("You need to specify a valid JDBC
connection string, e.g., <dburl>jdbc:driver:database</dburl>");
}
-
- if (maxConn < 0) {
+ if(maxConn < 0) {
throw new ConfigurationException("Maximum number of connections
specified must be at least 1 (0 means no limit).");
}
-
getLogger().debug("Starting connection pooler");
getLogger().debug("driver = " + jdbcDriver);
getLogger().debug("dburl = " + jdbcURL);
getLogger().debug("username = " + jdbcUsername);
//We don't show the password
getLogger().debug("max connections = " + maxConn);
-
- pool = new Vector();
+ pool = new Vector();
reaperActive = true;
- reaper = new Thread(this);
-
+ reaper = new Thread(this);
reaper.setDaemon(true);
reaper.start();
-
- } catch (ConfigurationException ce) {
+ } catch(ConfigurationException ce) {
//Let this pass through...
throw ce;
- } catch (Exception e) {
+ }
+ catch(Exception e) {
throw new ConfigurationException("Error configuring JdbcDataSource", e);
}
}
-
-
- private static int total_served = 0;
-
- // The limit that an active connection can be running
- public final static long ACTIVE_CONN_TIME_LIMIT = 60000; // (one minute)
-
- // How long before you kill off a connection due to inactivity
- public final static long CONN_IDLE_LIMIT = 600000; // (10 minutes)
-
- // Thread that checks for dead/aged connections and removes them from pool
- private Thread reaper;
-
- // Flag to indicate whether reaper thread should run
- private boolean reaperActive = false;
-
- // Driver class
- private String jdbcDriver;
-
- // Server to connect to database (this really is the jdbc URL)
- private String jdbcURL;
-
- // Username to login to database
- private String jdbcUsername;
-
- // Password to login to database
- private String jdbcPassword;
-
- // Maximum number of connections to have open at any point
- private int maxConn = 0;
-
- // collection of connection objects
- private Vector pool;
-
- // connection number for like of this broker
- private int connectionCount;
-
- // This is a temporary variable used to track how many active threads
- // are in createConnection(). This is to prevent to many connections
- // from being opened at once.
- private int connCreationsInProgress = 0;
-
- // the last time a connection was created...
- private long connLastCreated = 0;
-
- // a SQL command to execute to see if the connection is still ok
- private String verifyConnSQL;
-
- // The error message is the conn pooler cannot serve connections for whatever
reason
- private String connErrorMessage = null;
-
-
-
-
-
-
/**
- * Creates a new connection as per these properties, adds it to the pool,
- * and logs the creation.
- *
-
- * @return PoolConnEntry the new connection wrapped as an entry
- *
-
- * @throws SQLException
+ * Need to clean up all connections
*/
- private PoolConnEntry createConn() throws SQLException {
- PoolConnEntry entry = null;
-
- synchronized (this) {
- if (connCreationsInProgress > 0) {
- //We are already creating one in another place
- return null;
- }
-
- long now = System.currentTimeMillis();
- if (now - connLastCreated < 1000 * pool.size()) {
- //We don't want to scale up too quickly...
- if (DEEP_DEBUG) {
- System.err.println("We don't want to scale up too quickly");
- }
- return null;
- }
-
- if (maxConn == 0 || pool.size() < maxConn) {
- connCreationsInProgress++;
- connLastCreated = now;
- } else {
- // We've already hit a limit... fail silently
- getLogger().debug("Connection limit hit... " + pool.size() + " in
pool and " + connCreationsInProgress + " + on the way.");
- return null;
- }
- }
-
- try {
- entry = new PoolConnEntry(this,
- java.sql.DriverManager.getConnection(jdbcURL, jdbcUsername,
jdbcPassword),
- ++connectionCount);
- getLogger().debug("Opening connection " + entry);
- entry.lock();
- pool.addElement(entry);
- return entry;
- } catch (SQLException sqle) {
- //Shouldn't ever happen, but it did, just return null.
- return null;
- } finally {
- synchronized (this) {
- connCreationsInProgress--;
- }
-
+ public void dispose() {
+ // Stop the background monitoring thread
+ if(reaper != null) {
+ reaperActive = false;
+ //In case it's sleeping, help it quit faster
+ reaper.interrupt();
+ reaper = null;
}
+ // The various entries will finalize themselves once the reference
+ // is removed, so no need to do it here
}
/**
- * Implements the ConnDefinition behavior when a connection is no longer needed.
- * This resets flags on the wrapper of the connection to allow others to use
- * this connection.
+ * Close all connections. The connection pooler will recreate these
connections if something
+ * starts requesting them again.
*
-
- * @param java.sql.Connection
+ * @deprecated This was left over code from Town... but not exposed in Avalon.
*/
- public void releaseConnection(PoolConnEntry entry) {
- //PoolConnEntry entry = findEntry(conn);
-
- if (entry != null) {
- entry.unlock();
- return;
- } else {
- getLogger().warn("----> Could not find the connection to free!!!");
- return;
- }
+ public synchronized void killAllConnections() {
+ //Just remove the references to all the connections... this will cause them
to get
+ // finalized before very long. (not an instant shutdown, but that's ok).
+ pool.clear();
}
/**
- * Implements the ConnDefinition behavior when something bad has happened to
- * a connection.
- * If a sql command was provided in the properties file, it will run this and
- * attempt to determine whether the connection is still valid. If it is,
- * it recycles this connection back into the pool. If it is not, it closes
- * the connection.
- *
- * @param java.sql.Connection the connection that had problems
+ * Implements the ConnDefinition behavior when something bad has happened to a
connection. If a
+ * sql command was provided in the properties file, it will run this and
attempt to determine
+ * whether the connection is still valid. If it is, it recycles this
connection back into the
+ * pool. If it is not, it closes the connection.
*
+ * @param entry the connection that had problems
* @deprecated - No longer used in the new approach.
*/
public void killConnection(PoolConnEntry entry) {
- if (entry != null) {
+ if(entry != null) {
// if we were provided SQL to test the connection with, we will use
// this and possibly just release the connection after clearing warnings
- if (verifyConnSQL != null) {
+ if(verifyConnSQL != null) {
try {
// Test this connection
java.sql.Statement stmt = entry.createStatement();
@@ -272,15 +291,13 @@
stmt.close();
// Passed test... recycle the entry
entry.unlock();
- } catch (SQLException e1) {
+ } catch(SQLException e1) {
// Failed test... close the entry
finalizeEntry(entry);
-
}
} else {
// No SQL was provided... we have to kill this entry to be sure
finalizeEntry(entry);
-
}
return;
} else {
@@ -291,144 +308,44 @@
}
/**
- * Closes a connection and removes it from the pool.
- * @param PoolConnEntry entry
- */
- private synchronized void finalizeEntry(PoolConnEntry entry) {
- try{
- entry.finalize();
- }catch(Exception fe){
- }
- pool.removeElement(entry);
- }
-
- /**
- * Implements the ConnDefinition behavior when a connection is needed.
- * Checks the pool of connections to see if there is one available. If there
- * is not and we are below the max number of connections limit, it tries to
create
- * another connection. It retries this 10 times until a connection is
available or
- * can be created
+ * Implements the ConnDefinition behavior when a connection is no longer
needed. This resets
+ * flags on the wrapper of the connection to allow others to use this
connection.
*
- * @return java.sql.Connection
+ * @param entry
*/
- public Connection getConnection() throws SQLException {
- //If the conn definition has a fatal connection problem, need to return
that error
- if (connErrorMessage != null) {
- throw new SQLException(connErrorMessage);
- }
-
- //Look through our list of open connections right now, starting from
beginning.
-
- //If we find one, book it.
-
- int count = total_served++;
- if (DEEP_DEBUG) {
- System.out.println(new java.util.Date() + " trying to get a connection
(" + count + ")");
- }
- for (int attempts = 1; attempts <= 100; attempts++) {
- synchronized (pool) {
- for (int i = 0; i < pool.size(); i++) {
- PoolConnEntry entry = (PoolConnEntry) pool.elementAt(i);
- //Set the appropriate flags to make this connection
- //marked as in use
- try {
- if (entry.lock()) {
- if (DEEP_DEBUG) {
- System.out.println(new java.util.Date() + " return
a connection (" + count + ")");
- }
- return entry;
- }
- } catch (SQLException se) {
- //Somehow a closed connection appeared in our pool.
- //Remove it immediately.
- finalizeEntry(entry);
- continue;
- }
- //we were unable to get a lock on this entry.. so continue
through list
- } //loop through existing connections
- }
-
- //If we have 0, create another
- if (DEEP_DEBUG) {
- System.out.println(pool.size());
- }
- try {
- if (pool.size() == 0) {
- //create a connection
- PoolConnEntry entry = createConn();
- if (entry != null) {
- if (DEEP_DEBUG) {
- System.out.println(new java.util.Date() + " returning
new connection (" + count + ")");
- }
- return entry;
- }
- //looks like a connection was already created
- } else {
-
- //Since we didn't find one, and we have < max connections, then
consider whether
- // we create another
-
- //if we've hit the 3rd attempt without getting a connection,
- // let's create another to anticipate a slow down
- if (attempts == 2 && (pool.size() < maxConn || maxConn == 0)) {
- PoolConnEntry entry = createConn();
- if (entry != null) {
- if (DEEP_DEBUG) {
- System.out.println(" returning new connection (" +
count + "(");
- }
- return entry;
- } else {
- attempts = 1;
- }
- }
- }
- } catch (SQLException sqle) {
- //Ignore... error creating the connection
- StringWriter sout = new StringWriter();
- PrintWriter pout = new PrintWriter(sout, true);
- pout.println("Error creating connection: ");
- sqle.printStackTrace(pout);
- getLogger().error(sout.toString());
- }
-
- //otherwise sleep 50ms 10 times, then create a connection
- try {
- Thread.currentThread().sleep(50);
- } catch (InterruptedException ie) {
- }
+ public void releaseConnection(PoolConnEntry entry) {
+ //PoolConnEntry entry = findEntry(conn);
+ if(entry != null) {
+ entry.unlock();
+ return;
+ } else {
+ getLogger().warn("----> Could not find the connection to free!!!");
+ return;
}
-
- // Give up... no connections available
- throw new SQLException("Giving up... no connections available.");
}
/**
- * Background thread that checks if there are fewer connections open than
- * minConn specifies, and checks whether connections have been checked out
- * for too long, killing them.
+ * Background thread that checks if there are fewer connections open than
minConn specifies,
+ * and checks whether connections have been checked out for too long, killing
them.
*/
public void run() {
- while (reaperActive) {
- for (int i = 0; i < pool.size(); i++) {
- PoolConnEntry entry = (PoolConnEntry) pool.elementAt(i);
-
- long age = System.currentTimeMillis()
- - entry.getLastActivity();
-
- synchronized (entry) {
- if (entry.getStatus() == PoolConnEntry.ACTIVE &&
- age > ACTIVE_CONN_TIME_LIMIT) {
- getLogger().info(" ***** connection " + entry.getId() + "
is way too old: "
- + age + " > " + ACTIVE_CONN_TIME_LIMIT);
-
+ while(reaperActive) {
+ for(int i = 0; i < pool.size(); i++) {
+ PoolConnEntry entry = (PoolConnEntry)pool.elementAt(i);
+ long age = System.currentTimeMillis() -
entry.getLastActivity();
+ synchronized(entry) {
+ if((entry.getStatus() == PoolConnEntry.ACTIVE) &&
+ (age > ACTIVE_CONN_TIME_LIMIT)) {
+ getLogger().info(
+ " ***** connection " + entry.getId() + " is way too
old: " + age +
+ " > " + ACTIVE_CONN_TIME_LIMIT);
// This connection is way too old...
// kill it no matter what
finalizeEntry(entry);
continue;
}
-
- if (entry.getStatus() == PoolConnEntry.AVAILABLE &&
- age > CONN_IDLE_LIMIT) {
+ if((entry.getStatus() == PoolConnEntry.AVAILABLE) &&
+ (age > CONN_IDLE_LIMIT)) {
//We've got a connection that's too old... kill it
finalizeEntry(entry);
continue;
@@ -436,47 +353,89 @@
}
}
try {
-
// Check for activity every 5 seconds
Thread.sleep(5000L);
- } catch (InterruptedException ex) {}
+ } catch(InterruptedException ex) {
+ }
}
}
- /**
- * Close all connections. The connection pooler will recreate these connections
- * if something starts requesting them again.
- *
- * @deprecated This was left over code from Town... but not exposed in Avalon.
+ protected void debug(String message) {
+ getLogger().debug(message);
+ }
+
+ protected void info(String message) {
+ getLogger().info(message);
+ }
+
+ /*
+ * This is a real hack, but oh well for now
*/
- public synchronized void killAllConnections() {
- //Just remove the references to all the connections... this will cause them
to get
- // finalized before very long. (not an instant shutdown, but that's ok).
- pool.clear();
+ protected void warn(String message) {
+ getLogger().warn(message);
}
/**
- * Need to clean up all connections
+ * Creates a new connection as per these properties, adds it to the pool, and
logs the creation.
+ *
+ * @return PoolConnEntry the new connection wrapped as an entry
+ * @throws SQLException
*/
- public void dispose() {
-
- // Stop the background monitoring thread
- if (reaper != null) {
- reaperActive = false;
- //In case it's sleeping, help it quit faster
- reaper.interrupt();
- reaper = null;
+ private PoolConnEntry createConn() throws SQLException {
+ PoolConnEntry entry = null;
+ synchronized(this) {
+ if(connCreationsInProgress > 0) {
+ //We are already creating one in another place
+ return null;
+ }
+ long now = System.currentTimeMillis();
+ if((now - connLastCreated) < (1000 * pool.size())) {
+ //We don't want to scale up too quickly...
+ if(DEEP_DEBUG) {
+ System.err.println("We don't want to scale up too quickly");
+ }
+ return null;
+ }
+ if((maxConn == 0) || (pool.size() < maxConn)) {
+ connCreationsInProgress++;
+ connLastCreated = now;
+ } else {
+ // We've already hit a limit... fail silently
+ getLogger().debug(
+ "Connection limit hit... " + pool.size() + " in pool and " +
+ connCreationsInProgress + " + on the way.");
+ return null;
+ }
+ }
+ try {
+ entry = new PoolConnEntry(this,
+ java.sql.DriverManager.getConnection(jdbcURL,
jdbcUsername,
+
jdbcPassword),
+ ++connectionCount);
+ getLogger().debug("Opening connection " + entry);
+ entry.lock();
+ pool.addElement(entry);
+ return entry;
+ } catch(SQLException sqle) {
+ //Shouldn't ever happen, but it did, just return null.
+ return null;
+ } finally {
+ synchronized(this) {
+ connCreationsInProgress--;
+ }
}
-
- // The various entries will finalize themselves once the reference
- // is removed, so no need to do it here
}
- /*
- * This is a real hack, but oh well for now
+ /**
+ * Closes a connection and removes it from the pool.
+ *
+ * @param entry entry
*/
- protected void warn(String message) { getLogger().warn(message); }
- protected void info(String message) { getLogger().info(message); }
- protected void debug(String message) { getLogger().debug(message); }
-
-}
+ private synchronized void finalizeEntry(PoolConnEntry entry) {
+ try {
+ entry.finalize();
+ } catch(Exception fe) {
+ }
+ pool.removeElement(entry);
+ }
+}
\ No newline at end of file
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>