Print

Print


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);
     }
 }