Print

Print


Author: [log in to unmask]
Date: Tue Aug 25 16:01:09 2015
New Revision: 3401

Log:
Add classes for storing trigger config in run db.  Currently only has TI time offset.  HPSJAVA-580

Added:
    java/trunk/record-util/src/main/java/org/hps/datacat/
    java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClient.java
    java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClientImpl.java
    java/trunk/record-util/src/main/java/org/hps/datacat/DatacatConstants.java
    java/trunk/record-util/src/main/java/org/hps/datacat/DatacatUtilities.java
    java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfig.java
    java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDao.java
    java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDaoImpl.java
Modified:
    java/trunk/record-util/pom.xml
    java/trunk/record-util/src/main/java/org/hps/record/epics/EpicsEvioProcessor.java
    java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java
    java/trunk/record-util/src/main/java/org/hps/record/evio/EventTagConstant.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/EvioFileSource.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/RunSummary.java
    java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java

Modified: java/trunk/record-util/pom.xml
 =============================================================================
--- java/trunk/record-util/pom.xml	(original)
+++ java/trunk/record-util/pom.xml	Tue Aug 25 16:01:09 2015
@@ -40,5 +40,10 @@
             <groupId>org.hps</groupId>
             <artifactId>hps-conditions</artifactId>
         </dependency>
+        <dependency>
+	    <groupId>org.json</groupId>
+	    <artifactId>json</artifactId>
+	    <version>20140107</version>
+        </dependency>
     </dependencies>
 </project>

Added: java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClient.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClient.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClient.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,32 @@
+package org.hps.datacat;
+
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * Interface to the SLAC SRS datacat system via HTTP/REST calls.
+ * 
+ * @author Jeremy McCormick, SLAC
+ */
+public interface DatacatClient {
+    
+    int addDataset(String folder, Map<String, Object> parameters);
+    
+    int makeFolder(String folder);
+    
+    int patchDataset(String folder, String datasetName, Map<String, Object> metaData);
+    
+    int removeFolder(String folder);
+    
+    int deleteDataset(String path);
+    
+    // TODO: get full info on dataset
+    
+    // TODO: query for datasets on meta data or other info
+    
+    String getRootDir();
+    
+    URL getBaseUrl();
+    
+    String getSite();
+}

Added: java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClientImpl.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClientImpl.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/datacat/DatacatClientImpl.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,97 @@
+package org.hps.datacat;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.json.JSONObject;
+
+
+public class DatacatClientImpl implements DatacatClient {
+
+    private URL url;
+    private String site;
+    private String rootDir;
+    
+    /**
+     * Create client with default parameters.
+     */
+    DatacatClientImpl() {        
+        this(DatacatConstants.BASE_URL, DatacatConstants.SLAC_SITE, DatacatConstants.ROOT_DIR);
+    }
+    
+    /**
+     * Create client.
+     * @param baseUrl
+     * @param site
+     * @param rootDir
+     */
+    DatacatClientImpl(String baseUrl, String site, String rootDir) {
+        try {
+            url = new URL(baseUrl);
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException("The URL is bad.", e);
+        }
+        if (site == null) {
+            throw new IllegalArgumentException("The site argument is null.");
+        }
+        this.site = site;
+        if (rootDir == null) {
+            throw new IllegalArgumentException("The root dir argument is null.");
+        }
+        this.rootDir = rootDir;
+        System.out.println("rootUrl: " + baseUrl);
+        System.out.println("site: " + site);
+        System.out.println("rootDir: " + rootDir);
+    }
+    
+    @Override
+    public int removeFolder(String folder) {
+        String fullUrl = url.toString() + "/r/folders.json/" + this.rootDir + folder;
+        return DatacatUtilities.doDelete(fullUrl);
+    }
+
+    @Override
+    public int deleteDataset(String path) {
+        String fullUrl = url.toString() + "/r/datasets.json/" + this.rootDir + path;
+        return DatacatUtilities.doDelete(fullUrl);
+    }
+
+    @Override
+    public int addDataset(String folder, Map<String, Object> parameters) {
+        JSONObject dataset = DatacatUtilities.createJSONDataset(parameters);
+        return DatacatUtilities.doPost(url + "/r/datasets.json/" + this.rootDir + "/" + folder, dataset.toString());
+    }
+        
+    @Override
+    public int makeFolder(String path) {
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put("path", "/" + DatacatConstants.ROOT_DIR + "/" + path);
+        String name = new File(path).getName();       
+        parameters.put("name", name);
+        parameters.put("_type", "folder");
+        JSONObject object = DatacatUtilities.createJSONFromMap(parameters);
+        return DatacatUtilities.doPost(url + "/r/folders.json/" + this.rootDir, object.toString());
+    }
+
+    @Override
+    public int patchDataset(String folder, String name, Map<String, Object> metaData) {
+        JSONObject object = DatacatUtilities.createJSONMetaData(metaData);
+        String patchUrl = this.url.toString() + "/r/datasets.json/" + this.rootDir + "/" + folder + "/" + name + ";v=current;s=" + this.site;
+        return DatacatUtilities.doPost(patchUrl, object.toString());
+    }      
+    
+    public String getRootDir() {
+        return this.rootDir;
+    }
+    
+    public URL getBaseUrl() {
+        return this.url;
+    }
+    
+    public String getSite() {
+        return this.site;
+    }
+}

Added: java/trunk/record-util/src/main/java/org/hps/datacat/DatacatConstants.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/datacat/DatacatConstants.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/datacat/DatacatConstants.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,29 @@
+package org.hps.datacat;
+
+
+public class DatacatConstants {
+
+    public static final String ROOT_DIR = "HPS";
+        
+    public static final String BASE_URL = "http://localhost:8080/datacat-v0.4-SNAPSHOT";
+    
+    public static final String SLAC_SITE = "SLAC";
+    
+    public static final String JLAB_SITE = "JLAB";
+    
+    public static final String EVIO_FORMAT = "EVIO";
+    
+    public static final String LCIO_FORMAT = "LCIO";
+    
+    public static final String ROOT_FORMAT = "ROOT";
+    
+    public static final String AIDA_FORMAT = "AIDA";
+    
+    public static final String DQM_TYPE = "DQM";
+    
+    public static final String RAW_TYPE = "RAW";
+    
+    public static final String RECON_TYPE = "RECON";
+    
+    public static final String DST_TYPE = "DST";        
+}

Added: java/trunk/record-util/src/main/java/org/hps/datacat/DatacatUtilities.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/datacat/DatacatUtilities.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/datacat/DatacatUtilities.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,86 @@
+package org.hps.datacat;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+public final class DatacatUtilities {
+
+    static JSONObject createJSONDataset(Map<String, Object> parameters) {
+        JSONObject dataset = new JSONObject();
+        dataset.put("dataType", parameters.get("dataType"));
+        dataset.put("versionId", "new");
+        JSONObject location = new JSONObject();
+        location.put("resource", parameters.get("resource"));
+        location.put("site", parameters.get("site"));
+        JSONArray array = new JSONArray();
+        array.put(location);        
+        dataset.put("locations", array);                
+        dataset.put("fileFormat", parameters.get("fileFormat"));
+        dataset.put("name", parameters.get("name"));
+        return dataset;
+    }
+    
+    static JSONObject createJSONFromMap(Map<String, Object> parameters) {
+        JSONObject object = new JSONObject();
+        for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+            object.put(entry.getKey(), entry.getValue());
+        }
+        return object;
+    }
+    
+    static JSONObject createJSONMetaData(Map<String, Object> metaData) {
+        JSONObject object = new JSONObject();
+        JSONArray array = new JSONArray();
+        for (Map.Entry<String, Object> entry : metaData.entrySet()) {
+            JSONObject value = new JSONObject();
+            value.put(entry.getKey(), entry.getValue());
+            array.put(value);
+        }                
+        object.put("versionMetadata", array);
+        return object;
+    }
+        
+    static int doPost(String urlLocation, String data) {
+        int responseCode = 520;
+        try {
+            URL url = new URL(urlLocation);
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            connection.setRequestMethod("POST");
+            connection.setRequestProperty("Content-Type", "application/json");
+            connection.setDoOutput(true);
+            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
+            out.write(data);
+            out.close();
+            System.out.println("url: " + urlLocation);
+            System.out.println("data: " + data);
+            System.out.println("response: " + connection.getResponseCode());
+            System.out.println("message: " + connection.getResponseMessage());
+            responseCode = connection.getResponseCode();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return responseCode;
+    }    
+    
+    static int doDelete(String fullUrl) {
+        int responseCode = 520;
+        try {
+            URL url = new URL(fullUrl);
+            System.out.println("deleting url: " + fullUrl);
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            connection.setDoOutput(true);
+            connection.setRequestMethod("DELETE");
+            connection.connect();
+            responseCode = connection.getResponseCode();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return responseCode;
+    }
+}

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	Tue Aug 25 16:01:09 2015
@@ -42,18 +42,18 @@
     /**
      * Process EVIO data and create a {@link EpicsData} if EPICS data bank exists in the event.
      *
-     * @param evio the <code>EvioEvent</code> that possibly has EPICS data
+     * @param evioEvent the <code>EvioEvent</code> that possibly has EPICS data
      */
     @Override
-    public void process(final EvioEvent evio) {
+    public void process(final EvioEvent evioEvent) {
 
         // Is this an EPICS event?
-        if (EventTagConstant.EPICS.isEventTag(evio)) {
+        if (EventTagConstant.EPICS.equals(evioEvent)) {
 
-            LOGGER.fine("processing EPICS event " + evio.getEventNumber());
+            LOGGER.fine("processing EPICS event " + evioEvent.getEventNumber());
 
             // Find the bank with the EPICS data string.
-            final BaseStructure epicsBank = EvioBankTag.EPICS_STRING.findBank(evio);
+            final BaseStructure epicsBank = EvioBankTag.EPICS_STRING.findBank(evioEvent);
 
             // Was EPICS data found in the event?
             if (epicsBank != null) {
@@ -62,7 +62,7 @@
                 this.data = new EpicsData(epicsBank.getStringData()[0]);
 
                 // Find the header information in the event.
-                final BaseStructure headerBank = EvioBankTag.EPICS_HEADER.findBank(evio);
+                final BaseStructure headerBank = EvioBankTag.EPICS_HEADER.findBank(evioEvent);
 
                 if (headerBank != null) {
                     // Set the header object.

Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EventCountProcessor.java	Tue Aug 25 16:01:09 2015
@@ -71,13 +71,13 @@
     /**
      * Process an EVIO event and add its type to the map.
      *
-     * @param event the EVIO event
+     * @param evioEvent the EVIO event
      */
     @Override
-    public void process(final EvioEvent event) {
+    public void process(final EvioEvent evioEvent) {
 
         // Increment physics event count.
-        if (EvioEventUtilities.isPhysicsEvent(event)) {
+        if (EvioEventUtilities.isPhysicsEvent(evioEvent)) {
             ++this.physicsEventCount;
         }
 
@@ -86,7 +86,7 @@
 
         // Increment counts for event tag values.
         for (final EventTagConstant constant : EventTagConstant.values()) {
-            if (constant.isEventTag(event)) {
+            if (constant.equals(evioEvent)) {
                 final int count = this.eventTypeCounts.get(constant) + 1;
                 this.eventTypeCounts.put(constant, count);
             }
@@ -94,7 +94,7 @@
 
         // Increment counts for event tags with bit masks (different types of physics events).
         for (final EventTagBitMask mask : EventTagBitMask.values()) {
-            if (mask.isEventTag(event)) {
+            if (mask.isEventTag(evioEvent)) {
                 final int count = this.eventTypeCounts.get(mask) + 1;
                 this.eventTypeCounts.put(mask, count);
             }

Modified: java/trunk/record-util/src/main/java/org/hps/record/evio/EventTagConstant.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/evio/EventTagConstant.java	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EventTagConstant.java	Tue Aug 25 16:01:09 2015
@@ -58,4 +58,12 @@
     public int tag() {
         return this.tag;
     }
+    
+    public boolean equals(final int tag) {
+        return tag == this.tag;
+    }
+    
+    public boolean equals(final EvioEvent evioEvent) {
+        return evioEvent.getHeader().getTag() == this.tag;
+    }
 }

Modified: 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	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaData.java	Tue Aug 25 16:01:09 2015
@@ -306,8 +306,8 @@
      */
     @Override
     public String toString() {
-        return "EvioFileMetaData { evioFile: " + this.evioFile + ", startDate: " + this.startDate + "endDate: "
-                + this.endDate + "badEventCount: " + this.badEventCount + ", byteCount: " + this.byteCount
+        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 + " }";

Modified: 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	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/evio/EvioFileMetaDataReader.java	Tue Aug 25 16:01:09 2015
@@ -25,6 +25,8 @@
      */
     private static Logger LOGGER = LogUtil.create(EvioFileMetaDataReader.class, new DefaultLogFormatter(), Level.ALL);
 
+    final static int MILLIS = 1000;
+
     /**
      * Get meta data from the EVIO file.
      *
@@ -51,6 +53,8 @@
         Integer endEvent = null;
         Integer startEvent = null;
 
+        int nPhysicsEventsProcessed = 0;
+
         final int fileNumber = EvioFileUtilities.getSequenceFromName(evioFile);
         LOGGER.info("set file number to " + fileNumber);
 
@@ -70,18 +74,18 @@
                     continue;
                 }
                 byteCount += evioEvent.getTotalBytes();
-                if (EventTagConstant.PRESTART.isEventTag(evioEvent)) {
+                if (EventTagConstant.PRESTART.equals(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);
+                    LOGGER.info("set start date to " + startDate + " from PRESTART");
                     if (run == null) {
                         run = controlEventData[1];
                         LOGGER.info("set run to " + run);
                     }
-                } else if (EventTagConstant.END.isEventTag(evioEvent)) {
+                } else if (EventTagConstant.END.equals(evioEvent)) {
                     LOGGER.info("found END");
                     hasEnd = true;
                     final int[] controlEventData = EvioEventUtilities.getControlEventData(evioEvent);
@@ -92,29 +96,29 @@
                         run = controlEventData[1];
                         LOGGER.info("set run to " + run);
                     }
-                } else if (EventTagBitMask.PHYSICS.isEventTag(evioEvent)) {
+                } else if (EvioEventUtilities.isPhysicsEvent(evioEvent)) {
+                    // LOGGER.info("physics event " + evioEvent.getEventNumber());
                     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");
-                        }
+                    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);
-                        }
+                    if (startEvent == null) {
+                        startEvent = eventIdData[0];
+                        LOGGER.info("set start event " + startEvent);
                     }
+                    ++nPhysicsEventsProcessed;
                 }
                 LOGGER.getHandlers()[0].flush();
             }
+
+            LOGGER.info("processed " + nPhysicsEventsProcessed + " in " + evioFile.getPath());
 
             if (endDate == null) {
                 if (headBankData != null) {
@@ -125,8 +129,6 @@
             if (eventIdData != null) {
                 endEvent = eventIdData[0];
                 LOGGER.info("set end event " + endEvent);
-            } else {
-                throw new IllegalStateException("Missing last event ID data in " + evioFile.getPath());
             }
         } catch (EvioException | IOException e) {
             throw new RuntimeException(e);

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	Tue Aug 25 16:01:09 2015
@@ -5,8 +5,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.freehep.record.source.AbstractRecordSource;
 import org.freehep.record.source.NoSuchRecordException;
+import org.hps.record.AbstractRecordQueue;
 import org.jlab.coda.jevio.EvioEvent;
 import org.jlab.coda.jevio.EvioException;
 import org.jlab.coda.jevio.EvioReader;
@@ -19,7 +19,7 @@
  *
  * @author Jeremy McCormick, SLAC
  */
-public final class EvioFileSource extends AbstractRecordSource {
+public final class EvioFileSource extends AbstractRecordQueue<EvioEvent> {
 
     /**
      * The current event.

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	Tue Aug 25 16:01:09 2015
@@ -170,11 +170,11 @@
 
         // Get run start date.
         LOGGER.info("setting run start date");
-        this.setRunStartDate();
+        this.processFirstFile();
 
         // Get run end date.
         LOGGER.info("setting run end date");
-        this.setRunEndDate();
+        this.processLastFile();
 
         // Update run summary from processors.
         LOGGER.info("updating run summary");
@@ -186,41 +186,50 @@
     /**
      * Set the run end date by getting meta data from the last file and copying it to the run summary.
      */
-    private void setRunEndDate() {
+    private void processLastFile() {
         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());
+        if (metaData.getEndDate() == null) {
+            throw new IllegalStateException("The end date is not set in the EVIO file meta data from "
+                    + lastEvioFile.getPath());
+        }
         LOGGER.info("setting unix end time to " + metaData.getEndDate().getTime() + " from meta data");
-        runSummary.setEndTimeUtc(metaData.getEndDate().getTime());
+        runSummary.setEndDate(metaData.getEndDate());
         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() {
+    private void processFirstFile() {
         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());
+        if (metaData.getStartDate() == null) {
+            throw new IllegalStateException("The start date is not set in the EVIO file meta data from "
+                    + firstEvioFile.getPath());
+        }
         LOGGER.info("setting unix start time to " + metaData.getStartDate().getTime() + " from meta data");
-        runSummary.setStartTimeUtc(metaData.getStartDate().getTime());
+        runSummary.setStartDate(metaData.getStartDate());
     }
 
     /**
      * 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.
+
+        // Set total number of events from the event loop.
+        runSummary.setTotalEvents((int) evioLoop.getTotalCountableConsumed());
+
+        // Add scaler data from the scalers EVIO processor.
         runSummary.setScalerData(this.scalersProcessor.getScalerData());
 
-        // Set total number of events on the run summary from the event counter.
-        runSummary.setTotalEvents((int) evioLoop.getTotalCountableConsumed());
-
-        // Set EpicsData for the run.
+        // Add EPICS data from the EPICS EVIO processor.
         runSummary.setEpicsData(this.epicsLog.getEpicsData());
     }
 

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	Tue Aug 25 16:01:09 2015
@@ -56,6 +56,11 @@
     private Date created;
 
     /**
+     * End date of run.
+     */
+    private Date endDate;
+
+    /**
      * This is <code>true</code> if the END event is found in the data.
      */
     private boolean endOkay;
@@ -96,9 +101,9 @@
     private List<ScalerData> scalerDataList;
 
     /**
-     * The run start time in UTC (milliseconds).
-     */
-    private long startTimeUtc;
+     * Start date of run.
+     */
+    private Date startDate;
 
     /**
      * The total events found in the run across all files.
@@ -148,7 +153,7 @@
      * @return the end date
      */
     public Date getEndDate() {
-        return new Date(this.endTimeUtc);
+        return endDate;
     }
 
     /**
@@ -158,15 +163,6 @@
      */
     public boolean getEndOkay() {
         return this.endOkay;
-    }
-
-    /**
-     * Get the end time in UTC (milliseconds)
-     *
-     * @return the end time in milliseconds
-     */
-    public long getEndTimeUtc() {
-        return this.endTimeUtc;
     }
 
     /**
@@ -242,16 +238,7 @@
      * @return the start date
      */
     public Date getStartDate() {
-        return new Date(this.startTimeUtc);
-    }
-
-    /**
-     * Get the run start time in UTC (milliseconds).
-     *
-     * @return the start time in milliseconds
-     */
-    public long getStartTimeUtc() {
-        return this.startTimeUtc;
+        return startDate;
     }
 
     /**
@@ -278,7 +265,7 @@
      * @return the total seconds in the run
      */
     public long getTotalSeconds() {
-        return (this.endTimeUtc - this.startTimeUtc) / 1000;
+        return (endDate.getTime() - startDate.getTime()) / 1000;
     }
 
     /**
@@ -325,6 +312,15 @@
     }
 
     /**
+     * Set the start date.
+     *
+     * @param startDate the start date
+     */
+    public void setEndDate(final Date endDate) {
+        this.endDate = endDate;
+    }
+
+    /**
      * Set if end is okay.
      *
      * @param endOkay <code>true</code> if end is okay
@@ -388,12 +384,12 @@
     }
 
     /**
-     * Set the start date of the run.
-     *
-     * @param startTimeUtc the start date of the run
-     */
-    public void setStartTimeUtc(final long startTimeUtc) {
-        this.startTimeUtc = startTimeUtc;
+     * Set the start date.
+     *
+     * @param startDate the start date
+     */
+    public void setStartDate(final Date startDate) {
+        this.startDate = startDate;
     }
 
     /**
@@ -437,9 +433,9 @@
      */
     @Override
     public String toString() {
-        return "RunSummary { run: " + this.getRun() + ", startTimeUtc: " + this.getStartTimeUtc() + ", endTimeUtc: "
-                + this.getEndTimeUtc() + ", totalEvents: " + this.getTotalEvents() + ", totalFiles: "
-                + this.getTotalFiles() + ", endOkay: " + this.getEndOkay() + ", runOkay: " + this.getRunOkay()
-                + ", updated: " + this.getUpdated() + ", created: " + this.getCreated() + " }";
+        return "RunSummary { run: " + this.getRun() + ", startDate: " + DATE_DISPLAY.format(this.getStartDate())
+                + ", endDate: " + DATE_DISPLAY.format(this.getEndDate()) + ", totalEvents: " + this.getTotalEvents()
+                + ", totalFiles: " + this.getTotalFiles() + ", endOkay: " + this.getEndOkay() + ", runOkay: "
+                + this.getRunOkay() + ", updated: " + this.getUpdated() + ", created: " + this.getCreated() + " }";
     }
 }

Modified: 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	(original)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/RunSummaryDaoImpl.java	Tue Aug 25 16:01:09 2015
@@ -5,7 +5,10 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.List;
+import java.util.TimeZone;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -31,7 +34,7 @@
         /**
          * 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())";
+        private static final String INSERT = "INSERT INTO runs (run, start_date, end_date, nevents, nfiles, end_ok, created) VALUES(?, ?, ?, ?, ?, ?, NOW())";
         /**
          * Select all records.
          */
@@ -39,12 +42,17 @@
         /**
          * 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 = ?";
+        private static final String SELECT_RUN = "SELECT run, start_date, end_date, 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 = ?";
-    }
+        private static final String UPDATE_RUN = "UPDATE runs SET start_date, end_date, nevents, nfiles, end_ok, run_ok WHERE run = ?";
+    }
+
+    /**
+     * Eastern time zone.
+     */
+    private static Calendar CALENDAR = new GregorianCalendar(TimeZone.getTimeZone("America/New_York"));
 
     /**
      * Setup class logging.
@@ -203,8 +211,8 @@
             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.setStartDate(resultSet.getTimestamp("start_date"));
+                runSummary.setEndDate(resultSet.getTimestamp("end_date"));
                 runSummary.setTotalEvents(resultSet.getInt("nevents"));
                 runSummary.setTotalFiles(resultSet.getInt("nfiles"));
                 runSummary.setEndOkay(resultSet.getBoolean("end_ok"));
@@ -246,8 +254,8 @@
             }
 
             runSummary = new RunSummary(run);
-            runSummary.setStartTimeUtc(resultSet.getLong("start_time_utc"));
-            runSummary.setEndTimeUtc(resultSet.getLong("end_time_utc"));
+            runSummary.setStartDate(resultSet.getTimestamp("start_date"));
+            runSummary.setEndDate(resultSet.getTimestamp("end_date"));
             runSummary.setTotalEvents(resultSet.getInt("nevents"));
             runSummary.setTotalFiles(resultSet.getInt("nfiles"));
             runSummary.setEndOkay(resultSet.getBoolean("end_ok"));
@@ -385,8 +393,8 @@
         try {
             preparedStatement = connection.prepareStatement(RunSummaryQuery.INSERT);
             preparedStatement.setInt(1, runSummary.getRun());
-            preparedStatement.setLong(2, runSummary.getStartTimeUtc());
-            preparedStatement.setLong(3, runSummary.getEndTimeUtc());
+            preparedStatement.setTimestamp(2, new java.sql.Timestamp(runSummary.getStartDate().getTime()), CALENDAR);
+            preparedStatement.setTimestamp(3, new java.sql.Timestamp(runSummary.getEndDate().getTime()), CALENDAR);
             preparedStatement.setInt(4, runSummary.getTotalEvents());
             preparedStatement.setInt(5, runSummary.getEvioFileList().size());
             preparedStatement.setBoolean(6, runSummary.getEndOkay());
@@ -465,8 +473,8 @@
         PreparedStatement preparedStatement = null;
         try {
             preparedStatement = connection.prepareStatement(RunSummaryQuery.UPDATE_RUN);
-            preparedStatement.setLong(1, runSummary.getStartTimeUtc());
-            preparedStatement.setLong(2, runSummary.getEndTimeUtc());
+            preparedStatement.setTimestamp(1, new java.sql.Timestamp(runSummary.getStartDate().getTime()), CALENDAR);
+            preparedStatement.setTimestamp(2, new java.sql.Timestamp(runSummary.getEndDate().getTime()), CALENDAR);
             preparedStatement.setInt(3, runSummary.getTotalEvents());
             preparedStatement.setInt(4, runSummary.getEvioFileList().size());
             preparedStatement.setBoolean(5, runSummary.getEndOkay());

Added: java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfig.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfig.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfig.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,34 @@
+package org.hps.record.run;
+
+/**
+ * Trigger information available in the run database.
+ * <p>
+ * Currently this only has the TI time offset.
+ * 
+ * @author Jeremy McCormick, SLAC
+ */
+public final class TriggerConfig {
+    
+    /**
+     * The TI time offset.
+     */
+    private long tiTimeOffset;
+    
+    /**
+     * Set the TI time offset.
+     * 
+     * @param tiTimeOffset the TI time offset
+     */
+    void setTiTimeOffset(long tiTimeOffset) {
+        this.tiTimeOffset = tiTimeOffset;
+    }
+    
+    /**
+     * Get the TI time offset.
+     * 
+     * @return the TI time offset
+     */
+    public long getTiTimeOffset() {
+        return tiTimeOffset;
+    }
+}

Added: java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDao.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDao.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDao.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,41 @@
+package org.hps.record.run;
+
+/**
+ * Database interface to trigger config.
+ * 
+ * @author Jeremy McCormick, SLAC
+ */
+public interface TriggerConfigDao {
+   
+    /**
+     * Get the trigger config by run.
+     * 
+     * @param run the run number
+     * @return the trigger config
+     */
+    TriggerConfig getTriggerConfig(int run);
+    
+    /**
+     * Insert a trigger config for a run.
+     * 
+     * @param run the run number
+     * @param triggerConfig the trigger config
+     */
+    void insertTriggerConfig(int run, TriggerConfig triggerConfig);
+    
+
+    /**
+     * Update a trigger config by run number.
+     * 
+     * @param run the run number
+     * @param triggerConfig the trigger config
+     */
+    void updateTriggerConfig(int run, TriggerConfig triggerConfig);
+    
+    /**
+     * Delete a trigger config by run number.
+     * 
+     * @param run the run number
+     */
+    void deleteTriggerConfig(int run);
+}

Added: java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDaoImpl.java
 =============================================================================
--- java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDaoImpl.java	(added)
+++ java/trunk/record-util/src/main/java/org/hps/record/run/TriggerConfigDaoImpl.java	Tue Aug 25 16:01:09 2015
@@ -0,0 +1,160 @@
+package org.hps.record.run;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Implementation of trigger config database interface.
+ * 
+ * @author Jeremy McCormick, SLAC
+ */
+public class TriggerConfigDaoImpl implements TriggerConfigDao {
+
+    /**
+     * The database connection.
+     */
+    private Connection connection;
+    
+    /**
+     * SQL query strings.
+     */
+    static final class TriggerConfigQuery {
+        /**
+         * Select by run.
+         */
+        static final String SELECT_RUN = "SELECT * FROM run_trigger_config WHERE run = ?";
+        /**
+         * Insert by run.
+         */
+        static final String INSERT_RUN = "INSERT INTO run_trigger_config (run, ti_time_offset) VALUES (?, ?)";
+        /**
+         * Update by run.
+         */
+        static final String UPDATE_RUN = "UPDATE run_trigger_config SET ti_time_offset = ? WHERE run = ?";
+        /**
+         * Delete by run.
+         */
+        static final String DELETE_RUN = "DELETE FROM run_trigger_config WHERE run = ?";
+    }
+    
+    /**
+     * Create a new object.
+     * 
+     * @param connection the database connection
+     */
+    TriggerConfigDaoImpl(Connection connection) { 
+        this.connection = connection;
+    }
+    
+    /**
+     * Get the trigger config by run.
+     * 
+     * @param run the run number
+     * @return the trigger config
+     */
+    @Override
+    public TriggerConfig getTriggerConfig(int run) {
+        PreparedStatement preparedStatement = null;
+        TriggerConfig triggerConfig = null;
+        try {
+            preparedStatement = connection.prepareStatement(TriggerConfigQuery.SELECT_RUN);
+            preparedStatement.setInt(1, run);
+            final ResultSet resultSet = preparedStatement.executeQuery();
+            if (resultSet.next()) {
+                triggerConfig = new TriggerConfig();
+                triggerConfig.setTiTimeOffset(resultSet.getLong("ti_time_offset"));
+            }
+        } catch (final SQLException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                preparedStatement.close();
+            } catch (final SQLException e) {
+                e.printStackTrace();
+            }
+        }
+        return triggerConfig;
+    }
+
+    /**
+     * Insert a trigger config for a run.
+     * 
+     * @param run the run number
+     * @param triggerConfig the trigger config
+     */
+    @Override
+    public void insertTriggerConfig(int run, TriggerConfig triggerConfig) {
+        PreparedStatement preparedStatement = null;
+        try {
+            preparedStatement = connection.prepareStatement(TriggerConfigQuery.INSERT_RUN);            
+            preparedStatement.setInt(1, run);
+            preparedStatement.setLong(2, triggerConfig.getTiTimeOffset());
+            preparedStatement.executeUpdate();
+        } catch (final SQLException e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (preparedStatement != null) {
+                try {
+                    preparedStatement.close();
+                } catch (final SQLException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * Update a trigger config by run number.
+     * 
+     * @param run the run number
+     * @param triggerConfig the trigger config
+     */
+    @Override
+    public void updateTriggerConfig(int run, TriggerConfig triggerConfig) {
+        PreparedStatement preparedStatement = null;
+        try {
+            preparedStatement = connection.prepareStatement(TriggerConfigQuery.UPDATE_RUN);
+            preparedStatement.setLong(1, triggerConfig.getTiTimeOffset());
+            preparedStatement.setInt(2, 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 trigger config by run number.
+     * 
+     * @param run the run number
+     */
+    @Override
+    public void deleteTriggerConfig(int run) {
+        PreparedStatement preparedStatement = null;
+        try {
+            preparedStatement = connection.prepareStatement(TriggerConfigQuery.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();
+                }
+            }
+        }        
+    }
+}