Print

Print


Author: [log in to unmask]
Date: Fri Jul 17 16:51:55 2015
New Revision: 3266

Log:
Minor changes to crawler and run db API.

Modified:
    java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java
    java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java
    java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataReader.java
    java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java

Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java	Fri Jul 17 16:51:55 2015
@@ -378,6 +378,7 @@
             LOGGER.config("added date filter with time stamp " + config.timestamp());
         }
 
+        // Is the accept run list not empty? (Empty means accept all runs.)
         if (!config.acceptRuns().isEmpty()) {
             // List of run numbers to accept.
             visitor.addFilter(new RunFilter(config.acceptRuns()));

Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java	Fri Jul 17 16:51:55 2015
@@ -5,6 +5,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -26,9 +27,10 @@
     private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
     /**
-     * A list of run numbers to accept in the job.
-     */
-    private Set<Integer> acceptRuns;
+     * A list of run numbers to accept in the job; this default will probably get overridden but it is here to avoid
+     * null pointer exceptions. An empty list is assumed to mean "accept all runs" e.g. no run number filtering.
+     */
+    private Set<Integer> acceptRuns = new LinkedHashSet<Integer>();
 
     /**
      * <code>true</code> if database updates are allowed meaning existing records can be deleted and replaced.
@@ -244,8 +246,9 @@
      *
      * @param maxDepth the max depth
      */
-    void setMaxDepth(final Integer maxDepth) {
+    CrawlerConfig setMaxDepth(final Integer maxDepth) {
         this.maxDepth = maxDepth;
+        return this;
     }
 
     /**

Modified: java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataReader.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataReader.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataReader.java	Fri Jul 17 16:51:55 2015
@@ -7,7 +7,7 @@
 import org.hps.record.epics.EpicsData;
 
 /**
- * Convert run database records from the <i>run_epics</i> table in to a {@link EpicsData} object.
+ * Convert run database records from the <i>run_epics</i> table into a {@link EpicsData} object.
  *
  * @author Jeremy McCormick, SLAC
  */

Modified: java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java	Fri Jul 17 16:51:55 2015
@@ -1,27 +1,37 @@
 package org.hps.record.run;
 
 import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.hps.conditions.database.ConnectionParameters;
 import org.lcsim.conditions.ConditionsEvent;
 import org.lcsim.conditions.ConditionsListener;
 import org.lcsim.util.log.DefaultLogFormatter;
 import org.lcsim.util.log.LogUtil;
 
 /**
- * Manages access to the run database and creates a {@link RunSummary} object from the data for a specific run.
+ * Manages read-only access to the run database and creates a {@link RunSummary} object from the data for a specific
+ * run.
  * <p>
- * This class can also convert database records into {@link org.hps.record.epics.EpicsData},
- * {@link org.hps.record.scalers.ScalerData}, and {@link org.hps.record.evio.crawler.EvioFileList} using their
- * {@link AbstractRunDatabaseReader} implementation classes.
+ * This class converts database records into {@link RunSummary}, {@link org.hps.record.epics.EpicsData},
+ * {@link org.hps.record.scalers.ScalerData}, and {@link org.hps.record.evio.crawler.EvioFileList} objects using their
+ * corresponding {@link AbstractRunDatabaseReader} implementation classes.
  *
  * @author Jeremy McCormick, SLAC
  */
 public final class RunManager implements ConditionsListener {
 
     /**
+     * The default connection parameters for read-only access to the run database using the standard 'hpsuser' account.
+     */
+    private static ConnectionParameters DEFAULT_CONNECTION_PARAMETERS = new ConnectionParameters("hpsuser",
+            "darkphoton", "hps_run_db", "hpsdb.jlab.org");
+
+    /**
      * The singleton instance of the RunManager.
      */
     private static RunManager INSTANCE;
@@ -32,9 +42,9 @@
     private static Logger LOGGER = LogUtil.create(RunManager.class, new DefaultLogFormatter(), Level.ALL);
 
     /**
-     * Get the instance of the {@link RunManager}.
-     *
-     * @return the instance of the {@link RunManager}.
+     * Get the global instance of the {@link RunManager}.
+     *
+     * @return the global instance of the {@link RunManager}
      */
     public static RunManager getRunManager() {
         if (INSTANCE == null) {
@@ -44,11 +54,16 @@
     }
 
     /**
-     * The database connection.
+     * The active database connection.
      */
     private Connection connection;
 
     /**
+     * The database connection parameters, initially set to the default parameters.
+     */
+    private ConnectionParameters connectionParameters = DEFAULT_CONNECTION_PARAMETERS;
+
+    /**
      * The run number; the -1 value indicates that this has not been set externally yet.
      */
     private int run = -1;
@@ -58,18 +73,18 @@
      */
     private RunSummary runSummary = null;
 
+    /**
+     * Load new run information when conditions have changed.
+     */
     @Override
-    public void conditionsChanged(final ConditionsEvent conditionsEvent) {
-        final int newRun = conditionsEvent.getConditionsManager().getRun();
-        LOGGER.info("initializing for run " + newRun + " ...");
-        this.setRun(newRun);
-        LOGGER.info("done initializing for run " + this.getRun());
+    public synchronized void conditionsChanged(final ConditionsEvent conditionsEvent) {
+        this.setRun(conditionsEvent.getConditionsManager().getRun());
     }
 
     /**
      * Get the database connection.
      *
-     * @return the database connection
+     * @return the database connection or <code>null</code> if it is not set
      */
     Connection getConnection() {
         return this.connection;
@@ -97,28 +112,29 @@
      * Read information from the run database and create a {@link RunSummary} from it.
      */
     private void readRun() {
-        // Load main RunSummary object.
+
+        // Read main RunSummary object but not objects that it references.
         final RunSummaryReader runSummaryReader = new RunSummaryReader();
         runSummaryReader.setRun(this.getRun());
         runSummaryReader.setConnection(this.getConnection());
         runSummaryReader.read();
         this.setRunSummary(runSummaryReader.getData());
 
-        // Set EpicsData on RunSummary.
+        // Read EpicsData and set on RunSummary.
         final EpicsDataReader epicsDataReader = new EpicsDataReader();
         epicsDataReader.setRun(this.getRun());
         epicsDataReader.setConnection(this.getConnection());
         epicsDataReader.read();
         this.getRunSummary().setEpicsData(epicsDataReader.getData());
 
-        // Set ScalerData on RunSummary.
+        // Read ScalerData and set on RunSummary.
         final ScalerDataReader scalerDataReader = new ScalerDataReader();
         scalerDataReader.setRun(this.getRun());
         scalerDataReader.setConnection(this.getConnection());
         scalerDataReader.read();
         this.getRunSummary().setScalerData(scalerDataReader.getData());
 
-        // Set ScalerData on RunSummary.
+        // Read ScalerData and set on RunSummary.
         final EvioFileListReader evioFileListReader = new EvioFileListReader();
         evioFileListReader.setRun(this.getRun());
         evioFileListReader.setConnection(this.getConnection());
@@ -127,38 +143,83 @@
     }
 
     /**
-     * Set the database connection.
-     *
-     * @param connection the database connection
-     */
-    public void setConnection(final Connection connection) {
-        this.connection = connection;
+     * Check if the current run number exists in the run database.
+     *
+     * @return <code>true</code> if run exists
+     */
+    private boolean runExists() throws SQLException {
+        PreparedStatement statement = null;
+        boolean exists = false;
+        try {
+            statement = connection.prepareStatement("SELECT run FROM runs where run = ?");
+            statement.setInt(1, this.run);
+            final ResultSet resultSet = statement.executeQuery();
+            exists = resultSet.next();
+        } finally {
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (final SQLException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return exists;
+    }
+
+    /**
+     * Set the database connection parameters.
+     */
+    public void setConnectionParameters(final ConnectionParameters connectionParameters) {
+        this.connectionParameters = connectionParameters;
     }
 
     /**
      * Set the run number.
+     * <p>
+     * This is public in order for the class to be usable without the conditions system but it should not be called
+     * within a standard lcsim job as it resets the global state of the RunManager.
      *
      * @param run the run number
      */
-    public void setRun(final int run) {
-
-        // Check status of database connection (must be open).
+    public synchronized void setRun(final int run) {
+
+        if (run < 0) {
+            throw new IllegalArgumentException("invalid run number: " + run);
+        }
+
         try {
-            if (this.connection.isClosed()) {
-                throw new IllegalStateException("The connection is closed.");
+
+            // Setup the database connection.
+            if (this.connection == null || this.connection.isClosed()) {
+                this.connection = connectionParameters.createConnection();
             }
+
+            // Set the current run number.
+            this.run = run;
+
+            // Does the current run exist in the database?
+            if (this.runExists()) {
+                LOGGER.info("run record found in hps_run_db for " + run);
+                try {
+                    // Read the records from the database and convert into Java objects.
+                    this.readRun();
+                } catch (final Exception e) {
+                    // There was some unknown error when reading in the run records.
+                    LOGGER.log(Level.SEVERE, "Error reading from run database for run: " + run, e);
+                    throw new RuntimeException(e);
+                }
+            } else {
+                // Run is not in the database.
+                LOGGER.warning("run database record does not exist for run " + run);
+            }
+
+            // Close the database connection.
+            this.connection.close();
+
         } catch (final SQLException e) {
             throw new RuntimeException(e);
         }
-
-        this.run = run;
-
-        try {
-            // Read the run records from the database and convert into Java objects.
-            this.readRun();
-        } catch (final Exception e) {
-            LOGGER.log(Level.SEVERE, "Error reading from run database for run: " + run, e);
-        }
     }
 
     /**