Author: [log in to unmask] Date: Thu Sep 24 12:42:52 2015 New Revision: 3693 Log: Add command line tool for updating run database from EVIO files in the data catalog (needs to be tested). Added: java/trunk/run-database/src/main/java/org/hps/run/database/RunDatabaseCommandLine.java Modified: java/trunk/run-database/src/main/java/org/hps/run/database/RunManager.java Added: java/trunk/run-database/src/main/java/org/hps/run/database/RunDatabaseCommandLine.java ============================================================================= --- java/trunk/run-database/src/main/java/org/hps/run/database/RunDatabaseCommandLine.java (added) +++ java/trunk/run-database/src/main/java/org/hps/run/database/RunDatabaseCommandLine.java Thu Sep 24 12:42:52 2015 @@ -0,0 +1,272 @@ +package org.hps.run.database; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; +import org.hps.conditions.database.ConnectionParameters; +import org.hps.datacat.client.DatacatClient; +import org.hps.datacat.client.DatacatClientFactory; +import org.hps.datacat.client.Dataset; +import org.hps.record.evio.EvioFileUtilities; +import org.lcsim.util.log.DefaultLogFormatter; +import org.lcsim.util.log.LogUtil; + +/** + * Command line tool for updating the run database from the EVIO files in the data catalog. + * + * @author Jeremy McCormick, SLAC + */ +public class RunDatabaseCommandLine { + + /** + * Set of features supported by the tool. + */ + static enum Feature { + SUMMARY, + EPICS, + SCALERS, + TRIGGER_CONFIG + } + + /** + * Setup the logger. + */ + private static final Logger LOGGER = LogUtil.create(RunDatabaseCommandLine.class, new DefaultLogFormatter(), Level.ALL); + + /** + * Command line options for the crawler. + */ + private static final Options OPTIONS = new Options(); + + /** + * The run manager for interacting with the run db. + */ + private RunManager runManager; + + /** + * The set of enabled features. + */ + private Set<Feature> features = new HashSet<Feature>(); + + /** + * Allow updating of the database for existing runs. + */ + private boolean allowUpdates = false; + + /** + * Statically define the command options. + */ + static { + OPTIONS.addOption("f", "feature", true, "enable a feature"); + OPTIONS.addOption("p", "connection-properties", true, "database connection properties file (required)"); + OPTIONS.addOption("h", "help", false, "print help and exit (overrides all other arguments)"); + OPTIONS.addOption("r", "run", true, "run to update"); + OPTIONS.addOption("u", "update", false, "allow updating existing run in the database"); + } + + /** + * Run the program from the command line. + * + * @param args the command line arguments + */ + public static void main(String args[]) { + new RunDatabaseCommandLine().parse(args).run(); + } + + /** + * Parse command line options and return reference to <code>this</code>. + * + * @param args the command line arguments + * @return reference to this object + */ + RunDatabaseCommandLine parse(String args[]) { + try { + final CommandLine cl = new PosixParser().parse(OPTIONS, args); + + // Print help and exit. + if (cl.hasOption("h")) { + final HelpFormatter help = new HelpFormatter(); + help.printHelp("RunDatabaseCommandLine [options]", "", OPTIONS, ""); + System.exit(0); + } + + // Database connection properties file. + if (cl.hasOption("p")) { + final String dbPropPath = cl.getOptionValue("p"); + final File dbPropFile = new File(dbPropPath); + if (!dbPropFile.exists()) { + throw new IllegalArgumentException("Connection properties file " + dbPropFile.getPath() + + " does not exist."); + } + final ConnectionParameters connectionParameters = ConnectionParameters.fromProperties(dbPropFile); + LOGGER.config("using " + dbPropPath + " for db connection properties"); + + runManager = new RunManager(connectionParameters.createConnection()); + + } else { + // Database connection properties file is required. + throw new RuntimeException("Connection properties are required."); + } + + Integer run = null; + if (cl.hasOption("r")) { + run = Integer.parseInt(cl.getOptionValue("r")); + } else { + throw new RuntimeException("The run number is required."); + } + runManager.setRun(run); + + if (cl.hasOption("f")) { + // Enable individual features. + for (String arg : cl.getOptionValues("f")) { + features.add(Feature.valueOf(arg)); + } + } else { + // By default all features are enabled. + features.addAll(Arrays.asList(Feature.values())); + } + for (Feature feature : features) { + LOGGER.config("feature " + feature.name() + " is enabled."); + } + + // Allow updates to existing runs in the db. + if (cl.hasOption("u")) { + this.allowUpdates = true; + LOGGER.config("updating or replacing existing run data is enabled"); + } + + } catch (ParseException e) { + throw new RuntimeException(e); + } + + return this; + } + + /** + * Run the job to update the information in the run database. + */ + private void run() { + + boolean runExists = runManager.runExists(); + + // Fail if run exists and updates are not allowed. + if (runExists && !allowUpdates) { + throw new IllegalStateException("The run " + runManager.getRun() + " already exists and updates are not allowed."); + } + + // Get the run number configured from command line. + int run = runManager.getRun(); + + // Get the list of EVIO files for the run using a data catalog query. + List<File> files = getEvioFiles(run); + EvioFileUtilities.sortBySequence(files); + + // Process the run's files to get information. + RunSummaryImpl runSummary = new RunSummaryImpl(run); + RunProcessor runProcessor = this.createEvioRunProcessor(runSummary); + try { + runProcessor.processRun(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + // Delete existing run. + if (runExists) { + runManager.deleteRun(); + } + + // Insert run into database. + insertRun(runManager, runSummary); + + // Close the database connection. + runManager.closeConnection(); + } + + /** + * Insert information for a run into the database. + * + * @param runManager the run manager for interacting with the run db + * @param runSummary the run summary with information about the run + */ + private void insertRun(RunManager runManager, RunSummary runSummary) { + + RunDatabaseDaoFactory runFactory = new RunDatabaseDaoFactory(runManager.getConnection()); + + // Add the run summary record. + if (this.features.contains(Feature.SUMMARY)) { + runFactory.createRunSummaryDao().insertRunSummary(runSummary); + } + + // Does run exist now? + if (runManager.runExists()) { + + if (this.features.contains(Feature.EPICS)) { + runFactory.createEpicsDataDao().insertEpicsData(runSummary.getEpicsData()); + } + + if (this.features.contains(Feature.SCALERS)) { + runFactory.createScalerDataDao().insertScalerData(runSummary.getScalerData(), runManager.getRun()); + } + + if (this.features.contains(Feature.TRIGGER_CONFIG)) { + runFactory.createTriggerConfigDao().insertTriggerConfig(runSummary.getTriggerConfig(), runManager.getRun()); + } + } else { + // The run summary must be present to update any of the other information in the db. + throw new RuntimeException("Run " + runManager.getRun() + " does not exist in the database."); + } + } + + /** + * Create a run processor from the current configuration. + * + * @return the run processor + */ + private RunProcessor createEvioRunProcessor(final RunSummaryImpl runSummary) { + + final RunProcessor runProcessor = new RunProcessor(runSummary); + + if (features.contains(Feature.EPICS)) { + runProcessor.addEpicsProcessor(); + } + if (features.contains(Feature.SCALERS)) { + runProcessor.addScalerProcessor(); + } + if (features.contains(Feature.TRIGGER_CONFIG)) { + runProcessor.addTriggerTimeProcessor(); + } + + return runProcessor; + } + + /** + * Get the list of EVIO files for the run. + * + * @param run the run number + * @return the list of EVIO files from the run + */ + private List<File> getEvioFiles(int run) { + DatacatClient datacatClient = new DatacatClientFactory().createClient(); + Set<String> metadata = new HashSet<String>(); + List<Dataset> datasets = datacatClient.findDatasets("data/raw", "dataFormat eq 'EVIO' AND dataType eq 'RAW' AND runMin eq " + run, metadata); + if (datasets.isEmpty()) { + throw new IllegalStateException("No EVIO datasets for run " + run + " were found in the data catalog."); + } + List<File> files = new ArrayList<File>(); + for (Dataset dataset : datasets) { + files.add(new File(dataset.getLocations().get(0).getResource())); + } + return files; + } +} Modified: java/trunk/run-database/src/main/java/org/hps/run/database/RunManager.java ============================================================================= --- java/trunk/run-database/src/main/java/org/hps/run/database/RunManager.java (original) +++ java/trunk/run-database/src/main/java/org/hps/run/database/RunManager.java Thu Sep 24 12:42:52 2015 @@ -301,5 +301,14 @@ if (this.run == null) { throw new IllegalStateException("The run number was not set."); } - } + } + + /** + * Return the database connection. + * + * @return the database connection + */ + Connection getConnection() { + return this.connection; + } }