Author: [log in to unmask]
Date: Thu Aug 20 12:50:12 2015
New Revision: 3380
Log:
Major overhaul of record-util module for supporting run database. HPSJAVA-575, HPSJAVA-576
Added:
java/trunk/record-util/src/main/java/org/hps/record/epics/Epics20sVariables.java
java/trunk/record-util/src/main/java/org/hps/record/epics/Epics2sVariables.java
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsRunProcessor.java
- copied, changed from r3364, 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/EventCountProcessor.java
- copied, changed from r3364, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EventCountProcessor.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileFilter.java
- copied, changed from r3364, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileFilter.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaData.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaDataReader.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSequenceComparator.java
- copied, changed from r3364, 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/EvioFileUtilities.java
- copied, changed from r3364, 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/EvioLoop.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoopAdapter.java
java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryMap.java
- copied, changed from r3364, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java
java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDao.java
java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDaoImpl.java
java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDao.java
java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDaoImpl.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDao.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java
java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDao.java
java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDaoImpl.java
java/trunk/record-util/src/main/java/org/hps/record/run/package-info.java
Removed:
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsCsvExporter.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/EventCountProcessor.java
java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileFilter.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/EvioFileSequenceComparator.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/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/RunSummaryUpdater.java
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/RunSummaryReader.java
java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataReader.java
Modified:
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsData.java
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java
java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsHeader.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java
java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java
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/EvioFileVisitor.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/RunFilter.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/run/RunManager.java
java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java
java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalerData.java
java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java
Added: java/trunk/record-util/src/main/java/org/hps/record/epics/Epics20sVariables.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/Epics20sVariables.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/Epics20sVariables.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,54 @@
+package org.hps.record.epics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Static list of variable names contained in 20s EPICS data block from Eng Run 2015 data along
+ * with a brief description (if known).
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public final class Epics20sVariables {
+
+ /**
+ * Map with variable names and description.
+ */
+ static final Map<String, String> VARIABLES = new HashMap<String, String>();
+
+ /**
+ * Variable definitions.
+ */
+ static {
+ VARIABLES.put("beam_stop.RBV", "beam stop motor position");
+ VARIABLES.put("hps:svt_bot:motor.RBV", "SVT bottom motor position");
+ VARIABLES.put("hps:svt_top:motor.RBV", "SVT top motor position");
+ VARIABLES.put("hps:target:motor.RBV", "target motor position");
+ VARIABLES.put("hps_collimator.RBV", "collimator motor position");
+ VARIABLES.put("scalerS10b", "DWN-B beamline counter");
+ VARIABLES.put("scalerS11b", "DWN-R beamline counter");
+ VARIABLES.put("scalerS8b", "DWN-T beamline counter");
+ VARIABLES.put("scalerS9b", "DWN-L beamline counter");
+ VARIABLES.put("scaler_cS3b", "UPS-L beamline counter");
+ VARIABLES.put("scaler_cS4b", "UPS-R beamline counter");
+ VARIABLES.put("scaler_cS5b", "TAG-L beamline counter");
+ VARIABLES.put("scaler_cS6b", "TAG-T beamline counter");
+ VARIABLES.put("scaler_cS7b", "TAG-T2 beamline counter");
+ VARIABLES.put("SMRPOSB", "");
+ }
+
+ /**
+ * Get the variable map with the names and descriptions.
+ *
+ * @return the variable map
+ */
+ public static Map<String, String> getVariables() {
+ return VARIABLES;
+ }
+
+ /**
+ * Do not allow class instantiation.
+ */
+ private Epics20sVariables() {
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/epics/Epics2sVariables.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/Epics2sVariables.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/Epics2sVariables.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,65 @@
+package org.hps.record.epics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * List of EPICS variables and their descriptions contained in the 2s data bank from Eng Run 2015 data.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public final class Epics2sVariables {
+
+ /**
+ * Map with variable names and description.
+ */
+ static final Map<String, String> VARIABLES = new HashMap<String, String>();
+
+ /**
+ * Variable definitions.
+ */
+ static {
+ VARIABLES.put("MBSY2C_energy", "Beam energy according to Hall B BSY dipole string");
+ VARIABLES.put("PSPECIRBCK", "Pair Spectrometer Current Readback");
+ VARIABLES.put("HPS:LS450_2:FIELD", "Frascati probe field");
+ VARIABLES.put("HPS:LS450_1:FIELD", "Pair Spectrometer probe field");
+ VARIABLES.put("MTIRBCK", "Frascati Current Readback");
+ VARIABLES.put("VCG2C21 2C21", "Vacuum gauge pressure");
+ VARIABLES.put("VCG2C21A", "2C21A Vacuum gauge pressure");
+ VARIABLES.put("VCG2C24A", "2C24A Vacuum gauge pressure");
+ VARIABLES.put("VCG2H00A", "2H00 Vacuum gauge pressure");
+ VARIABLES.put("VCG2H01A", "2H01 Vacuum gauge pressure");
+ VARIABLES.put("VCG2H02A", "2H02 Vacuum gauge pressure");
+ VARIABLES.put("scaler_calc1", "Faraday cup current");
+ VARIABLES.put("scalerS12b", "HPS-Left beam halo count");
+ VARIABLES.put("scalerS13b", "HPS-Right beam halo count");
+ VARIABLES.put("scalerS14b", "HPS-Top beam halo count");
+ VARIABLES.put("scalerS15b", "HPS-SC beam halo count");
+ VARIABLES.put("hallb_IPM2C21A_XPOS", "Beam position X at 2C21");
+ VARIABLES.put("hallb_IPM2C21A_YPOS", "Beam position Y at 2C21");
+ VARIABLES.put("hallb_IPM2C21A_CUR", "Current at 2C21");
+ VARIABLES.put("hallb_IPM2C24A_XPOS", "Beam position X at 2C24");
+ VARIABLES.put("hallb_IPM2C24A_YPOS", "Beam position Y at 2C24");
+ VARIABLES.put("hallb_IPM2C24A_CUR", "Current at 2C24");
+ VARIABLES.put("hallb_IPM2H00_XPOS", "Beam position X at 2H00");
+ VARIABLES.put("hallb_IPM2H00_YPOS", "Beam position Y at 2H00");
+ VARIABLES.put("hallb_IPM2H00_CUR", "Current at 2H00");
+ VARIABLES.put("hallb_IPM2H02_YPOS", "Beam position X at 2H02");
+ VARIABLES.put("hallb_IPM2H02_XPOS", "Beam position Y at 2H02");
+ }
+
+ /**
+ * Get the variable map.
+ *
+ * @return the variable map
+ */
+ public static Map<String, String> getVariables() {
+ return VARIABLES;
+ }
+
+ /**
+ * Do not allow class instantiation.
+ */
+ private Epics2sVariables() {
+ }
+}
Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsData.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsData.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsData.java Thu Aug 20 12:50:12 2015
@@ -42,66 +42,6 @@
private static final String EPICS_VARIABLE_NAMES = "EPICS_VARIABLE_NAMES";
/**
- * This map contains the list of EPICS keys and their descriptions from the<br/>
- * <a href="https://confluence.slac.stanford.edu/display/hpsg/EVIO+Data+Format">EVIO Data Format Confluence Page</a>
- */
- private final static Map<String, String> VARIABLES = new HashMap<String, String>();
-
- /**
- * List of possible EPICS keys.
- */
- static {
- VARIABLES.put("MBSY2C_energy", "Beam energy according to Hall B BSY dipole string");
- VARIABLES.put("PSPECIRBCK", "Pair Spectrometer Current Readback");
- VARIABLES.put("HPS:LS450_2:FIELD", "Frascati probe field");
- VARIABLES.put("HPS:LS450_1:FIELD", "Pair Spectrometer probe field");
- VARIABLES.put("MTIRBCK", "Frascati Current Readback");
- VARIABLES.put("VCG2C21 2C21", "Vacuum gauge pressure");
- VARIABLES.put("VCG2C21A", "2C21A Vacuum gauge pressure");
- VARIABLES.put("VCG2C24A", "2C24A Vacuum gauge pressure");
- VARIABLES.put("VCG2H00A", "2H00 Vacuum gauge pressure");
- VARIABLES.put("VCG2H01A", "2H01 Vacuum gauge pressure");
- VARIABLES.put("VCG2H02A", "2H02 Vacuum gauge pressure");
- VARIABLES.put("scaler_calc1", "Faraday cup current");
- VARIABLES.put("scalerS12b", "HPS-Left beam halo count");
- VARIABLES.put("scalerS13b", "HPS-Right beam halo count");
- VARIABLES.put("scalerS14b", "HPS-Top beam halo count");
- VARIABLES.put("scalerS15b", "HPS-SC beam halo count");
- VARIABLES.put("hallb_IPM2C21A_XPOS", "Beam position X at 2C21");
- VARIABLES.put("hallb_IPM2C21A_YPOS", "Beam position Y at 2C21");
- VARIABLES.put("hallb_IPM2C21A_CUR", "Current at 2C21");
- VARIABLES.put("hallb_IPM2C24A_XPOS", "Beam position X at 2C24");
- VARIABLES.put("hallb_IPM2C24A_YPOS", "Beam position Y at 2C24");
- VARIABLES.put("hallb_IPM2C24A_CUR", "Current at 2C24");
- VARIABLES.put("hallb_IPM2H00_XPOS", "Beam position X at 2H00");
- VARIABLES.put("hallb_IPM2H00_YPOS", "Beam position Y at 2H00");
- VARIABLES.put("hallb_IPM2H00_CUR", "Current at 2H00");
- VARIABLES.put("hallb_IPM2H02_YPOS", "Beam position X at 2H02");
- VARIABLES.put("hallb_IPM2H02_XPOS", "Beam position Y at 2H02");
- }
-
- /**
- * Get the description of a named EPICS variable.
- *
- * @param name the name of the variable
- */
- public static String getVariableDescription(final String name) {
- return VARIABLES.get(name);
- }
-
- /**
- * Get the static list of all available EPICs variable names.
- * <p>
- * This could be different than the variable names which were actually written into the collection header. For this,
- * instead use the method {@link #getKeys()} method.
- *
- * @return the set of default EPICS variable names
- */
- public static Set<String> getVariableNames() {
- return VARIABLES.keySet();
- };
-
- /**
* <p>
* Read data into this object from an LCIO event using the default collection name.
* <p>
@@ -109,7 +49,7 @@
* {@link org.lcsim.util.Driver#process(EventHeader)} method.
*
* @param event the LCIO event
- * @return the EPICS data from the event
+ * @return the EPICS data from the event or null if none exists
*/
public static EpicsData read(final EventHeader event) {
if (event.hasCollection(GenericObject.class, EpicsData.DEFAULT_COLLECTION_NAME)) {
@@ -210,9 +150,6 @@
/**
* Get the list of EPICS variables used by this object.
- * <p>
- * This could potentially be different than the list of default names from {@link #getVariableNames()} as not all
- * variables are included in every EPICS event.
*
* @return the list of used EPICS variable names
*/
@@ -243,14 +180,15 @@
*
* @param epicsHeader the {@link EpicsHeader} object
*/
- void setEpicsHeader(final EpicsHeader epicsHeader) {
+ public void setEpicsHeader(final EpicsHeader epicsHeader) {
this.epicsHeader = epicsHeader;
}
/**
- * Set a double value by name.
- *
- * @return the value from the key
+ * Set a variable's value.
+ *
+ * @param name the name of the variable
+ * @param value the new value of the variable
*/
public void setValue(final String name, final double value) {
this.dataMap.put(name, value);
@@ -268,7 +206,7 @@
newObject.setKeys(new String[this.dataMap.size()]);
newObject.setValues(new double[this.dataMap.size()]);
-
+
int index = 0;
for (final String key : this.dataMap.keySet()) {
newObject.setKey(index, key);
@@ -278,10 +216,8 @@
// Write header information into the object's int array.
if (epicsHeader != null) {
- final int[] headerData = new int[] {
- epicsHeader.getRun(),
- epicsHeader.getSequence(),
- epicsHeader.getTimeStamp()};
+ final int[] headerData = new int[] {epicsHeader.getRun(), epicsHeader.getSequence(),
+ epicsHeader.getTimestamp()};
newObject.setHeaderData(headerData);
}
return newObject;
Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java Thu Aug 20 12:50:12 2015
@@ -50,7 +50,7 @@
// Is this an EPICS event?
if (EventTagConstant.EPICS.isEventTag(evio)) {
- LOGGER.info("processing EPICS event " + evio.getEventNumber());
+ LOGGER.fine("processing EPICS event " + evio.getEventNumber());
// Find the bank with the EPICS data string.
final BaseStructure epicsBank = EvioBankTag.EPICS_STRING.findBank(evio);
@@ -73,7 +73,7 @@
} else {
// This is an error because the string data bank should always be present in EPICS events.
- final RuntimeException x = new RuntimeException("No EPICS data bank found in EPICS event.");
+ final RuntimeException x = new RuntimeException("No data bank found in EPICS event.");
LOGGER.log(Level.SEVERE, x.getMessage(), x);
throw x;
}
Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsGenericObject.java Thu Aug 20 12:50:12 2015
@@ -36,11 +36,23 @@
return this.values[index];
}
+ /**
+ * Dummy implementation.
+ *
+ * @param index the array index
+ * @return always returns 0
+ */
@Override
public float getFloatVal(final int index) {
return 0;
}
+ /**
+ * Get an int value which is used to store the EPICS header information.
+ *
+ * @param index the array index
+ * @return the int value at <code>index</code>
+ */
@Override
public int getIntVal(final int index) {
return headerData[index];
@@ -75,11 +87,21 @@
return this.values.length;
}
+ /**
+ * Dummy implementation.
+ *
+ * @return always returns 0
+ */
@Override
public int getNFloat() {
return 0;
}
+ /**
+ * Get the number of int values which is the length of the data header.
+ *
+ * @return the number of int values
+ */
@Override
public int getNInt() {
return this.headerData.length;
Modified: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsHeader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsHeader.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsHeader.java Thu Aug 20 12:50:12 2015
@@ -1,7 +1,7 @@
package org.hps.record.epics;
/**
- * Representation of EPICs header data (run, sequence, time stamp).
+ * Representation of EPICs header data from the EVIO bank (run, sequence, time stamp).
*
* @author Jeremy McCormick, SLAC
*/
@@ -31,14 +31,15 @@
private final int sequence;
/**
- * The time stamp in seconds (Unix).
+ * The unix time in seconds.
*/
private final int timestamp;
/**
* Class constructor.
* <p>
- * The data array should be length 3 and usually will come from the int data of a <code>GenericObject</code>.
+ * The data array should be length 3 and usually will come from the int data of a <code>GenericObject</code>. In
+ * order, it should contain the run, sequence and timestamp values.
*
* @param data the header data with length 3
*/
@@ -74,7 +75,7 @@
*
* @return the time stamp
*/
- public int getTimeStamp() {
+ public int getTimestamp() {
return timestamp;
}
}
Copied: java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsRunProcessor.java (from r3364, 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/epics/EpicsRunProcessor.java Thu Aug 20 12:50:12 2015
@@ -1,25 +1,19 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.epics;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
-import org.hps.record.epics.EpicsData;
-import org.hps.record.epics.EpicsEvioProcessor;
import org.hps.record.evio.EvioEventProcessor;
import org.jlab.coda.jevio.EvioEvent;
/**
- * Create a summary log of EPICS information found in EVIO events.
+ * Creates a list of EPICS data found in EVIO events across an entire job.
*
* @author Jeremy McCormick, SLAC
*/
-final class EpicsLog extends EvioEventProcessor {
-
- /**
- * 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>();
+public final class EpicsRunProcessor extends EvioEventProcessor {
/**
* The current EPICS data block from the EVIO events (last one that was found).
@@ -27,9 +21,11 @@
private EpicsData currentEpicsData;
/**
- * The summary information for the variables computed from the mean values across the whole run.
+ * Collection of the EPICS data accumulated during the job.
+ * <p>
+ * A set is used here to avoid adding duplicate objects.
*/
- private final EpicsData logData = new EpicsData();
+ private Set<EpicsData> epicsDataSet;
/**
* The processor for extracting the EPICS information from EVIO events.
@@ -39,31 +35,16 @@
/**
* Create an EPICs log.
*/
- EpicsLog() {
+ public EpicsRunProcessor() {
}
/**
- * End of job hook which computes the mean values for all EPICS variables found in the run.
+ * Get the EPICS data from the job.
+ *
+ * @return the EPICS data from the job
*/
- @Override
- public void endJob() {
- System.out.println(this.logData);
-
- // Compute means for all EPICS variables.
- for (final String name : this.logData.getKeys()) {
- final double total = this.logData.getValue(name);
- final double mean = total / this.counts.get(name);
- this.logData.setValue(name, mean);
- }
- }
-
- /**
- * 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;
+ public List<EpicsData> getEpicsData() {
+ return new ArrayList<EpicsData>(this.epicsDataSet);
}
/**
@@ -71,33 +52,22 @@
*/
@Override
public void process(final EvioEvent evioEvent) {
+
+ // Call the processor that will load EPICS data if it exists in the event.
this.processor.process(evioEvent);
this.currentEpicsData = this.processor.getEpicsData();
- this.update();
+
+ // Add EPICS data to the collection.
+ if (this.currentEpicsData != null) {
+ this.epicsDataSet.add(this.currentEpicsData);
+ }
}
/**
- * Update state from the current EPICS data.
- * <p>
- * If the current data is <code>null</code>, this method does nothing.
+ * Start of job hook (reset the list of EPICS data).
*/
- private void update() {
- if (this.currentEpicsData != null) {
- for (final String name : this.currentEpicsData.getKeys()) {
- if (!this.logData.getKeys().contains(name)) {
- this.logData.setValue(name, 0.);
- }
- if (!this.counts.keySet().contains(name)) {
- this.counts.put(name, 0);
- }
- int count = this.counts.get(name);
- count += 1;
- this.counts.put(name, count);
- 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);
- }
- }
+ @Override
+ public void startJob() {
+ epicsDataSet = new HashSet<EpicsData>();
}
}
Copied: java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java (from r3364, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EventCountProcessor.java)
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EventCountProcessor.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java Thu Aug 20 12:50:12 2015
@@ -1,12 +1,8 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.evio;
import java.util.HashMap;
import java.util.Map;
-import org.hps.record.evio.EventTagBitMask;
-import org.hps.record.evio.EventTagConstant;
-import org.hps.record.evio.EvioEventProcessor;
-import org.hps.record.evio.EvioEventUtilities;
import org.jlab.coda.jevio.EvioEvent;
/**
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioEventConstants.java Thu Aug 20 12:50:12 2015
@@ -16,29 +16,16 @@
* EPICS bank tag.
*/
public static final int EPICS_BANK_TAG = 57620;
-
-
- /**
- * Tag of bank containing the EPICS data bank.
- */
- public static final int EPICS_PARENT_BANK_TAG = 129;
-
- /**
- * EPICS 20 second event tag.
- */
- // FIXME: This is unused and not handled in event processing.
- public static final int EPICS_BANK_TAG_20s = -1;
-
- /**
- * EPICS 2 second event tag.
- */
- // FIXME: This is unused and not handled in event processing.
- public static final int EPICS_BANK_TAG_2s = -1;
/**
* EPICS event tag.
*/
public static final int EPICS_EVENT_TAG = 31;
+
+ /**
+ * Tag of bank containing the EPICS data bank.
+ */
+ public static final int EPICS_PARENT_BANK_TAG = 129;
/**
* Event ID bank tag.
@@ -58,7 +45,6 @@
/**
* Pause event tag.
*/
- // FIXME: Not generally handled or used in event processing.
public static final int PAUSE_EVENT_TAG = 19;
/**
Copied: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileFilter.java (from r3364, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileFilter.java)
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileFilter.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileFilter.java Thu Aug 20 12:50:12 2015
@@ -1,27 +1,29 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.evio;
import java.io.File;
import java.io.FileFilter;
/**
- * This is a simple file filter that will accept EVIO files with a certain convention to their naming which looks like
- * <i>FILENAME.evio.SEQUENCE</i>. This matches the convention used by the CODA DAQ software.
+ * This is a simple file filter that will accept EVIO files with a certain pattern to their file names:<br/>
+ * <i>FILENAME.evio.SEQUENCE</i>.
+ * <p>
+ * This matches the convention used by the CODA DAQ software.
*
* @author Jeremy McCormick, SLAC
*/
-final class EvioFileFilter implements FileFilter {
+public final class EvioFileFilter implements FileFilter {
/**
- * Return <code>true</code> if file is an EVIO file with correct file name convention.
+ * Return <code>true</code> if file is an EVIO file with the correct file naming convention.
*
- * @return <code>true</code> if file is an EVIO file with correct file name convention
+ * @return <code>true</code> if file is an EVIO file with correct file naming convention
*/
@Override
public boolean accept(final File pathname) {
final boolean isEvio = pathname.getName().contains(".evio");
boolean hasSeqNum = false;
try {
- EvioFileUtilities.getSequence(pathname);
+ EvioFileUtilities.getSequenceFromName(pathname);
hasSeqNum = true;
} catch (final Exception e) {
}
Added: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaData.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaData.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaData.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,315 @@
+package org.hps.record.evio;
+
+import java.io.File;
+import java.util.Date;
+
+/**
+ * Meta data that can be extracted from EVIO files.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public final class EvioFileMetaData {
+
+ /**
+ * The number of bad events in the file that are unreadable.
+ */
+ private int badEventCount;
+
+ /**
+ * The total number of bytes in the file.
+ */
+ private long byteCount;
+
+ /**
+ * The end date of the file which will be taken from the <i>END</i> event or the last physics event.
+ */
+ private Date endDate;
+
+ /**
+ * The last event number in the file.
+ */
+ private int endEvent;
+
+ /**
+ * The number of events in the file.
+ */
+ private int eventCount;
+
+ /**
+ * The EVIO file which is set at class construction time and cannot be changed.
+ */
+ private final File evioFile;
+
+ /**
+ * <code>true</code> if there is an <i>END</i> event in this file.
+ */
+ private boolean hasEnd;
+
+ /**
+ * <code>true</code> if there is a <i>PRESTART</i> event in this file.
+ */
+ private boolean hasPrestart;
+
+ /**
+ * The run number.
+ */
+ private int run;
+
+ /**
+ * The file sequence number.
+ */
+ private int sequence;
+
+ /**
+ * The start date which comes from the <i>PRESTART</i> event or the first physics event.
+ */
+ private Date startDate;
+
+ /**
+ * The first event number in the file.
+ */
+ private int startEvent;
+
+ /**
+ * Create a meta data object.
+ *
+ * @param evioFile the EVIO file to which the meta data applies
+ */
+ public EvioFileMetaData(final File evioFile) {
+ if (evioFile == null) {
+ throw new IllegalArgumentException("The EVIO file argument is null.");
+ }
+ if (!evioFile.exists()) {
+ throw new IllegalArgumentException("The file " + evioFile.getPath()
+ + " does not exist or it is inaccessible.");
+ }
+ this.evioFile = evioFile;
+ }
+
+ /**
+ * Get the bad event count.
+ *
+ * @return the bad event count
+ */
+ public int getBadEventCount() {
+ return badEventCount;
+ }
+
+ /**
+ * Get the byte count.
+ *
+ * @return the byte count
+ */
+ public long getByteCount() {
+ return byteCount;
+ }
+
+ /**
+ * Get the end date.
+ *
+ * @return the end date
+ */
+ public Date getEndDate() {
+ return endDate;
+ }
+
+ /**
+ * Get the end event number.
+ *
+ * @return the end event number
+ */
+ public int getEndEvent() {
+ return endEvent;
+ }
+
+ /**
+ * Get the number of events in the file (all types).
+ *
+ * @return the number of events in the file
+ */
+ public int getEventCount() {
+ return eventCount;
+ }
+
+ /**
+ * Get the EVIO file.
+ *
+ * @return the EVIO file
+ */
+ public File getEvioFile() {
+ return evioFile;
+ }
+
+ /**
+ * Get the run number.
+ *
+ * @return the run number
+ */
+ public Integer getRun() {
+ return run;
+ }
+
+ /**
+ * Get the file sequence number, numbered from 0.
+ *
+ * @return the file sequence number
+ */
+ public int getSequence() {
+ return sequence;
+ }
+
+ /**
+ * Get the start date.
+ *
+ * @return the start date
+ */
+ public Date getStartDate() {
+ return startDate;
+ }
+
+ /**
+ * Get the first event number in the file.
+ *
+ * @return the first event number in the file
+ */
+ public int getStartEvent() {
+ return startEvent;
+ }
+
+ /**
+ * Return <code>true</code> if the file has an EVIO <i>END</i> event.
+ *
+ * @return <code>true</code> if the file has an EVIO <i>END</i> event
+ */
+ public boolean hasEnd() {
+ return hasEnd;
+ }
+
+ /**
+ * Return <code>true</code> if the file has an EVIO <i>PRESTART</i> event.
+ *
+ * @return <code>true</code> if the file has an EVIO <i>PRESTART</i> event
+ */
+ public boolean hasPrestart() {
+ return hasPrestart;
+ }
+
+ /**
+ * Set the bad event count.
+ *
+ * @param badEventCount the bad event count
+ */
+ void setBadEventCount(final int badEventCount) {
+ if (badEventCount < 0) {
+ throw new IllegalArgumentException("badEventCount");
+ }
+ this.badEventCount = badEventCount;
+ }
+
+ /**
+ * Set the byte count.
+ *
+ * @param byteCount the byte count
+ */
+ void setByteCount(final long byteCount) {
+ if (byteCount < 0) {
+ throw new IllegalArgumentException("byteCount");
+ }
+ this.byteCount = byteCount;
+ }
+
+ /**
+ * Set the end date.
+ *
+ * @param endDate the end date
+ */
+ void setEndDate(final Date endDate) {
+ this.endDate = endDate;
+ }
+
+ /**
+ * Set the end event number.
+ *
+ * @param endEvent the end event number
+ */
+ void setEndEvent(final int endEvent) {
+ this.endEvent = endEvent;
+ }
+
+ /**
+ * Set the event count.
+ *
+ * @param eventCount the event count
+ */
+ void setEventCount(final int eventCount) {
+ this.eventCount = eventCount;
+ }
+
+ /**
+ * Set whether the file has an EVIO <i>END</i> event.
+ *
+ * @param hasEnd <code>true</code> if file has an EVIO <i>END</i> event
+ */
+ void setHasEnd(final boolean hasEnd) {
+ this.hasEnd = hasEnd;
+ }
+
+ /**
+ * Set whether the file has an EVIO <i>PRESTART</i> event.
+ *
+ * @param hasPrestart <code>true</code> if file has an EVIO <i>PRESTART</i> event
+ */
+ void setHasPrestart(final boolean hasPrestart) {
+ this.hasPrestart = hasPrestart;
+ }
+
+ /**
+ * Set the run number.
+ *
+ * @param run the run number
+ */
+ void setRun(final int run) {
+ this.run = run;
+ }
+
+ /**
+ * Set the sequence number
+ *
+ * @param sequence the sequence number
+ */
+ void setSequence(final int sequence) {
+ this.sequence = sequence;
+ }
+
+ /**
+ * Set the start date.
+ *
+ * @param startDate the start date
+ */
+ void setStartDate(final Date startDate) {
+ this.startDate = startDate;
+ }
+
+ /**
+ * Set the start event number.
+ *
+ * @param startEvent the start event number
+ */
+ void setStartEvent(final int startEvent) {
+ this.startEvent = startEvent;
+ }
+
+ /**
+ * Convert this object to a human readable string.
+ *
+ * @return this object converted to a string
+ */
+ @Override
+ public String toString() {
+ return "EvioFileMetaData { evioFile: " + this.evioFile + ", startDate: " + this.startDate + "endDate: "
+ + this.endDate + "badEventCount: " + this.badEventCount + ", byteCount: " + this.byteCount
+ + ", eventCount: " + this.eventCount + ", hasPrestart: " + this.hasPrestart + ", hasEnd: "
+ + this.hasEnd + ", run: " + this.run + ", fileNumber: " + sequence + ", startEvent: "
+ + this.startEvent + ", endEvent: " + endEvent + " }";
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaDataReader.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaDataReader.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaDataReader.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,151 @@
+package org.hps.record.evio;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.jlab.coda.jevio.BaseStructure;
+import org.jlab.coda.jevio.EvioEvent;
+import org.jlab.coda.jevio.EvioException;
+import org.jlab.coda.jevio.EvioReader;
+import org.lcsim.util.log.DefaultLogFormatter;
+import org.lcsim.util.log.LogUtil;
+
+/**
+ * Read {@link EvioFileMetaData} from an EVIO file.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class EvioFileMetaDataReader {
+
+ /**
+ * The class logger.
+ */
+ private static Logger LOGGER = LogUtil.create(EvioFileMetaDataReader.class, new DefaultLogFormatter(), Level.ALL);
+
+ /**
+ * Get meta data from the EVIO file.
+ *
+ * @param evioFile the EVIO file
+ * @return the file's meta data
+ */
+ public EvioFileMetaData getMetaData(final File evioFile) {
+
+ LOGGER.info("getting meta data for " + evioFile.getPath());
+
+ final EvioFileMetaData metaData = new EvioFileMetaData(evioFile);
+
+ EvioEvent evioEvent = null;
+ Date startDate = null;
+ Date endDate = null;
+ int badEventCount = 0;
+ int eventCount = 0;
+ int byteCount = 0;
+ boolean hasPrestart = false;
+ boolean hasEnd = false;
+ int[] headBankData = null;
+ int[] eventIdData = null;
+ Integer run = null;
+ Integer endEvent = null;
+ Integer startEvent = null;
+
+ final int fileNumber = EvioFileUtilities.getSequenceFromName(evioFile);
+ LOGGER.info("set file number to " + fileNumber);
+
+ try {
+ final EvioReader evioReader = EvioFileUtilities.open(evioFile, false);
+ LOGGER.getHandlers()[0].flush();
+ eventCount = evioReader.getEventCount();
+ while (true) {
+ try {
+ evioEvent = evioReader.parseNextEvent();
+ if (evioEvent == null) {
+ break;
+ }
+ } catch (final Exception e) {
+ badEventCount++;
+ LOGGER.log(Level.WARNING, "got bad EVIO event", e);
+ continue;
+ }
+ byteCount += evioEvent.getTotalBytes();
+ if (EventTagConstant.PRESTART.isEventTag(evioEvent)) {
+ LOGGER.info("found PRESTART");
+ hasPrestart = true;
+ final int[] controlEventData = EvioEventUtilities.getControlEventData(evioEvent);
+ final long timestamp = controlEventData[0] * 1000L;
+ startDate = new Date(timestamp);
+ LOGGER.info("set start date to " + startDate);
+ if (run == null) {
+ run = controlEventData[1];
+ LOGGER.info("set run to " + run);
+ }
+ } else if (EventTagConstant.END.isEventTag(evioEvent)) {
+ LOGGER.info("found END");
+ hasEnd = true;
+ final int[] controlEventData = EvioEventUtilities.getControlEventData(evioEvent);
+ final long timestamp = controlEventData[0] * 1000L;
+ endDate = new Date(timestamp);
+ LOGGER.info("set end date to " + endDate);
+ if (run == null) {
+ run = controlEventData[1];
+ LOGGER.info("set run to " + run);
+ }
+ } else if (EventTagBitMask.PHYSICS.isEventTag(evioEvent)) {
+ final BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent);
+ if (headBank != null) {
+ headBankData = headBank.getIntData();
+ if (startDate == null) {
+ startDate = new Date(headBankData[3] * 1000);
+ LOGGER.info("set start date to " + endDate + " from physics event");
+ }
+ if (run == null) {
+ run = headBankData[1];
+ LOGGER.info("set run to " + run + " from physics event");
+ }
+ }
+ eventIdData = EvioEventUtilities.getEventIdData(evioEvent);
+ if (eventIdData != null) {
+ if (startEvent == null) {
+ startEvent = eventIdData[0];
+ LOGGER.info("set start event " + startEvent);
+ }
+ }
+ }
+ LOGGER.getHandlers()[0].flush();
+ }
+
+ if (endDate == null) {
+ if (headBankData != null) {
+ endDate = new Date(headBankData[3] * 1000);
+ LOGGER.info("set end date to " + endDate + " from last head bank");
+ }
+ }
+ if (eventIdData != null) {
+ endEvent = eventIdData[0];
+ LOGGER.info("set end event " + endEvent);
+ }
+ } catch (EvioException | IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ metaData.setStartDate(startDate);
+ metaData.setEndDate(endDate);
+ metaData.setBadEventCount(badEventCount);
+ metaData.setByteCount(byteCount);
+ metaData.setEventCount(eventCount);
+ metaData.setHasPrestart(hasPrestart);
+ metaData.setHasEnd(hasEnd);
+ metaData.setRun(run);
+ metaData.setSequence(fileNumber);
+ if (endEvent != null) {
+ metaData.setEndEvent(endEvent);
+ }
+ if (startEvent != null) {
+ metaData.setStartEvent(startEvent);
+ }
+
+ return metaData;
+ }
+}
Copied: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSequenceComparator.java (from r3364, 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/EvioFileSequenceComparator.java Thu Aug 20 12:50:12 2015
@@ -1,4 +1,4 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.evio;
import java.io.File;
import java.util.Comparator;
@@ -8,7 +8,7 @@
*
* @author Jeremy McCormick, SLAC
*/
-final class EvioFileSequenceComparator implements Comparator<File> {
+public final class EvioFileSequenceComparator implements Comparator<File> {
/**
* Compare two EVIO files by their sequence numbers.
@@ -17,8 +17,8 @@
*/
@Override
public int compare(final File o1, final File o2) {
- final Integer sequenceNumber1 = EvioFileUtilities.getSequence(o1);
- final Integer sequenceNumber2 = EvioFileUtilities.getSequence(o2);
+ final Integer sequenceNumber1 = EvioFileUtilities.getSequenceFromName(o1);
+ final Integer sequenceNumber2 = EvioFileUtilities.getSequenceFromName(o2);
return sequenceNumber1.compareTo(sequenceNumber2);
}
}
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileSource.java Thu Aug 20 12:50:12 2015
@@ -12,12 +12,12 @@
import org.jlab.coda.jevio.EvioReader;
/**
- * A basic implementation of an <tt>AbstractRecordSource</tt> for supplying <tt>EvioEvent</tt> objects to a loop from
- * EVIO files.
+ * A basic implementation of an <tt>AbstractRecordSource</tt> for supplying <tt>EvioEvent</tt> objects to a loop from a
+ * list of EVIO files.
* <p>
* Unlike the LCIO record source, it has no rewind or indexing capabilities.
*
- * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ * @author Jeremy McCormick, SLAC
*/
public final class EvioFileSource extends AbstractRecordSource {
@@ -48,7 +48,7 @@
*/
public EvioFileSource(final File file) {
this.files.add(file);
- openReader();
+ this.openReader();
}
/**
@@ -58,7 +58,7 @@
*/
public EvioFileSource(final List<File> files) {
this.files.addAll(files);
- openReader();
+ this.openReader();
}
/**
@@ -89,6 +89,15 @@
@Override
public Object getCurrentRecord() throws IOException {
return this.currentEvent;
+ }
+
+ /**
+ * Get the list of files.
+ *
+ * @return the list of files
+ */
+ public List<File> getFiles() {
+ return this.files;
}
/**
@@ -130,10 +139,10 @@
throw new IOException(e);
}
if (this.currentEvent == null) {
- closeReader();
+ this.closeReader();
this.fileIndex++;
- if (!endOfFiles()) {
- openReader();
+ if (!this.endOfFiles()) {
+ this.openReader();
continue;
} else {
throw new NoSuchRecordException();
@@ -151,7 +160,7 @@
private void openReader() {
try {
System.out.println("Opening reader for file " + this.files.get(this.fileIndex) + " ...");
- this.reader = new EvioReader(this.files.get(this.fileIndex), false,true);
+ this.reader = new EvioReader(this.files.get(this.fileIndex), false, true);
System.out.println("Done opening file.");
} catch (EvioException | IOException e) {
throw new RuntimeException(e);
@@ -167,4 +176,5 @@
public boolean supportsNext() {
return true;
}
+
}
Copied: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileUtilities.java (from r3364, 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/EvioFileUtilities.java Thu Aug 20 12:50:12 2015
@@ -1,26 +1,24 @@
-package org.hps.record.evio.crawler;
+package org.hps.record.evio;
import java.io.File;
import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
import java.util.logging.Logger;
-import org.hps.record.evio.EvioEventConstants;
-import org.hps.record.evio.EvioEventUtilities;
-import org.jlab.coda.jevio.BaseStructure;
-import org.jlab.coda.jevio.EvioEvent;
import org.jlab.coda.jevio.EvioException;
import org.jlab.coda.jevio.EvioReader;
import org.lcsim.util.log.LogUtil;
/**
- * A miscellaneous collection of EVIO file utility methods used by the crawler package.
+ * A miscellaneous collection of EVIO file utility methods.
*
* @author Jeremy McCormick, SLAC
*/
-final class EvioFileUtilities {
+public final class EvioFileUtilities {
/**
- * Setup logger.
+ * Setup class logger.
*/
private static final Logger LOGGER = LogUtil.create(EvioFileUtilities.class);
@@ -36,7 +34,7 @@
* @return the cached file path (prepends "/cache" to the path)
* @throws IllegalArgumentException if the file is not on the MSS (e.g. path does not start with "/mss")
*/
- static File getCachedFile(final File file) {
+ public static File getCachedFile(final File file) {
if (!isMssFile(file)) {
throw new IllegalArgumentException("File " + file.getPath() + " is not on the JLab MSS.");
}
@@ -47,80 +45,13 @@
}
/**
- * Get the end date
- *
- * @param evioReader the <code>EvioReader</code>
- * @return the run end date
- */
- static Long getEndTimestamp(final EvioReader evioReader) {
-
- // Date endDate = null;
- Long timestamp = null;
-
- try {
- // Search for the last physics event in the last 5 events of the file.
- System.out.println("going to event " + (evioReader.getEventCount() - 5) + " / "
- + evioReader.getEventCount() + " to find end date");
- evioReader.gotoEventNumber(evioReader.getEventCount() - 5);
- EvioEvent evioEvent = null;
- EvioEvent lastPhysicsEvent = null;
-
- // Find last physics event.
- while ((evioEvent = evioReader.parseNextEvent()) != null) {
- if (EvioEventUtilities.isPhysicsEvent(evioEvent)) {
- lastPhysicsEvent = evioEvent;
- }
- }
-
- // If there is no physics event found this is an error.
- if (lastPhysicsEvent == null) {
- throw new RuntimeException("No physics event found.");
- }
-
- // Get the timestamp from the head bank of the physics event.
- LOGGER.info("getting head bank date from " + lastPhysicsEvent.getEventNumber());
- final Long eventTimestamp = getHeadBankTimestamp(lastPhysicsEvent);
- if (eventTimestamp != null) {
- LOGGER.info("found end timestamp " + eventTimestamp);
- timestamp = eventTimestamp;
- } else {
- throw new RuntimeException("No timestamp found in head bank.");
- }
-
- } catch (EvioException | IOException e) {
- throw new RuntimeException(e);
- }
- return timestamp;
- }
-
- /**
- * Get the date from the head bank.
- *
- * @param event the EVIO file
- * @return the date from the head bank or null if not found
- */
- static Long getHeadBankTimestamp(final EvioEvent event) {
- // Date date = null;
- Long timestamp = null;
- final BaseStructure headBank = EvioEventUtilities.getHeadBank(event);
- if (headBank != null) {
- final int[] data = headBank.getIntData();
- final long time = data[3];
- if (time != 0L) {
- timestamp = time * MILLISECONDS;
- }
- }
- return timestamp;
- }
-
- /**
* Get the run number from the file name.
*
* @param file the EVIO file
* @return the run number
* @throws Exception if there is a problem parsing out the run number
*/
- static Integer getRun(final File file) {
+ public static Integer getRunFromName(final File file) {
final String name = file.getName();
final int startIndex = name.lastIndexOf("_") + 1;
final int endIndex = name.indexOf(".");
@@ -134,65 +65,9 @@
* @return the file's sequence number
* @throws Exception if there is an error parsing out the sequence number
*/
- static Integer getSequence(final File file) {
+ public static Integer getSequenceFromName(final File file) {
final String name = file.getName();
return Integer.parseInt(name.substring(name.lastIndexOf(".") + 1));
- }
-
- /**
- * Get the start date from the first physics event.
- *
- * @param evioReader the <code>EvioReader</code>
- * @return the run start date
- */
- static Long getStartTimestamp(final EvioReader evioReader) {
-
- Long timestamp = null;
-
- // Read events until there is a physics event and return its timestamp.
- try {
- EvioEvent event = null;
- while ((event = evioReader.parseNextEvent()) != null) {
- if (EvioEventUtilities.isPhysicsEvent(event)) {
- if ((timestamp = getHeadBankTimestamp(event)) != null) {
- break;
- }
- }
- }
- } catch (EvioException | IOException e) {
- throw new RuntimeException(e);
- }
- return timestamp;
- }
-
- /**
- * Get the date from the control bank of an EVIO event.
- *
- * @param file the EVIO file
- * @param eventTag the event tag on the bank
- * @param gotoEvent an event to start the scanning
- * @return the control bank date or null if not found
- */
- static Long getTimestamp(final EvioReader evioReader, final int eventTag, final int gotoEvent) {
- Long timestamp = null;
- try {
- EvioEvent evioEvent;
- if (gotoEvent > 0) {
- evioReader.gotoEventNumber(gotoEvent);
- } else if (gotoEvent < 0) {
- evioReader.gotoEventNumber(evioReader.getEventCount() + gotoEvent);
- }
- while ((evioEvent = evioReader.parseNextEvent()) != null) {
- if (evioEvent.getHeader().getTag() == eventTag) {
- final int[] data = EvioEventUtilities.getControlEventData(evioEvent);
- timestamp = (long) (data[0] * MILLISECONDS);
- break;
- }
- }
- } catch (EvioException | IOException e) {
- throw new RuntimeException(e);
- }
- return timestamp;
}
/**
@@ -201,35 +76,8 @@
* @param file the file
* @return <code>true</code> if the file is a cached file
*/
- static boolean isCachedFile(final File file) {
+ public static boolean isCachedFile(final File file) {
return file.getPath().startsWith("/cache");
- }
-
- /**
- * 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
- * @throws Exception if there are IO problems using the reader
- */
- static 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) {
- endOkay = true;
- break;
- }
- }
- return endOkay;
}
/**
@@ -238,7 +86,7 @@
* @param file the file
* @return <code>true</code> if the file is on the MSS
*/
- static boolean isMssFile(final File file) {
+ public static boolean isMssFile(final File file) {
return file.getPath().startsWith("/mss");
}
@@ -250,7 +98,7 @@
* @throws IOException if there is an IO problem
* @throws EvioException if there is an error reading the EVIO data
*/
- static EvioReader open(final File file) throws IOException, EvioException {
+ public static EvioReader open(final File file) throws IOException, EvioException {
return open(file, false);
}
@@ -263,7 +111,7 @@
* @throws IOException if there is an IO problem
* @throws EvioException if there is an error reading the EVIO data
*/
- static EvioReader open(final File file, final boolean sequential) throws IOException, EvioException {
+ public static EvioReader open(final File file, final boolean sequential) throws IOException, EvioException {
File openFile = file;
if (isMssFile(file)) {
openFile = getCachedFile(file);
@@ -284,12 +132,21 @@
* @throws IOException if there is an IO problem
* @throws EvioException if there is an error reading the EVIO data
*/
- static EvioReader open(final String path) throws IOException, EvioException {
+ public static EvioReader open(final String path) throws IOException, EvioException {
return open(new File(path), false);
}
/**
- * Present class instantiation.
+ * Sort a list of EVIO files by their sequence numbers.
+ *
+ * @param evioFileList the list of files to sort
+ */
+ public static void sortBySequence(final List<File> evioFileList) {
+ Collections.sort(evioFileList, new EvioFileSequenceComparator());
+ }
+
+ /**
+ * Prevent class instantiation.
*/
private EvioFileUtilities() {
}
Added: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoop.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoop.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoop.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,58 @@
+package org.hps.record.evio;
+
+import org.freehep.record.loop.DefaultRecordLoop;
+
+/**
+ * Implementation of a Freehep <code>RecordLoop</code> for EVIO data.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class EvioLoop extends DefaultRecordLoop {
+
+ /**
+ * The record adapter.
+ */
+ private final EvioLoopAdapter adapter = new EvioLoopAdapter();
+
+ /**
+ * Create a new record loop.
+ */
+ public EvioLoop() {
+ this.addLoopListener(adapter);
+ this.addRecordListener(adapter);
+ }
+
+ /**
+ * Add an EVIO event processor to the adapter which will be activated for every EVIO event that is processed.
+ *
+ * @param evioEventProcessor the EVIO processor to add
+ */
+ public void addEvioEventProcessor(final EvioEventProcessor evioEventProcessor) {
+ adapter.addEvioEventProcessor(evioEventProcessor);
+ }
+
+ /**
+ * Loop over events from the source.
+ *
+ * @param number the number of events to process or -1L for all events from the source
+ * @return the number of records that were processed
+ */
+ public long loop(final long number) {
+ if (number < 0L) {
+ this.execute(Command.GO, true);
+ } else {
+ this.execute(Command.GO_N, number, true);
+ this.execute(Command.STOP);
+ }
+ return this.getSupplied();
+ }
+
+ /**
+ * Set the EVIO data source.
+ *
+ * @param evioFileSource the EVIO data source
+ */
+ public void setEvioFileSource(final EvioFileSource evioFileSource) {
+ this.setRecordSource(evioFileSource);
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoopAdapter.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoopAdapter.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioLoopAdapter.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,96 @@
+package org.hps.record.evio;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.freehep.record.loop.AbstractLoopListener;
+import org.freehep.record.loop.LoopEvent;
+import org.freehep.record.loop.RecordEvent;
+import org.freehep.record.loop.RecordListener;
+import org.jlab.coda.jevio.EvioEvent;
+import org.lcsim.util.log.DefaultLogFormatter;
+import org.lcsim.util.log.LogUtil;
+
+/**
+ * A loop adapter for the {@link EvioLoop} which manages and activates a list of {@link EvioEventProcessor} objects.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public final class EvioLoopAdapter extends AbstractLoopListener implements RecordListener {
+
+ /**
+ * Setup class logger.
+ */
+ private final Logger LOGGER = LogUtil.create(EvioLoopAdapter.class, new DefaultLogFormatter(), Level.ALL);
+
+ /**
+ * List of event processors to activate.
+ */
+ private final List<EvioEventProcessor> processors = new ArrayList<EvioEventProcessor>();
+
+ /**
+ * Create a new loop adapter.
+ */
+ EvioLoopAdapter() {
+ }
+
+ /**
+ * Add an EVIO processor to the adapter.
+ *
+ * @param processor the EVIO processor to add to the adapter
+ */
+ void addEvioEventProcessor(final EvioEventProcessor processor) {
+ LOGGER.info("adding " + processor.getClass().getName() + " to EVIO processors");
+ this.processors.add(processor);
+ }
+
+ /**
+ * Implementation of the finish hook which activates the {@link EvioEventProcessor#endJob()} method of all
+ * registered processors.
+ */
+ @Override
+ protected void finish(final LoopEvent event) {
+ LOGGER.info("executing finish hook");
+ for (final EvioEventProcessor processor : processors) {
+ processor.endJob();
+ }
+ }
+
+ /**
+ * Primary event processing method that activates the {@link EvioEventProcessor#process(EvioEvent)} method of all
+ * registered processors.
+ *
+ * @param recordEvent the record event to process which should have an EVIO event
+ * @throws IllegalArgumentException if the record is the wrong type
+ */
+ @Override
+ public void recordSupplied(final RecordEvent recordEvent) {
+ final Object record = recordEvent.getRecord();
+ if (record instanceof EvioEvent) {
+ final EvioEvent evioEvent = EvioEvent.class.cast(record);
+ for (final EvioEventProcessor processor : processors) {
+ try {
+ processor.process(evioEvent);
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("The supplied record has the wrong type: " + record.getClass());
+ }
+ }
+
+ /**
+ * Implementation of the start hook which activates the {@link EvioEventProcessor#startJob()} method of all
+ * registered processors.
+ */
+ @Override
+ protected void start(final LoopEvent event) {
+ LOGGER.info("executing start hook");
+ for (final EvioEventProcessor processor : processors) {
+ processor.startJob();
+ }
+ }
+}
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 Aug 20 12:50:12 2015
@@ -7,6 +7,7 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
@@ -20,6 +21,8 @@
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.hps.conditions.database.ConnectionParameters;
+import org.hps.record.run.RunSummary;
+import org.hps.record.run.RunSummaryDaoImpl;
import org.lcsim.util.log.DefaultLogFormatter;
import org.lcsim.util.log.LogUtil;
@@ -50,20 +53,20 @@
* Statically define the command options.
*/
static {
- OPTIONS.addOption("a", "runs", true, "list of run numbers to accept (others will be excluded)");
+ // TODO: add -f argument with file name to include; others would be excluded if they do not match
OPTIONS.addOption("b", "min-date", true, "min date for a file (example \"2015-03-26 11:28:59\")");
OPTIONS.addOption("c", "cache", false, "automatically cache files from MSS to cache disk (JLAB only)");
OPTIONS.addOption("C", "connection-properties", true, "database connection properties file (required)");
OPTIONS.addOption("d", "directory", true, "root directory to start crawling (default is current dir)");
OPTIONS.addOption("E", "evio-processor", true, "class name of an EvioEventProcessor to execute");
OPTIONS.addOption("h", "help", false, "print help and exit (overrides all other arguments)");
- OPTIONS.addOption("m", "max-files", true, "max number of files to process per run (mostly for debugging)");
- OPTIONS.addOption("p", "print", true, "set event printing interval during EVIO processing");
- OPTIONS.addOption("r", "insert", false, "insert information into the run database (not done by default)");
+ OPTIONS.addOption("i", "insert", false, "insert information into the run database (not done by default)");
+ OPTIONS.addOption("L", "log-level", true, "set the log level (INFO, FINE, etc.)");
+ OPTIONS.addOption("r", "run", true, "add a run number to accept (when used others will be excluded)");
OPTIONS.addOption("t", "timestamp-file", true, "existing or new timestamp file name");
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("u", "update", false,
+ "allow replacement of existing data in the run db (not allowed by default)");
OPTIONS.addOption("x", "max-depth", true, "max depth to crawl in the directory tree");
}
@@ -179,9 +182,9 @@
}
// List of one or more runs to accept in the job.
- if (cl.hasOption("a")) {
+ if (cl.hasOption("r")) {
final Set<Integer> acceptRuns = new HashSet<Integer>();
- for (final String runString : cl.getOptionValues("a")) {
+ for (final String runString : cl.getOptionValues("r")) {
final Integer acceptRun = Integer.parseInt(runString);
acceptRuns.add(acceptRun);
LOGGER.config("added run filter " + acceptRun);
@@ -189,7 +192,7 @@
config.setAcceptRuns(acceptRuns);
}
- // Enable run log updating (off by default).
+ // Enable updating of run database.
if (cl.hasOption("r")) {
config.setUpdateRunLog(true);
LOGGER.config("inserting into run database is enabled");
@@ -208,21 +211,7 @@
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")) {
- 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")) {
- final int eventPrintInterval = Integer.parseInt(cl.getOptionValue("p"));
- config.setEventPrintInterval(eventPrintInterval);
- LOGGER.config("event print interval set to " + eventPrintInterval);
- }
-
- // Flag to allow replacement of existing records in the database; not allowed by default.
+ // Allow deletion and replacement of records in run database.
if (cl.hasOption("u")) {
config.setAllowUpdates(true);
LOGGER.config("deletion and replacement of existing runs in the database is enabled");
@@ -267,7 +256,13 @@
throw new RuntimeException("Error parsing options.", e);
}
+ // Configure the max wait time for file caching operations.
+ if (config.waitTime() != null && config.waitTime() > 0L) {
+ cacheManager.setWaitTime(config.waitTime());
+ }
+
LOGGER.info("done parsing command line options");
+ LOGGER.getHandlers()[0].flush();
return this;
}
@@ -293,31 +288,32 @@
LOGGER.info("running Crawler job");
// Create the file visitor for crawling the root directory with the given date filter.
+ LOGGER.info("creating file visitor");
+ LOGGER.getHandlers()[0].flush();
final EvioFileVisitor visitor = new EvioFileVisitor(config.timestamp());
// Walk the file tree using the visitor.
+ LOGGER.info("walking the dir tree");
+ LOGGER.getHandlers()[0].flush();
this.walk(visitor);
// Get the list of run data created by the visitor.
- final RunLog runs = visitor.getRunLog();
-
- // Print the run numbers that were found.
- runs.printRunNumbers();
-
- // Sort the files on their sequence numbers.
- runs.sortFiles();
+ final RunSummaryMap runs = visitor.getRunMap();
// Process all the files, performing caching from the MSS if necessary.
+ LOGGER.info("processing all runs");
RunProcessor.processAllRuns(this.cacheManager, runs, config);
-
- // Print the summary information after the run processing is done.
- runs.printRunSummaries();
+ LOGGER.getHandlers()[0].flush();
// Execute the run database update.
+ LOGGER.info("updating run database");
this.updateRunDatabase(runs);
+ LOGGER.getHandlers()[0].flush();
// Update the timestamp output file.
+ LOGGER.info("updating the timestamp");
this.updateTimestamp();
+ LOGGER.getHandlers()[0].flush();
LOGGER.info("Crawler job is done!");
}
@@ -328,21 +324,26 @@
* @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 {
+ private void updateRunDatabase(final RunSummaryMap runs) throws SQLException {
// Insert the run information into the database.
if (config.updateRunLog()) {
+ LOGGER.info("updating run database");
+
// Open a DB connection.
final Connection connection = config.connectionParameters().createConnection();
- // Create and configure RunLogUpdater which updates the run log for all runs found in the crawl job.
- final RunLogUpdater runUpdater = new RunLogUpdater(connection, runs, config.allowUpdates());
-
- // Update the DB.
- runUpdater.insert();
+ // Insert all run summaries into the database.
+ new RunSummaryDaoImpl(connection).insertFullRunSummaries(new ArrayList<RunSummary>(runs.getRunSummaries()),
+ config.allowUpdates());
// Close the DB connection.
connection.close();
+
+ LOGGER.info("done updating run database");
+
+ } else {
+ LOGGER.info("run database will not be updated");
}
}
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 Aug 20 12:50:12 2015
@@ -13,7 +13,7 @@
import org.hps.record.evio.EvioEventProcessor;
/**
- * Full configuration information for the {@link Crawler class}.
+ * Full configuration information for the {@link Crawler} class.
* <p>
* Method chaining of setters is supported.
*
@@ -38,19 +38,9 @@
private boolean allowUpdates = false;
/**
- * The database connection parameters which must be provided by command line argument.
+ * The database connection parameters which must be provided by a command line argument.
*/
private ConnectionParameters connectionParameters;
-
- /**
- * Default event print interval.
- */
- private final int DEFAULT_EVENT_PRINT_INTERVAL = 1000;
-
- /**
- * Interval for printing out event number while running EVIO processors.
- */
- private int eventPrintInterval = DEFAULT_EVENT_PRINT_INTERVAL;
/**
* The maximum depth to crawl.
@@ -151,15 +141,6 @@
}
/**
- * 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
@@ -231,17 +212,6 @@
}
/**
- * 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
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileVisitor.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileVisitor.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileVisitor.java Thu Aug 20 12:50:12 2015
@@ -12,11 +12,13 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.hps.record.evio.EvioFileFilter;
+import org.hps.record.evio.EvioFileUtilities;
import org.lcsim.util.log.DefaultLogFormatter;
import org.lcsim.util.log.LogUtil;
/**
- * A file visitor that crawls directories for EVIO files and returns the information as a {@link RunLog}.
+ * A file visitor that crawls directories for EVIO files and returns the information as a {@link RunSummaryMap}.
*
* @author Jeremy McCormick, SLAC
*/
@@ -35,8 +37,8 @@
/**
* The run log containing information about files from each run.
*/
- private final RunLog runs = new RunLog();
-
+ private final RunSummaryMap runs = new RunSummaryMap();
+
/**
* Create a new file visitor.
*
@@ -83,7 +85,7 @@
*
* @return the run log
*/
- RunLog getRunLog() {
+ RunSummaryMap getRunMap() {
return this.runs;
}
@@ -99,10 +101,10 @@
if (this.accept(file)) {
// Get the run number from the file name.
- final Integer run = EvioFileUtilities.getRun(file);
+ final Integer run = EvioFileUtilities.getRunFromName(file);
// Get the sequence number from the file name.
- final Integer seq = EvioFileUtilities.getSequence(file);
+ final Integer seq = EvioFileUtilities.getSequenceFromName(file);
LOGGER.info("accepted file " + file.getPath() + " with run " + run + " and seq " + seq);
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 Aug 20 12:50:12 2015
@@ -13,6 +13,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.hps.record.evio.EvioFileUtilities;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunFilter.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunFilter.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunFilter.java Thu Aug 20 12:50:12 2015
@@ -3,6 +3,8 @@
import java.io.File;
import java.io.FileFilter;
import java.util.Set;
+
+import org.hps.record.evio.EvioFileUtilities;
/**
* A filter which rejects files with run numbers not in a specified set.
@@ -36,6 +38,6 @@
*/
@Override
public boolean accept(final File file) {
- return this.acceptRuns.contains(EvioFileUtilities.getRun(file));
+ return this.acceptRuns.contains(EvioFileUtilities.getRunFromName(file));
}
}
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 Aug 20 12:50:12 2015
@@ -1,19 +1,16 @@
package org.hps.record.evio.crawler;
import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
-import org.hps.record.evio.EvioEventConstants;
-import org.hps.record.evio.EvioEventProcessor;
+import org.hps.record.epics.EpicsRunProcessor;
+import org.hps.record.evio.EvioFileMetaData;
+import org.hps.record.evio.EvioFileMetaDataReader;
+import org.hps.record.evio.EvioFileSource;
+import org.hps.record.evio.EvioLoop;
import org.hps.record.run.RunSummary;
import org.hps.record.scalers.ScalersEvioProcessor;
-import org.jlab.coda.jevio.EvioEvent;
-import org.jlab.coda.jevio.EvioException;
-import org.jlab.coda.jevio.EvioReader;
import org.lcsim.util.log.DefaultLogFormatter;
import org.lcsim.util.log.LogUtil;
@@ -40,35 +37,24 @@
* @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 processAllRuns(final JCacheManager cacheManager, final RunLog runs, final CrawlerConfig config)
+ static void processAllRuns(final JCacheManager cacheManager, final RunSummaryMap runs, final CrawlerConfig config)
throws Exception {
- // Configure the max wait time for file caching operations.
- if (config.waitTime() != null && config.waitTime() > 0L) {
- cacheManager.setWaitTime(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);
+ for (final RunSummary runSummary : runs.getRunSummaries()) {
// Clear the cache manager.
if (config.useFileCache()) {
+ LOGGER.info("clearing file cache");
cacheManager.clear();
}
// Create a processor to process all the EVIO events in the run.
+ LOGGER.info("creating run processor for " + runSummary.getRun());
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.
+ LOGGER.info("processing run " + runSummary.getRun());
runProcessor.processRun();
}
}
@@ -81,27 +67,17 @@
/**
* Processor for extracting EPICS information.
*/
- private final EpicsLog epicsLog;
-
- /**
- * Processor for extracting event type counts (sync, physics, trigger types, etc.).
- */
- private final EventCountProcessor eventCountProcessor;
-
- /**
- * The event printing interval when processing EVIO files.
- */
- private int eventPrintInterval = 1000;
-
- /**
- * Max total files to read (default is 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>();
+ private final EpicsRunProcessor epicsLog;
+
+ /**
+ * The data source with the list of EVIO files to process.
+ */
+ private final EvioFileSource evioFileSource;
+
+ /**
+ * The EVIO event processing loop.
+ */
+ private final EvioLoop evioLoop = new EvioLoop();
/**
* The run summary information updated by running this processor.
@@ -119,9 +95,9 @@
private boolean useFileCache;
/**
- * Create the processor for a single run.
- *
- * @param runSummary the run summary for the run
+ * Create a run processor.
+ *
+ * @param runSummary the run summary object for the run
* @return the run processor
*/
RunProcessor(final JCacheManager cacheManager, final RunSummary runSummary, final CrawlerConfig config) {
@@ -129,39 +105,22 @@
this.runSummary = runSummary;
this.cacheManager = cacheManager;
- // EPICS processor.
- epicsLog = new EpicsLog();
- this.addProcessor(epicsLog);
-
- // Scaler data processor.
+ // Setup record loop.
+ runSummary.sortFiles();
+ evioFileSource = new EvioFileSource(runSummary.getEvioFileList());
+ evioLoop.setEvioFileSource(evioFileSource);
+
+ // Add EPICS processor.
+ epicsLog = new EpicsRunProcessor();
+ evioLoop.addEvioEventProcessor(epicsLog);
+
+ // Add Scaler data processor.
scalersProcessor = new ScalersEvioProcessor();
scalersProcessor.setResetEveryEvent(false);
- this.addProcessor(scalersProcessor);
-
- // Event log processor.
- eventCountProcessor = new EventCountProcessor();
- this.addProcessor(eventCountProcessor);
-
- // Max files.
- if (config.maxFiles() != -1) {
- this.setMaxFiles(config.maxFiles());
- }
-
- // Enable file caching.
+ evioLoop.addEvioEventProcessor(scalersProcessor);
+
+ // Set whether file caching from MSS is enabled.
this.useFileCache(config.useFileCache());
-
- // Set event printing interval.
- this.setEventPrintInterval(config.eventPrintInterval());
- }
-
- /**
- * Add a processor of EVIO events.
- *
- * @param processor the EVIO event processor
- */
- void addProcessor(final EvioEventProcessor processor) {
- this.processors.add(processor);
- LOGGER.config("added processor " + processor.getClass().getSimpleName());
}
/**
@@ -172,10 +131,10 @@
*/
private void cacheFiles() {
- LOGGER.info("caching files from run " + this.runSummary.getRun() + " ...");
+ LOGGER.info("caching files from run " + this.runSummary.getRun());
// Cache all the files and wait for the operation to complete (it will take awhile!).
- this.cacheManager.cache(this.getFiles());
+ this.cacheManager.cache(this.runSummary.getEvioFileList());
final boolean cached = this.cacheManager.waitForCache();
// If the files weren't cached then die.
@@ -187,245 +146,82 @@
}
/**
- * Find the end date in the EVIO events.
- *
- * @param evioReader the open <code>EvioReader</code>
- */
- private void findEndDate(final EvioReader evioReader) {
-
- // Try to get end date from END event.
- Long endTimestamp = EvioFileUtilities.getTimestamp(evioReader, EvioEventConstants.END_EVENT_TAG, -5);
-
- if (endTimestamp != null) {
- // Flag end okay for the run.
- this.runSummary.setEndOkay(true);
- } else {
- // Try to find the end date from the last physics event.
- endTimestamp = EvioFileUtilities.getEndTimestamp(evioReader);
- this.runSummary.setEndOkay(false);
- }
-
- if (endTimestamp == null) {
- // Not finding the end date is a fatal error.
- throw new RuntimeException("Failed to find end date.");
- }
-
- LOGGER.info("found end timestamp " + endTimestamp);
- this.runSummary.setEndTimeUtc(endTimestamp);
- }
-
- /**
- * Find the start date in the EVIO events.
- *
- * @param evioReader the open <code>EvioReader</code>
- */
- private void findStartDate(final EvioReader evioReader) {
-
- // First try to find the start date in the PRESTART event.
- Long startTimestamp = EvioFileUtilities.getTimestamp(evioReader, EvioEventConstants.PRESTART_EVENT_TAG, 0);
-
- if (startTimestamp == null) {
- // Search for start date in first physics event.
- startTimestamp = EvioFileUtilities.getStartTimestamp(evioReader);
- }
-
- if (startTimestamp == null) {
- // Not finding the start date is a fatal error.
- throw new RuntimeException("Failed to find start date.");
- }
-
- LOGGER.fine("got run start " + startTimestamp);
- this.runSummary.setStartTimeUtc(startTimestamp);
- }
-
- /**
- * Get the list of files to process, which will be limited by the {@link #maxFiles} value if it is set.
- *
- * @return the files to process
- */
- private List<File> getFiles() {
- // Get the list of files to process, taking into account the max files setting.
- List<File> files = this.runSummary.getEvioFileList();
- if (this.maxFiles != -1) {
- int toIndex = this.maxFiles;
- if (toIndex > files.size()) {
- toIndex = files.size();
- }
- files = files.subList(0, toIndex);
- }
- return files;
- }
-
- /**
- * Get the list of EVIO processors.
- *
- * @return the list of EVIO processors
- */
- List<EvioEventProcessor> getProcessors() {
- return this.processors;
- }
-
- /**
- * Return <code>true</code> if the file is the first one in the list for the run.
- *
- * @param file the EVIO <code>File</code>
- * @return <code>true</code> if the file is the first one in the list for the run
- */
- private boolean isFirstFile(final File file) {
- return file.equals(this.runSummary.getEvioFileList().first());
- }
-
- /**
- * Return <code>true</code> if the file is the last one in the list for the run.
- *
- * @param file the EVIO <code>File</code>
- * @return <code>true</code> if the file is the last one in the list for the run
- */
- private boolean isLastFile(final File file) {
- return file.equals(this.getFiles().get(this.getFiles().size() - 1));
- }
-
- /**
- * Process events using the list of EVIO processors.
- *
- * @param evioReader the open <code>EvioReader</code>
- * @throws IOException if there is a file IO error
- * @throws EvioException if there is an EVIO error
- * @throws Exception if there is some other error
- */
- private void processEvents(final EvioReader evioReader) throws IOException, EvioException, Exception {
- LOGGER.finer("running EVIO processors ...");
- evioReader.gotoEventNumber(0);
- int nProcessed = 0;
- if (!this.processors.isEmpty()) {
- EvioEvent event = null;
- while ((event = evioReader.parseNextEvent()) != null) {
- for (final EvioEventProcessor processor : this.processors) {
- processor.process(event);
- }
- ++nProcessed;
- if (nProcessed % this.eventPrintInterval == 0) {
- LOGGER.finer("processed " + nProcessed + " EVIO events");
- }
- }
- LOGGER.info("done running EVIO processors");
- }
- }
-
- /**
- * Process a single EVIO file from the run.
- *
- * @param file the EVIO file
- * @throws EvioException if there is an EVIO error
- * @throws IOException if there is some kind of IO error
- * @throws Exception if there is a generic error thrown by event processing
- */
- private void processFile(final File file) throws EvioException, IOException, Exception {
-
- LOGGER.fine("processing file " + file.getPath() + " ...");
-
- EvioReader evioReader = null;
- try {
-
- // Open file for reading (flag should be true for sequential or false for mem map).
- evioReader = EvioFileUtilities.open(file, true);
-
- // If this is the first file then get the start date.
- if (this.isFirstFile(file)) {
- LOGGER.fine("getting run start from first file " + file.getPath() + " ...");
- this.findStartDate(evioReader);
- }
-
- // Go back to the first event and process the events using the list of EVIO processors.
- this.processEvents(evioReader);
-
- // Find end date from last file in the run.
- if (this.isLastFile(file)) {
- LOGGER.fine("getting run end from last file " + file.getPath() + " ...");
- this.findEndDate(evioReader);
- }
-
- } finally {
- // Close the EvioReader for the current file.
- if (evioReader != null) {
- evioReader.close();
- }
- }
- LOGGER.fine("done processing " + file.getPath());
- }
-
- /**
- * Process the run by executing the registered {@link org.hps.record.evio.EvioEventProcessor}s extracting the start
- * and end dates.
+ * Process the run by executing the registered {@link org.hps.record.evio.EvioEventProcessor}s and extracting the
+ * start and end dates.
* <p>
- * This method will also activate file caching, if enabled by the {@link #useFileCache} option.
+ * This method will also execute file caching from MSS, if enabled by the {@link #useFileCache} option.
*
* @throws Exception if there is an error processing a file
*/
void processRun() throws Exception {
- LOGGER.info("processing run " + this.runSummary.getRun() + " ...");
-
- // First cache all the files we will process, if necessary.
+ LOGGER.info("processing " + this.runSummary.getEvioFileList().size() + " files from run "
+ + this.runSummary.getRun());
+
+ // Cache files from MSS if this is enabled.
if (this.useFileCache) {
+ LOGGER.info("caching files from MSS");
this.cacheFiles();
}
- // Run the start of job hooks.
- for (final EvioEventProcessor processor : this.processors) {
- processor.startJob();
- }
-
- // Get the list of files, limited by max files setting.
- final List<File> files = this.getFiles();
-
- LOGGER.info("processing " + files.size() + " from run " + this.runSummary.getRun());
-
- // Process all the files.
- for (final File file : files) {
- this.processFile(file);
- }
-
- // Run the end job hooks.
- LOGGER.info("running end of job hooks on EVIO processors ...");
- for (final EvioEventProcessor processor : this.processors) {
- processor.endJob();
- }
-
+ // Run processors over all files.
+ LOGGER.info("looping over all events");
+ evioLoop.loop(-1);
+
+ // Get run start date.
+ LOGGER.info("setting run start date");
+ this.setRunStartDate();
+
+ // Get run end date.
+ LOGGER.info("setting run end date");
+ this.setRunEndDate();
+
+ // Update run summary from processors.
+ LOGGER.info("updating run summary");
+ this.updateRunSummary();
+
+ LOGGER.info("done processing run " + this.runSummary.getRun());
+ }
+
+ /**
+ * Set the run end date by getting meta data from the last file and copying it to the run summary.
+ */
+ private void setRunEndDate() {
+ final File lastEvioFile = runSummary.getEvioFileList().get(runSummary.getEvioFileList().size() - 1);
+ LOGGER.info("getting meta data for " + lastEvioFile.getPath());
+ final EvioFileMetaDataReader metaDataReader = new EvioFileMetaDataReader();
+ final EvioFileMetaData metaData = metaDataReader.getMetaData(lastEvioFile);
+ LOGGER.info(metaData.toString());
+ LOGGER.info("setting unix end time to " + metaData.getEndDate().getTime() + " from meta data");
+ runSummary.setEndTimeUtc(metaData.getEndDate().getTime());
+ runSummary.setEndOkay(metaData.hasEnd());
+ }
+
+ /**
+ * Set the run start date by getting meta data from the first file and copying it to the run summary.
+ */
+ private void setRunStartDate() {
+ final File firstEvioFile = runSummary.getEvioFileList().get(0);
+ LOGGER.info("getting meta data for " + firstEvioFile.getPath());
+ final EvioFileMetaDataReader metaDataReader = new EvioFileMetaDataReader();
+ final EvioFileMetaData metaData = metaDataReader.getMetaData(firstEvioFile);
+ LOGGER.info(metaData.toString());
+ LOGGER.info("setting unix start time to " + metaData.getStartDate().getTime() + " from meta data");
+ runSummary.setStartTimeUtc(metaData.getStartDate().getTime());
+ }
+
+ /**
+ * Update the current run summary by copying data to it from the EVIO processors.
+ */
+ private void updateRunSummary() {
// 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(eventCountProcessor.getEventCounts());
-
// Set total number of events on the run summary from the event counter.
- runSummary.setTotalEvents(this.eventCountProcessor.getTotalEventCount());
+ runSummary.setTotalEvents((int) evioLoop.getTotalCountableConsumed());
// Set EpicsData for the run.
runSummary.setEpicsData(this.epicsLog.getEpicsData());
-
- LOGGER.info("done processing run " + this.runSummary.getRun());
- }
-
- /**
- * Set the event print interval when running the EVIO processors.
- *
- * @param eventPrintInterval the event print interval when running the EVIO processors
- */
- void setEventPrintInterval(final int eventPrintInterval) {
- this.eventPrintInterval = eventPrintInterval;
- }
-
- /**
- * Set the maximum number of files to process.
- * <p>
- * This is intended primarily for debugging.
- *
- * @param maxFiles the maximum number of files to process
- */
- void setMaxFiles(final int maxFiles) {
- this.maxFiles = maxFiles;
- LOGGER.config("max files set to " + maxFiles);
}
/**
Copied: java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryMap.java (from r3364, 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/RunSummaryMap.java Thu Aug 20 12:50:12 2015
@@ -1,32 +1,33 @@
package org.hps.record.evio.crawler;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.HashMap;
import java.util.logging.Logger;
import org.hps.record.run.RunSummary;
import org.lcsim.util.log.LogUtil;
/**
- * This class contains information about a series of runs which each have a {@link RunSummary} object.
+ * This class maps run numbers to {@link RunSummary} objects.
*
* @author Jeremy McCormick, SLAC
*/
-final class RunLog {
+@SuppressWarnings("serial")
+final class RunSummaryMap extends HashMap<Integer, RunSummary> {
/**
* Setup logging.
*/
- private static final Logger LOGGER = LogUtil.create(RunLog.class);
+ private static final Logger LOGGER = LogUtil.create(RunSummaryMap.class);
/**
- * A map between run numbers and the run summary information.
+ * Get the collection of {@link RunSummary} objects.
+ *
+ * @return the collection of {@link RunSummary} objects
*/
- private final Map<Integer, RunSummary> runs = new LinkedHashMap<Integer, RunSummary>();
+ public Collection<RunSummary> getRunSummaries() {
+ return this.values();
+ }
/**
* Get a {@link RunSummary} by its run number.
@@ -37,63 +38,10 @@
* @return the <code>RunSummary</code> for the run number
*/
public RunSummary getRunSummary(final int run) {
- if (!this.runs.containsKey(run)) {
+ if (!this.containsKey(run)) {
LOGGER.info("creating new RunSummary for run " + run);
- this.runs.put(run, new RunSummary(run));
+ this.put(run, new RunSummary(run));
}
- return this.runs.get(run);
+ return this.get(run);
}
-
- /**
- * Get the collection of {@link RunSummary} objects.
- *
- * @return the collection of {@link RunSummary} objects
- */
- public Collection<RunSummary> getRunSummaries() {
- return this.runs.values();
- }
-
- /**
- * Get a list of sorted run numbers from this run log.
- * <p>
- * This is a copy of the keys from the map, so modifying it will have no effect on the original.
- *
- * @return the list of sorted run numbers
- */
- List<Integer> getSortedRunNumbers() {
- final List<Integer> runList = new ArrayList<Integer>(this.runs.keySet());
- Collections.sort(runList);
- return runList;
- }
-
- /**
- * Print out each {@link RunSummary} to <code>System.out</code>.
- */
- void printRunSummaries() {
- for (final int run : this.runs.keySet()) {
- this.runs.get(run).printOut(System.out);
- }
- }
-
- /**
- * Sort the file list for each run in place by EVIO sequence numbers.
- */
- void sortFiles() {
- for (final Integer run : this.runs.keySet()) {
- this.runs.get(run).sortFiles();
- }
- }
-
- /**
- * Print the run numbers to the log.
- */
- void printRunNumbers() {
- // Print the list of runs that were found.
- final StringBuffer sb = new StringBuffer();
- for (final Integer run : getSortedRunNumbers()) {
- sb.append(run + " ");
- }
- LOGGER.info("found EVIO files from runs: " + sb.toString());
- }
-
}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDao.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDao.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDao.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,65 @@
+package org.hps.record.run;
+
+import java.util.List;
+
+import org.hps.record.epics.EpicsData;
+
+/**
+ * Database Access Object (DAO) API for EPICS data from the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public interface EpicsDataDao {
+
+ /**
+ * Delete EPICS data from the database.
+ *
+ * @param epicsData the EPICS data to delete
+ */
+ void deleteEpicsData(EpicsData epicsData);
+
+ /**
+ * Delete all EPICS data for a run from the database.
+ *
+ * @param run the run number
+ */
+ void deleteEpicsData(int run);
+
+ /**
+ * Get all the EPICS data in the database.
+ *
+ * @return the list of EPICS data
+ */
+ List<EpicsData> getAllEpicsData();
+
+ /**
+ * Get EPICS data by run.
+ *
+ * @param run the run number
+ * @return the EPICS data
+ */
+ List<EpicsData> getEpicsData(int run);
+
+ /**
+ * Get the list of unique variables names used in the database records.
+ *
+ * @return the list of unique variable names
+ */
+ List<String> getVariableNames();
+
+ /**
+ * Insert a list of EPICS data into the database.
+ * <p>
+ * The run number comes from the header information.
+ *
+ * @param epicsDataList the list of EPICS data
+ */
+ void insertEpicsData(List<EpicsData> epicsDataList);
+
+ /**
+ * Updates EPICS data in the database.
+ *
+ * @param epicsData the EPICS data to update
+ */
+ void updateEpicsData(EpicsData epicsData);
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDaoImpl.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDaoImpl.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EpicsDataDaoImpl.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,362 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.record.epics.EpicsData;
+import org.hps.record.epics.EpicsHeader;
+
+/**
+ * Implementation of database operations for EPICS data.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class EpicsDataDaoImpl implements EpicsDataDao {
+
+ /**
+ * SQL data query strings.
+ */
+ private static class EpicsDataQuery {
+
+ /**
+ * Delete by run number.
+ */
+ private static final String DELETE_BY_RUN = "DELETE FROM run_epics WHERE run = ?";
+ /**
+ * Delete by run and sequence number.
+ */
+ private static final String DELETE_RUN_AND_SEQUENCE = "DELETE FROM run_epics WHERE run = ? and sequence = ?";
+ /**
+ * Insert a record.
+ */
+ private static final String INSERT = "INSERT INTO run_epics (run, sequence, timestamp, variable_name, value) VALUES (?, ?, ?, ?, ?)";
+ /**
+ * Select all records.
+ */
+ private static final String SELECT_ALL = "SELECT * FROM run_epics ORDER BY run, sequence";
+ /**
+ * Select by run number.
+ */
+ private static final String SELECT_RUN = "SELECT * FROM run_epics WHERE run = ? ORDER BY `sequence`";
+ /**
+ * Select unique variable names.
+ */
+ private static final String SELECT_VARIABLE_NAMES = "SELECT DISTINCT(variable_name) FROM run_epics ORDER BY variable_name";
+ /**
+ * Update a record.
+ */
+ private static final String UPDATE = "UPDATE run_epics SET run = ?, sequence = ?, timestamp = ?, variable_name = ?, value = ? WHERE run = ? and sequence = ? and variable_name = ?";
+ }
+
+ /**
+ * The database connection.
+ */
+ private final Connection connection;
+
+ /**
+ * Create a new DAO implementation for EPICS data.
+ *
+ * @param connection the database connection
+ */
+ public EpicsDataDaoImpl(final Connection connection) {
+ if (connection == null) {
+ throw new IllegalArgumentException("The connection is null.");
+ }
+ this.connection = connection;
+ }
+
+ /**
+ * Delete the record for this EPICS data object using its run and sequence number.
+ *
+ * @param run the run number
+ * @throws IllegalArgumentException if the EPICS data is missing a header object
+ */
+ @Override
+ public void deleteEpicsData(final EpicsData epicsData) {
+ PreparedStatement preparedStatement = null;
+ try {
+ final EpicsHeader epicsHeader = epicsData.getEpicsHeader();
+ if (epicsHeader == null) {
+ throw new IllegalArgumentException("The EPICS data is missing header information.");
+ }
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.DELETE_RUN_AND_SEQUENCE);
+ preparedStatement.setInt(1, epicsHeader.getRun());
+ preparedStatement.setInt(2, epicsHeader.getSequence());
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Delete all EPICS data for a run from the database.
+ *
+ * @param run the run number
+ */
+ @Override
+ public void deleteEpicsData(final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.DELETE_BY_RUN);
+ preparedStatement.setInt(1, run);
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Get all the EPICS data in the database.
+ *
+ * @return the list of EPICS data
+ */
+ @Override
+ public List<EpicsData> getAllEpicsData() {
+ PreparedStatement preparedStatement = null;
+ final List<EpicsData> epicsDataList = new ArrayList<EpicsData>();
+ try {
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.SELECT_ALL);
+ final ResultSet resultSet = preparedStatement.executeQuery();
+ Integer currentRun = null;
+ Integer currentSequence = null;
+ EpicsData epicsData = new EpicsData();
+ while (resultSet.next()) {
+ if (currentRun == null) {
+ currentRun = resultSet.getInt("run");
+ }
+ if (currentSequence == null) {
+ currentSequence = resultSet.getInt("sequence");
+ }
+ final int run = resultSet.getInt("run");
+ final int sequence = resultSet.getInt("sequence");
+ final int timestamp = resultSet.getInt("timestamp");
+ final String variableName = resultSet.getString("variable_name");
+ final double value = resultSet.getDouble("value");
+ if (currentRun != run || currentSequence != sequence) {
+ epicsDataList.add(epicsData);
+ epicsData = new EpicsData();
+ final EpicsHeader epicsHeader = new EpicsHeader(new int[] {run, sequence, timestamp});
+ epicsData.setEpicsHeader(epicsHeader);
+ }
+ epicsData.setValue(variableName, value);
+ }
+ epicsDataList.add(epicsData);
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ return epicsDataList;
+ }
+
+ /**
+ * Get EPICS data by run.
+ *
+ * @param run the run number
+ * @return the EPICS data
+ */
+ @Override
+ public List<EpicsData> getEpicsData(final int run) {
+ PreparedStatement preparedStatement = null;
+ final List<EpicsData> epicsDataList = new ArrayList<EpicsData>();
+ try {
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.SELECT_RUN);
+ preparedStatement.setInt(1, run);
+ final ResultSet resultSet = preparedStatement.executeQuery();
+ Integer currentSequence = null;
+ EpicsData epicsData = new EpicsData();
+ EpicsHeader epicsHeader = null;
+ while (resultSet.next()) {
+
+ // Get record data.
+ final int sequence = resultSet.getInt("sequence");
+ final int timestamp = resultSet.getInt("timestamp");
+ final String variableName = resultSet.getString("variable_name");
+ final double value = resultSet.getDouble("value");
+
+ // Get sequence first time.
+ if (currentSequence == null) {
+ currentSequence = resultSet.getInt("sequence");
+ }
+
+ // Create EPICS header.
+ epicsHeader = new EpicsHeader(new int[] {run, sequence, timestamp});
+
+ // First time need to set header here.
+ if (epicsData.getEpicsHeader() == null) {
+ epicsData.setEpicsHeader(epicsHeader);
+ }
+
+ // New sequence number occurred.
+ if (currentSequence != sequence) {
+
+ // Add the EPICS data to the list.
+ epicsDataList.add(epicsData);
+
+ // Use the new sequence number.
+ currentSequence = sequence;
+
+ // Create new EPICS data.
+ epicsData = new EpicsData();
+
+ // Set header from current record.
+ epicsData.setEpicsHeader(epicsHeader);
+ }
+
+ // Set the value of the variable from the current record.
+ epicsData.setValue(variableName, value);
+ }
+
+ // Add the last object which will not happen inside the loop.
+ epicsDataList.add(epicsData);
+
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ return epicsDataList;
+ }
+
+ /**
+ * Get the list of unique variables names used in the database records.
+ *
+ * @return the list of unique variable names
+ */
+ @Override
+ public List<String> getVariableNames() {
+ final List<String> variableNames = new ArrayList<String>();
+ Statement statement = null;
+ try {
+ statement = connection.createStatement();
+ final ResultSet resultSet = statement.executeQuery(EpicsDataQuery.SELECT_VARIABLE_NAMES);
+ while (resultSet.next()) {
+ variableNames.add(resultSet.getString(1));
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return variableNames;
+ }
+
+ /**
+ * Insert a list of EPICS data into the database.
+ * <p>
+ * The run number comes from the header information.
+ *
+ * @param epicsDataList the list of EPICS data
+ */
+ @Override
+ public void insertEpicsData(final List<EpicsData> epicsDataList) {
+ if (epicsDataList.isEmpty()) {
+ throw new IllegalStateException("The EPICS data list is empty.");
+ }
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.INSERT);
+ for (final EpicsData epicsData : epicsDataList) {
+ final EpicsHeader epicsHeader = epicsData.getEpicsHeader();
+ if (epicsHeader == null) {
+ throw new IllegalArgumentException("The EPICS data is missing header information.");
+ }
+ for (final String variableName : epicsData.getKeys()) {
+ preparedStatement.setInt(1, epicsData.getEpicsHeader().getRun());
+ preparedStatement.setInt(2, epicsData.getEpicsHeader().getSequence());
+ preparedStatement.setInt(3, epicsData.getEpicsHeader().getTimestamp());
+ preparedStatement.setString(4, variableName);
+ preparedStatement.setDouble(5, epicsData.getValue(variableName));
+ preparedStatement.executeUpdate();
+ }
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates EPICS data in the database.
+ *
+ * @param epicsData the EPICS data to update
+ */
+ @Override
+ public void updateEpicsData(final EpicsData epicsData) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(EpicsDataQuery.UPDATE);
+ final int run = epicsData.getEpicsHeader().getRun();
+ final int sequence = epicsData.getEpicsHeader().getSequence();
+ final int timestamp = epicsData.getEpicsHeader().getTimestamp();
+ for (final String variableName : epicsData.getKeys()) {
+ preparedStatement.setInt(1, run);
+ preparedStatement.setInt(2, sequence);
+ preparedStatement.setInt(3, timestamp);
+ preparedStatement.setString(4, variableName);
+ preparedStatement.setDouble(5, epicsData.getValue(variableName));
+ preparedStatement.setInt(6, run);
+ preparedStatement.setInt(7, sequence);
+ preparedStatement.setString(8, variableName);
+ preparedStatement.executeUpdate();
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ if (preparedStatement != null) {
+ preparedStatement.close();
+ }
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ connection.setAutoCommit(true);
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDao.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDao.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDao.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,43 @@
+package org.hps.record.run;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Database Access Object (DAO) interface to EVIO files in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public interface EvioFilesDao {
+
+ /**
+ * Delete the EVIO file records for a run.
+ *
+ * @param run the run number
+ */
+ void deleteEvioFiles(int run);
+
+ /**
+ * Get all EVIO files from the database.
+ *
+ * @return all EVIO files from the database
+ */
+ List<File> getAllEvioFiles();
+
+ /**
+ * Get a list of EVIO files by run number.
+ *
+ * @param run the run number
+ * @return the list of EVIO files for the run
+ */
+ List<File> getEvioFiles(int run);
+
+ /**
+ * Insert the list of files for a run.
+ *
+ * @param fileList the list of files
+ * @param run the run number
+ */
+ void insertEvioFiles(List<File> fileList, int run);
+
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDaoImpl.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDaoImpl.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/EvioFilesDaoImpl.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,168 @@
+package org.hps.record.run;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of database operations for EVIO files in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class EvioFilesDaoImpl implements EvioFilesDao {
+
+ /**
+ * SQL query strings.
+ */
+ private static final class EvioFilesQuery {
+
+ /**
+ * Delete files by run number.
+ */
+ private static final String DELETE_RUN = "DELETE FROM run_files where run = ?";
+ /**
+ * Insert files by run number.
+ */
+ private static final String INSERT_RUN = "INSERT INTO run_files (run, directory, name) VALUES(?, ?, ?)";
+ /**
+ * Select all records.
+ */
+ private static final String SELECT_ALL = "SELECT directory, name FROM run_files";
+ /**
+ * Select records by run number.
+ */
+ private static final String SELECT_RUN = "SELECT directory, name FROM run_files WHERE run = ?";
+ }
+
+ /**
+ * The database connection.
+ */
+ private final Connection connection;
+
+ public EvioFilesDaoImpl(final Connection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * Delete the EVIO file records for a run.
+ *
+ * @param run the run number
+ */
+ @Override
+ public void deleteEvioFiles(final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(EvioFilesQuery.DELETE_RUN);
+ preparedStatement.setInt(1, run);
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Get all EVIO files from the database.
+ *
+ * @return all EVIO files from the database
+ */
+ @Override
+ public List<File> getAllEvioFiles() {
+ Statement statement = null;
+ final List<File> evioFileList = new ArrayList<File>();
+ try {
+ statement = this.connection.createStatement();
+ final ResultSet resultSet = statement.executeQuery(EvioFilesQuery.SELECT_ALL);
+ while (resultSet.next()) {
+ evioFileList.add(new File(resultSet.getString("directory") + File.separator
+ + resultSet.getString("name")));
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return evioFileList;
+ }
+
+ /**
+ * Get a list of EVIO files by run number.
+ *
+ * @param run the run number
+ * @return the list of EVIO files for the run
+ */
+ @Override
+ public List<File> getEvioFiles(final int run) {
+ PreparedStatement preparedStatement = null;
+ final List<File> evioFileList = new ArrayList<File>();
+ try {
+ preparedStatement = this.connection.prepareStatement(EvioFilesQuery.SELECT_RUN);
+ preparedStatement.setInt(1, run);
+ final ResultSet resultSet = preparedStatement.executeQuery();
+ while (resultSet.next()) {
+ evioFileList.add(new File(resultSet.getString("directory") + File.separator
+ + resultSet.getString("name")));
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return evioFileList;
+ }
+
+ /**
+ * Insert the list of files for a run.
+ *
+ * @param fileList the list of files
+ * @param run the run number
+ */
+ @Override
+ public void insertEvioFiles(final List<File> fileList, final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(EvioFilesQuery.INSERT_RUN);
+ for (final File file : fileList) {
+ preparedStatement.setInt(1, run);
+ preparedStatement.setString(2, file.getParentFile().getPath());
+ preparedStatement.setString(3, file.getName());
+ preparedStatement.executeUpdate();
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Modified: java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunManager.java Thu Aug 20 12:50:12 2015
@@ -1,9 +1,8 @@
package org.hps.record.run;
import java.sql.Connection;
-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;
@@ -14,19 +13,14 @@
import org.lcsim.util.log.LogUtil;
/**
- * Manages read-only access to the run database and creates a {@link RunSummary} object from the data for a specific
- * run.
- * <p>
- * This class converts database records into {@link RunSummary}, {@link org.hps.record.epics.EpicsData},
- * {@link org.hps.record.scalers.ScalerData}, and {@link org.hps.record.evio.crawler.EvioFileList} objects using their
- * corresponding {@link AbstractRunDatabaseReader} implementation classes.
+ * Manages read-only access to the run database and creates a {@link RunSummary} for a specific run.
*
* @author Jeremy McCormick, SLAC
*/
public final class RunManager implements ConditionsListener {
/**
- * The default connection parameters for read-only access to the run database using the standard 'hpsuser' account.
+ * The default connection parameters for read-only access to the run database.
*/
private static ConnectionParameters DEFAULT_CONNECTION_PARAMETERS = new ConnectionParameters("hpsuser",
"darkphoton", "hps_run_db", "hpsdb.jlab.org");
@@ -61,7 +55,7 @@
/**
* The database connection parameters, initially set to the default parameters.
*/
- private ConnectionParameters connectionParameters = DEFAULT_CONNECTION_PARAMETERS;
+ private final ConnectionParameters connectionParameters = DEFAULT_CONNECTION_PARAMETERS;
/**
* The run number; the -1 value indicates that this has not been set externally yet.
@@ -73,11 +67,18 @@
*/
private RunSummary runSummary = null;
- void closeConnection() {
- try {
- this.connection.close();
- } catch (final SQLException e) {
- e.printStackTrace();
+ /**
+ * Close the database connection.
+ */
+ private void closeConnection() {
+ if (!(this.connection == null)) {
+ try {
+ if (!this.connection.isClosed()) {
+ this.connection.close();
+ }
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
}
}
@@ -90,21 +91,21 @@
}
/**
- * Get the database connection.
- *
- * @return the database connection or <code>null</code> if it is not set
- */
- Connection getConnection() {
- return this.connection;
- }
-
- /**
- * Get the run number.
+ * Get the current run number.
*
* @return the run number
*/
public int getRun() {
return run;
+ }
+
+ /**
+ * Get the complete list of run numbers from the database.
+ *
+ * @return the complete list of run numbers
+ */
+ List<Integer> getRuns() {
+ return new RunSummaryDaoImpl(this.connection).getRuns();
}
/**
@@ -117,122 +118,70 @@
}
/**
- * Read information from the run database and create a {@link RunSummary} from it.
+ * Open a new database connection from the connection parameters if the current one is closed or <code>null</code>.
+ * <p>
+ * This method does nothing if the connection is already open.
*/
- private void readRun() {
-
- // Read main RunSummary object but not objects that it references.
- final RunSummaryReader runSummaryReader = new RunSummaryReader();
- runSummaryReader.setRun(this.getRun());
- runSummaryReader.setConnection(this.getConnection());
- runSummaryReader.read();
- this.setRunSummary(runSummaryReader.getData());
-
- // Read EpicsData and set on RunSummary.
- final EpicsDataReader epicsDataReader = new EpicsDataReader();
- epicsDataReader.setRun(this.getRun());
- epicsDataReader.setConnection(this.getConnection());
- epicsDataReader.read();
- this.getRunSummary().setEpicsData(epicsDataReader.getData());
-
- // Read ScalerData and set on RunSummary.
- final ScalerDataReader scalerDataReader = new ScalerDataReader();
- scalerDataReader.setRun(this.getRun());
- scalerDataReader.setConnection(this.getConnection());
- scalerDataReader.read();
- this.getRunSummary().setScalerData(scalerDataReader.getData());
-
- // Read ScalerData and set on RunSummary.
- final EvioFileListReader evioFileListReader = new EvioFileListReader();
- evioFileListReader.setRun(this.getRun());
- evioFileListReader.setConnection(this.getConnection());
- evioFileListReader.read();
- this.getRunSummary().setEvioFileList(evioFileListReader.getData());
+ private void openConnection() {
+ try {
+ if (this.connection == null || this.connection.isClosed()) {
+ LOGGER.info("creating database connection");
+ this.connection = connectionParameters.createConnection();
+ } else {
+ LOGGER.warning("connection already open");
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException("Error opening database connection.", e);
+ }
}
/**
- * Check if the current run number exists in the run database.
+ * Set the connection externally if using a database other than the default one at JLAB.
*
- * @return <code>true</code> if run exists
+ * @param connection the database connection
*/
- private boolean runExists() throws SQLException {
- PreparedStatement statement = null;
- boolean exists = false;
- try {
- statement = connection.prepareStatement("SELECT run FROM runs where run = ?");
- statement.setInt(1, this.run);
- final ResultSet resultSet = statement.executeQuery();
- exists = resultSet.next();
- } finally {
- if (statement != null) {
- try {
- statement.close();
- } catch (final SQLException e) {
- e.printStackTrace();
- }
- }
- }
- return exists;
+ public void setConnection(final Connection connection) {
+ this.connection = connection;
}
/**
- * Set the database connection parameters.
- */
- public void setConnectionParameters(final ConnectionParameters connectionParameters) {
- this.connectionParameters = connectionParameters;
- }
-
- /**
- * Set the run number and load the applicable {@link RunSummary} from the db.
+ * Set the run number and then load the applicable {@link RunSummary} from the database.
*
* @param run the run number
*/
- synchronized void setRun(final int run) {
+ public synchronized void setRun(final int run) {
+ // Check if run number is valid.
if (run < 0) {
throw new IllegalArgumentException("invalid run number: " + run);
}
- try {
+ // Setup the database connection.
+ this.openConnection();
- // Setup the database connection.
- if (this.connection == null || this.connection.isClosed()) {
- this.connection = connectionParameters.createConnection();
+ // Initialize database interface.
+ final RunSummaryDao runSummaryDao = new RunSummaryDaoImpl(this.connection);
+
+ // Set the current run number.
+ this.run = run;
+
+ // Does the current run exist in the database?
+ if (runSummaryDao.runSummaryExists(this.getRun())) {
+ LOGGER.info("run " + run + " found in database");
+ try {
+ // Read the records from the database and convert into complex Java object.
+ this.runSummary = runSummaryDao.readFullRunSummary(this.getRun());
+ } catch (final Exception e) {
+ // There was some unknown error when reading in the run records.
+ LOGGER.log(Level.SEVERE, "Error reading from run database.", e);
+ throw new RuntimeException(e);
}
+ } else {
+ // Run is not in the database.
+ LOGGER.warning("run database record does not exist for run " + run);
+ }
- // Set the current run number.
- this.run = run;
-
- // Does the current run exist in the database?
- if (this.runExists()) {
- LOGGER.info("run record found in hps_run_db for " + run);
- try {
- // Read the records from the database and convert into Java objects.
- this.readRun();
- } catch (final Exception e) {
- // There was some unknown error when reading in the run records.
- LOGGER.log(Level.SEVERE, "Error reading from run database for run: " + run, e);
- throw new RuntimeException(e);
- }
- } else {
- // Run is not in the database.
- LOGGER.warning("run database record does not exist for run " + run);
- }
-
- // Close the database connection.
- this.connection.close();
-
- } catch (final SQLException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Set the current {@link RunSummary}.
- *
- * @param runSummary the current {@link RunSummary}
- */
- void setRunSummary(final RunSummary runSummary) {
- this.runSummary = runSummary;
+ // Close the database connection.
+ this.closeConnection();
}
}
Modified: java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunSummary.java Thu Aug 20 12:50:12 2015
@@ -4,13 +4,16 @@
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.hps.record.epics.EpicsData;
-import org.hps.record.evio.crawler.EvioFileList;
+import org.hps.record.evio.EvioFileSequenceComparator;
import org.hps.record.scalers.ScalerData;
/**
@@ -26,11 +29,10 @@
* <li>number of EVIO files in the run</li>
* <li>whether the END event was found indicating that the DAQ did not crash</li>
* <li>whether the run is considered good (all <code>true</code> for now)</li>
- * <li>list of EVIO files in the run</li>
* </ul>
- * There are also associated {@link org.hps.record.epics.EpicsData} and {@link org.hps.record.scalers.ScalerData}
- * objects representing the EPICS and scaler data summaries for the run. The EPICS data is averaged over the whole run
- * while the scalers are from the last scaler data bank that was found.
+ * <p>
+ * It also references several complex objects including lists of {@link org.hps.record.epics.EpicsData} and
+ * {@link org.hps.record.scalers.ScalerData} for the run, as well as a list of EVIO files.
*
* @author Jeremy McCormick, SLAC
*/
@@ -48,6 +50,9 @@
DATE_DISPLAY.setCalendar(new GregorianCalendar(TimeZone.getTimeZone("America/New_York")));
}
+ /**
+ * Date this record was created.
+ */
private Date created;
/**
@@ -61,9 +66,9 @@
private long endTimeUtc;
/**
- * The combined EPICS information for the run (uses the mean values for each variable).
- */
- private EpicsData epics;
+ * The EPICS data from the run.
+ */
+ private List<EpicsData> epicsDataList;
/**
* The counts of different types of events that were found.
@@ -73,7 +78,7 @@
/**
* The list of EVIO files in the run.
*/
- private EvioFileList evioFileList = new EvioFileList();
+ private List<File> evioFileList = new ArrayList<File>();
/**
* The run number.
@@ -86,9 +91,9 @@
private boolean runOkay = true;
/**
- * The scaler data from the last physics event in the run.
- */
- private ScalerData scalerData;
+ * The scaler data for the run.
+ */
+ private List<ScalerData> scalerDataList;
/**
* The run start time in UTC (milliseconds).
@@ -165,14 +170,12 @@
}
/**
- * Get the EPICS data summary.
- * <p>
- * This is computed by taking the mean of each variable for the run.
- *
- * @return the EPICS data summary
- */
- public EpicsData getEpicsData() {
- return this.epics;
+ * Get the EPICS data from the run.
+ *
+ * @return the EPICS data from the run
+ */
+ public List<EpicsData> getEpicsDataSet() {
+ return this.epicsDataList;
}
/**
@@ -202,7 +205,7 @@
*
* @return the list of EVIO files in this run
*/
- public EvioFileList getEvioFileList() {
+ public List<File> getEvioFileList() {
return this.evioFileList;
}
@@ -225,12 +228,12 @@
}
/**
- * Get the scaler data of this run (last event only).
- *
- * @return the scaler data of this run from the last event
- */
- public ScalerData getScalerData() {
- return this.scalerData;
+ * Get the scaler data of this run.
+ *
+ * @return the scaler data of this run
+ */
+ public List<ScalerData> getScalerData() {
+ return this.scalerDataList;
}
/**
@@ -295,8 +298,8 @@
public void printOut(final PrintStream ps) {
ps.println("--------------------------------------------");
ps.println("run: " + this.run);
- ps.println("first file: " + this.evioFileList.first());
- ps.println("last file: " + this.evioFileList.last());
+ ps.println("first file: " + this.evioFileList.get(0));
+ ps.println("last file: " + this.evioFileList.get(evioFileList.size() - 1));
ps.println("started: " + DATE_DISPLAY.format(this.getStartDate()));
ps.println("ended: " + DATE_DISPLAY.format(this.getEndDate()));
ps.println("total events: " + this.getTotalEvents());
@@ -333,7 +336,7 @@
/**
* Set the end date.
*
- * @param endDate the end date
+ * @param endTimeUtc the end date
*/
public void setEndTimeUtc(final long endTimeUtc) {
this.endTimeUtc = endTimeUtc;
@@ -344,8 +347,8 @@
*
* @param epics the EPICS data for the run
*/
- public void setEpicsData(final EpicsData epics) {
- this.epics = epics;
+ public void setEpicsData(final List<EpicsData> epicsDataList) {
+ this.epicsDataList = epicsDataList;
}
/**
@@ -362,7 +365,7 @@
*
* @param evioFileList the list of EVIO files for the run
*/
- public void setEvioFileList(final EvioFileList evioFileList) {
+ public void setEvioFileList(final List<File> evioFileList) {
this.evioFileList = evioFileList;
}
@@ -380,14 +383,14 @@
*
* @param scalerData the scaler data
*/
- public void setScalerData(final ScalerData scalerData) {
- this.scalerData = scalerData;
+ public void setScalerData(final List<ScalerData> scalerDataList) {
+ this.scalerDataList = scalerDataList;
}
/**
* Set the start date of the run.
*
- * @param startDate the start date of the run
+ * @param startTimeUtc the start date of the run
*/
public void setStartTimeUtc(final long startTimeUtc) {
this.startTimeUtc = startTimeUtc;
@@ -424,7 +427,7 @@
* Sort the files in the run by sequence number in place.
*/
public void sortFiles() {
- this.evioFileList.sort();
+ Collections.sort(this.evioFileList, new EvioFileSequenceComparator());
}
/**
Added: java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDao.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDao.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDao.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,99 @@
+package org.hps.record.run;
+
+import java.util.List;
+
+/**
+ * Data Access Object (DAO) API for managing run summary information in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public interface RunSummaryDao {
+
+ /**
+ * Delete a run summary from the database including its referenced objects such as EPICS data.
+ *
+ * @param runSummary the run summary to delete
+ */
+ void deleteFullRunSummary(RunSummary runSummary);
+
+ /**
+ * Delete a run summary by run number.
+ *
+ * @param run the run number
+ */
+ void deleteRunSummary(int run);
+
+ /**
+ * Delete a run summary but not its objects.
+ *
+ * @param runSummary the run summary object
+ */
+ void deleteRunSummary(RunSummary runSummary);
+
+ /**
+ * Get the list of run numbers.
+ *
+ * @return the list of run numbers
+ */
+ List<Integer> getRuns();
+
+ /**
+ * Get a list of run summaries without loading their objects such as EPICS data.
+ *
+ * @return the list of run summaries
+ */
+ List<RunSummary> getRunSummaries();
+
+ /**
+ * Get a run summary by run number without loading object state.
+ *
+ * @param run the run number
+ * @return the run summary object
+ */
+ RunSummary getRunSummary(int run);
+
+ /**
+ * Insert a list of run summaries along with its referenced objects such as scaler and EPICS data.
+ *
+ * @param runSummaryList the list of run summaries
+ * @param deleteExisting <code>true</code> to allow deletion and replacement of existing run summaries
+ */
+ void insertFullRunSummaries(List<RunSummary> runSummaryList, boolean deleteExisting);
+
+ /**
+ * Insert a run summary including all its objects.
+ *
+ * @param runSummary the run summary object
+ */
+ void insertFullRunSummary(RunSummary runSummary);
+
+ /**
+ * Insert a run summary but not its objects.
+ *
+ * @param runSummary the run summary object
+ */
+ void insertRunSummary(RunSummary runSummary);
+
+ /**
+ * Read a run summary and its objects such as scaler data.
+ *
+ * @param run the run number
+ * @return the full run summary
+ */
+ RunSummary readFullRunSummary(int run);
+
+ /**
+ * Return <code>true</code> if a run summary exists in the database.
+ *
+ * @param run the run number
+ * @return <code>true</code> if <code>run</code> exists in the database
+ */
+ boolean runSummaryExists(int run);
+
+ /**
+ * Update a run summary but not its objects.
+ *
+ * @param runSummary the run summary to update
+ */
+ void updateRunSummary(RunSummary runSummary);
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,488 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.util.log.DefaultLogFormatter;
+import org.lcsim.util.log.LogUtil;
+
+/**
+ * Implementation of database operations for {@link RunSummary} objects in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class RunSummaryDaoImpl implements RunSummaryDao {
+
+ /**
+ * SQL query strings.
+ */
+ private static final class RunSummaryQuery {
+
+ /**
+ * Delete by run number.
+ */
+ private static final String DELETE_RUN = "DELETE FROM runs WHERE run = ?";
+ /**
+ * Insert a record for a run.
+ */
+ private static final String INSERT = "INSERT INTO runs (run, start_time_utc, end_time_utc, nevents, nfiles, end_ok, created) VALUES(?, ?, ?, ?, ?, ?, NOW())";
+ /**
+ * Select all records.
+ */
+ private static final String SELECT_ALL = "SELECT * from runs";
+ /**
+ * Select record by run number.
+ */
+ private static final String SELECT_RUN = "SELECT run, start_time_utc, end_time_utc, nevents, nfiles, end_ok, run_ok, updated, created FROM runs WHERE run = ?";
+ /**
+ * Update information for a run.
+ */
+ private static final String UPDATE_RUN = "UPDATE runs SET start_time_utc, end_time_utc, nevents, nfiles, end_ok, run_ok WHERE run = ?";
+ }
+
+ /**
+ * Setup class logging.
+ */
+ private static final Logger LOGGER = LogUtil.create(RunSummaryDaoImpl.class, new DefaultLogFormatter(), Level.ALL);
+
+ /**
+ * The database connection.
+ */
+ private final Connection connection;
+
+ /**
+ * The database API for EPICS data.
+ */
+ private EpicsDataDao epicsDataDao = null;
+
+ /**
+ * The database API for EVIO file information.
+ */
+ private EvioFilesDao evioFilesDao = null;
+
+ /**
+ * The database API for scaler data.
+ */
+ private ScalerDataDao scalerDataDao = null;
+
+ /**
+ * Create a new DAO object for run summary information.
+ *
+ * @param connection the database connection
+ */
+ public RunSummaryDaoImpl(final Connection connection) {
+ // Set the connection.
+ if (connection == null) {
+ throw new IllegalArgumentException("The connection is null.");
+ }
+ this.connection = connection;
+
+ // Setup DAO API objects for managing complex object state.
+ epicsDataDao = new EpicsDataDaoImpl(this.connection);
+ scalerDataDao = new ScalerDataDaoImpl(this.connection);
+ evioFilesDao = new EvioFilesDaoImpl(this.connection);
+ }
+
+ /**
+ * Delete a run summary from the database including its referenced objects such as EPICS data.
+ *
+ * @param runSummary the run summary to delete
+ */
+ @Override
+ public void deleteFullRunSummary(final RunSummary runSummary) {
+ // Delete EPICS log.
+ epicsDataDao.deleteEpicsData(runSummary.getRun());
+
+ // Delete scaler data.
+ scalerDataDao.deleteScalerData(runSummary.getRun());
+
+ // Delete file list.
+ evioFilesDao.deleteEvioFiles(runSummary.getRun());
+
+ // Finally delete the run summary information.
+ this.deleteRunSummary(runSummary.getRun());
+ }
+
+ /**
+ * Delete a run summary by run number.
+ *
+ * @param run the run number
+ */
+ @Override
+ public void deleteRunSummary(final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(RunSummaryQuery.DELETE_RUN);
+ preparedStatement.setInt(1, run);
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Delete a run summary but not its objects.
+ *
+ * @param runSummary the run summary object
+ */
+ @Override
+ public void deleteRunSummary(final RunSummary runSummary) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(RunSummaryQuery.DELETE_RUN);
+ preparedStatement.setInt(1, runSummary.getRun());
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the list of run numbers.
+ *
+ * @return the list of run numbers
+ */
+ @Override
+ public List<Integer> getRuns() {
+ final List<Integer> runs = new ArrayList<Integer>();
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = this.connection.prepareStatement("SELECT distinct(run) FROM runs ORDER BY run");
+ final ResultSet resultSet = preparedStatement.executeQuery();
+ while (resultSet.next()) {
+ final Integer run = resultSet.getInt(1);
+ runs.add(run);
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return runs;
+ }
+
+ /**
+ * Get a list of run summaries without loading their objects such as EPICS data.
+ *
+ * @return the list of run summaries
+ */
+ @Override
+ public List<RunSummary> getRunSummaries() {
+ PreparedStatement statement = null;
+ final List<RunSummary> runSummaries = new ArrayList<RunSummary>();
+ try {
+ statement = this.connection.prepareStatement(RunSummaryQuery.SELECT_ALL);
+ final ResultSet resultSet = statement.executeQuery();
+ while (resultSet.next()) {
+ final RunSummary runSummary = new RunSummary(resultSet.getInt("run"));
+ runSummary.setStartTimeUtc(resultSet.getLong("start_time_utc"));
+ runSummary.setEndTimeUtc(resultSet.getLong("end_time_utc"));
+ 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"));
+ runSummaries.add(runSummary);
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return runSummaries;
+ }
+
+ /**
+ * Get a run summary by run number without loading object state.
+ *
+ * @param run the run number
+ * @return the run summary object
+ */
+ @Override
+ public RunSummary getRunSummary(final int run) {
+ PreparedStatement statement = null;
+ RunSummary runSummary = null;
+ try {
+ statement = this.connection.prepareStatement(RunSummaryQuery.SELECT_RUN);
+ statement.setInt(1, run);
+ final ResultSet resultSet = statement.executeQuery();
+ if (!resultSet.next()) {
+ throw new IllegalArgumentException("No record exists for run " + run + " in database.");
+ }
+
+ runSummary = new RunSummary(run);
+ runSummary.setStartTimeUtc(resultSet.getLong("start_time_utc"));
+ runSummary.setEndTimeUtc(resultSet.getLong("end_time_utc"));
+ 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"));
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return runSummary;
+ }
+
+ /**
+ * Insert a list of run summaries along with their complex state such as referenced scaler and EPICS data.
+ *
+ * @param runSummaryList the list of run summaries
+ * @param deleteExisting <code>true</code> to allow deletion and replacement of existing run summaries
+ */
+ @Override
+ public void insertFullRunSummaries(final List<RunSummary> runSummaryList, final boolean deleteExisting) {
+
+ if (runSummaryList == null) {
+ throw new IllegalArgumentException("The run summary list is null.");
+ }
+ if (runSummaryList.isEmpty()) {
+ throw new IllegalArgumentException("The run summary list is empty.");
+ }
+
+ LOGGER.info("inserting " + runSummaryList.size() + " run summaries into database");
+
+ // Turn off auto commit.
+ try {
+ LOGGER.info("turning off auto commit");
+ this.connection.setAutoCommit(false);
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ }
+
+ // Loop over all runs found while crawling.
+ for (final RunSummary runSummary : runSummaryList) {
+
+ final int run = runSummary.getRun();
+
+ LOGGER.info("inserting run summary for run " + run + " into database");
+
+ // Does the run exist in the database already?
+ if (this.runSummaryExists(run)) {
+ // Is deleting existing rows allowed?
+ if (deleteExisting) {
+ LOGGER.info("deleting existing run summary");
+ // Delete the existing rows.
+ this.deleteFullRunSummary(runSummary);
+ } else {
+ // Rows exist but updating is disallowed which is a fatal error.
+ throw new IllegalStateException("Run " + runSummary.getRun()
+ + " already exists and updates are disallowed.");
+ }
+ }
+
+ // Insert full run summary information including sub-objects.
+ LOGGER.info("inserting run summary");
+ this.insertFullRunSummary(runSummary);
+ LOGGER.info("run summary for " + run + " inserted successfully");
+
+ try {
+ // Commit the transaction for the run.
+ LOGGER.info("committing transaction");
+ this.connection.commit();
+ } catch (final SQLException e1) {
+ try {
+ LOGGER.severe("rolling back transaction");
+ // Rollback the transaction if there was an error.
+ this.connection.rollback();
+ } catch (final SQLException e2) {
+ throw new RuntimeException(e2);
+ }
+ }
+
+ LOGGER.info("done inserting run summary " + run);
+
+ LOGGER.getHandlers()[0].flush();
+ }
+
+ try {
+ LOGGER.info("turning auto commit on");
+ // Turn auto commit back on.
+ this.connection.setAutoCommit(true);
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+
+ LOGGER.info("done inserting run summaries");
+ }
+
+ /**
+ * Insert a run summary including all its objects.
+ *
+ * @param runSummary the run summary object to insert
+ */
+ @Override
+ public void insertFullRunSummary(final RunSummary runSummary) {
+
+ // Insert basic run log info.
+ this.insertRunSummary(runSummary);
+
+ // Insert list of files.
+ LOGGER.info("inserting EVIO " + runSummary.getEvioFileList().size() + " files");
+ evioFilesDao.insertEvioFiles(runSummary.getEvioFileList(), runSummary.getRun());
+
+ // Insert EPICS data.
+ LOGGER.info("inserting " + runSummary.getEpicsDataSet().size() + " EPICS records");
+ epicsDataDao.insertEpicsData(runSummary.getEpicsDataSet());
+
+ // Insert scaler data.
+ LOGGER.info("inserting " + runSummary.getScalerData().size() + " scaler data records");
+ scalerDataDao.insertScalerData(runSummary.getScalerData(), runSummary.getRun());
+ }
+
+ /**
+ * Insert a run summary but not its objects.
+ *
+ * @param runSummary the run summary object
+ */
+ @Override
+ public void insertRunSummary(final RunSummary runSummary) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(RunSummaryQuery.INSERT);
+ preparedStatement.setInt(1, runSummary.getRun());
+ preparedStatement.setLong(2, runSummary.getStartTimeUtc());
+ preparedStatement.setLong(3, runSummary.getEndTimeUtc());
+ preparedStatement.setInt(4, runSummary.getTotalEvents());
+ preparedStatement.setInt(5, runSummary.getEvioFileList().size());
+ preparedStatement.setBoolean(6, runSummary.getEndOkay());
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Read a run summary and its objects such as scaler data.
+ *
+ * @param run the run number
+ * @return the full run summary
+ */
+ @Override
+ public RunSummary readFullRunSummary(final int run) {
+
+ // Read main run summary but not referenced objects.
+ final RunSummary runSummary = this.getRunSummary(run);
+
+ // Read EPICS data and set on RunSummary.
+ runSummary.setEpicsData(epicsDataDao.getEpicsData(run));
+
+ // Read scaler data and set on RunSummary.
+ runSummary.setScalerData(scalerDataDao.getScalerData(run));
+
+ // Read EVIO file list and set on RunSummary.
+ runSummary.setEvioFileList(evioFilesDao.getEvioFiles(run));
+
+ return runSummary;
+ }
+
+ /**
+ * Return <code>true</code> if a run summary exists in the database for the run number.
+ *
+ * @param run the run number
+ * @return <code>true</code> if run exists in the database
+ */
+ @Override
+ public boolean runSummaryExists(final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement("SELECT run FROM runs where run = ?");
+ preparedStatement.setInt(1, run);
+ final ResultSet rs = preparedStatement.executeQuery();
+ return rs.first();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Update a run summary but not its complex state.
+ *
+ * @param runSummary the run summary to update
+ */
+ @Override
+ public void updateRunSummary(final RunSummary runSummary) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(RunSummaryQuery.UPDATE_RUN);
+ preparedStatement.setLong(1, runSummary.getStartTimeUtc());
+ preparedStatement.setLong(2, runSummary.getEndTimeUtc());
+ preparedStatement.setInt(3, runSummary.getTotalEvents());
+ preparedStatement.setInt(4, runSummary.getEvioFileList().size());
+ preparedStatement.setBoolean(5, runSummary.getEndOkay());
+ preparedStatement.setBoolean(6, runSummary.getRunOkay());
+ preparedStatement.setInt(7, runSummary.getRun());
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDao.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDao.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDao.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,36 @@
+package org.hps.record.run;
+
+import java.util.List;
+
+import org.hps.record.scalers.ScalerData;
+
+/**
+ * Database Access Object (DAO) for scaler data in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public interface ScalerDataDao {
+
+ /**
+ * Delete scaler data for the run.
+ *
+ * @param run the run number
+ */
+ void deleteScalerData(int run);
+
+ /**
+ * Get scaler data for a run.
+ *
+ * @param run the run number
+ * @return the scaler data for the run
+ */
+ List<ScalerData> getScalerData(int run);
+
+ /**
+ * Insert scaler data for a run.
+ *
+ * @param scalerData the list of scaler data
+ * @param run the run number
+ */
+ void insertScalerData(List<ScalerData> scalerData, int run);
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDaoImpl.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDaoImpl.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/ScalerDataDaoImpl.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,175 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+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;
+
+/**
+ * Implementation of database API for {@link org.hps.record.scalers.ScalerData} in the run database.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+public class ScalerDataDaoImpl implements ScalerDataDao {
+
+ /**
+ * SQL query strings.
+ */
+ private static final class ScalerDataQuery {
+
+ /**
+ * Delete by run.
+ */
+ private static final String DELETE_RUN = "DELETE FROM run_scalers WHERE run = ?";
+ /**
+ * Insert a record.
+ */
+ private static final String INSERT = "INSERT INTO run_scalers (run, event, idx, value) VALUES (?, ?, ?, ?)";
+ /**
+ * Select by run.
+ */
+ private static final String SELECT_RUN = "SELECT event, idx, value FROM run_scalers WHERE run = ? ORDER BY event, idx";
+ }
+
+ /**
+ * The database connection.
+ */
+ private final Connection connection;
+
+ /**
+ * Create object for managing scaler data in the run database.
+ *
+ * @param connection the database connection
+ */
+ public ScalerDataDaoImpl(final Connection connection) {
+ if (connection == null) {
+ throw new IllegalArgumentException("The connection is null.");
+ }
+ this.connection = connection;
+ }
+
+ /**
+ * Delete scaler data for the run.
+ *
+ * @param run the run number
+ */
+ @Override
+ public void deleteScalerData(final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = connection.prepareStatement(ScalerDataQuery.DELETE_RUN);
+ preparedStatement.setInt(1, run);
+ preparedStatement.executeUpdate();
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Get scaler data for a run.
+ *
+ * @param run the run number
+ * @return the scaler data for the run
+ */
+ @Override
+ public List<ScalerData> getScalerData(final int run) {
+ PreparedStatement preparedStatement = null;
+ final List<ScalerData> scalerDataList = new ArrayList<ScalerData>();
+ try {
+ preparedStatement = this.connection.prepareStatement(ScalerDataQuery.SELECT_RUN);
+ preparedStatement.setInt(1, run);
+ final ResultSet resultSet = preparedStatement.executeQuery();
+
+ int[] scalerArray = new int[ScalerData.ARRAY_SIZE];
+ int event = 0;
+
+ while (resultSet.next()) {
+
+ // Get record data.
+ event = resultSet.getInt("event");
+ final int idx = resultSet.getInt("idx");
+ final int value = resultSet.getInt("value");
+
+ // Is this the start of a new scaler data set and not the first one?
+ if (idx == 0 && resultSet.getRow() > 1) {
+ // Create new scaler data object and add to list.
+ final ScalerData scalerData = new ScalerData(scalerArray, event);
+ scalerDataList.add(scalerData);
+
+ // Reset the data array for next object.
+ scalerArray = new int[ScalerData.ARRAY_SIZE];
+ }
+
+ // Set value by index.
+ scalerArray[idx] = value;
+ }
+
+ // Add the last object which will not happen inside the loop.
+ if (scalerArray != null) {
+ scalerDataList.add(new ScalerData(scalerArray, event));
+ }
+
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return scalerDataList;
+ }
+
+ /**
+ * Insert scaler data for a run.
+ *
+ * @param scalerData the list of scaler data
+ * @param run the run number
+ */
+ @Override
+ public void insertScalerData(final List<ScalerData> scalerDataList, final int run) {
+ PreparedStatement preparedStatement = null;
+ try {
+ preparedStatement = this.connection.prepareStatement(ScalerDataQuery.INSERT);
+ for (final ScalerData scalerData : scalerDataList) {
+ final int size = scalerData.size();
+ final Integer event = scalerData.getEventId();
+ if (event == null) {
+ throw new IllegalStateException("The scaler data is missing the event ID.");
+ }
+ for (int i = 0; i < size; i++) {
+ preparedStatement.setInt(1, run);
+ preparedStatement.setInt(2, event);
+ preparedStatement.setInt(3, i);
+ preparedStatement.setInt(4, scalerData.getValue(i));
+ preparedStatement.executeUpdate();
+ }
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (preparedStatement != null) {
+ try {
+ preparedStatement.close();
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
Added: java/trunk/record-util/src/main/java/org/hps/record/run/package-info.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/package-info.java (added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/package-info.java Thu Aug 20 12:50:12 2015
@@ -0,0 +1,4 @@
+/**
+ * API for accessing the HPS run database with run summary information.
+ */
+package org.hps.record.run;
Modified: java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalerData.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalerData.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalerData.java Thu Aug 20 12:50:12 2015
@@ -13,6 +13,11 @@
* @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
*/
public final class ScalerData {
+
+ /**
+ * Fixed array size of scaler data in the EVIO bank.
+ */
+ public static final int ARRAY_SIZE = 72;
/**
* Default name of scaler data collection in LCSim events.
@@ -38,10 +43,11 @@
public static ScalerData read(final EventHeader event, final String collectionName) {
ScalerData data = null;
if (event.hasCollection(GenericObject.class, collectionName)) {
- //System.out.println("ScalerData - found collection");
+ // System.out.println("ScalerData - found collection");
final List<GenericObject> objects = event.get(GenericObject.class, collectionName);
data = new ScalerData();
data.fromGenericObject(objects.get(0));
+ data.setEventId(event.getEventNumber());
}
return data;
}
@@ -50,6 +56,11 @@
* The scaler data values.
*/
private int[] data;
+
+ /**
+ * The event ID of the data.
+ */
+ private Integer eventId;
/**
* This is the no argument constructor which is for package internal use only.
@@ -62,9 +73,10 @@
*
* @param data the scaler data
*/
- public ScalerData(final int[] data) {
+ public ScalerData(final int[] data, final int eventId) {
this.data = new int[data.length];
System.arraycopy(data, 0, this.data, 0, data.length);
+ this.eventId = eventId;
}
/**
@@ -80,6 +92,18 @@
}
/**
+ * Get the event ID of the scaler data.
+ * <p>
+ * This information is not persisted to the LCIO.
+ *
+ * @return the event ID of the scaler data
+ */
+ public Integer getEventId() {
+ // Null value will be returned here to indicate not set.
+ return this.eventId;
+ }
+
+ /**
* Get the scaler data value at the index.
*
* @param index the scaler data index
@@ -88,14 +112,23 @@
public Integer getValue(final int index) {
return this.data[index];
}
-
+
/**
* Get the value using a {@link ScalerDataIndex} enum.
- *
+ *
* @return the value at the index
*/
- public Integer getValue(ScalerDataIndex scalarDataIndex) {
+ public Integer getValue(final ScalerDataIndex scalarDataIndex) {
return this.data[scalarDataIndex.index()];
+ }
+
+ /**
+ * Set the event ID of the scaler data.
+ *
+ * @param eventId the event ID of the scaler data
+ */
+ void setEventId(final int eventId) {
+ this.eventId = eventId;
}
/**
@@ -154,5 +187,5 @@
final List<GenericObject> collection = new ArrayList<GenericObject>();
collection.add(this.toGenericObject());
event.put(collectionName, collection, GenericObject.class, 0);
- }
+ }
}
Modified: java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java
=============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java (original)
+++ java/trunk/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java Thu Aug 20 12:50:12 2015
@@ -1,10 +1,15 @@
package org.hps.record.scalers;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hps.record.evio.EvioEventConstants;
import org.hps.record.evio.EvioEventProcessor;
+import org.hps.record.evio.EvioEventUtilities;
import org.jlab.coda.jevio.BaseStructure;
import org.jlab.coda.jevio.EvioEvent;
import org.lcsim.util.log.DefaultLogFormatter;
@@ -15,38 +20,36 @@
*
* @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
*/
-public final class ScalersEvioProcessor extends EvioEventProcessor {
+public class ScalersEvioProcessor extends EvioEventProcessor {
- private static final Logger LOGGER = LogUtil.create(ScalersEvioProcessor.class, new DefaultLogFormatter(), Level.INFO);
+ private static final Logger LOGGER = LogUtil.create(ScalersEvioProcessor.class, new DefaultLogFormatter(),
+ Level.ALL);
/**
* Currently cached ScalerData object which was created by the process method.
*/
- private ScalerData data;
+ private ScalerData currentScalerData;
+ private boolean resetEveryEvent = true;
- boolean resetEveryEvent = true;
+ private Set<ScalerData> scalerDataSet = new LinkedHashSet<ScalerData>();
+
+ public ScalerData getCurrentScalerData() {
+ return this.currentScalerData;
+ }
/**
* Get the current scaler data or null if there was none in the last event processed.
*
* @return the current scaler data or <code>null</code> if none exists
*/
- public ScalerData getScalerData() {
- return this.data;
+ public List<ScalerData> getScalerData() {
+ return new ArrayList<ScalerData>(this.scalerDataSet);
}
- /**
- * This method will create a <code>ScalerData</code> object and cache it. The current object is first reset to <code>null</code> every time this
- * method is called.
- *
- * @param evio the EVIO event data
- */
- @Override
- public void process(final EvioEvent evio) {
- if (resetEveryEvent) {
- this.data = null;
- }
- for (final BaseStructure bank : evio.getChildrenList()) {
+ private ScalerData getScalerData(final EvioEvent evioEvent) {
+ ScalerData scalerData = null;
+ // Proceed if sync bit checking is not enabled or sync bit is on.
+ outerBankLoop: for (final BaseStructure bank : evioEvent.getChildrenList()) {
// Does the crate tag match?
if (bank.getHeader().getTag() == EvioEventConstants.SCALERS_CRATE_TAG) {
if (bank.getChildrenList() != null) {
@@ -54,19 +57,48 @@
// Does the bank tag match?
if (subBank.getHeader().getTag() == EvioEventConstants.SCALERS_BANK_TAG) {
- LOGGER.fine("found scaler data in bank " + subBank.getHeader().getTag() + " and EVIO event " + evio.getEventNumber());
+ LOGGER.fine("found scaler data in bank " + subBank.getHeader().getTag()
+ + " and EVIO event " + evioEvent.getEventNumber());
// Scaler data exists in event so create object and stop processing.
- this.data = new ScalerData(subBank.getIntData());
- break;
+ scalerData = new ScalerData(subBank.getIntData(),
+ EvioEventUtilities.getEventIdData(evioEvent)[0]);
+
+ break outerBankLoop;
}
}
}
}
+ }
+ return scalerData;
+ }
+
+ /**
+ * This method will create a <code>ScalerData</code> object and cache it. The current object is first reset to
+ * <code>null</code> every time this method is called.
+ *
+ * @param evioEvent the EVIO event data
+ */
+ @Override
+ public void process(final EvioEvent evioEvent) {
+ if (resetEveryEvent) {
+ // Reset the cached data object.
+ this.currentScalerData = null;
+ }
+
+ final ScalerData scalerData = this.getScalerData(evioEvent);
+ if (scalerData != null) {
+ this.currentScalerData = scalerData;
+ this.scalerDataSet.add(this.currentScalerData);
}
}
public void setResetEveryEvent(final boolean resetEveryEvent) {
this.resetEveryEvent = resetEveryEvent;
}
+
+ @Override
+ public void startJob() {
+ this.scalerDataSet = new LinkedHashSet<ScalerData>();
+ }
}
|