Author: [log in to unmask]
Date: Thu Jul 16 18:47:15 2015
New Revision: 3263
Log:
Latest iteration of the crawler and run db API. Add separate run package for getting run db info into a user job. HPSJAVA-558
Added:
java/trunk/record-util/src/main/java/org/hps/record/run/
java/trunk/record-util/src/main/java/org/hps/record/run/AbstractRunDatabaseReader.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/EvioFileListReader.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java
- copied, changed from r3257, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryReader.java
java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataReader.java
Removed:
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/ScalerDataUpdater.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/CrawlerConfig.java
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/EventTypeLog.java
java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileList.java
java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileUtilities.java
java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.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/RunSummaryUpdater.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 Thu Jul 16 18:47:15 2015
@@ -24,8 +24,8 @@
import org.lcsim.util.log.LogUtil;
/**
- * Search for EVIO files in a directory tree, group the files that are found by run, extract meta data from these
- * files, and optionally update a run database with the information that was found.
+ * Search for EVIO files in a directory tree, group the files that are found by run, extract meta data from these files,
+ * and optionally update a run database with the information that was found.
*
* @author Jeremy McCormick, SLAC
*/
@@ -64,6 +64,7 @@
OPTIONS.addOption("w", "max-cache-wait", true, "total time to allow for file caching (seconds)");
OPTIONS.addOption("L", "log-level", true, "set the log level (INFO, FINE, etc.)");
OPTIONS.addOption("u", "update", false, "allow overriding existing data in the run db (not allowed by default)");
+ OPTIONS.addOption("x", "max-depth", true, "max depth to crawl in the directory tree");
}
/**
@@ -85,14 +86,14 @@
private final JCacheManager cacheManager = new JCacheManager();
/**
+ * Configuration options from the command line.
+ */
+ private CrawlerConfig config;
+
+ /**
* The options parser.
*/
private final PosixParser parser = new PosixParser();
-
- /**
- * Configuration options from the command line.
- */
- private CrawlerConfig config;
/**
* Parse command line options and create a new {@link Crawler} object from the configuration.
@@ -129,7 +130,7 @@
throw new IllegalArgumentException("Connection properties file " + dbPropFile.getPath()
+ " does not exist.");
}
- ConnectionParameters connectionParameters = ConnectionParameters.fromProperties(dbPropFile);
+ final ConnectionParameters connectionParameters = ConnectionParameters.fromProperties(dbPropFile);
config.setConnection(connectionParameters);
LOGGER.config("using " + dbPropPath + " for db connection properties");
} else {
@@ -139,7 +140,7 @@
// Root directory for file crawling.
if (cl.hasOption("d")) {
- File rootDir = new File(cl.getOptionValue("d"));
+ final File rootDir = new File(cl.getOptionValue("d"));
if (!rootDir.exists()) {
throw new IllegalArgumentException("The directory does not exist.");
}
@@ -152,7 +153,7 @@
// Timestamp file for date filtering.
if (cl.hasOption("t")) {
- File timestampFile = new File(cl.getOptionValue("t"));
+ final File timestampFile = new File(cl.getOptionValue("t"));
config.setTimestampFile(timestampFile);
if (!timestampFile.exists()) {
try {
@@ -165,7 +166,7 @@
} else {
try {
// Get the date filter for files from an existing time stamp file provided by the user.
- Date timestamp = new Date(Files
+ final Date timestamp = new Date(Files
.readAttributes(config.timestampFile().toPath(), BasicFileAttributes.class)
.lastModifiedTime().toMillis());
config.setTimestamp(timestamp);
@@ -179,7 +180,7 @@
// List of one or more runs to accept in the job.
if (cl.hasOption("a")) {
- Set<Integer> acceptRuns = new HashSet<Integer>();
+ final Set<Integer> acceptRuns = new HashSet<Integer>();
for (final String runString : cl.getOptionValues("a")) {
final Integer acceptRun = Integer.parseInt(runString);
acceptRuns.add(acceptRun);
@@ -191,7 +192,7 @@
// Enable run log updating (off by default).
if (cl.hasOption("r")) {
config.setUpdateRunLog(true);
- LOGGER.config("updating run database is enabled");
+ LOGGER.config("inserting into run database is enabled");
}
// Enable file cache usage for running at JLAB.
@@ -202,21 +203,21 @@
// Max wait time for file caching.
if (cl.hasOption("w")) {
- Long waitTime = Long.parseLong(cl.getOptionValue("w")) * MILLISECONDS;
+ final Long waitTime = Long.parseLong(cl.getOptionValue("w")) * MILLISECONDS;
config.setWaitTime(waitTime);
LOGGER.config("max time for file caching set to " + config.waitTime());
}
// Max files to process per run; mostly just here for debugging purposes.
if (cl.hasOption("m")) {
- int maxFiles = Integer.parseInt(cl.getOptionValue("m"));
+ final int maxFiles = Integer.parseInt(cl.getOptionValue("m"));
config.setMaxFiles(maxFiles);
LOGGER.config("max files set to " + maxFiles);
}
// Event printing interval when doing EVIO event processing.
if (cl.hasOption("p")) {
- int eventPrintInterval = Integer.parseInt(cl.getOptionValue("p"));
+ final int eventPrintInterval = Integer.parseInt(cl.getOptionValue("p"));
config.setEventPrintInterval(eventPrintInterval);
LOGGER.config("event print interval set to " + eventPrintInterval);
}
@@ -224,7 +225,7 @@
// Flag to allow replacement of existing records in the database; not allowed by default.
if (cl.hasOption("u")) {
config.setAllowUpdates(true);
- LOGGER.config("replacement of existing run log information in database is enabled");
+ LOGGER.config("deletion and replacement of existing runs in the database is enabled");
}
// User supplied timestamp string that is converted to a date for file filtering.
@@ -253,6 +254,15 @@
}
}
+ // Max depth to crawl.
+ if (cl.hasOption("x")) {
+ final Integer maxDepth = Integer.parseInt(cl.getOptionValue("x"));
+ if (maxDepth < 1) {
+ throw new IllegalArgumentException("invalid -x argument for maxDepth: " + maxDepth);
+ }
+ config.setMaxDepth(maxDepth);
+ }
+
} catch (final ParseException e) {
throw new RuntimeException("Error parsing options.", e);
}
@@ -286,7 +296,7 @@
final EvioFileVisitor visitor = new EvioFileVisitor(config.timestamp());
// Walk the file tree using the visitor.
- walk(visitor);
+ this.walk(visitor);
// Get the list of run data created by the visitor.
final RunLog runs = visitor.getRunLog();
@@ -303,16 +313,22 @@
// Print the summary information after the run processing is done.
runs.printRunSummaries();
- // Execute the database update.
- executeRunLogUpdate(runs);
+ // Execute the run database update.
+ this.updateRunDatabase(runs);
// Update the timestamp output file.
- updateTimestamp();
+ this.updateTimestamp();
LOGGER.info("Crawler job is done!");
}
- private void executeRunLogUpdate(final RunLog runs) throws SQLException {
+ /**
+ * Update the database with information found from crawling the files.
+ *
+ * @param runs the list of runs to update
+ * @throws SQLException if there is a database query error
+ */
+ private void updateRunDatabase(final RunLog runs) throws SQLException {
// Insert the run information into the database.
if (config.updateRunLog()) {
@@ -330,28 +346,11 @@
}
}
- private void walk(final EvioFileVisitor visitor) {
- if (config.timestamp() != null) {
- // Date filter from timestamp.
- visitor.addFilter(new DateFileFilter(config.timestamp()));
- LOGGER.config("added date filter " + config.timestamp());
- }
-
- if (!config.acceptRuns().isEmpty()) {
- // List of run numbers to accept.
- visitor.addFilter(new RunFilter(config.acceptRuns()));
- LOGGER.config("added run number filter");
- }
-
- try {
- // Walk the file tree from the root directory.
- final EnumSet<FileVisitOption> options = EnumSet.noneOf(FileVisitOption.class);
- Files.walkFileTree(config.rootDir().toPath(), options, Integer.MAX_VALUE, visitor);
- } catch (final IOException e) {
- throw new RuntimeException("Error while walking the directory tree.", e);
- }
- }
-
+ /**
+ * Update the timestamp file's modification date to the time when this job ended.
+ * <p>
+ * This can be then be used in subsequent crawl jobs to filter out files that have already been seen.
+ */
private void updateTimestamp() {
// Update the timestamp file which can be used to tell which files have been processed by their creation date.
if (config.timestampFile() == null) {
@@ -366,4 +365,33 @@
config.timestampFile().setLastModified(System.currentTimeMillis());
LOGGER.config("set modified on timestamp file: " + new Date(config.timestampFile().lastModified()));
}
+
+ /**
+ * Walk the directory tree to find EVIO files for the runs that are being processed in the job.
+ *
+ * @param visitor the file visitor
+ */
+ private void walk(final EvioFileVisitor visitor) {
+ if (config.timestamp() != null) {
+ // Date filter from timestamp.
+ visitor.addFilter(new DateFileFilter(config.timestamp()));
+ LOGGER.config("added date filter with time stamp " + config.timestamp());
+ }
+
+ if (!config.acceptRuns().isEmpty()) {
+ // List of run numbers to accept.
+ visitor.addFilter(new RunFilter(config.acceptRuns()));
+ LOGGER.config("added run number filter");
+ } else {
+ LOGGER.config("no run number filter used");
+ }
+
+ try {
+ // Walk the file tree from the root directory.
+ final EnumSet<FileVisitOption> options = EnumSet.noneOf(FileVisitOption.class);
+ Files.walkFileTree(config.rootDir().toPath(), options, config.maxDepth(), visitor);
+ } catch (final IOException e) {
+ throw new RuntimeException("Error while walking the directory tree.", e);
+ }
+ }
}
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 Thu Jul 16 18:47:15 2015
@@ -14,7 +14,7 @@
/**
* Full configuration information for the {@link Crawler class}.
* <p>
- * The setter methods use the builder pattern so method chaining them is possible.
+ * Method chaining of setters is supported.
*
* @author Jeremy McCormick, SLAC
*/
@@ -23,7 +23,22 @@
/**
* The format for input timestamps used for file filtering.
*/
- private static final SimpleDateFormat TIMESTAMP_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ 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;
+
+ /**
+ * <code>true</code> if database updates are allowed meaning existing records can be deleted and replaced.
+ */
+ private boolean allowUpdates = false;
+
+ /**
+ * The database connection parameters which must be provided by command line argument.
+ */
+ private ConnectionParameters connectionParameters;
/**
* Default event print interval.
@@ -36,19 +51,9 @@
private int eventPrintInterval = DEFAULT_EVENT_PRINT_INTERVAL;
/**
- * A list of run numbers to accept in the job.
- */
- private Set<Integer> acceptRuns;
-
- /**
- * <code>true</code> if database updates are allowed meaning existing records can be deleted and replaced.
- */
- private boolean allowUpdates = false;
-
- /**
- * The database connection parameters which must be provided by command line argument.
- */
- private ConnectionParameters connectionParameters;
+ * The maximum depth to crawl.
+ */
+ private Integer maxDepth = Integer.MAX_VALUE;
/**
* The maximum number of files to accept (just used for debugging purposes).
@@ -91,8 +96,17 @@
private Long waitTime;
/**
+ * Get the set of runs that will be accepted for the job.
+ *
+ * @return the list of runs that will be accepted
+ */
+ Set<Integer> acceptRuns() {
+ return acceptRuns;
+ }
+
+ /**
* Add an {@link org.hps.record.evio.EvioEventProcessor} to the job.
- *
+ *
* @param processor
* @return this object
*/
@@ -103,22 +117,87 @@
/**
* Add an {@link org.hps.record.evio.EvioEventProcessor} to the job by its class name.
- *
+ *
* @param processor the <code>EvioEventProcessor</code> to instantiate
* @return this object
*/
CrawlerConfig addProcessor(final String className) {
try {
this.processors.add(EvioEventProcessor.class.cast(Class.forName(className).newInstance()));
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException("Error creating EvioEventProcessor with type: " + className, e);
}
return this;
}
/**
+ * Return <code>true</code> if updates/deletions of existing records in the database is allowed.
+ *
+ * @return <code>true</code> if updating/deleting records in the database is allowed
+ */
+ boolean allowUpdates() {
+ return allowUpdates;
+ }
+
+ /**
+ * Get the database connection parameters.
+ *
+ * @return the database connection parameters
+ */
+ ConnectionParameters connectionParameters() {
+ return connectionParameters;
+ }
+
+ /**
+ * Get the event print interval.
+ *
+ * @return the event print interval
+ */
+ int eventPrintInterval() {
+ return this.eventPrintInterval;
+ }
+
+ /**
+ * Get the max depth in the directory tree to crawl.
+ *
+ * @return the max depth
+ */
+ Integer maxDepth() {
+ return maxDepth;
+ }
+
+ /**
+ * Get the maximum number of files that the job can process.
+ *
+ * @return the maximum number of files
+ */
+ int maxFiles() {
+ return maxFiles;
+ }
+
+ /**
+ * Get the list of extra event processors that will run with the job.
+ * <p>
+ * Required (default) processors for the job are not included here.
+ *
+ * @return the list of extra event processors
+ */
+ List<EvioEventProcessor> processors() {
+ return processors;
+ }
+
+ /**
+ * Get the root directory for the file search.
+ *
+ * @return the root directory for the file search
+ */
+ File rootDir() {
+ return rootDir;
+ }
+
+ /**
* Set the list of run numbers that should be accepted.
- *
+ *
* @param acceptRuns the list of acceptable run numbers
* @return this object
*/
@@ -129,7 +208,7 @@
/**
* Set whether database updates are allowed, i.e. replacement of existing records.
- *
+ *
* @param allowUpdates <code>true</code> to allow database record deletion/updates
* @return this object
*/
@@ -140,7 +219,7 @@
/**
* Set the database connection parameters.
- *
+ *
* @param connectionParameters the database connection parameters
* @return this object
*/
@@ -150,10 +229,30 @@
}
/**
+ * Set the interval for printing the EVIO event numbers during processing.
+ *
+ * @param eventPrintInterval the event print interval
+ * @return this object
+ */
+ CrawlerConfig setEventPrintInterval(final int eventPrintInterval) {
+ this.eventPrintInterval = eventPrintInterval;
+ return this;
+ }
+
+ /**
+ * Set the max depth.
+ *
+ * @param maxDepth the max depth
+ */
+ void setMaxDepth(final Integer maxDepth) {
+ this.maxDepth = maxDepth;
+ }
+
+ /**
* Set the maximum number of files that will be processed by the job.
* <p>
* This should only be used for debugging purposes as it results in incorrect event counts for the run.
- *
+ *
* @param maxFiles the maximum number of files to process or -1 for unlimited
* @return this object
*/
@@ -164,11 +263,11 @@
/**
* Set the root directory for the file search.
- *
+ *
* @param rootDir the root directory for the file search
* @return this object
*/
- CrawlerConfig setRootDir(File rootDir) {
+ CrawlerConfig setRootDir(final File rootDir) {
this.rootDir = rootDir;
return this;
}
@@ -177,11 +276,11 @@
* Set a date for filtering input files.
* <p>
* Those files created before this date will not be processed.
- *
+ *
* @param timestamp the date for filtering files
* @return this object
*/
- CrawlerConfig setTimestamp(Date timestamp) {
+ CrawlerConfig setTimestamp(final Date timestamp) {
this.timestamp = timestamp;
return this;
}
@@ -191,22 +290,22 @@
* <code>TIMESTAMP_DATE_FORMAT</code>.
* <p>
* Those files created before this date will not be processed.
- *
+ *
* @param timestamp the date string for filtering files
* @return this object
*/
- CrawlerConfig setTimestamp(String timestampString) throws ParseException {
- TIMESTAMP_DATE_FORMAT.parse(timestampString);
+ CrawlerConfig setTimestamp(final String timestampString) throws ParseException {
+ TIMESTAMP_FORMAT.parse(timestampString);
return this;
}
/**
* Set a date for filtering files based on the modification date of a timestamp file.
- *
+ *
* @param timestampFile the timestamp file for date filtering
* @return this object
*/
- CrawlerConfig setTimestampFile(File timestampFile) {
+ CrawlerConfig setTimestampFile(final File timestampFile) {
this.timestampFile = timestampFile;
return this;
}
@@ -216,11 +315,11 @@
* <p>
* This will not allow replacement of existing run log records. The {@link #allowUpdates()} flag must be on for this
* be allowed.
- *
+ *
* @param updateRunLog <code>true</code> if the run database should be updated
* @return this object
*/
- CrawlerConfig setUpdateRunLog(boolean updateRunLog) {
+ CrawlerConfig setUpdateRunLog(final boolean updateRunLog) {
this.updateRunLog = updateRunLog;
return this;
}
@@ -229,11 +328,11 @@
* Set whether file caching using the 'jcache' program should be enabled.
* <p>
* This is only relevant for jobs run at JLAB.
- *
+ *
* @param useFileCache <code>true</code> to allow file caching
* @return this object
*/
- CrawlerConfig setUseFileCache(boolean useFileCache) {
+ CrawlerConfig setUseFileCache(final boolean useFileCache) {
this.useFileCache = useFileCache;
return this;
}
@@ -242,87 +341,20 @@
* Set the max wait time in seconds for all file caching operations to complete.
* <p>
* If this time is exceeded then the job will fail with an error.
- *
+ *
* @param waitTime the max wait time in seconds allowed for file caching to complete
* @return this object
*/
- CrawlerConfig setWaitTime(long waitTime) {
+ CrawlerConfig setWaitTime(final long waitTime) {
this.waitTime = waitTime;
return this;
}
/**
- * Set the interval for printing the EVIO event numbers during processing.
- *
- * @param eventPrintInterval the event print interval
- * @return this object
- */
- CrawlerConfig setEventPrintInterval(int eventPrintInterval) {
- this.eventPrintInterval = eventPrintInterval;
- return this;
- }
-
- /**
- * Get the set of runs that will be accepted for the job.
- *
- * @return the list of runs that will be accepted
- */
- Set<Integer> acceptRuns() {
- return acceptRuns;
- }
-
- /**
- * Return <code>true</code> if updates/deletions of existing records in the database is allowed.
- *
- * @return <code>true</code> if updating/deleting records in the database is allowed
- */
- boolean allowUpdates() {
- return allowUpdates;
- }
-
- /**
- * Get the database connection parameters.
- *
- * @return the database connection parameters
- */
- ConnectionParameters connectionParameters() {
- return connectionParameters;
- }
-
- /**
- * Get the maximum number of files that the job can process.
- *
- * @return the maximum number of files
- */
- int maxFiles() {
- return maxFiles;
- }
-
- /**
- * Get the list of extra event processors that will run with the job.
- * <p>
- * Required (default) processors for the job are not included here.
- *
- * @return the list of extra event processors
- */
- List<EvioEventProcessor> processors() {
- return processors;
- }
-
- /**
- * Get the root directory for the file search.
- *
- * @return the root directory for the file search
- */
- File rootDir() {
- return rootDir;
- }
-
- /**
* Get the timestamp for file filtering.
* <p>
* Files older than this will not be included in the job.
- *
+ *
* @return the timestamp for file filtering
*/
Date timestamp() {
@@ -331,7 +363,7 @@
/**
* Get the timestamp file using for filtering EVIO files.
- *
+ *
* @return the timestamp file used for filtering EVIO files (can be null)
*/
File timestampFile() {
@@ -340,7 +372,7 @@
/**
* Return <code>true</code> if the run database should be updated.
- *
+ *
* @return <code>true</code> if the run database should be updated
*/
boolean updateRunLog() {
@@ -349,7 +381,7 @@
/**
* Return <code>true</code> if file caching should be enabled.
- *
+ *
* @return <code>true</code> if file caching should be enabled
*/
boolean useFileCache() {
@@ -358,19 +390,10 @@
/**
* Get the max wait time in seconds to allow for file caching operations to complete.
- *
+ *
* @return the max wait time in seconds to allow for file caching operations to complete
*/
Long waitTime() {
return waitTime;
}
-
- /**
- * Get the event print interval.
- *
- * @return the event print interval
- */
- int eventPrintInterval() {
- return this.eventPrintInterval;
- }
}
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 Thu Jul 16 18:47:15 2015
@@ -16,18 +16,18 @@
final class EpicsLog extends EvioEventProcessor {
/**
- * A count of how many times a given EPICS variable is found in the input, e.g. for computing the mean value across
- * the entire run.
+ * A count of how many times a given EPICS variable is found in the input for computing the mean value across the
+ * entire run.
*/
private final Map<String, Integer> counts = new HashMap<String, Integer>();
/**
* The current EPICS data block from the EVIO events (last one that was found).
*/
- private EpicsData currentData;
+ private EpicsData currentEpicsData;
/**
- * The summary information for the variables from computing the mean across the whole run.
+ * The summary information for the variables computed from the mean values across the whole run.
*/
private final EpicsData logData = new EpicsData();
@@ -37,17 +37,9 @@
private final EpicsEvioProcessor processor = new EpicsEvioProcessor();
/**
- * Reference to the run summary which will contain the EPICs information.
+ * Create an EPICs log.
*/
- private final RunSummary runSummary;
-
- /**
- * Create an EPICs log pointing to a run summary.
- *
- * @param runSummary the run summary
- */
- EpicsLog(final RunSummary runSummary) {
- this.runSummary = runSummary;
+ EpicsLog() {
}
/**
@@ -63,9 +55,15 @@
final double mean = total / this.counts.get(name);
this.logData.setValue(name, mean);
}
+ }
- // Set the EPICS data on the run summary.
- this.runSummary.setEpicsData(this.logData);
+ /**
+ * Get the {@link org.hps.record.epics.EpicsData} which contains mean values for the run.
+ *
+ * @return the {@link org.hps.record.epics.EpicsData} for the run
+ */
+ EpicsData getEpicsData() {
+ return this.logData;
}
/**
@@ -74,7 +72,7 @@
@Override
public void process(final EvioEvent evioEvent) {
this.processor.process(evioEvent);
- this.currentData = this.processor.getEpicsData();
+ this.currentEpicsData = this.processor.getEpicsData();
this.update();
}
@@ -84,8 +82,8 @@
* If the current data is <code>null</code>, this method does nothing.
*/
private void update() {
- if (this.currentData != null) {
- for (final String name : this.currentData.getUsedNames()) {
+ if (this.currentEpicsData != null) {
+ for (final String name : this.currentEpicsData.getUsedNames()) {
if (!this.logData.getUsedNames().contains(name)) {
this.logData.setValue(name, 0.);
}
@@ -95,7 +93,7 @@
int count = this.counts.get(name);
count += 1;
this.counts.put(name, count);
- final double value = this.logData.getValue(name) + this.currentData.getValue(name);
+ final double value = this.logData.getValue(name) + this.currentEpicsData.getValue(name);
this.logData.setValue(name, value);
// 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/EventTypeLog.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EventTypeLog.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EventTypeLog.java Thu Jul 16 18:47:15 2015
@@ -22,11 +22,6 @@
private final Map<Object, Integer> eventTypeCounts = new HashMap<Object, Integer>();
/**
- * The run summary to update.
- */
- private final RunSummary runSummary;
-
- /**
* The total number of physics events processed.
*/
private int physicsEventCount = 0;
@@ -36,22 +31,13 @@
*
* @param runSummary the run summary
*/
- EventTypeLog(final RunSummary runSummary) {
- this.runSummary = runSummary;
+ EventTypeLog() {
for (final EventTagConstant constant : EventTagConstant.values()) {
this.eventTypeCounts.put(constant, 0);
}
for (final EventTagBitMask mask : EventTagBitMask.values()) {
this.eventTypeCounts.put(mask, 0);
}
- }
-
- /**
- * End of job hook which sets the event type counts on the run summary.
- */
- @Override
- public void endJob() {
- this.runSummary.setEventTypeCounts(this.eventTypeCounts);
}
/**
@@ -65,7 +51,7 @@
/**
* Get the number of physics events counted.
- *
+ *
* @return the number of physics events counted
*/
int getPhysicsEventCount() {
@@ -79,7 +65,7 @@
*/
@Override
public void process(final EvioEvent event) {
-
+
// Increment counts for exact event tag values.
for (final EventTagConstant constant : EventTagConstant.values()) {
if (constant.isEventTag(event)) {
@@ -87,7 +73,7 @@
this.eventTypeCounts.put(constant, count);
}
}
-
+
// Increment counts for bit masking of tags.
for (final EventTagBitMask mask : EventTagBitMask.values()) {
if (mask.isEventTag(event)) {
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileList.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileList.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileList.java Thu Jul 16 18:47:15 2015
@@ -4,23 +4,21 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.logging.Logger;
-
-import org.lcsim.util.log.LogUtil;
/**
* This is a list of <code>File</code> objects that are assumed to be EVIO files.
*
* @author Jeremy McCormick, SLAC
*/
-final class EvioFileList extends ArrayList<File> {
+@SuppressWarnings("serial")
+public final class EvioFileList extends ArrayList<File> {
/**
* Get the first file.
*
* @return the first file
*/
- File first() {
+ public File first() {
return this.get(0);
}
@@ -29,14 +27,14 @@
*
* @return the last file
*/
- File last() {
+ public File last() {
return this.get(this.size() - 1);
}
/**
* Sort the files in-place by their sequence number.
*/
- void sort() {
+ public void sort() {
final List<File> fileList = new ArrayList<File>(this);
Collections.sort(fileList, new EvioFileSequenceComparator());
this.clear();
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileUtilities.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileUtilities.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileUtilities.java Thu Jul 16 18:47:15 2015
@@ -115,23 +115,23 @@
* @return the run end date
*/
static Date getRunEnd(final File file) {
-
+
// Search for the END event in the last 10 events of the file.
Date endDate = getControlDate(file, EvioEventConstants.END_EVENT_TAG, -10);
-
+
// Was the end date found from the END event?
if (endDate == null) {
-
+
EvioReader reader = null;
try {
reader = open(file, true);
-
+
// Search for the last physics event in the last 10 events of the file.
reader.gotoEventNumber(reader.getEventCount() - 10);
EvioEvent event = null;
while ((event = reader.parseNextEvent()) != null) {
if (EvioEventUtilities.isPhysicsEvent(event)) {
- Date eventDate = getHeadBankDate(event);
+ final Date eventDate = getHeadBankDate(event);
if (eventDate != null) {
// This might be set multiple times but should result in the time of the last physics event.
endDate = eventDate;
@@ -176,13 +176,13 @@
* @return the run start date
*/
static Date getRunStart(final File file) {
-
+
// First try to find the start date in the special PRESTART event.
Date date = getControlDate(file, EvioEventConstants.PRESTART_EVENT_TAG, 0);
-
+
// Was start date not found from PRESTART?
if (date == null) {
-
+
// Read events until there is a physics event and use its time for the start date.
EvioReader reader = null;
try {
@@ -271,7 +271,7 @@
final long start = System.currentTimeMillis();
final EvioReader reader = new EvioReader(openFile, false, sequential);
final long end = System.currentTimeMillis() - start;
- LOGGER.info("opened " + openFile.getPath() + " in " + end / MILLISECONDS + " seconds");
+ LOGGER.info("opened " + openFile.getPath() + " in " + (double) end / (double) MILLISECONDS + " seconds");
return reader;
}
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java Thu Jul 16 18:47:15 2015
@@ -22,6 +22,11 @@
/**
* Utility class for caching files from the MSS to cache disk at JLAB.
+ * <p>
+ * This class should <b>not</b> be activated when running the crawler on the Auger batch system as it will take up a lot
+ * of job time caching files, which is part of Auger's job staging that doesn't count towards the job time.
+ * <p>
+ * It is fine to use running on an interactive <i>ifarm</i> node at JLAB.
*
* @author Jeremy McCormick, SLAC
*/
@@ -66,6 +71,19 @@
CacheStatus(final File file, final Integer requestId) {
this.file = file;
this.requestId = requestId;
+ }
+
+ /**
+ * Get the error message from the XML request.
+ *
+ * @return the error message from the XML request
+ */
+ String getErrorMessage() {
+ if (this.xml.getChild("request").getChild("file").getChild("error") != null) {
+ return this.xml.getChild("request").getChild("file").getChild("error").getText();
+ } else {
+ return "";
+ }
}
/**
@@ -135,6 +153,13 @@
}
/**
+ * Return <code>true</code> if status is "failed".
+ */
+ boolean isFailed() {
+ return "failed".equals(this.status);
+ }
+
+ /**
* Return <code>true</code> if status is "hit".
*
* @return <code>true</code> if status is "hit"
@@ -153,28 +178,8 @@
}
/**
- * Return <code>true</code> if status is "failed".
- */
- boolean isFailed() {
- return "failed".equals(this.status);
- }
-
- /**
- * Get the error message from the XML request.
- *
- * @return the error message from the XML request
- */
- String getErrorMessage() {
- if (this.xml.getChild("request").getChild("file").getChild("error") != null) {
- return this.xml.getChild("request").getChild("file").getChild("error").getText();
- } else {
- return "";
- }
- }
-
- /**
* Run the <i>jcache request</i> command for this request ID and return the XML output.
- *
+ *
* @return the XML output from the <i>jcache request</i> command
*/
private Element request() {
@@ -201,7 +206,7 @@
*/
void update() {
// Request status update and get the XML from that process.
- this.xml = request();
+ this.xml = this.request();
// Update the status from the XML.
this.status = this.xml.getChild("request").getChild("file").getChildText("status");
@@ -340,60 +345,57 @@
}
/**
- * Return <code>true</code> if all files registered with the manager are cached.
+ * Return <code>true</code> if all files registered with the manager have been cached.
*
* @return <code>true</code> if all files registered with the manager are cached
*/
boolean checkCacheStatus() {
- // Flag which will be changed to false if we find non-cached files in the loop.
+ // Flag which will be changed to false if we find files that are not cached yet.
boolean allCached = true;
- // Loop over all cache statuses and refresh/check them.
+ // Loop over all files, refresh the status, and check that they are cached.
for (final Entry<File, CacheStatus> entry : this.cacheStatuses.entrySet()) {
- // Get the cache status for a single file.
+ // Get the cache status the file.
final CacheStatus cacheStatus = entry.getValue();
LOGGER.info("checking status of " + cacheStatus.getFile().getPath() + " with req ID '"
+ cacheStatus.getRequestId() + "' ...");
- // Is this file flagged as not non-cached?
+ // Does the file's status indicate it is not cached yet?
if (!cacheStatus.isCached()) {
+ // Update the cache status to see if it has changed.
LOGGER.info("updating status of " + cacheStatus.getFile().getPath() + " ...");
-
- // Update the cache status to see if it changed since last check.
cacheStatus.update();
- // Is status still non-cached after status update?
+ // Is this file's status still non-cached after the status update?
if (!cacheStatus.isCached()) {
// Set flag which indicates at least one file is not cached yet.
allCached = false;
LOGGER.info(entry.getKey() + " is NOT cached with status " + cacheStatus.getStatus(false));
- } else {
- // Log that this file is now cached. It will not be checked next time.
- LOGGER.info(cacheStatus.getFile().getPath() + " is cached with status "
- + cacheStatus.getStatus(false));
- }
-
- // Did the request fail?
- if (cacheStatus.isFailed()) {
+
+ break;
+
+ } else if (cacheStatus.isFailed()) {
// Cache failure is a fatal error.
LOGGER.severe("cache request failed with error: " + cacheStatus.getErrorMessage());
throw new RuntimeException("Cache request failed.");
+ } else {
+ // Log that this file is now cached. It will not be checked next time this method is called.
+ LOGGER.info(cacheStatus.getFile().getPath() + " is now cached with status "
+ + cacheStatus.getStatus(false));
}
- } else {
- LOGGER.info(cacheStatus.getFile().getPath() + " is already cached");
}
}
return allCached;
}
/**
- * Clear all cache statuses, which means files are no longer tracked by this manager.
+ * Clear the cache statuses which means the manager will no longer track any of the files that were registered.
*/
void clear() {
this.cacheStatuses.clear();
@@ -402,7 +404,7 @@
}
/**
- * Get the request ID from a process that ran the 'jcache request' command.
+ * Parse out the request ID from the output of a 'jcache request' process.
*
* @param process the system process
* @return the request ID
@@ -524,7 +526,7 @@
cached = true;
break;
} else {
- LOGGER.info(this.getUncachedCount() + " files still uncached");
+ LOGGER.info(this.getUncachedCount() + " files are not cached");
}
// Sleep for awhile before checking the cache statuses again.
@@ -537,7 +539,7 @@
}
}
- double end = (double) (System.currentTimeMillis() - this.start);
+ final double end = System.currentTimeMillis() - this.start;
LOGGER.info("caching took " + new DecimalFormat("#.##").format(end / 1000. / 60.) + " minutes");
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 Thu Jul 16 18:47:15 2015
@@ -8,6 +8,7 @@
import java.util.Map;
import java.util.logging.Logger;
+import org.hps.record.run.RunSummary;
import org.lcsim.util.log.LogUtil;
/**
@@ -70,7 +71,7 @@
*/
void printRunSummaries() {
for (final int run : this.runs.keySet()) {
- this.runs.get(run).printRunSummary(System.out);
+ this.runs.get(run).printOut(System.out);
}
}
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 Thu Jul 16 18:47:15 2015
@@ -5,6 +5,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.hps.record.run.RunSummary;
import org.lcsim.util.log.LogUtil;
/**
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 Thu Jul 16 18:47:15 2015
@@ -10,6 +10,7 @@
import org.hps.record.evio.EvioEventConstants;
import org.hps.record.evio.EvioEventProcessor;
+import org.hps.record.run.RunSummary;
import org.hps.record.scalers.ScalersEvioProcessor;
import org.jlab.coda.jevio.EvioEvent;
import org.jlab.coda.jevio.EvioException;
@@ -35,19 +36,89 @@
private static final Logger LOGGER = LogUtil.create(RunProcessor.class, new DefaultLogFormatter(), Level.FINE);
/**
+ * Process all the runs that were found.
+ *
+ * @param runs the run log containing the list of run summaries
+ * @throws Exception if there is an error processing one of the runs
+ */
+ static void processRuns(final JCacheManager cacheManager, final RunLog runs, final CrawlerConfig config)
+ throws Exception {
+
+ // Configure max wait time of jcache manager.
+ if (config.waitTime() != null && config.waitTime() > 0L) {
+ cacheManager.setWaitTime(config.waitTime());
+ LOGGER.config("JCacheManager max wait time set to " + config.waitTime());
+ }
+
+ // Process all of the runs that were found.
+ for (final int run : runs.getSortedRunNumbers()) {
+
+ // Get the run summary.
+ final RunSummary runSummary = runs.getRunSummary(run);
+
+ // Clear the cache manager.
+ if (config.useFileCache()) {
+ cacheManager.clear();
+ }
+
+ // Create a processor to process all the EVIO events in the run.
+ final RunProcessor runProcessor = new RunProcessor(cacheManager, runSummary, config);
+
+ // Add extra processors.
+ for (final EvioEventProcessor processor : config.processors()) {
+ runProcessor.addProcessor(processor);
+ LOGGER.config("added extra EVIO processor " + processor.getClass().getName());
+ }
+
+ // Process all of the run's files.
+ runProcessor.process();
+ }
+ }
+
+ /**
+ * The cache manager.
+ */
+ private final JCacheManager cacheManager;
+
+ /**
* Processor for extracting EPICS information.
*/
- private EpicsLog epicsLog;
+ private final EpicsLog epicsLog;
+
+ /**
+ * The event printing interval when processing EVIO files.
+ */
+ private int eventPrintInterval = 1000;
+
+ /**
+ * Processor for extracting event type counts (sync, physics, trigger types, etc.).
+ */
+ private final EventTypeLog eventTypeLog;
+
+ /**
+ * Max files to read (defaults to unlimited).
+ */
+ private int maxFiles = -1;
+
+ /**
+ * The list of EVIO processors to run on the files that are found.
+ */
+ private final List<EvioEventProcessor> processors = new ArrayList<EvioEventProcessor>();
+
+ /**
+ * The run summary information updated by running this processor.
+ */
+ private final RunSummary runSummary;
/**
* Processor for extracting scaler data.
*/
- private ScalersEvioProcessor scalersProcessor;
-
- /**
- * Processor for extracting event type counts (sync, physics, trigger types, etc.).
- */
- private EventTypeLog eventTypeLog;
+ private final ScalersEvioProcessor scalersProcessor;
+
+ /**
+ * Set to <code>true</code> to use file caching.
+ */
+ private boolean useFileCache;
/**
* Create the processor for a single run.
@@ -55,65 +126,35 @@
* @param runSummary the run summary for the run
* @return the run processor
*/
- RunProcessor(final JCacheManager cacheManager, final RunSummary runSummary, CrawlerConfig config) {
+ RunProcessor(final JCacheManager cacheManager, final RunSummary runSummary, final CrawlerConfig config) {
this.runSummary = runSummary;
this.cacheManager = cacheManager;
// EPICS processor.
- epicsLog = new EpicsLog(runSummary);
- addProcessor(epicsLog);
+ epicsLog = new EpicsLog();
+ this.addProcessor(epicsLog);
// Scaler data processor.
scalersProcessor = new ScalersEvioProcessor();
scalersProcessor.setResetEveryEvent(false);
- addProcessor(scalersProcessor);
+ this.addProcessor(scalersProcessor);
// Event log processor.
- eventTypeLog = new EventTypeLog(runSummary);
- addProcessor(eventTypeLog);
+ eventTypeLog = new EventTypeLog();
+ this.addProcessor(eventTypeLog);
// Max files.
if (config.maxFiles() != -1) {
- setMaxFiles(config.maxFiles());
+ this.setMaxFiles(config.maxFiles());
}
// Enable file caching.
- useFileCache(config.useFileCache());
+ this.useFileCache(config.useFileCache());
// Set event printing interval.
- setEventPrintInterval(config.eventPrintInterval());
- }
-
- /**
- * The cache manager.
- */
- private final JCacheManager cacheManager;
-
- /**
- * The event printing interval when processing EVIO files.
- */
- private int eventPrintInterval = 1000;
-
- /**
- * Max files to read (defaults to unlimited).
- */
- private int maxFiles = -1;
-
- /**
- * The list of EVIO processors to run on the files that are found.
- */
- private final List<EvioEventProcessor> processors = new ArrayList<EvioEventProcessor>();
-
- /**
- * The run summary information updated by running this processor.
- */
- private final RunSummary runSummary;
-
- /**
- * Set to <code>true</code> to use file caching.
- */
- private boolean useFileCache;
+ this.setEventPrintInterval(config.eventPrintInterval());
+ }
/**
* Add a processor of EVIO events.
@@ -235,7 +276,7 @@
processor.startJob();
}
- List<File> files = this.getFiles();
+ final List<File> files = this.getFiles();
LOGGER.info("processing " + files.size() + " from run " + this.runSummary.getRun());
@@ -248,6 +289,18 @@
for (final EvioEventProcessor processor : this.processors) {
processor.endJob();
}
+
+ // Put scaler data from EVIO processor into run summary.
+ runSummary.setScalerData(this.scalersProcessor.getScalerData());
+
+ // Set the counts of event types on the run summary.
+ runSummary.setEventTypeCounts(eventTypeLog.getEventTypeCounts());
+
+ // Set total number of physics events on the run summary from the event counter.
+ runSummary.setTotalEvents(this.eventTypeLog.getPhysicsEventCount());
+
+ // Set EpicsData for the run.
+ runSummary.setEpicsData(this.epicsLog.getEpicsData());
LOGGER.info("done processing run " + this.runSummary.getRun());
}
@@ -297,7 +350,7 @@
LOGGER.info("done running EVIO processors");
// Check if END event is present if this is the last file in the run.
- if (file.equals(getFiles().get(getFiles().size() - 1))) {
+ if (file.equals(this.getFiles().get(this.getFiles().size() - 1))) {
final boolean endOkay = this.isEndOkay(reader);
this.runSummary.setEndOkay(endOkay);
LOGGER.info("endOkay set to " + endOkay);
@@ -308,12 +361,6 @@
LOGGER.info("found end date " + endDate);
}
- // Pull scaler data from EVIO processor into run summary.
- runSummary.setScalerData(this.scalersProcessor.getScalerData());
-
- // Set total number of physics events.
- runSummary.setTotalEvents(this.eventTypeLog.getPhysicsEventCount());
-
} finally {
if (reader != null) {
reader.close();
@@ -355,43 +402,4 @@
this.useFileCache = cacheFiles;
LOGGER.config("file caching enabled");
}
-
- /**
- * Process all the runs that were found.
- *
- * @param runs the run log containing the list of run summaries
- * @throws Exception if there is an error processing one of the runs
- */
- static void processRuns(JCacheManager cacheManager, final RunLog runs, CrawlerConfig config) throws Exception {
-
- // Configure max wait time of jcache manager.
- if (config.waitTime() != null && config.waitTime() > 0L) {
- cacheManager.setWaitTime(config.waitTime());
- LOGGER.config("JCacheManager max wait time set to " + config.waitTime());
- }
-
- // Process all of the runs that were found.
- for (final int run : runs.getSortedRunNumbers()) {
-
- // Get the run summary.
- RunSummary runSummary = runs.getRunSummary(run);
-
- // Clear the cache manager.
- if (config.useFileCache()) {
- cacheManager.clear();
- }
-
- // Create a processor to process all the EVIO events in the run.
- final RunProcessor runProcessor = new RunProcessor(cacheManager, runSummary, config);
-
- // Add extra processors.
- for (final EvioEventProcessor processor : config.processors()) {
- runProcessor.addProcessor(processor);
- LOGGER.config("added extra EVIO processor " + processor.getClass().getName());
- }
-
- // Process all of the run's files.
- runProcessor.process();
- }
- }
}
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 Thu Jul 16 18:47:15 2015
@@ -9,6 +9,8 @@
import java.util.logging.Logger;
import org.hps.record.epics.EpicsData;
+import org.hps.record.run.RunSummary;
+import org.hps.record.scalers.ScalerData;
import org.lcsim.util.log.LogUtil;
/**
@@ -65,6 +67,11 @@
this.run = this.runSummary.getRun();
}
+ /**
+ * Delete all information for this run from all tables in the database.
+ *
+ * @throws SQLException if there is a SQL query error
+ */
private void delete() throws SQLException {
LOGGER.info("deleting existing information for run " + runSummary.getRun());
@@ -91,17 +98,6 @@
*/
private void deleteEpics() throws SQLException {
final PreparedStatement statement = connection.prepareStatement("DELETE FROM run_epics WHERE run = ?");
- statement.setInt(1, this.run);
- statement.executeUpdate();
- }
-
- /**
- * Delete existing EPICS data from the run_log_epics table.
- *
- * @throws SQLException if there is an error performing the db query
- */
- private void deleteScalerData() throws SQLException {
- final PreparedStatement statement = connection.prepareStatement("DELETE FROM run_scalers WHERE run = ?");
statement.setInt(1, this.run);
statement.executeUpdate();
}
@@ -122,8 +118,6 @@
/**
* 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
*/
@@ -135,6 +129,22 @@
LOGGER.info("deleted rows from runs for " + run);
}
+ /**
+ * Delete existing EPICS data from the run_log_epics table.
+ *
+ * @throws SQLException if there is an error performing the db query
+ */
+ private void deleteScalerData() throws SQLException {
+ final PreparedStatement statement = connection.prepareStatement("DELETE FROM run_scalers WHERE run = ?");
+ statement.setInt(1, this.run);
+ statement.executeUpdate();
+ }
+
+ /**
+ * Insert the current {@link RunSummary} into the run database.
+ *
+ * @throws SQLException if there is a SQL query error
+ */
void insert() throws SQLException {
LOGGER.info("performing db insert for " + runSummary);
@@ -167,9 +177,7 @@
this.insertEpics();
// Insert scaler data.
- if (runSummary.getScalerData() != null) {
- new ScalerDataUpdater(connection, runSummary.getScalerData(), run).insert();
- }
+ this.insertScalarData();
// Commit the transactions for this run.
LOGGER.info("committing transaction for run " + run);
@@ -238,9 +246,33 @@
statement.setTimestamp(3, new java.sql.Timestamp(runSummary.getEndDate().getTime()));
statement.setInt(4, runSummary.getTotalEvents());
statement.setInt(5, runSummary.getEvioFileList().size());
- statement.setBoolean(6, runSummary.isEndOkay());
+ statement.setBoolean(6, runSummary.getEndOkay());
statement.executeUpdate();
LOGGER.info("inserted run " + run + " to runs table");
+ }
+
+ /**
+ * Insert scaler data into the database.
+ *
+ * @throws SQLException if there is a SQL query error
+ */
+ private void insertScalarData() throws SQLException {
+ final PreparedStatement statement;
+ final ScalerData scalerData = this.runSummary.getScalerData();
+ if (scalerData == null) {
+ throw new RuntimeException("scaler data is missing");
+ }
+ try {
+ statement = connection.prepareStatement("INSERT INTO run_scalers (run, idx, value) VALUES (?, ?, ?)");
+ for (int idx = 0; idx < scalerData.size(); idx++) {
+ statement.setInt(1, run);
+ statement.setInt(2, idx);
+ statement.setInt(3, scalerData.getValue(idx));
+ statement.executeUpdate();
+ }
+ } finally {
+ connection.commit();
+ }
}
/**
@@ -257,9 +289,9 @@
}
/**
- * Set whether deletion and replacement of existing run information is allowed.
- *
- * @param allowDeleteExisting <code>true</code> to allow deletion and replacement of existing information
+ * Set whether replacement of existing rows in the database is allowed.
+ *
+ * @param allowDeleteExisting <code>true</code> to allow replacement of existing rows
*/
void setAllowDeleteExisting(final boolean allowDeleteExisting) {
this.allowDeleteExisting = allowDeleteExisting;
Added: java/trunk/record-util/src/main/java/org/hps/record/run/AbstractRunDatabaseReader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/AbstractRunDatabaseReader.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/AbstractRunDatabaseReader.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,88 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+
+/**
+ * Abstract class for performing conversion of records in the run database into Java objects.
+ * <p>
+ * Sub-classes must implement the {@link #read()} method.
+ *
+ * @author Jeremy McCormick, SLAC
+ * @param <T>
+ */
+public abstract class AbstractRunDatabaseReader<T> {
+
+ /**
+ * The database connection.
+ */
+ private Connection connection;
+
+ /**
+ * The object created from the table rows.
+ */
+ private T data;
+
+ /**
+ * The run number.
+ */
+ private int run = -1;
+
+ /**
+ * Get the database connection.
+ *
+ * @return the database connection
+ */
+ final Connection getConnection() {
+ return this.connection;
+ }
+
+ /**
+ * Get the data created from the {@link #read()} method being called.
+ *
+ * @return the data created from database records
+ */
+ final T getData() {
+ return data;
+ }
+
+ /**
+ * Get the run number.
+ *
+ * @return the run number
+ */
+ final int getRun() {
+ return this.run;
+ }
+
+ /**
+ * Read data from the database into a Java object accessible from the {@link #getData()} method.
+ */
+ abstract void read();
+
+ /**
+ * Set the database connection.
+ *
+ * @param connection the database connection
+ */
+ final void setConnection(final Connection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * Set the object converted from database records.
+ *
+ * @param data the object converted from database records
+ */
+ final void setData(final T data) {
+ this.data = data;
+ }
+
+ /**
+ * Set the run number.
+ *
+ * @param run the run number
+ */
+ final void setRun(final int run) {
+ this.run = run;
+ }
+}
Added: 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 (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataReader.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,59 @@
+package org.hps.record.run;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.hps.record.epics.EpicsData;
+
+/**
+ * Convert run database records from the <i>run_epics</i> table in to a {@link EpicsData} object.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+final class EpicsDataReader extends AbstractRunDatabaseReader<EpicsData> {
+
+ /**
+ * The SQL SELECT query string.
+ */
+ private final String SELECT_SQL = "SELECT variable_name, value FROM run_epics WHERE run = ?";
+
+ /**
+ * Read data from the database and convert to a {@link EpicsData} object.
+ */
+ @Override
+ void read() {
+ if (this.getRun() == -1) {
+ throw new IllegalStateException("run number is invalid: " + this.getRun());
+ }
+ if (this.getConnection() == null) {
+ throw new IllegalStateException("Connection is not set.");
+ }
+
+ PreparedStatement statement = null;
+ try {
+ statement = this.getConnection().prepareStatement(SELECT_SQL);
+ statement.setInt(1, this.getRun());
+ final ResultSet resultSet = statement.executeQuery();
+
+ final EpicsData epicsData = new EpicsData();
+
+ while (resultSet.next()) {
+ epicsData.setValue(resultSet.getString("variable_name"), resultSet.getDouble("value"));
+ }
+
+ this.setData(epicsData);
+
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/EvioFileListReader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EvioFileListReader.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EvioFileListReader.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,62 @@
+package org.hps.record.run;
+
+import java.io.File;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.hps.record.evio.crawler.EvioFileList;
+
+/**
+ * Convert run database records from the <i>run_files</i> table into an {@link EvioFileList} object.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+final class EvioFileListReader extends AbstractRunDatabaseReader<EvioFileList> {
+
+ /**
+ * The SQL SELECT query string.
+ */
+ private final String SELECT_SQL = "SELECT directory, name FROM run_files WHERE run = ?";
+
+ /**
+ * Read data from the database and convert to an {@link EvioFileList} object.
+ */
+ @Override
+ void read() {
+ if (this.getRun() == -1) {
+ throw new IllegalStateException("run number is invalid: " + this.getRun());
+ }
+ if (this.getConnection() == null) {
+ throw new IllegalStateException("Connection is not set.");
+ }
+
+ PreparedStatement statement = null;
+ try {
+ statement = this.getConnection().prepareStatement(SELECT_SQL);
+ statement.setInt(1, this.getRun());
+ final ResultSet resultSet = statement.executeQuery();
+
+ final EvioFileList evioFileList = new EvioFileList();
+
+ while (resultSet.next()) {
+ evioFileList.add(new File(resultSet.getString("directory") + File.separator
+ + resultSet.getString("name")));
+ }
+
+ this.setData(evioFileList);
+
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
Added: 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 (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,172 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+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.
+ * <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.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public final class RunManager implements ConditionsListener {
+
+ /**
+ * The singleton instance of the RunManager.
+ */
+ private static RunManager INSTANCE;
+
+ /**
+ * The class's logger.
+ */
+ 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}.
+ */
+ public static RunManager getRunManager() {
+ if (INSTANCE == null) {
+ INSTANCE = new RunManager();
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * The database connection.
+ */
+ private Connection connection;
+
+ /**
+ * The run number; the -1 value indicates that this has not been set externally yet.
+ */
+ private int run = -1;
+
+ /**
+ * The {@link RunSummary} for the current run.
+ */
+ private RunSummary runSummary = null;
+
+ @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());
+ }
+
+ /**
+ * Get the database connection.
+ *
+ * @return the database connection
+ */
+ Connection getConnection() {
+ return this.connection;
+ }
+
+ /**
+ * Get the run number.
+ *
+ * @return the run number
+ */
+ public int getRun() {
+ return run;
+ }
+
+ /**
+ * Get the current {@link RunSummary}.
+ *
+ * @return the current {@link RunSummary} or <code>null</code> if it is not set
+ */
+ public RunSummary getRunSummary() {
+ return this.runSummary;
+ }
+
+ /**
+ * Read information from the run database and create a {@link RunSummary} from it.
+ */
+ private void readRun() {
+ // Load main RunSummary object.
+ final RunSummaryReader runSummaryReader = new RunSummaryReader();
+ runSummaryReader.setRun(this.getRun());
+ runSummaryReader.setConnection(this.getConnection());
+ runSummaryReader.read();
+ this.setRunSummary(runSummaryReader.getData());
+
+ // Set EpicsData 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.
+ final ScalerDataReader scalerDataReader = new ScalerDataReader();
+ scalerDataReader.setRun(this.getRun());
+ scalerDataReader.setConnection(this.getConnection());
+ scalerDataReader.read();
+ this.getRunSummary().setScalerData(scalerDataReader.getData());
+
+ // Set ScalerData on RunSummary.
+ final EvioFileListReader evioFileListReader = new EvioFileListReader();
+ evioFileListReader.setRun(this.getRun());
+ evioFileListReader.setConnection(this.getConnection());
+ evioFileListReader.read();
+ this.getRunSummary().setEvioFileList(evioFileListReader.getData());
+ }
+
+ /**
+ * Set the database connection.
+ *
+ * @param connection the database connection
+ */
+ public void setConnection(final Connection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * Set the run number.
+ *
+ * @param run the run number
+ */
+ public void setRun(final int run) {
+
+ // Check status of database connection (must be open).
+ try {
+ if (this.connection.isClosed()) {
+ throw new IllegalStateException("The connection is closed.");
+ }
+ } 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);
+ }
+ }
+
+ /**
+ * Set the current {@link RunSummary}.
+ *
+ * @param runSummary the current {@link RunSummary}
+ */
+ void setRunSummary(final RunSummary runSummary) {
+ this.runSummary = runSummary;
+ }
+}
Copied: java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java (from r3257, 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/run/RunSummary.java Thu Jul 16 18:47:15 2015
@@ -1,4 +1,4 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.run;
import java.io.File;
import java.io.PrintStream;
@@ -8,11 +8,10 @@
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.TimeZone;
-import java.util.logging.Logger;
import org.hps.record.epics.EpicsData;
+import org.hps.record.evio.crawler.EvioFileList;
import org.hps.record.scalers.ScalerData;
-import org.lcsim.util.log.LogUtil;
/**
* This class models the run summary information which is persisted as a row in the <i>run_log</i> table of the run
@@ -37,14 +36,15 @@
* Set up date formatting to display EST (GMT-4).
*/
private static final DateFormat DATE_DISPLAY = new SimpleDateFormat();
+
static {
+ /**
+ * Set default time zone to East Coast (JLAB) where data was taken.
+ */
DATE_DISPLAY.setCalendar(new GregorianCalendar(TimeZone.getTimeZone("America/New_York")));
}
- /**
- * Setup logger.
- */
- private static final Logger LOGGER = LogUtil.create(RunSummary.class);
+ private Date created;
/**
* The end date of the run.
@@ -69,7 +69,7 @@
/**
* The list of EVIO files in the run.
*/
- private final EvioFileList files = new EvioFileList();
+ private EvioFileList evioFileList = new EvioFileList();
/**
* The run number.
@@ -77,6 +77,11 @@
private final int run;
/**
+ * Flag to indicate run was okay.
+ */
+ private boolean runOkay = true;
+
+ /**
* The scaler data from the last physics event in the run.
*/
private ScalerData scalerData;
@@ -92,11 +97,21 @@
private int totalEvents = -1;
/**
+ * The total number of files in the run.
+ */
+ private int totalFiles = 0;
+
+ /**
+ * Date when the run record was last updated.
+ */
+ private Date updated;
+
+ /**
* Create a run summary.
*
* @param run the run number
*/
- RunSummary(final int run) {
+ public RunSummary(final int run) {
this.run = run;
}
@@ -105,11 +120,17 @@
*
* @param file the file to add
*/
- void addFile(final File file) {
- this.files.add(file);
-
- // Total events must be recomputed.
- this.totalEvents = -1;
+ public void addFile(final File file) {
+ this.evioFileList.add(file);
+ }
+
+ /**
+ * Get the creation date of this run record.
+ *
+ * @return the creation date of this run record
+ */
+ public Date getCreated() {
+ return this.created;
}
/**
@@ -124,6 +145,15 @@
}
/**
+ * Return <code>true</code> if END event was found in the data.
+ *
+ * @return <code>true</code> if END event was in the data
+ */
+ public boolean getEndOkay() {
+ return this.endOkay;
+ }
+
+ /**
* Get the EPICS data summary.
* <p>
* This is computed by taking the mean of each variable for the run.
@@ -135,6 +165,19 @@
}
/**
+ * Get the event rate (effectively the trigger rate) which is the total events divided by the number of seconds in
+ * the run.
+ *
+ * @return the event rate
+ */
+ public double getEventRate() {
+ if (this.getTotalEvents() <= 0) {
+ throw new RuntimeException("Total events is zero or invalid.");
+ }
+ return (double) this.getTotalEvents() / (double) this.getTotalSeconds();
+ }
+
+ /**
* Get the counts of different event types.
*
* @return the counts of different event types
@@ -149,7 +192,7 @@
* @return the list of EVIO files in this run
*/
public EvioFileList getEvioFileList() {
- return this.files;
+ return this.evioFileList;
}
/**
@@ -162,8 +205,17 @@
}
/**
+ * Return <code>true</code> if the run was okay (no major errors or data corruption occurred).
+ *
+ * @return <code>true</code> if the run was okay
+ */
+ public boolean getRunOkay() {
+ return this.runOkay;
+ }
+
+ /**
* Get the scaler data of this run (last event only).
- *
+ *
* @return the scaler data of this run from the last event
*/
public ScalerData getScalerData() {
@@ -188,13 +240,18 @@
return this.totalEvents;
}
- void setTotalEvents(int totalEvents) {
- this.totalEvents = totalEvents;
+ /**
+ * Get the total number of files for this run.
+ *
+ * @return the total number of files for this run
+ */
+ public int getTotalFiles() {
+ return this.totalFiles;
}
/**
* Get the number of seconds in the run which is the difference between the start and end times.
- *
+ *
* @return the total seconds in the run
*/
public long getTotalSeconds() {
@@ -204,29 +261,16 @@
if (this.getEndDate() == null) {
throw new RuntimeException("missing end date");
}
- return (getEndDate().getTime() - getStartDate().getTime()) / 1000;
- }
-
- /**
- * Get the event rate (effectively the trigger rate) which is the total events divided by the number of seconds in
- * the run.
- *
- * @return the event rate
- */
- public double getEventRate() {
- if (this.getTotalEvents() <= 0) {
- throw new RuntimeException("Total events is zero or invalid.");
- }
- return (double) this.getTotalEvents() / (double) this.getTotalSeconds();
- }
-
- /**
- * Return <code>true</code> if END event was found in the data.
- *
- * @return <code>true</code> if END event was in the data
- */
- public boolean isEndOkay() {
- return this.endOkay;
+ return (this.getEndDate().getTime() - this.getStartDate().getTime()) / 1000;
+ }
+
+ /**
+ * Get the date when this run record was last updated.
+ *
+ * @return the date when this run record was last updated
+ */
+ public Date getUpdated() {
+ return updated;
}
/**
@@ -234,32 +278,41 @@
*
* @param ps the print stream for output
*/
- public void printRunSummary(final PrintStream ps) {
+ public void printOut(final PrintStream ps) {
ps.println("--------------------------------------------");
ps.println("run: " + this.run);
- ps.println("first file: " + this.files.first());
- ps.println("last file: " + this.files.last());
+ ps.println("first file: " + this.evioFileList.first());
+ ps.println("last file: " + this.evioFileList.last());
ps.println("started: " + DATE_DISPLAY.format(this.getStartDate()));
ps.println("ended: " + DATE_DISPLAY.format(this.getEndDate()));
ps.println("total events: " + this.getTotalEvents());
- ps.println("end OK: " + this.isEndOkay());
+ ps.println("end OK: " + this.getEndOkay());
ps.println("event rate: " + this.getEventRate());
ps.println("event types");
for (final Object key : this.eventTypeCounts.keySet()) {
ps.println(" " + key + ": " + this.eventTypeCounts.get(key));
}
- ps.println(this.files.size() + " files");
- for (final File file : this.files) {
+ ps.println(this.evioFileList.size() + " files");
+ for (final File file : this.evioFileList) {
ps.println(" " + file.getPath());
}
}
/**
+ * Set the creation date of the run record.
+ *
+ * @param created the creation date of the run record
+ */
+ public void setCreated(final Date created) {
+ this.created = created;
+ }
+
+ /**
* Set the end date.
*
* @param endDate the end date
*/
- void setEndDate(final Date endDate) {
+ public void setEndDate(final Date endDate) {
this.endDate = endDate;
}
@@ -268,7 +321,7 @@
*
* @param endOkay <code>true</code> if end is okay
*/
- void setEndOkay(final boolean endOkay) {
+ public void setEndOkay(final boolean endOkay) {
this.endOkay = endOkay;
}
@@ -277,7 +330,7 @@
*
* @param epics the EPICS data for the run
*/
- void setEpicsData(final EpicsData epics) {
+ public void setEpicsData(final EpicsData epics) {
this.epics = epics;
}
@@ -286,16 +339,34 @@
*
* @param eventTypeCounts the event type counts for the run
*/
- void setEventTypeCounts(final Map<Object, Integer> eventTypeCounts) {
+ public void setEventTypeCounts(final Map<Object, Integer> eventTypeCounts) {
this.eventTypeCounts = eventTypeCounts;
}
/**
+ * Set the list of EVIO files for the run.
+ *
+ * @param evioFileList the list of EVIO files for the run
+ */
+ public void setEvioFileList(final EvioFileList evioFileList) {
+ this.evioFileList = evioFileList;
+ }
+
+ /**
+ * Set whether the run was "okay" meaning the data is usable for physics analysis.
+ *
+ * @param runOkay <code>true</code> if the run is okay
+ */
+ public void setRunOkay(final boolean runOkay) {
+ this.runOkay = runOkay;
+ }
+
+ /**
* Set the scaler data of the run.
- *
+ *
* @param scalerData the scaler data
*/
- void setScalerData(final ScalerData scalerData) {
+ public void setScalerData(final ScalerData scalerData) {
this.scalerData = scalerData;
}
@@ -304,25 +375,54 @@
*
* @param startDate the start date of the run
*/
- void setStartDate(final Date startDate) {
+ public void setStartDate(final Date startDate) {
this.startDate = startDate;
}
/**
+ * Set the total number of physics events in the run.
+ *
+ * @param totalEvents the total number of physics events in the run
+ */
+ public void setTotalEvents(final int totalEvents) {
+ this.totalEvents = totalEvents;
+ }
+
+ /**
+ * Set the total number of EVIO files in the run.
+ *
+ * @param totalFiles the total number of EVIO files in the run
+ */
+ public void setTotalFiles(final int totalFiles) {
+ this.totalFiles = totalFiles;
+ }
+
+ /**
+ * Set the date when this run record was last updated.
+ *
+ * @param updated the date when the run record was last updated
+ */
+ public void setUpdated(final Date updated) {
+ this.updated = updated;
+ }
+
+ /**
* Sort the files in the run by sequence number in place.
*/
- void sortFiles() {
- this.files.sort();
+ public void sortFiles() {
+ this.evioFileList.sort();
}
/**
* Convert this object to a string.
- *
+ *
* @return this object converted to a string
*/
@Override
public String toString() {
- return "RunSummary { run: " + this.run + ", started: " + this.getStartDate() + ", ended: " + this.getEndDate()
- + ", events: " + this.getTotalEvents() + ", endOkay: " + endOkay + " }";
+ return "RunSummary { run: " + this.getRun() + ", startDate: " + this.getStartDate() + ", endDate: "
+ + this.getEndDate() + ", totalEvents: " + this.getTotalEvents() + ", totalFiles: "
+ + this.getTotalFiles() + ", endOkay: " + this.getEndOkay() + ", runOkay: " + this.getRunOkay()
+ + ", updated: " + this.getUpdated() + ", created: " + this.getCreated() + " }";
}
}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryReader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryReader.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryReader.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,68 @@
+package org.hps.record.run;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Convert run database records from the <i>runs</i> table into a {@link RunSummary} object.
+ * <p>
+ * This class will not create the sub-objects for the {@link RunSummary} which must be read using their own
+ * {@link AbstractRunDatabaseReader} implementation classes. Then these objects should be set on the {@link RunSummary}
+ * e.g. using {@link RunSummary#setEpicsData(org.hps.record.epics.EpicsData)}, etc.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class RunSummaryReader extends AbstractRunDatabaseReader<RunSummary> {
+
+ /**
+ * The SQL SELECT query string.
+ */
+ private final String SELECT_SQL = "SELECT run, start_date, end_date, nevents, nfiles, end_ok, run_ok, updated, created FROM runs WHERE run = ?";
+
+ /**
+ * Read data from the database and convert to a {@link RunSummary} object.
+ */
+ @Override
+ void read() {
+ if (this.getRun() == -1) {
+ throw new IllegalStateException("run number is invalid: " + this.getRun());
+ }
+ if (this.getConnection() == null) {
+ throw new IllegalStateException("Connection is not set.");
+ }
+
+ PreparedStatement statement = null;
+ try {
+ statement = this.getConnection().prepareStatement(SELECT_SQL);
+ statement.setInt(1, this.getRun());
+ final ResultSet resultSet = statement.executeQuery();
+ if (!resultSet.next()) {
+ throw new RuntimeException("No record exists for run " + this.getRun() + " in database.");
+ }
+
+ final RunSummary runSummary = new RunSummary(this.getRun());
+ runSummary.setStartDate(resultSet.getTimestamp("start_date"));
+ runSummary.setEndDate(resultSet.getTimestamp("end_date"));
+ runSummary.setTotalEvents(resultSet.getInt("nevents"));
+ runSummary.setTotalFiles(resultSet.getInt("nfiles"));
+ runSummary.setEndOkay(resultSet.getBoolean("end_ok"));
+ runSummary.setRunOkay(resultSet.getBoolean("run_ok"));
+ runSummary.setUpdated(resultSet.getTimestamp("updated"));
+ runSummary.setCreated(resultSet.getTimestamp("created"));
+
+ this.setData(runSummary);
+
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataReader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataReader.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataReader.java Thu Jul 16 18:47:15 2015
@@ -0,0 +1,58 @@
+package org.hps.record.run;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.record.scalers.ScalerData;
+
+/**
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class ScalerDataReader extends AbstractRunDatabaseReader<ScalerData> {
+
+ private String SELECT_SQL = "SELECT idx, value FROM run_scalers WHERE run = ? ORDER BY idx";
+
+ @Override
+ void read() {
+ if (getRun() == -1) {
+ throw new IllegalStateException("run number is invalid: " + getRun());
+ }
+ if (getConnection() == null) {
+ throw new IllegalStateException("Connection is not set.");
+ }
+
+ PreparedStatement statement = null;
+ try {
+ statement = getConnection().prepareStatement(SELECT_SQL);
+ statement.setInt(1, getRun());
+ ResultSet resultSet = statement.executeQuery();
+
+ List<Integer> scalerValues = new ArrayList<Integer>();
+ while (resultSet.next()) {
+ scalerValues.add(resultSet.getInt("value"));
+ }
+
+ int[] scalerArray = new int[scalerValues.size()];
+ for (int i = 0; i < scalerArray.length; i++) {
+ scalerArray[i] = scalerValues.get(i);
+ }
+
+ setData(new ScalerData(scalerArray));
+
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
|