parallel connection testing: avoid deadlocks – preload drivers + better exception handling and logging v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 18 May 2015 00:33:10 +0200
branchv_0
changeset 19676da38d49e81
parent 195 aed11d9107bf
child 197 7a2f535017e4
parallel connection testing: avoid deadlocks – preload drivers + better exception handling and logging
java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java
java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java
     1.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java	Sun May 17 15:43:20 2015 +0200
     1.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java	Mon May 18 00:33:10 2015 +0200
     1.3 @@ -35,6 +35,7 @@
     1.4  import java.io.PrintStream;
     1.5  import java.sql.Array;
     1.6  import java.sql.Driver;
     1.7 +import java.sql.DriverManager;
     1.8  import java.sql.DriverPropertyInfo;
     1.9  import java.sql.SQLException;
    1.10  import java.util.ArrayList;
    1.11 @@ -47,6 +48,7 @@
    1.12  import java.util.concurrent.Executors;
    1.13  import java.util.concurrent.TimeUnit;
    1.14  import java.util.logging.Level;
    1.15 +import java.util.logging.LogRecord;
    1.16  import java.util.logging.Logger;
    1.17  import javax.sql.rowset.RowSetMetaDataImpl;
    1.18  
    1.19 @@ -306,6 +308,10 @@
    1.20  		printHeader(currentFormatter, header, "-- database configuration and connectivity test", null);
    1.21  
    1.22  		for (final String dbName : options.getDatabaseNamesToTest()) {
    1.23 +			preloadDriver(dbName);
    1.24 +		}
    1.25 +
    1.26 +		for (final String dbName : options.getDatabaseNamesToTest()) {
    1.27  			es.submit(new Runnable() {
    1.28  				// TODO: Java 8 – lambda
    1.29  				@Override
    1.30 @@ -335,6 +341,29 @@
    1.31  		printFooter(currentFormatter);
    1.32  	}
    1.33  
    1.34 +	/**
    1.35 +	 * JDBC driver classes should be preloaded in single thread to avoid deadlocks while doing
    1.36 +	 * {@linkplain DriverManager#registerDriver(java.sql.Driver)} during parallel connections.
    1.37 +	 *
    1.38 +	 * @param dbName
    1.39 +	 */
    1.40 +	private void preloadDriver(String dbName) {
    1.41 +		try {
    1.42 +			DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName);
    1.43 +			Driver driver = findDriver(dd);
    1.44 +			if (driver == null) {
    1.45 +				log.log(Level.WARNING, "No Driver found for DB: {0}", dbName);
    1.46 +			} else {
    1.47 +				log.log(Level.FINEST, "Driver preloading for DB: {0} was successfull", dbName);
    1.48 +			}
    1.49 +		} catch (Exception e) {
    1.50 +			LogRecord r = new LogRecord(Level.WARNING, "Failed to preload the Driver for DB: {0}");
    1.51 +			r.setParameters(new Object[]{dbName});
    1.52 +			r.setThrown(e);
    1.53 +			log.log(r);
    1.54 +		}
    1.55 +	}
    1.56 +
    1.57  	public Object[] testConnection(String dbName) {
    1.58  		log.log(Level.FINE, "Testing connection to database: {0}", dbName);
    1.59  
    1.60 @@ -349,7 +378,7 @@
    1.61  				succesfullyConnected = dc.test();
    1.62  			}
    1.63  			log.log(Level.FINE, "Database connection test was successful");
    1.64 -		} catch (ConfigurationException | SQLException e) {
    1.65 +		} catch (ConfigurationException | SQLException | RuntimeException e) {
    1.66  			log.log(Level.SEVERE, "Error during testing connection " + dbName, e);
    1.67  		}
    1.68  
     2.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java	Sun May 17 15:43:20 2015 +0200
     2.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java	Mon May 18 00:33:10 2015 +0200
     2.3 @@ -78,7 +78,13 @@
     2.4  			try {
     2.5  				Class<Driver> driverClass = (Class<Driver>) Class.forName(driverClassName);
     2.6  				Driver driver = driverClass.newInstance();
     2.7 -				return driver.connect(url, javaProperties);
     2.8 +				Connection connection = driver.connect(url, javaProperties);
     2.9 +				if (connection == null) {
    2.10 +					log.log(Level.SEVERE, "Driver „{0}“ returend null → it does not accept the URL: „{1}“", new Object[]{driverClassName, url});
    2.11 +					throw new SQLException("Unable to connect: driver returned null.");
    2.12 +				} else {
    2.13 +					return connection;
    2.14 +				}
    2.15  			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) {
    2.16  				throw new SQLException("Unable to connect usig specific driver: " + driverClassName, e);
    2.17  			}