# HG changeset patch # User František Kučera # Date 1431901990 -7200 # Node ID 76da38d49e810606be3ead8e565855628f62b3b3 # Parent aed11d9107bfd9f3488f35d4a4945a290d7f585c parallel connection testing: avoid deadlocks – preload drivers + better exception handling and logging diff -r aed11d9107bf -r 76da38d49e81 java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java --- a/java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java Sun May 17 15:43:20 2015 +0200 +++ b/java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java Mon May 18 00:33:10 2015 +0200 @@ -35,6 +35,7 @@ import java.io.PrintStream; import java.sql.Array; import java.sql.Driver; +import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.ArrayList; @@ -47,6 +48,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.sql.rowset.RowSetMetaDataImpl; @@ -306,6 +308,10 @@ printHeader(currentFormatter, header, "-- database configuration and connectivity test", null); for (final String dbName : options.getDatabaseNamesToTest()) { + preloadDriver(dbName); + } + + for (final String dbName : options.getDatabaseNamesToTest()) { es.submit(new Runnable() { // TODO: Java 8 – lambda @Override @@ -335,6 +341,29 @@ printFooter(currentFormatter); } + /** + * JDBC driver classes should be preloaded in single thread to avoid deadlocks while doing + * {@linkplain DriverManager#registerDriver(java.sql.Driver)} during parallel connections. + * + * @param dbName + */ + private void preloadDriver(String dbName) { + try { + DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName); + Driver driver = findDriver(dd); + if (driver == null) { + log.log(Level.WARNING, "No Driver found for DB: {0}", dbName); + } else { + log.log(Level.FINEST, "Driver preloading for DB: {0} was successfull", dbName); + } + } catch (Exception e) { + LogRecord r = new LogRecord(Level.WARNING, "Failed to preload the Driver for DB: {0}"); + r.setParameters(new Object[]{dbName}); + r.setThrown(e); + log.log(r); + } + } + public Object[] testConnection(String dbName) { log.log(Level.FINE, "Testing connection to database: {0}", dbName); @@ -349,7 +378,7 @@ succesfullyConnected = dc.test(); } log.log(Level.FINE, "Database connection test was successful"); - } catch (ConfigurationException | SQLException e) { + } catch (ConfigurationException | SQLException | RuntimeException e) { log.log(Level.SEVERE, "Error during testing connection " + dbName, e); } diff -r aed11d9107bf -r 76da38d49e81 java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java --- a/java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java Sun May 17 15:43:20 2015 +0200 +++ b/java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java Mon May 18 00:33:10 2015 +0200 @@ -78,7 +78,13 @@ try { Class driverClass = (Class) Class.forName(driverClassName); Driver driver = driverClass.newInstance(); - return driver.connect(url, javaProperties); + Connection connection = driver.connect(url, javaProperties); + if (connection == null) { + log.log(Level.SEVERE, "Driver „{0}“ returend null → it does not accept the URL: „{1}“", new Object[]{driverClassName, url}); + throw new SQLException("Unable to connect: driver returned null."); + } else { + return connection; + } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) { throw new SQLException("Unable to connect usig specific driver: " + driverClassName, e); }