From eabc21d32c8fd67dc7c784f5873527f7ba518945 Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Tue, 5 Dec 2017 10:06:42 +0100 Subject: [PATCH 1/6] added a new configuration item for specifying the type of database to connect to --- DAQAggregator_example.properties | 1 + src/main/java/rcms/utilities/daqaggregator/Settings.java | 1 + .../daqaggregator/datasource/HardwareConnector.java | 9 +++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/DAQAggregator_example.properties b/DAQAggregator_example.properties index b79d59a2..81749f34 100644 --- a/DAQAggregator_example.properties +++ b/DAQAggregator_example.properties @@ -41,6 +41,7 @@ session.l0filter2 = PublicGlobal # settings concerning HWCFG DB # ask your collegue for credentials # +hwcfgdb.type = ORACLE hwcfgdb.host = localhost hwcfgdb.port = 10121 hwcfgdb.sid = diff --git a/src/main/java/rcms/utilities/daqaggregator/Settings.java b/src/main/java/rcms/utilities/daqaggregator/Settings.java index 32e26f8e..3ecbcc67 100644 --- a/src/main/java/rcms/utilities/daqaggregator/Settings.java +++ b/src/main/java/rcms/utilities/daqaggregator/Settings.java @@ -29,6 +29,7 @@ public enum Settings { MONITOR_SETUPNAME("monitor.setupName"), // settings concerning HWCFG DB + HWCFGDB_TYPE("hwcfgdb.type"), HWCFGDB_DBURL("hwcfgdb.dburl"), HWCFGDB_HOST("hwcfgdb.host"), HWCFGDB_PORT("hwcfgdb.port"), diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java index d96a6070..b3f80e4a 100644 --- a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java @@ -26,14 +26,14 @@ public DAQPartition getPartition(String _dpsetPath) return dpset.getDPs().values().iterator().next(); } - public void initialize(String url, String host, String port, String sid, String user, String passwd) + public void initialize(String dbType, String url, String host, String port, String sid, String user, String passwd) throws DBConnectorException, HardwareConfigurationException { - String _dbType = "ORACLE"; + if (url == null || url.isEmpty()) { url = "jdbc:oracle:thin:@" + host + ":" + port + "/" + sid; } - if (_dbType.equals("ORACLE")) + if (dbType.equals("ORACLE")) _dbconn = new DBConnectorOracle(url, user, passwd); else _dbconn = new DBConnectorMySQL(url, user, passwd); @@ -44,6 +44,7 @@ public void initialize(String url, String host, String port, String sid, String public void initialize(Properties prop) throws DBConnectorException, HardwareConfigurationException { + String type = prop.getProperty(Settings.HWCFGDB_TYPE.getKey()); String url = prop.getProperty(Settings.HWCFGDB_DBURL.getKey()); String host = prop.getProperty(Settings.HWCFGDB_HOST.getKey()); String port = prop.getProperty(Settings.HWCFGDB_PORT.getKey()); @@ -51,6 +52,6 @@ public void initialize(Properties prop) throws DBConnectorException, String user = prop.getProperty(Settings.HWCFGDB_LOGIN.getKey()); String passwd = prop.getProperty(Settings.HWCFGDB_PWD.getKey()); - initialize(url, host, port, sid, user, passwd); + initialize(type, url, host, port, sid, user, passwd); } } From a9697e6b28af8735eb189d99bf828cd1dcad1611 Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Tue, 5 Dec 2017 10:09:05 +0100 Subject: [PATCH 2/6] added a method to get the database connection in class HardwareConnector --- .../daqaggregator/datasource/HardwareConnector.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java index b3f80e4a..a3b2cfd4 100644 --- a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java @@ -54,4 +54,9 @@ public void initialize(Properties prop) throws DBConnectorException, initialize(type, url, host, port, sid, user, passwd); } + + static DBConnectorIF getDbconn() { + return _dbconn; + } + } From d7f72338006c99636cda9da751cb36cf2009717b Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Fri, 22 Dec 2017 11:58:02 +0100 Subject: [PATCH 3/6] added support to connect to a sqlite hardware database --- pom.xml | 8 +++-- .../datasource/DBConnectorSqlite.java | 31 +++++++++++++++++++ .../datasource/HardwareConnector.java | 2 ++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java diff --git a/pom.xml b/pom.xml index ae9ac7bd..9bfa86f5 100644 --- a/pom.xml +++ b/pom.xml @@ -177,9 +177,11 @@ commons-math3 3.0 - - - + + org.xerial + sqlite-jdbc + 3.21.0 + diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java b/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java new file mode 100644 index 00000000..26e1af43 --- /dev/null +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java @@ -0,0 +1,31 @@ +package rcms.utilities.daqaggregator.datasource; + +import java.sql.DriverManager; +import java.sql.SQLException; +import rcms.common.db.AbstractDBConnector; +import rcms.common.db.DBConnectorException; + +/** + * class to access hardware database information in an SQLite database + */ +public class DBConnectorSqlite extends AbstractDBConnector { + + DBConnectorSqlite(String url) { + this.url = url; + super.startQueryWatcher(); + } + + @Override + public void openConnection() throws DBConnectorException { + + if (!queryWatcher.isAlive()) { + super.startQueryWatcher(); + } + + try { + this.connection = DriverManager.getConnection(url); + } catch (SQLException ex) { + throw new DBConnectorException("failed to connect to database " + url, ex); + } + } +} diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java index a3b2cfd4..9a66b01f 100644 --- a/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/HardwareConnector.java @@ -35,6 +35,8 @@ public void initialize(String dbType, String url, String host, String port, Stri if (dbType.equals("ORACLE")) _dbconn = new DBConnectorOracle(url, user, passwd); + else if (dbType.equals("SQLITE")) + _dbconn = new DBConnectorSqlite(url); else _dbconn = new DBConnectorMySQL(url, user, passwd); From 04c4dd5b2945da74b0463dd09f7416d6ed1234b0 Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Fri, 22 Dec 2017 12:23:04 +0100 Subject: [PATCH 4/6] Added a new class HwdbToSqlite which can also be run as a standalone application to write out selected dpset paths into an sqlite file --- .../datasource/HwdbToSqlite.java | 549 ++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 src/main/java/rcms/utilities/daqaggregator/datasource/HwdbToSqlite.java diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/HwdbToSqlite.java b/src/main/java/rcms/utilities/daqaggregator/datasource/HwdbToSqlite.java new file mode 100644 index 00000000..554a835e --- /dev/null +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/HwdbToSqlite.java @@ -0,0 +1,549 @@ +package rcms.utilities.daqaggregator.datasource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.commons.lang3.StringUtils; +import rcms.common.db.DBConnectorException; +import rcms.common.db.DBConnectorIF; +import rcms.common.db.preparedstatement.DBPreparedStatement; +import rcms.utilities.hwcfg.HardwareConfigurationException; +import rcms.utilities.hwcfg.InvalidNodeTypeException; +import rcms.utilities.hwcfg.PathNotFoundException; +import rcms.utilities.hwcfg.dp.DAQPartition; +import rcms.utilities.hwcfg.dp.DAQPartitionSet; + +/** + * given a eqset path, produces a sqlite database with the required entries + * copied from the hardware database + */ +public class HwdbToSqlite { + + private final List daqPartitions = new ArrayList(); + + /** maps from numeric SQL type to String */ + private static final Map sqlTypesMap = makeSqlTypesMap(); + + private static class IdTriple { + + private final long eqsetId; + private final long fbsetId; + private final long dpsetId; + + public IdTriple(long eqsetId, long fbsetId, long dpsetId) { + this.eqsetId = eqsetId; + this.fbsetId = fbsetId; + this.dpsetId = dpsetId; + } + + public String makeSqlFilterQuery(boolean useEqsetId, boolean useFbsetId, boolean useDpsetId) { + + List filters = new ArrayList<>(); + + if (useEqsetId) { + filters.add("EQSET_ID = " + eqsetId); + } + + if (useFbsetId) { + filters.add("FBSET_ID = " + fbsetId); + } + + if (useDpsetId) { + filters.add("DPSET_ID = " + dpsetId); + } + + if (filters.isEmpty()) { + return null; + } else { + return StringUtils.join(filters, " AND "); + } + } + + } + + private static Map makeSqlTypesMap() { + + Map result = new HashMap<>(); + + for (Field field : Types.class.getFields()) { + try { + result.put((Integer) field.get(null), field.getName()); + } catch (IllegalArgumentException | IllegalAccessException ex) { + Logger.getLogger(HwdbToSqlite.class.getName()).log(Level.SEVERE, null, ex); + } + } + + return result; + + } + + private static Connection connectSqlite(File dbfile) throws SQLException { + String url = "jdbc:sqlite:" + dbfile.getAbsolutePath(); + return DriverManager.getConnection(url); + } + + /** + * @return a list of column names in the given table + */ + List getColumnNames(DBConnectorIF dbconnSrc, String tableName) throws DBConnectorException, SQLException { + + ResultSet res = dbconnSrc.DBExecuteQuery("select * from " + tableName + " where 1 = 0"); + ResultSetMetaData metaData = res.getMetaData(); + + List result = new ArrayList(); + + // note the one based indexing + for (int col = 1; col <= metaData.getColumnCount(); ++col) { + + String colName = metaData.getColumnName(col); + result.add(colName.toUpperCase()); + } + + return result; + } + + /** + * given the source database connector and a table name, creates an (empty) + * table in the destination database. (Note: does not copy any other things + * like default values, constraints etc.) + */ + private void copyTableSchema(DBConnectorIF dbconnSrc, + Connection dbconnDest, String tableName) throws DBConnectorException, SQLException { + + // get table description + // setting the table name as a parameter does not work... + DBPreparedStatement dbps = new DBPreparedStatement("select * from " + tableName + " where 1 = 0"); + + ResultSet res = dbconnSrc.DBPreparedStatementExecuteQuery(dbps); + + ResultSetMetaData metaData = res.getMetaData(); + + // note the one based indexing + StringBuilder query = new StringBuilder(); + query.append("CREATE TABLE IF NOT EXISTS "); + query.append(tableName); + query.append(" ("); + + for (int col = 1; col <= metaData.getColumnCount(); ++col) { + + String colName = metaData.getColumnName(col); + String typeName = sqlTypesMap.get(metaData.getColumnType(col)); + + if (col > 1) { + query.append(", "); + } + + query.append(colName); + query.append(" "); + query.append(typeName); + } + query.append(" )"); + + // create the table + Statement stmt = dbconnDest.createStatement(); + stmt.execute(query.toString()); + } + + /** + * copies table content from source to destination. + * + * @param condition text added after the where clause to filter rows to be + * copied. May be null. + */ + private void copyTableContent(DBConnectorIF dbconnSrc, + Connection dbconnDest, String tableName, String condition) throws DBConnectorException, SQLException { + + String query = "select * from " + tableName; + + if (condition != null) { + query += " where " + condition; + } + + // fetch data from the source DB + ResultSet res = dbconnSrc.DBExecuteQuery(query); + + // make the output prepared statement from the result set meta data + StringBuilder destStmtCmd = new StringBuilder(), sbValues = new StringBuilder(); + destStmtCmd.append("INSERT INTO "); + destStmtCmd.append(tableName); + destStmtCmd.append(" ("); + + sbValues.append(" VALUES ("); + + ResultSetMetaData metaData = res.getMetaData(); + + int numCols = metaData.getColumnCount(); + + for (int col = 1; col <= numCols; ++col) { + + if (col > 1) { + destStmtCmd.append(", "); + sbValues.append(", "); + } + + destStmtCmd.append(metaData.getColumnName(col)); + + sbValues.append("?"); + + } + + destStmtCmd.append(")"); + sbValues.append(")"); + + destStmtCmd.append(sbValues); + + PreparedStatement stmtDest = dbconnDest.prepareStatement(destStmtCmd.toString()); + + // copy the data + while (res.next()) { + + for (int col = 1; col <= numCols; ++col) { + + stmtDest.setObject(col, res.getObject(col)); + + } // loop over columns + + stmtDest.execute(); + } // loop over rows + } + + /** + * This function is intended to be used with the dpset, fbset and eqset tables + * to get the minimal set of ids to be copied. + * + * @return a set of ids which are found on the path from the given leaves in + * idValues to the root ('top directory') of the hierarchy + */ + private Set findIdPath(DBConnectorIF dbconnSrc, String tableName, String idVar, + Collection idValues) throws DBConnectorException, SQLException { + + Set result = new HashSet<>(); + + for (Long idValue : idValues) { + + while (idValue != null) { + + if (result.contains(idValue)) { + // we're on a part of a path now we already have followed, + // no need to continue + break; + } + + result.add(idValue); + // find parent + // TODO: should properly close this result set in case of failures + ResultSet res = dbconnSrc.DBExecuteQuery("SELECT parent_id FROM " + tableName + + " WHERE " + idVar + " = " + idValue); + + boolean rowFetched = false; + + Long parentIdValue = 0l; + + while (res.next()) { + + rowFetched = true; + parentIdValue = res.getLong(1); + + if (res.wasNull()) { + parentIdValue = null; + } + break; + } + + if (!rowFetched) { + throw new Error("could not find parent of id " + idValue); + } + + idValue = parentIdValue; + + } // while the top of the hierarchy was not reached + + } // loop over given id values + + return result; + } + + /** + * generates a SQL query condition to only include the given ids in the copy + * of the table (used for fb, dp and eq set tables). + */ + private String makeIdPathCondition(DBConnectorIF dbconnSrc, String tableName, + String idVar, Collection idValues) throws DBConnectorException, SQLException { + + // get the set of ids to select + Set ids = findIdPath(dbconnSrc, tableName, idVar, idValues); + + // make the query + List filters = new ArrayList(); + + for (Long id : ids) { + filters.add(idVar + " = " + id); + } + + return StringUtils.join(filters, " OR "); + + } + + private Set getEqSetIds(List ids) { + Set result = new HashSet<>(); + + for (IdTriple idt : ids) { + result.add(idt.eqsetId); + } + + return result; + } + + private Set getDpSetIds(List ids) { + Set result = new HashSet<>(); + + for (IdTriple idt : ids) { + result.add(idt.dpsetId); + } + + return result; + } + + private Set getFbSetIds(List ids) { + Set result = new HashSet<>(); + + for (IdTriple idt : ids) { + result.add(idt.fbsetId); + } + + return result; + } + + private void copyTable(DBConnectorIF dbconnSrc, + Connection dbconnDest, String tableName, + List ids) + throws DBConnectorException, SQLException { + + tableName = tableName.toUpperCase(); + + // copy the table schema + copyTableSchema(dbconnSrc, dbconnDest, tableName); + + List filters = new ArrayList(); + + List colNames = this.getColumnNames(dbconnSrc, tableName); + + // for the tables which contain the list of eq, fb and dp sets + // we copy only the necessary entries (requested ids and their parents) + // so that when we run tests on a dpset path which was not copied + // to the sqlite file, we get an exception about the missing dpset path + // and not an error elsewhere because e.g. a dpset was returned + // but it does not contain any FEDs etc. + if (tableName.equals("DAQ_EQCFG_EQSET")) { + + filters.add(makeIdPathCondition(dbconnSrc, tableName, "EQSET_ID", this.getEqSetIds(ids))); + + } else if (tableName.equals("DAQ_DPCFG_DPSET")) { + + filters.add(makeIdPathCondition(dbconnSrc, tableName, "DPSET_ID", this.getDpSetIds(ids))); + + } else if (tableName.equals("DAQ_FBCFG_FBSET")) { + + filters.add(makeIdPathCondition(dbconnSrc, tableName, "FBSET_ID", this.getFbSetIds(ids))); + + } else { + // other tables + + for (IdTriple id : ids) { + String filterExpr = id.makeSqlFilterQuery( + colNames.contains("EQSET_ID"), + colNames.contains("FBSET_ID"), + colNames.contains("DPSET_ID") + ); + + if (filterExpr != null) { + filters.add("(" + filterExpr + ")"); + } + } + } + + String condition = null; + + if (!filters.isEmpty()) { + condition = StringUtils.join(filters, " OR "); + } // if filter not empty + + this.copyTableContent(dbconnSrc, dbconnDest, tableName, condition); + } + + /** + * convenience function: copy one single path from the hardware database to an + * sqlite file + */ + void run(String hwcfgPath, File sqliteOutput) throws SQLException, DBConnectorException, + HardwareConfigurationException, IOException, PathNotFoundException, + InvalidNodeTypeException, IllegalArgumentException, IllegalAccessException { + + List paths = new ArrayList(); + paths.add(hwcfgPath); + + run(paths, sqliteOutput); + } + + /** + * copies the tables from the source database to the sqlite database + */ + void run(List hwcfgPaths, File sqliteOutput) throws SQLException, + DBConnectorException, HardwareConfigurationException, IOException, + PathNotFoundException, InvalidNodeTypeException, IllegalArgumentException, + IllegalAccessException { + + // retrieve from the hardware database + HardwareConnector hardwareConnector = new HardwareConnector(); + Properties prop = new Properties(); + prop.load(new FileInputStream("DAQAggregator.properties")); + + // connect to the hardware database + hardwareConnector.initialize(prop); + + // the list of dpset / fbset and eqset ids to be copied + List ids = new ArrayList<>(); + + // get the daq partition objects + for (String hwcfgPath : hwcfgPaths) { + + DAQPartition daqPartition = hardwareConnector.getPartition(hwcfgPath); + daqPartitions.add(daqPartition); + + DAQPartitionSet dpset = daqPartition.getDAQPartitionSet(); + + ids.add(new IdTriple( + dpset.getFEDBuilderSet().getEquipmentSet().getId(), + dpset.getFEDBuilderSet().getId(), + dpset.getId() + )); + + } + + // create the output file + // access the hardware database ourselves + DBConnectorIF dbconnSrc = HardwareConnector.getDbconn(); + Connection dbconnDest = connectSqlite(sqliteOutput); + + // tables we need to copy + final String tables[] = { + "DAQ_DPCFG_DAQPARTITION", + "DAQ_DPCFG_DPGENERICHOST", + "DAQ_DPCFG_DPGH_PARAMETER", + "DAQ_DPCFG_DPPROPERTY", + "DAQ_DPCFG_DPSET", + "DAQ_DPCFG_RU", + "DAQ_DPCFG_SOURCE_PORT", + "DAQ_EQCFG_DBPS", + "DAQ_EQCFG_DNSNAME", + "DAQ_EQCFG_EQSET", + "DAQ_EQCFG_FED", + "DAQ_EQCFG_FEDDEPENDENCY", + "DAQ_EQCFG_FMM", + "DAQ_EQCFG_FMMCRATE", + "DAQ_EQCFG_FMMFMM", + "DAQ_EQCFG_FMMTRIGGER", + "DAQ_EQCFG_FRL", + "DAQ_EQCFG_FRLCRATE", + "DAQ_EQCFG_FRL_NIC", + "DAQ_EQCFG_HOST", + "DAQ_EQCFG_HOST_ATTRIBUTE", + "DAQ_EQCFG_HOST_NIC", + "DAQ_EQCFG_HOST_ROLE", + "DAQ_EQCFG_HOST_ROLE_MAP", + "DAQ_EQCFG_LINECARD", + "DAQ_EQCFG_NETWORK", + "DAQ_EQCFG_NETWORK_NETWORK", + "DAQ_EQCFG_NETWORK_ROLE", + "DAQ_EQCFG_NIC", + "DAQ_EQCFG_NIC_PORT", + "DAQ_EQCFG_PORT", + "DAQ_EQCFG_PORT_PORT", + "DAQ_EQCFG_SUBSYSTEM", + "DAQ_EQCFG_SWITCH", + "DAQ_EQCFG_TCDS_ICI", + "DAQ_EQCFG_TCDS_PM", + "DAQ_EQCFG_TRIGGER", + "DAQ_EQCFG_TTCPARTITION", + "DAQ_FBCFG_FBI", + "DAQ_FBCFG_FBSET", + "DAQ_FBCFG_FEDBUILDER", + "DAQ_HWCONF_VERSION" + }; + + for (String table : tables) { + + this.copyTable(dbconnSrc, dbconnDest, table, + ids); + } + + dbconnDest.close(); + dbconnSrc.closeConnection(); + + } + + public List getDaqPartitions() { + return daqPartitions; + } + + /** + * entry point for the command line application to write an sqlite file with + * information taken from the configured database (typically the central + * hardware database). + */ + public static void main(String argv[]) throws DBConnectorException, IOException, + HardwareConfigurationException, PathNotFoundException, InvalidNodeTypeException, + SQLException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException { + + if (argv.length < 2) { + System.err.println(); + System.err.println("Utility program to extract a DAQPartition from the"); + System.err.println("hardware database (as described in DAQAggregator.properties)"); + System.err.println("given a DPSet path and an sqlite output file."); + System.err.println("usage:"); + System.err.println(); + System.err.println(" dpset-path2 [ dpset-path2 ... ] output.sqlite"); + System.err.println(); + System.err.println("WARNING: will overwrite the output file without"); + System.err.println(" prior notification if it exists already."); + System.err.println(" Note also that if the output file is an"); + System.err.println(" existing sqlite file it may be appended to"); + System.err.println(" instead of overwriting it."); + System.err.println(); + System.exit(1); + } + + // ensure the sqlite driver is registered + Class.forName("org.sqlite.JDBC"); + + List paths = new ArrayList(); + + for (int i = 0; i < argv.length - 1; ++i) { + paths.add(argv[i]); + } + + String outputFname = argv[argv.length - 1]; + + File sqliteOutput = new File(outputFname); + new HwdbToSqlite().run(paths, sqliteOutput); + } +} From 9626ab62a06792dc2793e974791231ab54e6e0eb Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Fri, 22 Dec 2017 12:26:29 +0100 Subject: [PATCH 5/6] added a test for the new class HwdbToSqlite --- .../datasource/HwdbToSqliteTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/test/java/rcms/utilities/daqaggregator/datasource/HwdbToSqliteTest.java diff --git a/src/test/java/rcms/utilities/daqaggregator/datasource/HwdbToSqliteTest.java b/src/test/java/rcms/utilities/daqaggregator/datasource/HwdbToSqliteTest.java new file mode 100644 index 00000000..56d0aa66 --- /dev/null +++ b/src/test/java/rcms/utilities/daqaggregator/datasource/HwdbToSqliteTest.java @@ -0,0 +1,72 @@ +package rcms.utilities.daqaggregator.datasource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.sql.SQLException; +import java.util.Properties; +import static org.junit.Assert.assertEquals; +import org.junit.Test; +import rcms.common.db.DBConnectorException; +import rcms.utilities.hwcfg.HardwareConfigurationException; +import rcms.utilities.hwcfg.InvalidNodeTypeException; +import rcms.utilities.hwcfg.PathNotFoundException; +import rcms.utilities.hwcfg.dp.DAQPartition; + +public class HwdbToSqliteTest { + + /** + * read a configuration from the hardware database, convert it to sqlite and + * read it back + */ + @Test + public void test01() throws FileNotFoundException, IOException, DBConnectorException, + HardwareConfigurationException, PathNotFoundException, InvalidNodeTypeException, SQLException, IllegalArgumentException, IllegalAccessException { + + final String path = "/daq2/eq_170517_01_ECAL622Optical/fb_all/dp_bl456_75BU"; + + //----- + // get the DAQPartition object and write it out to sqlite + //----- + // TODO: we could use Sqlite in memory instead + File sqliteFile = File.createTempFile("sqlite-test", ".sqlite"); + sqliteFile.deleteOnExit(); + + HwdbToSqlite converter = new HwdbToSqlite(); + converter.run(path, sqliteFile); + + // get the original object + DAQPartition daqPartition = converter.getDaqPartitions().get(0); + + //----- + // read the DAQPartition object back from the sqlite database + //----- + Properties prop = new Properties(); + prop.load(new FileInputStream("DAQAggregator.properties")); + + prop.setProperty("hwcfgdb.type", "SQLITE"); + prop.setProperty("hwcfgdb.dburl", "jdbc:sqlite:" + sqliteFile.getAbsolutePath()); + + HardwareConnector hardwareConnector = new HardwareConnector(); + hardwareConnector.initialize(prop); + + DAQPartition daqPartition2 = hardwareConnector.getPartition(path); + + // DAQPartition does not implement an .equals() method + // so any test for equality will default to pointer comparison + // which will result in 'not equal' when comparing daqPartition and daqPartition2 + assertEquals(daqPartition.getId(), daqPartition2.getId()); + + // at least check some numbers of items are equal between the + // original object and the one read back from the sqlite database + // number of FEDs + assertEquals(daqPartition.getDAQPartitionSet().getEquipmentSet().getFEDs().size(), + daqPartition2.getDAQPartitionSet().getEquipmentSet().getFEDs().size()); + + // number of FMMs + assertEquals(daqPartition.getDAQPartitionSet().getEquipmentSet().getFMMs().size(), + daqPartition2.getDAQPartitionSet().getEquipmentSet().getFMMs().size()); + + } +} From 356152d0982fe8157c4a7dd7c1fde1a4b195e8c4 Mon Sep 17 00:00:00 2001 From: Andre Holzner Date: Fri, 22 Dec 2017 12:29:54 +0100 Subject: [PATCH 6/6] added code to rewrite one hardware database sql query which is not sqlite compliant --- pom.xml | 5 ++ .../datasource/DBConnectorSqlite.java | 73 ++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9bfa86f5..e39be87c 100644 --- a/pom.xml +++ b/pom.xml @@ -182,6 +182,11 @@ sqlite-jdbc 3.21.0 + + commons-dbcp + commons-dbcp + 1.4 + diff --git a/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java b/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java index 26e1af43..b2e04bfb 100644 --- a/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java +++ b/src/main/java/rcms/utilities/daqaggregator/datasource/DBConnectorSqlite.java @@ -1,10 +1,81 @@ package rcms.utilities.daqaggregator.datasource; +import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.SQLException; +import org.apache.commons.dbcp.DelegatingConnection; import rcms.common.db.AbstractDBConnector; import rcms.common.db.DBConnectorException; +/** + * class wrapping around a SQLite connection object to rewrite certain SQL + * queries + * + * @author holzner + */ +class RewritingConnection extends DelegatingConnection { + + public RewritingConnection(Connection conn) { + super(conn); + } + + // original query to catch + private static final String refQuery1 = "WITH " + + " ho AS (SELECT * FROM DAQ_EQCFG_HOST WHERE eqset_id = ?), " + + " ha AS (SELECT * FROM DAQ_EQCFG_HOST_ATTRIBUTE WHERE eqset_id = ?), " + + " hn AS (SELECT * FROM DAQ_EQCFG_HOST_NIC WHERE eqset_id = ?), " + + " ni AS (SELECT * FROM DAQ_EQCFG_NIC WHERE eqset_id = ?), " + + " dn AS (SELECT * FROM DAQ_EQCFG_DNSNAME WHERE eqset_id = ?) " + + "SELECT ho.host_id, " + + " ho.ncores, " + + " ha.attr_name, " + + " ha.attr_value, " + + " ni.nic_id, " + + " ni.device_name, " + + " dn.dnsname, " + + " dn.network_name " + + "FROM ho, ha, hn, ni, dn WHERE " + + " ho.host_id = hn.host_id AND" + + " ha.host_id(+) = ho.host_id AND" + + " hn.nic_id = ni.nic_id AND" + + " ni.nic_id = dn.nic_id ORDER BY ho.host_id"; + + // substitution query + private static final String subsQuery1 = "WITH " + + " ho AS (SELECT * FROM DAQ_EQCFG_HOST WHERE eqset_id = ?), " + + " ha AS (SELECT * FROM DAQ_EQCFG_HOST_ATTRIBUTE WHERE eqset_id = ?), " + + " hn AS (SELECT * FROM DAQ_EQCFG_HOST_NIC WHERE eqset_id = ?), " + + " ni AS (SELECT * FROM DAQ_EQCFG_NIC WHERE eqset_id = ?), " + + " dn AS (SELECT * FROM DAQ_EQCFG_DNSNAME WHERE eqset_id = ?) " + + "SELECT ho.host_id, " + + " ho.ncores, " + + " ha.attr_name, " + + " ha.attr_value, " + + " ni.nic_id, " + + " ni.device_name, " + + " dn.dnsname, " + + " dn.network_name " + + "FROM ho, ha, hn, ni, dn WHERE " + + " ho.host_id = hn.host_id AND" + + // " ha.host_id(+) = ho.host_id AND" + + " ha.host_id = ho.host_id AND" + + " hn.nic_id = ni.nic_id AND" + + " ni.nic_id = dn.nic_id ORDER BY ho.host_id"; + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + + // TODO: should ignore/collapse multiple consecutive whitespace + // during comparison for somewhat more robust comparison + if (sql.equals(refQuery1)) { + sql = subsQuery1; + } + + return super.prepareStatement(sql); + } +} + /** * class to access hardware database information in an SQLite database */ @@ -23,7 +94,7 @@ public void openConnection() throws DBConnectorException { } try { - this.connection = DriverManager.getConnection(url); + this.connection = new RewritingConnection(DriverManager.getConnection(url)); } catch (SQLException ex) { throw new DBConnectorException("failed to connect to database " + url, ex); }