* Implement thread local connection caching for non-transactor threads.

Fixes problem with connection proliferation with helmaswarm id generator
  (see http://helma.org/bugs/show_bug.cgi?id=527)
This commit is contained in:
hns 2007-06-28 15:42:17 +00:00
parent d7618448fb
commit 8579a68675

View file

@ -21,6 +21,7 @@ import helma.util.ResourceProperties;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
import java.util.Hashtable; import java.util.Hashtable;
@ -40,6 +41,8 @@ public class DbSource {
private Hashtable dbmappings = new Hashtable(); private Hashtable dbmappings = new Hashtable();
// compute hashcode statically because it's expensive and we need it often // compute hashcode statically because it's expensive and we need it often
private int hashcode; private int hashcode;
// thread local connection holder for non-transactor threads
private ThreadLocal connection;
/** /**
* Creates a new DbSource object. * Creates a new DbSource object.
@ -65,11 +68,13 @@ public class DbSource {
*/ */
public synchronized Connection getConnection() public synchronized Connection getConnection()
throws ClassNotFoundException, SQLException { throws ClassNotFoundException, SQLException {
Connection con = null; Connection con;
Transactor tx = null; Transactor tx = null;
if (Thread.currentThread() instanceof Transactor) { if (Thread.currentThread() instanceof Transactor) {
tx = (Transactor) Thread.currentThread(); tx = (Transactor) Thread.currentThread();
con = tx.getConnection(this); con = tx.getConnection(this);
} else {
con = getThreadLocalConnection();
} }
boolean fileUpdated = props.lastModified() > lastRead || boolean fileUpdated = props.lastModified() > lastRead ||
@ -84,12 +89,40 @@ public class DbSource {
// System.err.println ("Created new Connection to "+url); // System.err.println ("Created new Connection to "+url);
if (tx != null) { if (tx != null) {
tx.registerConnection(this, con); tx.registerConnection(this, con);
} else {
connection.set(con);
} }
} }
return con; return con;
} }
/**
* Used for connections not managed by a Helma transactor
* @return a thread local tested connection, or null
*/
private Connection getThreadLocalConnection() {
if (connection == null) {
connection = new ThreadLocal();
return null;
}
Connection con = (Connection) connection.get();
if (con != null) {
// test if connection is still ok
try {
Statement stmt = con.createStatement();
stmt.execute("SELECT 1");
stmt.close();
} catch (SQLException sx) {
try {
con.close();
} catch (SQLException ignore) {/* nothing to do */}
return null;
}
}
return con;
}
/** /**
* Set the db properties to newProps, and return the old properties. * Set the db properties to newProps, and return the old properties.
* @param newProps the new properties to use for this db source * @param newProps the new properties to use for this db source