Author: [log in to unmask] Date: Thu Aug 27 18:42:21 2015 New Revision: 3428 Log: Use factory so DAO impl classes can be protected; rework EPICS data API and database structure. HPSJAVA-580, HPSJAVA-591 Added: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsType.java java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariable.java java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDao.java java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDaoImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/RunDatabaseDaoFactory.java java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDao.java - copied, changed from r3424, java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDao.java java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDaoImpl.java - copied, changed from r3424, java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDaoImpl.java Removed: java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDao.java java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDaoImpl.java Modified: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDao.java java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDaoImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDao.java java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDaoImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/RunSummary.java java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDao.java java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDaoImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/ScalerDataDaoImpl.java java/trunk/record-util/src/main/java/org/hps/rundb/package-info.java Modified: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDao.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDao.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDao.java Thu Aug 27 18:42:21 2015 @@ -12,40 +12,20 @@ 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(); + public void deleteEpicsData(EpicsType epicsType, final int run); /** * Get EPICS data by run. * * @param run the run number + * @param epicsType the type of EPICS data (1s or 10s) * @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(); + List<EpicsData> getEpicsData(EpicsType epicsType, int run); /** * Insert a list of EPICS data into the database. @@ -54,12 +34,5 @@ * * @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); + void insertEpicsData(List<EpicsData> epicsDataList); } Modified: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDaoImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDaoImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsDataDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -6,7 +6,9 @@ import java.sql.SQLException; import java.sql.Statement; 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.EpicsHeader; @@ -16,47 +18,17 @@ * * @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 = ?"; - } +final class EpicsDataDaoImpl implements EpicsDataDao { /** * The database connection. */ private final Connection connection; + + /** + * The database interface to get EPICS variable information. + */ + private final EpicsVariableDao epicsVariableDao; /** * Create a new DAO implementation for EPICS data. @@ -68,294 +40,217 @@ throw new IllegalArgumentException("The connection is null."); } this.connection = connection; - } - - /** - * Delete the record for this EPICS data object using its run and sequence number. + this.epicsVariableDao = new EpicsVariableDaoImpl(this.connection); + } + + /** + * Create SQL insert string for the EPICS type. + * + * @param epicsType the EPICS type + * @return the SQL insert string for the type + */ + private String createInsertSql(final EpicsType epicsType) { + final StringBuffer sb = new StringBuffer(); + sb.append("INSERT INTO " + epicsType.getTableName() + " ( epics_header_id, "); + final List<EpicsVariable> variables = epicsVariableDao.getEpicsVariables(epicsType); + for (final EpicsVariable variable : variables) { + sb.append(variable.getColumnName() + ", "); + } + sb.setLength(sb.length() - 2); + sb.append(" ) VALUES ( ?, "); + for (int i = 0; i < variables.size(); i++) { + sb.append("?, "); + } + sb.setLength(sb.length() - 2); + sb.append(" )"); + return sb.toString(); + } + + /** + * Delete all EPICS data for a run from the database. * * @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; + public void deleteEpicsData(final EpicsType epicsType, final int run) { + PreparedStatement selectHeaderIds = null; + PreparedStatement deleteEpicsData = null; + PreparedStatement deleteHeader = 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(); + selectHeaderIds = connection.prepareStatement("SELECT id FROM epics_headers WHERE run = ?"); + selectHeaderIds.setInt(1, run); + final ResultSet headerResultSet = selectHeaderIds.executeQuery(); + deleteEpicsData = connection.prepareStatement("DELETE FROM " + epicsType.getTableName() + + " WHERE epics_header_id = ?"); + deleteHeader = connection.prepareStatement("DELETE FROM epics_headers WHERE id = ?"); + final Set<Integer> headerIds = new HashSet<Integer>(); + while (headerResultSet.next()) { + headerIds.add(headerResultSet.getInt("id")); + } + for (final Integer headerId : headerIds) { + deleteEpicsData.setInt(1, headerId); + int rowsAffected = deleteEpicsData.executeUpdate(); + if (rowsAffected == 0) { + throw new SQLException("Deletion of EPICS data failed; no rows affect."); + } + deleteHeader.setInt(1, headerId); + rowsAffected = deleteHeader.executeUpdate(); + if (rowsAffected == 0) { + throw new SQLException("Deletion of EPICS header failed; no rows affect."); + } + } + } 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. + if (selectHeaderIds != null) { + try { + selectHeaderIds.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + if (deleteEpicsData != null) { + try { + deleteEpicsData.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + if (deleteHeader != null) { + try { + deleteHeader.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + } + } + + /** + * Get EPICS data by run. * * @param run the run number + * @param epicsType the type of EPICS data (1s or 10s) + * @return the EPICS data */ @Override - public void deleteEpicsData(final int run) { - PreparedStatement preparedStatement = null; + public List<EpicsData> getEpicsData(final EpicsType epicsType, final int run) { + final List<EpicsData> epicsDataList = new ArrayList<EpicsData>(); + PreparedStatement selectHeader = null; + PreparedStatement selectEpicsData = null; try { - preparedStatement = connection.prepareStatement(EpicsDataQuery.DELETE_BY_RUN); - preparedStatement.setInt(1, run); - preparedStatement.executeUpdate(); + selectHeader = connection.prepareStatement("SELECT * FROM epics_headers WHERE run = ?"); + selectHeader.setInt(1, run); + final ResultSet headerResultSet = selectHeader.executeQuery(); + selectEpicsData = connection.prepareStatement("SELECT * FROM " + epicsType.getTableName() + + " WHERE epics_header_id = ?"); + final List<EpicsVariable> variables = epicsVariableDao.getEpicsVariables(epicsType); + while (headerResultSet.next()) { + final int headerId = headerResultSet.getInt("id"); + final int headerRun = headerResultSet.getInt("run"); + final int sequence = headerResultSet.getInt("sequence"); + final int timestamp = headerResultSet.getInt("timestamp"); + selectEpicsData.setInt(1, headerId); + final ResultSet epicsDataResult = selectEpicsData.executeQuery(); + if (epicsDataResult.next()) { + final EpicsHeader header = new EpicsHeader(new int[] {headerRun, sequence, timestamp}); + final EpicsData epicsData = new EpicsData(); + epicsData.setEpicsHeader(header); + for (final EpicsVariable variable : variables) { + final double value = epicsDataResult.getDouble(variable.getColumnName()); + epicsData.setValue(variable.getVariableName(), value); + } + epicsDataList.add(epicsData); + } else { + throw new SQLException("Getting EPICS data failed; no data for header ID."); + } + } } 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 + if (selectHeader != null) { + try { + selectHeader.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + if (selectEpicsData != null) { + try { + selectEpicsData.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + } + + return epicsDataList; + } + + /** + * 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 List<EpicsData> getAllEpicsData() { - PreparedStatement preparedStatement = null; - final List<EpicsData> epicsDataList = new ArrayList<EpicsData>(); + public void insertEpicsData(final List<EpicsData> epicsDataList) { + if (epicsDataList.isEmpty()) { + throw new IllegalArgumentException("The EPICS data list is empty."); + } + System.out.println("inserting " + epicsDataList.size() + " EPICS records"); + PreparedStatement insertHeaderStatement = null; 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); + insertHeaderStatement = connection.prepareStatement( + "INSERT INTO epics_headers (run, sequence, timestamp) VALUES (?, ?, ?)", + Statement.RETURN_GENERATED_KEYS); + for (final EpicsData epicsData : epicsDataList) { + final EpicsHeader epicsHeader = epicsData.getEpicsHeader(); + if (epicsHeader == null) { + throw new IllegalArgumentException("The EPICS data is missing a header."); + } + insertHeaderStatement.setInt(1, epicsHeader.getRun()); + insertHeaderStatement.setInt(2, epicsHeader.getSequence()); + insertHeaderStatement.setInt(3, epicsHeader.getTimestamp()); + final int rowsCreated = insertHeaderStatement.executeUpdate(); + if (rowsCreated == 0) { + throw new SQLException("Creation of EPICS header record failed; no rows affected."); + } + int headerId = 0; + try (ResultSet generatedKeys = insertHeaderStatement.getGeneratedKeys()) { + if (generatedKeys.next()) { + headerId = generatedKeys.getInt(1); + } else { + throw new SQLException("Creation of EPICS header record failed; no ID obtained."); + } + } + final EpicsType epicsType = EpicsType.getEpicsType(epicsData); + final String insertSql = this.createInsertSql(epicsType); + final List<EpicsVariable> variables = epicsVariableDao.getEpicsVariables(epicsType); + final PreparedStatement insertStatement = connection.prepareStatement(insertSql); + insertStatement.setInt(1, headerId); + int parameterIndex = 2; + for (final EpicsVariable variable : variables) { + insertStatement.setDouble(parameterIndex, epicsData.getValue(variable.getVariableName())); + ++parameterIndex; + } + final int dataRowsCreated = insertStatement.executeUpdate(); + if (dataRowsCreated == 0) { + throw new SQLException("Creation of EPICS data failed; no rows affected."); + } + insertStatement.close(); + } } 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(); + if (insertHeaderStatement != null) { + try { + insertHeaderStatement.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } } } } Added: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsType.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsType.java (added) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsType.java Thu Aug 27 18:42:21 2015 @@ -0,0 +1,84 @@ +package org.hps.rundb; + +import org.hps.record.epics.EpicsData; + +/** + * Enum for representing different types of EPICS data in the run database, of which there are currently two (1s and + * 10s). + * + * @author Jeremy McCormick, SLAC + */ +public enum EpicsType { + + /** + * 10S EPICS data. + */ + EPICS_10S(10), + /** + * 1S EPICS data. + */ + EPICS_1S(1); + + /** + * Get the type from an int. + * + * @param type the type from an int + * @return the type from an int + * @throws IllegalArgumentException if <code>type</code> is invalid (not 1 or 10) + */ + public static EpicsType fromInt(final int type) { + if (type == EPICS_1S.type) { + return EPICS_1S; + } else if (type == EPICS_10S.type) { + return EPICS_10S; + } else { + throw new IllegalArgumentException("The type code is invalid (must be 1 or 10): " + type); + } + } + + /** + * Return the type of the EPICS data (1s or 10s). + * + * @return the type of the EPICS data + */ + public static EpicsType getEpicsType(final EpicsData epicsData) { + // FIXME: The type argument should be set on creation which would make this key check unnecessary. + if (epicsData.getKeys().contains("MBSY2C_energy")) { + return EpicsType.EPICS_1S; + } else { + return EpicsType.EPICS_10S; + } + } + + /** + * The type encoding (1 or 10). + */ + private int type; + + /** + * Create an EPICS type. + * + * @param type the type encoding (1 or 10) + */ + private EpicsType(final int type) { + this.type = type; + } + + /** + * Get the table name for this type of data. + * + * @return the table name + */ + public String getTableName() { + return this.name().toLowerCase(); + } + + /** + * Get the type encoding. + * + * @return the type encoding + */ + public int getTypeCode() { + return this.type; + } +} Added: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariable.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariable.java (added) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariable.java Thu Aug 27 18:42:21 2015 @@ -0,0 +1,113 @@ +package org.hps.rundb; + +/** + * Information about an EPICS variable including its name in the EPICS database, column name for the run database, + * description of the variable, and type (either 1s or 10s). + * <p> + * This class is used to represent data from the <i>epics_variables</i> table in the run database. + * + * @see EpicsType + * @see org.hps.rundb.EpicsVariableDao + * @see org.hps.rundb.EpicsVariableDaoImpl + * @author Jeremy McCormick, SLAC + */ +public final class EpicsVariable { + + /** + * The name of the variable in the run database. + */ + private final String columnName; + + /** + * A description of the variable. + */ + private final String description; + + /** + * The name of the variable in the EPICs system. + */ + private final String variableName; + + /** + * The type of the variable (1s or 10s). + */ + private final EpicsType variableType; + + /** + * Create an EPICs variable. + * + * @param variableName the name of the variable + * @param columnName the column name in the run db + * @param description the variable's description + * @param variableType the type of the variable + */ + public EpicsVariable(final String variableName, final String columnName, final String description, + final EpicsType variableType) { + this.variableName = variableName; + this.columnName = columnName; + this.description = description; + this.variableType = variableType; + } + + /** + * Create an EPICs variable. + * + * @param variableName the name of the variable + * @param columnName the column name in the run db + * @param description the variable's description + * @param variableType the type of the variable + */ + public EpicsVariable(final String variableName, final String columnName, final String description, final int type) { + this.variableName = variableName; + this.columnName = columnName; + this.description = description; + this.variableType = EpicsType.fromInt(type); + } + + /** + * Get the column name. + * + * @return the column name + */ + public String getColumnName() { + return columnName; + } + + /** + * Get the variable's description. + * + * @return the variable's description + */ + public String getDescription() { + return description; + } + + /** + * Get the variable name. + * + * @return the variable name + */ + public String getVariableName() { + return variableName; + } + + /** + * Get the variable's type. + * + * @return the variable's type + */ + public EpicsType getVariableType() { + return variableType; + } + + /** + * Return this object converted to a string. + * + * @return this object converted to a string + */ + @Override + public String toString() { + return "EpicsVariable { variableName: " + variableName + ", columnName: " + columnName + ", description: " + + description + ", variableType: " + variableType.name() + " }"; + } +} Added: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDao.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDao.java (added) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDao.java Thu Aug 27 18:42:21 2015 @@ -0,0 +1,26 @@ +package org.hps.rundb; + +import java.util.List; + +/** + * Database interface for EPICS variables. + * + * @author Jeremy McCormick, SLAC + */ +public interface EpicsVariableDao { + + /** + * Get the full list of EPICs variables. + * + * @return the full list of EPICS variables + */ + List<EpicsVariable> getEpicsVariables(); + + /** + * Get a list of EPICs variables by type. + * + * @param variableType the EPICS variable type + * @return the list of variables + */ + List<EpicsVariable> getEpicsVariables(EpicsType variableType); +} Added: java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDaoImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDaoImpl.java (added) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EpicsVariableDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -0,0 +1,98 @@ +package org.hps.rundb; + +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 interface for EPICS variable information in the run database. + * + * @author Jeremy McCormick, SLAC + */ +final class EpicsVariableDaoImpl implements EpicsVariableDao { + + /** + * The database connection. + */ + private final Connection connection; + + /** + * Create the object for accessing the db. + * + * @param connection the database connection + */ + public EpicsVariableDaoImpl(final Connection connection) { + this.connection = connection; + } + + /** + * Get the full list of EPICs variables. + * + * @return the full list of EPICS variables + */ + @Override + public List<EpicsVariable> getEpicsVariables() { + final List<EpicsVariable> epicsVariables = new ArrayList<EpicsVariable>(); + Statement statement = null; + try { + statement = connection.createStatement(); + final ResultSet resultSet = statement.executeQuery("SELECT * FROM epics_variables"); + while (resultSet.next()) { + final EpicsVariable epicsVariable = new EpicsVariable(resultSet.getString("variable"), + resultSet.getString("column_name"), resultSet.getString("description"), + resultSet.getInt("epics_type")); + epicsVariables.add(epicsVariable); + } + } catch (final SQLException e) { + throw new RuntimeException(e); + } finally { + if (statement != null) { + try { + statement.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + } + return epicsVariables; + } + + /** + * Get a list of EPICs variables by type. + * + * @param variableType the EPICS variable type + * @return the list of variables + */ + @Override + public List<EpicsVariable> getEpicsVariables(final EpicsType variableType) { + final List<EpicsVariable> epicsVariables = new ArrayList<EpicsVariable>(); + PreparedStatement preparedStatement = null; + try { + preparedStatement = connection.prepareStatement("SELECT * FROM epics_variables WHERE epics_type = ?"); + preparedStatement.setInt(1, variableType.getTypeCode()); + final ResultSet resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + final EpicsVariable epicsVariable = new EpicsVariable(resultSet.getString("variable"), + resultSet.getString("column_name"), resultSet.getString("description"), + resultSet.getInt("epics_type")); + epicsVariables.add(epicsVariable); + } + } catch (final SQLException e) { + throw new RuntimeException(e); + } finally { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } catch (final SQLException e) { + e.printStackTrace(); + } + } + } + return epicsVariables; + } + +} Modified: java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDao.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDao.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDao.java Thu Aug 27 18:42:21 2015 @@ -4,7 +4,7 @@ import java.util.List; /** - * Database Access Object (DAO) interface to EVIO files in the run database. + * Database interface to EVIO files in the run database. * * @author Jeremy McCormick, SLAC */ Modified: java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDaoImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDaoImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/EvioFilesDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -10,11 +10,11 @@ import java.util.List; /** - * Implementation of database operations for EVIO files in the run database. + * Implementation of database interface for EVIO files in the run database. * * @author Jeremy McCormick, SLAC */ -public class EvioFilesDaoImpl implements EvioFilesDao { +final class EvioFilesDaoImpl implements EvioFilesDao { /** * SQL query strings. Added: java/trunk/record-util/src/main/java/org/hps/rundb/RunDatabaseDaoFactory.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/RunDatabaseDaoFactory.java (added) +++ java/trunk/record-util/src/main/java/org/hps/rundb/RunDatabaseDaoFactory.java Thu Aug 27 18:42:21 2015 @@ -0,0 +1,94 @@ +package org.hps.rundb; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Factory for creating database API objects for interacting with the run database. + * <p> + * This allows the implementation classes to be package protected as only public interfaces are returned by this class. + * + * @author Jeremy McCormick, SLAC + * @see EpicsDataDao + * @see EpicsVariableDao + */ +public final class RunDatabaseDaoFactory { + + /** + * The database connection. + */ + private final Connection connection; + + /** + * Create a new factory. + * + * @param connection the database connection + */ + public RunDatabaseDaoFactory(final Connection connection) { + if (connection == null) { + throw new IllegalArgumentException("The connection is null."); + } + try { + if (connection.isClosed()) { + throw new IllegalStateException("The connection is closed."); + } + } catch (final SQLException e) { + throw new IllegalStateException("Error when checking connection status.", e); + } + this.connection = connection; + } + + /** + * Get the EPICS DAO. + * + * @return the EPICS DAO + */ + public EpicsDataDao createEpicsDataDao() { + return new EpicsDataDaoImpl(connection); + } + + /** + * Get the EPICS variable DAO. + * + * @return the EPICS variable DAO + */ + public EpicsVariableDao createEpicsVariableDao() { + return new EpicsVariableDaoImpl(connection); + } + + /** + * Get the EVIO files DAO. + * + * @return the EVIO files DAO + */ + public EvioFilesDao createEvioFilesDao() { + return new EvioFilesDaoImpl(connection); + } + + /** + * Get the run summary DAO. + * + * @return the run summary DAO + */ + public RunSummaryDao createRunSummaryDao() { + return new RunSummaryDaoImpl(connection); + } + + /** + * Get the scaler data DAO. + * + * @return the scaler data DAO + */ + public ScalerDataDao createScalerDataDao() { + return new ScalerDataDaoImpl(connection); + } + + /** + * Get the trigger config DAO. + * + * @return the trigger config DAO + */ + public TriggerConfigDao createTriggerConfigDao() { + return new TriggerConfigDaoImpl(connection); + } +} Modified: java/trunk/record-util/src/main/java/org/hps/rundb/RunSummary.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/RunSummary.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/RunSummary.java Thu Aug 27 18:42:21 2015 @@ -6,7 +6,7 @@ import org.hps.record.epics.EpicsData; import org.hps.record.scalers.ScalerData; -import org.hps.record.triggerbank.TriggerConfigInt; +import org.hps.record.triggerbank.TriggerConfig; /** * This is an API for accessing run summary information which is persisted as a row in the <i>runs</i> table of the run @@ -104,7 +104,7 @@ * * @return the trigger config int values */ - TriggerConfigInt getTriggerConfigInt(); + TriggerConfig getTriggerConfigInt(); /** * Get the start date. Modified: java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDao.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDao.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDao.java Thu Aug 27 18:42:21 2015 @@ -3,7 +3,7 @@ import java.util.List; /** - * Data Access Object (DAO) API for managing run summary information in the run database. + * Database API for managing basic run summary information in the run database. * * @author Jeremy McCormick, SLAC */ Modified: java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDaoImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDaoImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -12,6 +12,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.hps.record.epics.EpicsData; import org.lcsim.util.log.DefaultLogFormatter; import org.lcsim.util.log.LogUtil; @@ -20,7 +21,7 @@ * * @author Jeremy McCormick, SLAC */ -public class RunSummaryDaoImpl implements RunSummaryDao { +final class RunSummaryDaoImpl implements RunSummaryDao { /** * SQL query strings. @@ -78,11 +79,11 @@ * The database API for scaler data. */ private ScalerDataDao scalerDataDao = null; - + /** * The database API for integer trigger config. */ - private TriggerConfigIntDao triggerConfigIntDao = null; + private TriggerConfigDao triggerConfigIntDao = null; /** * Create a new DAO object for run summary information. @@ -100,7 +101,7 @@ epicsDataDao = new EpicsDataDaoImpl(this.connection); scalerDataDao = new ScalerDataDaoImpl(this.connection); evioFilesDao = new EvioFilesDaoImpl(this.connection); - triggerConfigIntDao = new TriggerConfigIntDaoImpl(this.connection); + triggerConfigIntDao = new TriggerConfigDaoImpl(this.connection); } /** @@ -110,18 +111,19 @@ */ @Override public void deleteFullRunSummary(final RunSummary runSummary) { - - int run = runSummary.getRun(); - + + final int run = runSummary.getRun(); + // Delete EPICS log. - this.epicsDataDao.deleteEpicsData(run); + this.epicsDataDao.deleteEpicsData(EpicsType.EPICS_1S, run); + this.epicsDataDao.deleteEpicsData(EpicsType.EPICS_10S, run); // Delete scaler data. this.scalerDataDao.deleteScalerData(run); // Delete file list. this.evioFilesDao.deleteEvioFiles(run); - + // Delete trigger config. this.triggerConfigIntDao.deleteTriggerConfigInt(run); @@ -392,11 +394,11 @@ // Insert scaler data. LOGGER.info("inserting " + runSummary.getScalerData().size() + " scaler data records"); scalerDataDao.insertScalerData(runSummary.getScalerData(), runSummary.getRun()); - + // Insert trigger config. LOGGER.info("inserting " + runSummary.getTriggerConfigInt().size() + " trigger config variables"); - triggerConfigIntDao.insertTriggerConfigInt(runSummary.getTriggerConfigInt(), runSummary.getRun()); - + triggerConfigIntDao.insertTriggerConfig(runSummary.getTriggerConfigInt(), runSummary.getRun()); + } /** @@ -442,16 +444,19 @@ final RunSummaryImpl runSummary = (RunSummaryImpl) this.getRunSummary(run); // Read EPICS data and set on RunSummary. - runSummary.setEpicsData(epicsDataDao.getEpicsData(run)); + final List<EpicsData> epicsDataList = new ArrayList<EpicsData>(); + epicsDataList.addAll(epicsDataDao.getEpicsData(EpicsType.EPICS_1S, run)); + epicsDataList.addAll(epicsDataDao.getEpicsData(EpicsType.EPICS_10S, run)); + runSummary.setEpicsData(epicsDataList); // Read scaler data and set on RunSummary. runSummary.setScalerData(scalerDataDao.getScalerData(run)); // Read EVIO file list and set on RunSummary. runSummary.setEvioFiles(evioFilesDao.getEvioFiles(run)); - + // Read trigger config. - runSummary.setTriggerConfigInt(triggerConfigIntDao.getTriggerConfigInt(run)); + runSummary.setTriggerConfigInt(triggerConfigIntDao.getTriggerConfig(run)); return runSummary; } Modified: java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/RunSummaryImpl.java Thu Aug 27 18:42:21 2015 @@ -11,7 +11,7 @@ import org.hps.record.epics.EpicsData; import org.hps.record.scalers.ScalerData; -import org.hps.record.triggerbank.TriggerConfigInt; +import org.hps.record.triggerbank.TriggerConfig; /** * Implementation of {@link RunSummary} for retrieving information from the run database. @@ -76,7 +76,7 @@ /** * The trigger data for the run. */ - private TriggerConfigInt triggerConfigInt; + private TriggerConfig triggerConfigInt; /** * Start date of run. @@ -207,7 +207,7 @@ * * @return the trigger config of this run */ - public TriggerConfigInt getTriggerConfigInt() { + public TriggerConfig getTriggerConfigInt() { return triggerConfigInt; } @@ -326,7 +326,7 @@ * * @param triggerConfig the trigger config */ - public void setTriggerConfigInt(final TriggerConfigInt triggerConfigInt) { + public void setTriggerConfigInt(final TriggerConfig triggerConfigInt) { this.triggerConfigInt = triggerConfigInt; } Modified: java/trunk/record-util/src/main/java/org/hps/rundb/ScalerDataDaoImpl.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/ScalerDataDaoImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/ScalerDataDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -14,7 +14,7 @@ * * @author Jeremy McCormick, SLAC */ -public class ScalerDataDaoImpl implements ScalerDataDao { +final class ScalerDataDaoImpl implements ScalerDataDao { /** * SQL query strings. Copied: java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDao.java (from r3424, java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDao.java) ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDao.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDao.java Thu Aug 27 18:42:21 2015 @@ -1,13 +1,13 @@ package org.hps.rundb; -import org.hps.record.triggerbank.TriggerConfigInt; +import org.hps.record.triggerbank.TriggerConfig; /** * Database interface to trigger config. * * @author Jeremy McCormick, SLAC */ -public interface TriggerConfigIntDao { +public interface TriggerConfigDao { /** * Get the trigger config by run. @@ -15,7 +15,7 @@ * @param run the run number * @return the trigger config */ - TriggerConfigInt getTriggerConfigInt(int run); + TriggerConfig getTriggerConfig(int run); /** * Insert a trigger config for a run. @@ -23,7 +23,7 @@ * @param run the run number * @param triggerConfig the trigger config */ - void insertTriggerConfigInt(TriggerConfigInt triggerConfig, int run); + void insertTriggerConfig(TriggerConfig triggerConfig, int run); /** * Delete a trigger config by run number. Copied: java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDaoImpl.java (from r3424, java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDaoImpl.java) ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigIntDaoImpl.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/TriggerConfigDaoImpl.java Thu Aug 27 18:42:21 2015 @@ -4,58 +4,73 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Map; -import org.hps.record.triggerbank.TriggerConfigInt; +import org.hps.record.triggerbank.TriggerConfig; +import org.hps.record.triggerbank.TriggerConfigVariable; /** * Implementation of trigger config database interface. - * + * * @author Jeremy McCormick, SLAC */ -public class TriggerConfigIntDaoImpl implements TriggerConfigIntDao { +final 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_int WHERE run = ?"; - /** - * Insert by run. - */ - static final String INSERT_VARIABLE = "INSERT INTO run_trigger_config_int (run, variable_name, value) VALUES (?, ?, ?)"; - /** - * Delete by run. - */ - static final String DELETE_RUN = "DELETE FROM run_trigger_config_int WHERE run = ?"; - } - + private final Connection connection; + /** * Create a new object. - * + * * @param connection the database connection */ - TriggerConfigIntDaoImpl(Connection connection) { + TriggerConfigDaoImpl(final Connection connection) { this.connection = connection; } + /** + * Delete a trigger config by run number. + * + * @param run the run number + */ @Override - public TriggerConfigInt getTriggerConfigInt(int run) { + public void deleteTriggerConfigInt(final int run) { PreparedStatement preparedStatement = null; - TriggerConfigInt triggerConfig = new TriggerConfigInt(); try { - preparedStatement = connection.prepareStatement(TriggerConfigQuery.SELECT_RUN); - ResultSet resultSet = preparedStatement.executeQuery(); - while (resultSet.next()) { - triggerConfig.put(resultSet.getString("variable_name"), resultSet.getLong("value")); + preparedStatement = connection.prepareStatement("DELETE FROM trigger_config WHERE 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 the trigger config by run. + * + * @param run the run number + * @return the trigger config + */ + @Override + public TriggerConfig getTriggerConfig(final int run) { + PreparedStatement preparedStatement = null; + final TriggerConfig triggerConfig = new TriggerConfig(); + try { + preparedStatement = connection.prepareStatement("SELECT * FROM trigger_config WHERE run = ?"); + final ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + triggerConfig.put(TriggerConfigVariable.TI_TIME_OFFSET, + resultSet.getLong(TriggerConfigVariable.TI_TIME_OFFSET.getColumnName())); } } catch (final SQLException e) { throw new RuntimeException(e); @@ -69,17 +84,21 @@ return triggerConfig; } + /** + * Insert a trigger config for a run. + * + * @param run the run number + * @param triggerConfig the trigger config + */ @Override - public void insertTriggerConfigInt(TriggerConfigInt triggerConfig, int run) { + public void insertTriggerConfig(final TriggerConfig triggerConfig, final int run) { + PreparedStatement preparedStatement = null; try { - preparedStatement = connection.prepareStatement(TriggerConfigQuery.INSERT_VARIABLE); - for (Map.Entry<String, Long> entry : triggerConfig.entrySet()) { - preparedStatement.setInt(1, run); - preparedStatement.setString(2, entry.getKey()); - preparedStatement.setLong(3, entry.getValue()); - preparedStatement.executeUpdate(); - } + preparedStatement = connection.prepareStatement("INSERT INTO trigger_config ( " + + TriggerConfigVariable.TI_TIME_OFFSET.getColumnName() + " ) VALUES (?)"); + preparedStatement.setLong(1, triggerConfig.getTiTimeOffset()); + preparedStatement.executeUpdate(); } catch (final SQLException e) { throw new RuntimeException(e); } finally { @@ -91,26 +110,6 @@ } } } - + } - - @Override - public void deleteTriggerConfigInt(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(); - } - } - } - } } Modified: java/trunk/record-util/src/main/java/org/hps/rundb/package-info.java ============================================================================= --- java/trunk/record-util/src/main/java/org/hps/rundb/package-info.java (original) +++ java/trunk/record-util/src/main/java/org/hps/rundb/package-info.java Thu Aug 27 18:42:21 2015 @@ -1,4 +1,4 @@ /** - * API for accessing the HPS run database with run summary information. + * API for accessing the HPS run database. */ package org.hps.rundb;