Author: [log in to unmask] Date: Wed Jun 10 13:10:16 2015 New Revision: 3119 Log: Cleanup database update interface; add full support for EPICS variables; add command line options; other misc changes. Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EpicsLog.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileCrawler.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileSequenceComparator.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EpicsLog.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EpicsLog.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EpicsLog.java Wed Jun 10 13:10:16 2015 @@ -99,5 +99,5 @@ //System.out.println(name + " => added " + this.currentData.getValue(name) + "; total = " + value + "; mean = " + value / count); } } - } + } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileCrawler.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileCrawler.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileCrawler.java Wed Jun 10 13:10:16 2015 @@ -20,6 +20,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; +import org.hps.conditions.database.DatabaseConditionsManager; import org.hps.record.evio.EvioEventProcessor; import org.lcsim.util.log.DefaultLogFormatter; import org.lcsim.util.log.LogUtil; @@ -30,13 +31,6 @@ * * @author Jeremy McCormick, SLAC */ -// TODO: need options for... -// -database connections prop file -// -writing Auger XML for crawl job (and don't actually execute job) -// -writing out a summary EVIO file containing control events only (PRESTART, EPICS, scalars?, END) -// -get supplementary information from run spreadsheet (including whether run was "JUNK" or not) -// -allow running arbitrary EvioEventProcessor classes by giving fully qualified class names as args on command line -// e.g. -E org.hps.derp.MyEvioEventProcessor public final class EvioFileCrawler { /** @@ -63,15 +57,16 @@ OPTIONS.addOption("a", "accept-runs", true, "list of run numbers to accept (others will be excluded)"); OPTIONS.addOption("b", "begin-date", true, "min date for files (example 2015-03-26 11:28:59)"); OPTIONS.addOption("c", "cache-files", false, "automatically cache files from MSS (JLAB only)"); + OPTIONS.addOption("C", "db-config", true, "database connection properties file (required)"); OPTIONS.addOption("d", "directory", true, "root directory to start crawling (default is current dir)"); - OPTIONS.addOption("e", "epics", false, "process EPICS data found in EVIO files"); - OPTIONS.addOption("E", "evio-processor", true, "class name of an additional EVIO processor to execute"); + OPTIONS.addOption("e", "epics", false, "process EPICS data found in EVIO files (run log is also updated if -r is used)"); + OPTIONS.addOption("E", "evio-processor", true, "class name of an additional EVIO processor to execute (can be used multiple times)"); OPTIONS.addOption("h", "help", false, "print help and exit"); OPTIONS.addOption("m", "max-files", true, "max number of files to process per run (only for debugging)"); OPTIONS.addOption("p", "print", true, "set event print interval during EVIO processing"); OPTIONS.addOption("r", "insert-run-log", false, "update the run database (not done by default)"); OPTIONS.addOption("t", "timestamp-file", true, "existing or new timestamp file name for date cut off"); - OPTIONS.addOption("s", "print-summary", false, "print run summary at the end of the job"); + OPTIONS.addOption("s", "print-summary", false, "print the run summaries at the end of the job"); OPTIONS.addOption("w", "max-cache-wait", true, "total seconds to allow for file caching"); OPTIONS.addOption("L", "log-level", true, "set the log level (INFO, FINE, etc.)"); OPTIONS.addOption("u", "update-run-log", false, "allow overriding existing data in the run db (not allowed by default)"); @@ -108,7 +103,7 @@ /** * Flag indicating whether EPICS data banks should be processed. */ - private boolean epics = false; + private boolean processEpicsData = false; /** * Interval for printing out event number while running EVIO processors. @@ -116,7 +111,7 @@ private int eventPrintInterval = DEFAULT_EVENT_PRINT_INTERVAL; /** - * The maximum number of files to + * The maximum number of files to accept (just used for debugging purposes). */ private int maxFiles = -1; @@ -172,7 +167,7 @@ */ private RunProcessor createRunProcessor(final RunSummary runSummary) { final RunProcessor processor = new RunProcessor(runSummary, this.cacheManager); - if (this.epics) { + if (this.processEpicsData) { processor.addProcessor(new EpicsLog(runSummary)); } if (this.printSummary) { @@ -204,6 +199,18 @@ final Level level = Level.parse(cl.getOptionValue("L")); LOGGER.info("setting log level to " + level); LOGGER.setLevel(level); + } + + if (cl.hasOption("C")) { + String dbPropPath = cl.getOptionValue("C"); + File dbPropFile = new File(dbPropPath); + if (!dbPropFile.exists()) { + throw new IllegalArgumentException("Connection properties file " + dbPropFile.getPath() + " does not exist."); + } + LOGGER.config("using " + dbPropPath + " for db connection properties"); + DatabaseConditionsManager.getInstance().setConnectionProperties(dbPropFile); + } else { + throw new RuntimeException("The -C switch providing the database connection properties file is a required argument."); } if (cl.hasOption("d")) { @@ -256,7 +263,7 @@ } if (cl.hasOption("e")) { - this.epics = true; + this.processEpicsData = true; LOGGER.config("EPICS processing enabled"); } @@ -412,9 +419,21 @@ // Insert run information into the database. if (this.updateRunLog) { - // Update run log. - new RunLogUpdater(runs, allowUpdates).insert(); - } + + // Create and configure RunLogUpdater which updates the run log for all runs found in crawl. + RunLogUpdater runUpdater = new RunLogUpdater(runs, allowUpdates); + + if (!this.processEpicsData) { + // Disable inserting EPICS data if it was not processed. + runUpdater.setInsertEpicsData(false); + } + + // Update the db. + runUpdater.insert(); + + // Close the db connection. + runUpdater.close(); + } // Update the timestamp file which can be used to tell which files have been processed. if (this.timestampFile == null) { @@ -430,7 +449,14 @@ LOGGER.info("set modified on timestamp file: " + new Date(this.timestampFile.lastModified())); } - EvioEventProcessor createEvioEventProcessor(String className) throws Exception { + /** + * Create an {@link org.hps.record.evio.EvioEventProcessor} by its class name. + * + * @param className the fully qualified name of the class + * @return the new object + * @throws Exception if there is a problem instantiating the class (does not exist; access exception etc.) + */ + private EvioEventProcessor createEvioEventProcessor(String className) throws Exception { return EvioEventProcessor.class.cast(Class.forName(className).newInstance()); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileSequenceComparator.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileSequenceComparator.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileSequenceComparator.java Wed Jun 10 13:10:16 2015 @@ -13,7 +13,7 @@ /** * Compare two EVIO files by their sequence numbers. * - * @return -1 if the first file's sequence number is less than the second's; 0 if equal; 1 if greater than + * @return -1, 0, or 1 if the first file's sequence number is less than, equal to, or greater than the second's */ @Override public int compare(final File o1, final File o2) { Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java Wed Jun 10 13:10:16 2015 @@ -12,9 +12,7 @@ /** * This class contains summary information about a series of runs that are themselves modeled with the {@link RunSummary} class. These can be looked - * up by their run number. - * <p> - * This class is able to update the run database using the <code>insert</code> methods. + * up by their run number {@link #getRunSummary(int)}. * * @author Jeremy McCormick, SLAC */ Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java Wed Jun 10 13:10:16 2015 @@ -9,7 +9,9 @@ import org.lcsim.util.log.LogUtil; /** - * Updates the run database with run log information from crawler job. + * Updates the run database with information from the crawler job. + * <p> + * The {@link RunSummaryUpdater} is used to insert rows for each run. * * @author Jeremy McCormick, SLAC */ @@ -20,12 +22,32 @@ */ private static final Logger LOGGER = LogUtil.create(RunLogUpdater.class); + /** + * The run log with information for all runs. + */ private RunLog runLog; + /** + * The database connection. + */ private final Connection connection; + /** + * <code>true</code> if updates should be allowed in database or only inserts. + */ private boolean allowUpdates = false; - + + /** + * <code>true</code> if EPICS data should be put into the database (skipped if not). + */ + private boolean insertEpicsData = true; + + /** + * Create a new updater. + * + * @param runLog the run information + * @param allowUpdates <code>true</code> if updates should be allowed + */ RunLogUpdater(RunLog runLog, boolean allowUpdates) { this.runLog = runLog; @@ -34,6 +56,18 @@ connection = cp.createConnection(); } + /** + * Set to <code>true</code> if EPICS data should be inserted. + * + * @param insertEpicsData <code>true</code> + */ + void setInsertEpicsData(boolean insertEpicsData) { + this.insertEpicsData = insertEpicsData; + } + + /** + * Close the database connection. + */ void close() { try { connection.close(); @@ -43,62 +77,87 @@ } /** - * Insert the run summary information into the database. + * Insert the run summary information into the database, including updating the run_log_files + * and run_log_epics tables. * * @param connection the database connection * @throws SQLException if there is an error querying the database */ void insert() throws SQLException { - LOGGER.info("inserting runs into run_log ..."); + LOGGER.info("inserting run data into database ..."); try { connection.setAutoCommit(false); - - // Update or insert a row for every run found. + + // Loop over all runs found while crawling. for (final Integer run : runLog.getSortedRunNumbers()) { + LOGGER.info("beginning transaction for run " + run); + + // Get the RunSummary data for the run. RunSummary runSummary = runLog.getRunSummary(run); LOGGER.info("updating " + runSummary); - RunSummaryUpdater updater = new RunSummaryUpdater(connection, runSummary); + // Create the db updater for the RunSummary. + RunSummaryUpdater runUpdater = new RunSummaryUpdater(connection, runSummary); - // Does a row already exist for run? - if (updater.runLogExists()) { + // Does a row already exist for the run? + if (runUpdater.runExists()) { LOGGER.info("record for " + run + " exists already"); // Are updates allowed? if (allowUpdates) { - LOGGER.info("updating existing row in run_log for " + run); + LOGGER.info("existing row for " + run + " will be updated"); // Update existing row. - updater.updateRunLog(); + runUpdater.updateRun(); } else { // Row exists and updates not allowed which is an error. - throw new RuntimeException("Row already exists for run " + run + " and allowUpdates is false"); + throw new RuntimeException("Row already exists for run " + run + " and allowUpdates is false."); } } else { - - LOGGER.info("inserting new row in run_log for " + run); + + LOGGER.info("inserting new row in runs for run " + run + " ..."); // Insert new record into run_log. - updater.insertRunLog(); - } - - boolean fileLogExists = updater.fileLogExists(); - - // Are updates disallowed and file log exists? - if (!allowUpdates && fileLogExists) { - // File records exist but updates not allowed so this is an error. - throw new RuntimeException("Cannot delete existing file records because allowUpdates is false"); + runUpdater.insertRun(); } - // Delete existing file log. - if (fileLogExists) { - // Delete the file log. - updater.deleteFileLog(); + // Do records exist in the run_log_files table? + if (runUpdater.filesExist()) { + // Are updates disallowed? + if (!allowUpdates) { + // File records exist for the run but updating is allowed so throw an exception. + throw new RuntimeException("Cannot delete existing records in run_log_files because allowUpdates is false."); + } else { + // Delete the file log. + runUpdater.deleteFiles(); + } + } + + // Insert records into run_log_files now that existing records were deleted, if necessary. + runUpdater.insertFiles(); + + // Is EPICS data processing enabled? + if (insertEpicsData) { + // Does the EPICS data already exist? + if (runUpdater.epicsExists()) { + // Is replacing data disallowed? + if (!allowUpdates) { + // EPICS data exists but updating is not allowed so throw exception. + throw new RuntimeException("EPICS run log already exists and allowUpdates is false."); + } else { + // Delete existing EPICS data. + runUpdater.deleteEpics(); + } + } + + // Insert EPICS data processed in the job for this run. + runUpdater.insertEpics(); } - // Insert the file log. - updater.insertFileLog(); + // Commit the transactions for this run. + LOGGER.info("committing transaction for run " + run); + connection.commit(); } } catch (final SQLException e) { @@ -106,15 +165,17 @@ try { connection.rollback(); } catch (final SQLException e2) { + LOGGER.log(Level.SEVERE, "error rolling back transaction", e2); throw new RuntimeException(e); } } finally { try { - connection.setAutoCommit(true); connection.close(); } catch (final SQLException e) { throw new RuntimeException(e); } } + + LOGGER.info("done inserting run data"); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java Wed Jun 10 13:10:16 2015 @@ -17,12 +17,11 @@ import org.lcsim.util.log.LogUtil; /** - * Processes all the EVIO files from a run. + * Processes all the EVIO files from a run in order to extract various information including start and end dates. * <p> - * This class is a wrapper for activating different sub-tasks, including optionally caching all files from the JLAB MSS to the cache disk using - * jcache. + * This class is a wrapper for activating different sub-tasks, including optionally caching all files from the JLAB MSS to the cache disk. * <p> - * There is also a list of processors which is run on all events from the run, if the processor list is not empty. + * There is also a list of processors which is run on all events from the run. * * @author Jeremy McCormick, SLAC */ @@ -106,6 +105,14 @@ LOGGER.info("done caching files from run " + this.runSummary.getRun()); } + /** + * Get the event count from the current <code>EvioReader</code>. + * + * @param reader the current <code>EvioReader</code> + * @return the event count + * @throws IOException if there is a generic IO error + * @throws EvioException if there is an EVIO related error + */ Integer computeEventCount(final EvioReader reader) throws IOException, EvioException { return reader.getEventCount(); } @@ -136,7 +143,8 @@ } /** - * Return <code>true</code> if valid END event can be located. + * Return <code>true</code> if a valid CODA <i>END</i> event can be located in the + * <code>EvioReader</code>'s current file. * * @param reader the EVIO reader * @return <code>true</code> if valid END event is located @@ -144,8 +152,13 @@ */ boolean isEndOkay(final EvioReader reader) throws Exception { LOGGER.info("checking is END okay ..."); + boolean endOkay = false; + + // Go to second to last event for searching. reader.gotoEventNumber(reader.getEventCount() - 2); + + // Look for END event. EvioEvent event = null; while ((event = reader.parseNextEvent()) != null) { if (event.getHeader().getTag() == EvioEventConstants.END_EVENT_TAG) { @@ -157,7 +170,10 @@ } /** - * Process the run. + * Process the run by executing the registered {@link org.hps.record.evio.EvioEventProcessor}s and + * performing special tasks such as the extraction of start and end dates. + * <p> + * This method will also activate file caching, if enabled by the {@link #useFileCache} option. * * @throws Exception if there is an error processing a file */ Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java Wed Jun 10 13:10:16 2015 @@ -190,9 +190,9 @@ for (final Object key : this.eventTypeCounts.keySet()) { ps.println(" " + key + ": " + this.eventTypeCounts.get(key)); } - ps.println("files" + this.files.size()); + ps.println("files " + this.files.size()); for (final File file : this.files) { - ps.println(file.getPath()); + ps.println(" " + file.getPath()); } } Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java Wed Jun 10 13:10:16 2015 @@ -5,13 +5,14 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; +import org.hps.record.epics.EpicsData; import org.lcsim.util.log.LogUtil; /** - * Utilities for updating or insert a run summary row into the run_log table. + * Updates the run database tables with information from a single run. * * @author Jeremy McCormick, SLAC */ @@ -36,7 +37,7 @@ * The run number (read from the summary in the constructor for convenience). */ private int run = -1; - + /** * Create a <code>RunSummaryUpdater</code> for the given <code>RunSummary</code>. * @@ -57,18 +58,18 @@ this.run = this.runSummary.getRun(); } - + /** * Execute a SQL update to modify an existing row in the database. * * @throws SQLException if there is an error executing the SQL statement */ - void updateRunLog() throws SQLException { + void updateRun() throws SQLException { PreparedStatement runLogStatement = null; runLogStatement = - connection.prepareStatement("UPDATE run_log SET start_date = ?, end_date = ?, nevents = ?, nfiles = ?, end_ok = ? where run = ?"); - LOGGER.info("preparing to update run " + run + " in run_log .."); + connection.prepareStatement("UPDATE runs SET start_date = ?, end_date = ?, nevents = ?, nfiles = ?, end_ok = ? where run = ?"); + LOGGER.info("preparing to update run " + run + " in runs table .."); runLogStatement.setTimestamp(1, new java.sql.Timestamp(runSummary.getStartDate().getTime())); runLogStatement.setTimestamp(2, new java.sql.Timestamp(runSummary.getEndDate().getTime())); runLogStatement.setInt(3, runSummary.getTotalEvents()); @@ -76,20 +77,19 @@ runLogStatement.setBoolean(5, runSummary.isEndOkay()); runLogStatement.setInt(6, run); runLogStatement.executeUpdate(); - connection.commit(); - LOGGER.info("run " + run + " was updated in run_log"); - } - - /** - * Insert a new row in the run_log table. + LOGGER.info("run " + run + " was updated"); + } + + /** + * Insert a new row in the <i>runs</i> table. * * @param connection the database connection * @throws SQLException if there is an error querying the database */ - void insertRunLog() throws SQLException { + void insertRun() throws SQLException { PreparedStatement statement = - connection.prepareStatement("INSERT INTO run_log (run, start_date, end_date, nevents, nfiles, end_ok) VALUES(?, ?, ?, ?, ?, ?)"); - LOGGER.info("preparing to insert run " + run + " into run_log .."); + connection.prepareStatement("INSERT INTO runs (run, start_date, end_date, nevents, nfiles, end_ok) VALUES(?, ?, ?, ?, ?, ?)"); + LOGGER.info("preparing to insert run " + run + " into runs table .."); statement.setInt(1, run); statement.setTimestamp(2, new java.sql.Timestamp(runSummary.getStartDate().getTime())); statement.setTimestamp(3, new java.sql.Timestamp(runSummary.getEndDate().getTime())); @@ -97,8 +97,7 @@ statement.setInt(5, runSummary.getEvioFileList().size()); statement.setBoolean(6, runSummary.isEndOkay()); statement.executeUpdate(); - connection.commit(); - LOGGER.info("insert run " + run + " to run_log"); + LOGGER.info("inserted run " + run + " to runs table"); } /** @@ -107,8 +106,8 @@ * @return <code>true</code> if there is an existing row for this run summary. * @throws SQLException if there is an error executing the SQL query */ - boolean runLogExists() throws SQLException { - PreparedStatement s = connection.prepareStatement("SELECT run from run_log where run = ?"); + boolean runExists() throws SQLException { + PreparedStatement s = connection.prepareStatement("SELECT run FROM runs where run = ?"); s.setInt(1, run); ResultSet rs = s.executeQuery(); return rs.first(); @@ -121,11 +120,11 @@ * @param run the run number * @throws SQLException if there is a problem executing one of the database queries */ - void insertFileLog() throws SQLException { + void insertFiles() throws SQLException { LOGGER.info("updating file list ..."); PreparedStatement filesStatement = null; - filesStatement = connection.prepareStatement("INSERT INTO run_log_files (run, directory, name) VALUES(?, ?, ?)"); - LOGGER.info("inserting files from run " + run + " into database"); + filesStatement = connection.prepareStatement("INSERT INTO run_files (run, directory, name) VALUES(?, ?, ?)"); + LOGGER.info("inserting files from run " + run + " into run_files ..."); for (final File file : runSummary.getEvioFileList()) { LOGGER.info("creating update statement for " + file.getPath()); filesStatement.setInt(1, run); @@ -134,8 +133,7 @@ LOGGER.info("executing statement: " + filesStatement); filesStatement.executeUpdate(); } - connection.commit(); - LOGGER.info("run_log_files was updated!"); + LOGGER.info("run_files was updated"); } /** @@ -144,27 +142,27 @@ * @param files the list of files * @throws SQLException if there is an error executing the SQL query */ - void deleteFileLog() throws SQLException { - LOGGER.info("deleting run_log_files for " + run + " ..."); - PreparedStatement s = connection.prepareStatement("DELETE FROM run_log_files where run = ?"); + void deleteFiles() throws SQLException { + LOGGER.info("deleting rows from run_files for " + run + " ..."); + PreparedStatement s = connection.prepareStatement("DELETE FROM run_files where run = ?"); s.setInt(1, run); s.executeUpdate(); - connection.commit(); - LOGGER.info("done deleting run_log_files for " + run); - } - - /** - * Delete the row for this run from the run_log table. - * - * @throws SQLException if there is an error executing the SQL query - */ - void deleteRunLog() throws SQLException { - LOGGER.info("deleting run_log for " + run + " ..."); - PreparedStatement s = connection.prepareStatement("DELETE FROM run_log where run = ?"); + LOGGER.info("done deleting rows from run_files for " + run); + } + + /** + * Delete the row for this run from the <i>runs</i> table. + * <p> + * This doesn't delete the rows from <i>run_epics</i> or <i>run_files</i>. + * + * @throws SQLException if there is an error executing the SQL query + */ + void deleteRun() throws SQLException { + LOGGER.info("deleting record from runs for " + run + " ..."); + PreparedStatement s = connection.prepareStatement("DELETE FROM runs where run = ?"); s.setInt(1, run); s.executeUpdate(); - connection.commit(); - LOGGER.info("done deleting run_log_files for " + run); + LOGGER.info("deleted rows from runs for " + run); } /** @@ -172,10 +170,54 @@ * @return <code>true</code> if there are file rows for this run * @throws SQLException if there is an error executing the SQL query */ - boolean fileLogExists() throws SQLException { - PreparedStatement s = connection.prepareStatement("SELECT run FROM run_log_files where run = ?"); + boolean filesExist() throws SQLException { + PreparedStatement s = connection.prepareStatement("SELECT run FROM run_files where run = ?"); s.setInt(1, run); ResultSet rs = s.executeQuery(); return rs.first(); } -} + + /** + * Insert EPICS data into the run_log_epics table. + * + * @throws SQLException if there is an error performing the db query + */ + void insertEpics() throws SQLException { + PreparedStatement statement = connection.prepareStatement("INSERT INTO run_epics (run, variable_name, value) values (?, ?, ?)"); + EpicsData data = runSummary.getEpicsData(); + if (data != null) { + for (String variableName : data.getUsedNames()) { + statement.setInt(1, this.run); + statement.setString(2, variableName); + statement.setDouble(3, data.getValue(variableName)); + statement.executeUpdate(); + } + } else { + LOGGER.warning("skipped inserting EPICS data (none found in RunSummary)"); + } + } + + /** + * Delete existing EPICS data from the run_log_epics table. + * + * @throws SQLException if there is an error performing the db query + */ + void deleteEpics() throws SQLException { + PreparedStatement statement = connection.prepareStatement("DELETE FROM run_epics WHERE run = ?"); + statement.setInt(1, this.run); + statement.executeUpdate(); + } + + /** + * Return <code>true</code> if there is an existing row for this run summary. + * + * @return <code>true</code> if there is an existing row for this run summary. + * @throws SQLException if there is an error executing the SQL query + */ + boolean epicsExists() throws SQLException { + PreparedStatement s = connection.prepareStatement("SELECT run from run_epics where run = ?"); + s.setInt(1, run); + ResultSet rs = s.executeQuery(); + return rs.first(); + } +} Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java (original) +++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java Wed Jun 10 13:10:16 2015 @@ -1,5 +1,5 @@ /** - * Implements an EVIO file crawler for extracting run and configuration information, including run start and end dates, event counts, etc. + * Implements an EVIO file crawler to extract run and configuration information, including run start and end dates, event counts, etc. * * @author Jeremy McCormick, SLAC */