Reuse database connections if a database identifier specifies the same

username and URL so as to minimize the number of connections opened by any
particular database-using entity.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@1641 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2005-05-06 18:48:35 +00:00
parent 3af029c652
commit ff74aa9f60
@@ -109,30 +109,31 @@ public class StaticConnectionProvider implements ConnectionProvider
public void shutdown () public void shutdown ()
{ {
// close all of the connections // close all of the connections
Iterator iter = _conns.keySet().iterator(); Iterator iter = _keys.keySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
String ident = (String)iter.next(); String key = (String)iter.next();
Connection conn = (Connection)_conns.get(ident); Mapping conmap = (Mapping)_keys.get(key);
try { try {
conn.close(); conmap.connection.close();
} catch (SQLException sqe) { } catch (SQLException sqe) {
Log.warning("Error shutting down connection " + Log.warning("Error shutting down connection " +
"[ident=" + ident + ", err=" + sqe + "]."); "[key=" + key + ", err=" + sqe + "].");
} }
} }
// clear out the connection table // clear out our mapping tables
_conns.clear(); _keys.clear();
_idents.clear();
} }
// documentation inherited // documentation inherited
public Connection getConnection (String ident) public Connection getConnection (String ident)
throws PersistenceException throws PersistenceException
{ {
Connection conn = (Connection)_conns.get(ident); Mapping conmap = (Mapping)_idents.get(ident);
// open the connection if we haven't already // open the connection if we haven't already
if (conn == null) { if (conmap == null) {
Properties props = Properties props =
PropertiesUtil.getSubProperties(_props, ident, DEFAULTS_KEY); PropertiesUtil.getSubProperties(_props, ident, DEFAULTS_KEY);
@@ -146,30 +147,27 @@ public class StaticConnectionProvider implements ConnectionProvider
err = "No driver password specified [ident=" + ident + "]."; err = "No driver password specified [ident=" + ident + "].";
String password = requireProp(props, "password", err); String password = requireProp(props, "password", err);
// load up the driver class // we cache connections by username+url to avoid making more
try { // that one connection to a particular database server
Class.forName(driver); String key = username + "@" + url;
} catch (Exception e) { conmap = (Mapping)_keys.get(key);
err = "Error loading driver [ident=" + ident + if (conmap == null) {
", class=" + driver + "]."; Log.debug("Creating " + key + " for " + ident + ".");
throw new PersistenceException(err, e); conmap = new Mapping();
} conmap.key = key;
conmap.connection =
// create the connection openConnection(driver, url, username, password);
try { _keys.put(key, conmap);
conn = DriverManager.getConnection(url, username, password); } else {
} catch (SQLException sqe) { Log.debug("Reusing " + key + " for " + ident + ".");
err = "Error creating database connection " +
"[ident=" + ident + ", driver=" + driver + ", url=" + url +
", username=" + username + "].";
throw new PersistenceException(err, sqe);
} }
// cache the connection // cache the connection
_conns.put(ident, conn); conmap.idents.add(ident);
_idents.put(ident, conmap);
} }
return conn; return conmap.connection;
} }
// documentation inherited // documentation inherited
@@ -182,20 +180,52 @@ public class StaticConnectionProvider implements ConnectionProvider
public void connectionFailed (String ident, Connection conn, public void connectionFailed (String ident, Connection conn,
SQLException error) SQLException error)
{ {
Mapping conmap = (Mapping)_idents.get(ident);
if (conmap == null) {
Log.warning("Unknown connection falied!? [ident=" + ident + "].");
return;
}
// attempt to close the connection // attempt to close the connection
try { try {
conn.close(); conmap.connection.close();
} catch (SQLException sqe) { } catch (SQLException sqe) {
Log.warning("Error closing failed connection [ident=" + ident + Log.warning("Error closing failed connection [ident=" + ident +
", error=" + sqe + "]."); ", error=" + sqe + "].");
} }
// and remove it from the cache // clear it from our mapping tables
_conns.remove(ident); for (int ii = 0; ii < conmap.idents.size(); ii++) {
_idents.remove(conmap.idents.get(ii));
}
_keys.remove(conmap.key);
} }
protected static String requireProp (Properties props, protected Connection openConnection (
String name, String errmsg) String driver, String url, String username, String password)
throws PersistenceException
{
// load up the driver class
try {
Class.forName(driver);
} catch (Exception e) {
String err = "Error loading driver [class=" + driver + "].";
throw new PersistenceException(err, e);
}
// create the connection
try {
return DriverManager.getConnection(url, username, password);
} catch (SQLException sqe) {
String err = "Error creating database connection " +
"[driver=" + driver + ", url=" + url +
", username=" + username + "].";
throw new PersistenceException(err, sqe);
}
}
protected static String requireProp (
Properties props, String name, String errmsg)
throws PersistenceException throws PersistenceException
{ {
String value = props.getProperty(name); String value = props.getProperty(name);
@@ -207,11 +237,29 @@ public class StaticConnectionProvider implements ConnectionProvider
return value; return value;
} }
/** Contains information on a particular connection to which any
* number of database identifiers can be mapped. */
protected static class Mapping
{
/** The combination of username and JDBC url that uniquely
* identifies our database connection. */
public String key;
/** The connection itself. */
public Connection connection;
/** The database identifiers that are mapped to this connection. */
public ArrayList idents = new ArrayList();
}
/** Our configuration in the form of a properties object. */ /** Our configuration in the form of a properties object. */
protected Properties _props; protected Properties _props;
/** Open database connections. */ /** A mapping from database identifier to connection records. */
protected HashMap _conns = new HashMap(); protected HashMap _idents = new HashMap();
/** A mapping from connection key to connection records. */
protected HashMap _keys = new HashMap();
/** The key used as defaults for the database definitions. */ /** The key used as defaults for the database definitions. */
protected static final String DEFAULTS_KEY = "default"; protected static final String DEFAULTS_KEY = "default";