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:
@@ -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";
|
||||||
|
|||||||
Reference in New Issue
Block a user