Author: [log in to unmask] Date: Sat Dec 27 19:43:28 2014 New Revision: 1808 Log: Do not leave connection open by closing and opening for each conversion. HPSJAVA-370 Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsObjectConverter.java Sat Dec 27 19:43:28 2014 @@ -1,12 +1,9 @@ package org.hps.conditions.database; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; +import java.sql.Statement; import org.hps.conditions.api.AbstractConditionsObjectCollection; import org.hps.conditions.api.ConditionsObject; @@ -56,10 +53,10 @@ @SuppressWarnings({ "unchecked", "rawtypes" }) public T getData(ConditionsManager conditionsManager, String name) { - + // Get the DatabaseConditionsManager which is required for using this converter. DatabaseConditionsManager databaseConditionsManager = DatabaseConditionsManager.getInstance(); - + // Get the table meta data from the key given by the caller. TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(name); if (tableMetaData == null) @@ -106,6 +103,9 @@ throw new RuntimeException(e); } + // Open a database connection. + databaseConditionsManager.openConnection(); + // Loop over all records, which could just be a single one. for (ConditionsRecord conditionsRecord : filteredConditionsRecords) { @@ -133,7 +133,13 @@ } catch (SQLException e) { throw new RuntimeException(e); } + + // Close the Statement and the ResultSet. + DatabaseUtilities.cleanup(resultSet); } + + // Close the database connection. + databaseConditionsManager.closeConnection(); return (T) collection; } Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsRecordConverter.java Sat Dec 27 19:43:28 2014 @@ -9,7 +9,7 @@ import org.lcsim.conditions.ConditionsManager; /** - * Read ConditionsRecord objects from the conditions database. + * Read ConditionsRecord objects from the conditions database and cache the conditions set. * @author Jeremy McCormick <[log in to unmask]> */ class ConditionsRecordConverter extends ConditionsObjectConverter<ConditionsRecordCollection> { @@ -25,6 +25,10 @@ public ConditionsRecordCollection getData(ConditionsManager manager, String name) { DatabaseConditionsManager databaseConditionsManager = DatabaseConditionsManager.getInstance(); + + // Open the db connection. + databaseConditionsManager.openConnection(); + TableMetaData tableMetaData = databaseConditionsManager.findTableMetaData(name); if (tableMetaData == null) @@ -50,6 +54,12 @@ } catch (SQLException x) { throw new RuntimeException("Database error", x); } + + // Close the ResultSet and Statement. + DatabaseUtilities.cleanup(resultSet); + + // Close the db connection. + databaseConditionsManager.closeConnection(); return getType().cast(collection); } Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/ConditionsSeriesConverter.java Sat Dec 27 19:43:28 2014 @@ -3,8 +3,8 @@ import java.sql.ResultSet; import java.sql.SQLException; +import org.hps.conditions.api.AbstractConditionsObjectCollection; import org.hps.conditions.api.ConditionsObject; -import org.hps.conditions.api.AbstractConditionsObjectCollection; import org.hps.conditions.api.ConditionsObjectException; import org.hps.conditions.api.ConditionsRecord; import org.hps.conditions.api.ConditionsRecord.ConditionsRecordCollection; @@ -50,6 +50,8 @@ */ @SuppressWarnings({ "unchecked", "rawtypes" }) public ConditionsSeries createSeries(String conditionsKey) { + + conditionsManager.openConnection(); // Get the table meta data from the key given by the caller. TableMetaData tableMetaData = conditionsManager.findTableMetaData(conditionsKey); @@ -98,8 +100,12 @@ throw new RuntimeException(e); } + DatabaseUtilities.cleanup(resultSet); + series.add(collection); } + + conditionsManager.closeConnection(); // Return new collection. return series; Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java Sat Dec 27 19:43:28 2014 @@ -79,7 +79,6 @@ protected List<ConditionsConverter> converters; protected File connectionPropertiesFile; protected ConnectionParameters connectionParameters; - //= new DefaultConnectionParameters(); protected Connection connection; protected boolean isConnected = false; protected ConditionsSeriesConverter conditionsSeriesConverter = new ConditionsSeriesConverter(this); @@ -101,15 +100,8 @@ logger.setLevel(Level.FINER); registerConditionsConverter(new DetectorConditionsConverter()); setupConnectionFromSystemProperty(); - register(); + ConditionsManager.setDefaultConditionsManager(this); this.setRun(-1); - } - - /** - * Register this conditions manager as the global default. - */ - public void register() { - ConditionsManager.setDefaultConditionsManager(this); } /** @@ -136,20 +128,30 @@ /** * Open the database connection. */ - public void openConnection() { - // Do the connection parameters need to be figured out automatically? - if (connectionParameters == null) { - // Setup the default read-only connection, which will choose a SLAC or JLab database. - connectionParameters = ConnectionParameters.fromResource(chooseConnectionPropertiesResource()); - } - logger.config("opening connection to " + connectionParameters.getConnectionString()); - logger.config("host " + connectionParameters.getHostname()); - logger.config("port " + connectionParameters.getPort()); - logger.config("user " + connectionParameters.getUser()); - logger.config("database " + connectionParameters.getDatabase()); - connection = connectionParameters.createConnection(); - logger.config("successfuly created connection"); - isConnected = true; + public Connection openConnection() { + if (!isConnected) { + // Do the connection parameters need to be figured out automatically? + if (connectionParameters == null) { + // Setup the default read-only connection, which will choose a SLAC or JLab database. + connectionParameters = ConnectionParameters.fromResource(chooseConnectionPropertiesResource()); + } + + // Print out connection info to the log. + logger.config("opening connection to " + connectionParameters.getConnectionString()); + logger.config("host " + connectionParameters.getHostname()); + logger.config("port " + connectionParameters.getPort()); + logger.config("user " + connectionParameters.getUser()); + logger.config("database " + connectionParameters.getDatabase()); + + // Create the connection using the parameters. + connection = connectionParameters.createConnection(); + + logger.config("successfuly created connection"); + isConnected = true; + } else { + logger.info("using existing connection"); + } + return connection; } /** @@ -173,13 +175,6 @@ logger.info("connection closed"); } - @Override - public void finalize() { - if (isConnected()) { - closeConnection(); - } - } - /** * Get multiple <code>ConditionsObjectCollection</code> objects that may * have overlapping time validity information. @@ -197,8 +192,6 @@ * @return A collection of objects of the given type from the conditions * database */ - // TODO: This should distinguish among multiple conditions sets of the same type by using the one with the most recent date - // in its ConditionsRecord. public <CollectionType extends AbstractConditionsObjectCollection> CollectionType getCollection(Class<CollectionType> type) { TableMetaData metaData = this.findTableMetaData(type).get(0); if (metaData == null) { @@ -222,7 +215,7 @@ throw new IllegalArgumentException("The detectorName argument is null."); } - logger.finest("setDetector detector " + detectorName + " and run #" + runNumber); + logger.finest("setDetector - detector " + detectorName + " and run #" + runNumber); if (!isInitialized || !detectorName.equals(this.getDetector()) || runNumber != this.getRun()) { if (!isInitialized) { @@ -235,8 +228,9 @@ if (runNumber != this.getRun()) { logger.finest("run number is different"); } - logger.info("setDetector with new detector " + detectorName + " and run #" + runNumber); + logger.info("new detector " + detectorName + " and run #" + runNumber); logger.fine("old detector " + this.getDetector() + " and run #" + this.getRun()); + initialize(detectorName, runNumber); } else { logger.finest("Conditions changed but will be ignored because manager is frozen."); @@ -370,13 +364,17 @@ connectionParameters = ConnectionParameters.fromProperties(file); } + /** + * Set the connection parameters to the conditions database. + * @param connectionParameters The connection parameters. + */ public void setConnectionParameters(ConnectionParameters connectionParameters) { this.connectionParameters = connectionParameters; } /** - * Set the connection parameters from an embedded resource. - * @param resource The classpath resource + * Set the connection parameters from an embedded resource location. + * @param resource The classpath resource location. */ public void setConnectionResource(String resource) { logger.config("setting connection resource " + resource); @@ -495,22 +493,24 @@ * @return The keys of the rows affected. */ public List<Integer> updateQuery(String query) { + openConnection(); logger.fine(query); List<Integer> keys = new ArrayList<Integer>(); Statement statement = null; + ResultSet resultSet = null; try { statement = connection.createStatement(); statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS); - ResultSet resultSet = statement.getGeneratedKeys(); + resultSet = statement.getGeneratedKeys(); while (resultSet.next()) { int key = resultSet.getInt(1); keys.add(key); } } catch (SQLException x) { throw new RuntimeException("Error in SQL query: " + query, x); - } finally { - DatabaseUtilities.close(statement); - } + } + DatabaseUtilities.cleanup(resultSet); + closeConnection(); return keys; } @@ -595,6 +595,7 @@ } public <ObjectType extends ConditionsObject> void insertCollection(AbstractConditionsObjectCollection<ObjectType> collection) throws SQLException, ConditionsObjectException { + if (collection == null) { throw new IllegalArgumentException("The collection is null."); } @@ -624,12 +625,15 @@ logger.info("inserting collection with ID " + collection.getCollectionId() + " and key " + collection.getTableMetaData().getKey() + " into table " + tableMetaData.getTableName()); + openConnection(); + + PreparedStatement preparedStatement = null; + try { connection.setAutoCommit(false); logger.finest("starting insert transaction"); String sql = QueryBuilder.buildPreparedInsert(tableMetaData.getTableName(), collection.iterator().next()); - PreparedStatement preparedStatement = - connection.prepareStatement(sql); + preparedStatement = connection.prepareStatement(sql); logger.finest("using prepared statement: " + sql); logger.finest("preparing updates"); int collectionId = collection.getCollectionId(); @@ -654,7 +658,33 @@ } finally { connection.setAutoCommit(true); } - } + + try { + preparedStatement.close(); + } catch (Exception e) { + } + + closeConnection(); + } + + /* + public void selectCollection(AbstractConditionsObjectCollection collection) throws ConditionsObjectException { + int collectionId = collection.getCollectionId(); + if (collectionId == -1) { + throw new ConditionsObjectException("Missing collection ID for select query."); + } + TableMetaData tableMetaData = collection.getTableMetaData(); + String tableName = null; + if (tableMetaData != null) { + tableName = tableMetaData.getTableName(); + } else { + List<TableMetaData> metaList = this.findTableMetaData(collection.getClass()); + if (metaList.size() == 0) { + throw new ConditionsObjectException("Could not find meta data for collection with type " + collection.getClass().getCanonicalName()); + } + } + } + */ private void setupEcal() { logger.config("setting up ECAL conditions on detector"); Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseUtilities.java Sat Dec 27 19:43:28 2014 @@ -1,42 +1,28 @@ package org.hps.conditions.database; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; public final class DatabaseUtilities { - - /** - * Close a JDBC <code>Statement</code>. - * @param statement the Statement to close - */ - public static void close(Statement statement) { - if (statement != null) { - try { - if (!statement.isClosed()) { - statement.close(); - } - } catch (SQLException x) { - throw new RuntimeException("Failed to close statement.", x); + + static void cleanup(ResultSet resultSet) { + Statement statement = null; + try { + statement = resultSet.getStatement(); + } catch (Exception e) { + } + try { + if (resultSet != null) { + resultSet.close(); } + } catch (Exception e) { } - } - - /** - * Close the JDBC the <code>Statement</code> connected to the <code>ResultSet</code>. - * @param resultSet the ResultSet to close - */ - public static void close(ResultSet resultSet) { - if (resultSet != null) { - try { - Statement statement = resultSet.getStatement(); - if (!statement.isClosed()) { - statement.close(); - } - } catch (SQLException x) { - throw new RuntimeException("Failed to close statement.", x); - } - } + try { + if (statement != null) { + statement.close(); + } + } catch (Exception e) { + } } } Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java ============================================================================= --- java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java (original) +++ java/trunk/conditions/src/main/java/org/hps/conditions/database/QueryBuilder.java Sat Dec 27 19:43:28 2014 @@ -17,8 +17,12 @@ private QueryBuilder() { } - - public static String buildSelect(String tableName, int collectionId, String[] fields, String order) { + + //static String buildSelect(TableMetaData tableMetaData, int collectionId) { + // return null; + //} + + static String buildSelect(String tableName, int collectionId, String[] fields, String order) { StringBuffer buff = new StringBuffer(); buff.append("SELECT "); if (fields == null) { @@ -40,7 +44,7 @@ return buff.toString(); } - public static String buildUpdate(String tableName, int rowId, String[] fields, Object[] values) { + static String buildUpdate(String tableName, int rowId, String[] fields, Object[] values) { if (fields.length != values.length) throw new IllegalArgumentException("The field and value arrays are different lengths."); StringBuffer buff = new StringBuffer(); @@ -69,7 +73,7 @@ return buff.toString(); } - public static String buildPreparedInsert(String tableName, ConditionsObject object) { + static String buildPreparedInsert(String tableName, ConditionsObject object) { if (object.getFieldValues().size() == 0) { throw new IllegalArgumentException("The ConditionsObject has no values set."); } @@ -133,14 +137,14 @@ return buff.toString(); } - public static String buildDelete(String tableName, int rowId) { + static String buildDelete(String tableName, int rowId) { if (rowId <= 0) throw new IllegalArgumentException("Invalid row ID: " + rowId); String query = "DELETE FROM " + tableName + " WHERE id = " + rowId; return query; } - public static String formatDate(Date date) { + static String formatDate(Date date) { return dateFormat.format(date); } }