Commit 06351394 authored by Guus der Kinderen's avatar Guus der Kinderen

Merge pull request #306 from AlphaGit/make-db-behavior-configurable

Made connection retry parameters configurable
parents 7c92d41c f499120f
...@@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory; ...@@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory;
*/ */
public class DbConnectionManager { public class DbConnectionManager {
private static final Logger Log = LoggerFactory.getLogger(DbConnectionManager.class); private static final Logger Log = LoggerFactory.getLogger(DbConnectionManager.class);
private static ConnectionProvider connectionProvider; private static ConnectionProvider connectionProvider;
private static final Object providerLock = new Object(); private static final Object providerLock = new Object();
...@@ -74,11 +74,41 @@ public class DbConnectionManager { ...@@ -74,11 +74,41 @@ public class DbConnectionManager {
/** True if the database supports the Statement.setFetchSize()) method. */ /** True if the database supports the Statement.setFetchSize()) method. */
static boolean pstmt_fetchSizeSupported = true; static boolean pstmt_fetchSizeSupported = true;
private static final String SETTING_DATABASE_MAX_RETRIES = "database.defaultProvider.maxRetries";
private static final String SETTING_DATABASE_RETRY_DELAY = "database.defaultProvider.retryDelay";
private static DatabaseType databaseType = DatabaseType.unknown; private static DatabaseType databaseType = DatabaseType.unknown;
private static SchemaManager schemaManager = new SchemaManager(); private static SchemaManager schemaManager = new SchemaManager();
/**
* Ensures that the connection provider exists and is set
*/
private static void ensureConnectionProvider() {
if (connectionProvider != null) return;
synchronized (providerLock) {
if (connectionProvider != null) return;
// Attempt to load the connection provider classname as a Jive property.
String className = JiveGlobals.getXMLProperty("connectionProvider.className");
if (className != null) {
// Attempt to load the class.
try {
Class conClass = ClassUtils.forName(className);
setConnectionProvider((ConnectionProvider)conClass.newInstance());
} catch (Exception e) {
Log.warn("Failed to create the " +
"connection provider specified by connection" +
"Provider.className. Using the default pool.", e);
setConnectionProvider(new DefaultConnectionProvider());
}
} else {
setConnectionProvider(new DefaultConnectionProvider());
}
}
}
/** /**
* Returns a database connection from the currently active connection * Returns a database connection from the currently active connection
* provider. An exception will be thrown if no connection was found. * provider. An exception will be thrown if no connection was found.
...@@ -88,41 +118,15 @@ public class DbConnectionManager { ...@@ -88,41 +118,15 @@ public class DbConnectionManager {
* @throws SQLException if a SQL exception occurs or no connection was found. * @throws SQLException if a SQL exception occurs or no connection was found.
*/ */
public static Connection getConnection() throws SQLException { public static Connection getConnection() throws SQLException {
if (connectionProvider == null) { ensureConnectionProvider();
synchronized (providerLock) {
if (connectionProvider == null) {
// Attempt to load the connection provider classname as
// a Jive property.
String className = JiveGlobals.getXMLProperty("connectionProvider.className");
if (className != null) {
// Attempt to load the class.
try {
Class conClass = ClassUtils.forName(className);
setConnectionProvider((ConnectionProvider)conClass.newInstance());
}
catch (Exception e) {
Log.warn("Failed to create the " +
"connection provider specified by connection" +
"Provider.className. Using the default pool.", e);
setConnectionProvider(new DefaultConnectionProvider());
}
}
else {
setConnectionProvider(new DefaultConnectionProvider());
}
}
}
}
// TODO: May want to make these settings configurable Integer currentRetryCount = 0;
Integer retryCnt = 0; Integer maxRetries = JiveGlobals.getIntProperty(SETTING_DATABASE_MAX_RETRIES, 10);
Integer retryMax = 10; Integer retryWait = JiveGlobals.getIntProperty(SETTING_DATABASE_RETRY_DELAY, 250); // milliseconds
Integer retryWait = 250; // milliseconds
Connection con = null;
SQLException lastException = null; SQLException lastException = null;
do { do {
try { try {
con = connectionProvider.getConnection(); Connection con = connectionProvider.getConnection();
if (con != null) { if (con != null) {
// Got one, lets hand it off. // Got one, lets hand it off.
// Usually profiling is not enabled. So we return a normal // Usually profiling is not enabled. So we return a normal
...@@ -130,28 +134,28 @@ public class DbConnectionManager { ...@@ -130,28 +134,28 @@ public class DbConnectionManager {
// connection with a profiled connection. // connection with a profiled connection.
if (!profilingEnabled) { if (!profilingEnabled) {
return con; return con;
} } else {
else {
return new ProfiledConnection(con); return new ProfiledConnection(con);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
// TODO distinguish recoverable from non-recoverable exceptions. // TODO distinguish recoverable from non-recoverable exceptions.
lastException = e; lastException = e;
Log.info("Unable to get a connection from the database pool " + Log.info("Unable to get a connection from the database pool " +
"(attempt "+retryCnt+" out of "+retryMax+").", e); "(attempt " + currentRetryCount + " out of " + maxRetries + ").", e);
} }
try { try {
Thread.sleep(retryWait); Thread.sleep(retryWait);
} catch (Exception e) {
// Ignored, the thread was interrupted while waiting, so no need to log either
} }
catch (Exception e) { currentRetryCount++;
// Ignored } while (currentRetryCount <= maxRetries);
}
retryCnt++;
} while (retryCnt <= retryMax);
throw new SQLException("ConnectionManager.getConnection() " + throw new SQLException("ConnectionManager.getConnection() " +
"failed to obtain a connection after " + retryCnt +" retries. " + "failed to obtain a connection after " + currentRetryCount + " retries. " +
"The exception from the last attempt is as follows: "+lastException); "The exception from the last attempt is as follows: " + lastException);
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment