From 8062085148d5820daeca8f4b4e7643daf6411911 Mon Sep 17 00:00:00 2001 From: Nikolaus Krismer <niko@krismer.de> Date: Thu, 27 Mar 2014 14:37:25 +0100 Subject: [PATCH] reworked database connection closing/opening (no more open connections should remain after testing now) --- .../inf/isochrone/algorithm/Isochrone.java | 36 ++- .../inf/isochrone/algorithm/MDijkstra.java | 9 +- .../unibz/inf/isochrone/algorithm/MineX.java | 13 +- .../unibz/inf/isochrone/algorithm/MrneX.java | 21 +- .../inf/isochrone/config/ConfigDataset.java | 2 +- .../inf/isochrone/config/ConfigIsochrone.java | 10 +- .../inf/isochrone/db/ConnectionFactory.java | 43 ++- .../it/unibz/inf/isochrone/db/Database.java | 10 +- .../it/unibz/inf/isochrone/util/Query.java | 6 +- .../it/unibz/inf/isoga/db/DatabaseWeb.java | 2 +- .../java/it/unibz/inf/isoga/db/DbUtility.java | 292 +++++++++--------- .../inf/isoga/service/AbstractService.java | 6 +- .../inf/isoga/service/ServiceIsochrone.java | 12 +- .../unibz/inf/isochrone/db/DatabaseTest.java | 16 +- .../isochrone/network/AlgorithmHelper.java | 11 +- .../inf/isochrone/network/ComparisonTest.java | 25 +- 16 files changed, 310 insertions(+), 204 deletions(-) diff --git a/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java b/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java index 7825d9f4..9b9f43e1 100644 --- a/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java +++ b/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java @@ -30,8 +30,7 @@ public abstract class Isochrone { private final Query query; private final PriorityQueue<Node> queue; private Set<Integer> codes; - - protected Database<ConfigDataset> db; + protected Database database; // Constructors @@ -39,17 +38,33 @@ public abstract class Isochrone { * Instantiates a new isochrone object. * * @param config the configuration of the dataset for the isochrone + * @param db the databse object used for db communication * @param query the parameters for the isochrone * @throws AlgorithmException thrown if there are no date codes in the database for the specified query */ - public Isochrone(final ConfigDataset config, final Query query) throws AlgorithmException { + public Isochrone(final ConfigDataset config, final Database db, final Query query) throws AlgorithmException { + this.database = db; this.query = query; this.queue = new PriorityQueue<Node>(); - this.db = new Database<>(config, query.getMode(), query.getDir()); + + if (database == null) { + database = new Database(config, query.getMode(), query.getDir()); + } initDateCodes(); } + /** + * Instantiates a new isochrone object. + * + * @param config the configuration of the dataset for the isochrone + * @param query the parameters for the isochrone + * @throws AlgorithmException thrown if there are no date codes in the database for the specified query + */ + public Isochrone(final ConfigDataset config, final Query query) throws AlgorithmException { + this(config, null, query); + } + // Public abstract methods /** @@ -77,6 +92,15 @@ public abstract class Isochrone { // Public methods + /** + * Closes all the resources needed by the isochrone class (like database connections). + */ + public void close() { + if (database != null) { + database.close(); + } + } + /** * Computes the isochrone. * @@ -223,7 +247,7 @@ public abstract class Isochrone { */ public double getAdjNodeCost(final Node node, final Node adjNode, final Set<Short> routeIds, final Set<Integer> dateCodes, final long fromTime, final long toTime) { - return db.getAdjNodeCost(node, adjNode, routeIds, dateCodes, fromTime, toTime); + return database.getAdjNodeCost(node, adjNode, routeIds, dateCodes, fromTime, toTime); } /** @@ -233,7 +257,7 @@ public abstract class Isochrone { * @return returns a set of date codes */ public Set<Integer> getDateCodes(final Calendar time) { - return db.getDateCodes(time); + return database.getDateCodes(time); } // Protected abstract methods diff --git a/src/main/java/it/unibz/inf/isochrone/algorithm/MDijkstra.java b/src/main/java/it/unibz/inf/isochrone/algorithm/MDijkstra.java index 03022765..ab34aa76 100644 --- a/src/main/java/it/unibz/inf/isochrone/algorithm/MDijkstra.java +++ b/src/main/java/it/unibz/inf/isochrone/algorithm/MDijkstra.java @@ -1,6 +1,7 @@ package it.unibz.inf.isochrone.algorithm; import it.unibz.inf.isochrone.config.ConfigDataset; +import it.unibz.inf.isochrone.db.Database; import it.unibz.inf.isochrone.network.Link; import it.unibz.inf.isochrone.network.Node; import it.unibz.inf.isochrone.util.Query; @@ -23,12 +24,16 @@ public class MDijkstra extends Isochrone { // Constructors public MDijkstra(final ConfigDataset config, final Query query) throws AlgorithmException { - super(config, query); + this(config, null, query); + } + + public MDijkstra(final ConfigDataset config, final Database db, final Query query) throws AlgorithmException { + super(config, db, query); links = new LinkedHashMap<Integer, Link>(); nodes = new HashMap<Integer, Node>(); - db.readNetwork(nodes, links); + database.readNetwork(nodes, links); } // Public methods diff --git a/src/main/java/it/unibz/inf/isochrone/algorithm/MineX.java b/src/main/java/it/unibz/inf/isochrone/algorithm/MineX.java index 03db5dd6..d10500c3 100644 --- a/src/main/java/it/unibz/inf/isochrone/algorithm/MineX.java +++ b/src/main/java/it/unibz/inf/isochrone/algorithm/MineX.java @@ -1,6 +1,7 @@ package it.unibz.inf.isochrone.algorithm; import it.unibz.inf.isochrone.config.ConfigDataset; +import it.unibz.inf.isochrone.db.Database; import it.unibz.inf.isochrone.network.Link; import it.unibz.inf.isochrone.network.Node; import it.unibz.inf.isochrone.util.Query; @@ -19,7 +20,11 @@ public class MineX extends Isochrone { // Constructors public MineX(final ConfigDataset config, final Query query) throws AlgorithmException { - super(config, query); + this(config, null, query); + } + + public MineX(final ConfigDataset config, final Database db, final Query query) throws AlgorithmException { + super(config, db, query); nodes = new HashMap<Integer, Node>(); } @@ -27,7 +32,7 @@ public class MineX extends Isochrone { @Override public Link getLink(final int linkId) { - final Link link = db.getLink(linkId, nodes); + final Link link = database.getLink(linkId, nodes); if (link == null) { throw new RuntimeException("LinkId not present: " + linkId); } @@ -39,7 +44,7 @@ public class MineX extends Isochrone { public Node getNode(final int nodeId) { Node node = nodes.get(nodeId); if (node == null) { - node = db.getNode(nodeId); + node = database.getNode(nodeId); if (node == null) { throw new RuntimeException("NodeId not present: " + nodeId); } @@ -59,7 +64,7 @@ public class MineX extends Isochrone { @Override protected Collection<Link> calcAdjLinks(final int nodeId) { - return db.getAdjLinks(nodeId, nodes); + return database.getAdjLinks(nodeId, nodes); } @Override diff --git a/src/main/java/it/unibz/inf/isochrone/algorithm/MrneX.java b/src/main/java/it/unibz/inf/isochrone/algorithm/MrneX.java index 6430a471..15c28b01 100644 --- a/src/main/java/it/unibz/inf/isochrone/algorithm/MrneX.java +++ b/src/main/java/it/unibz/inf/isochrone/algorithm/MrneX.java @@ -1,6 +1,7 @@ package it.unibz.inf.isochrone.algorithm; import it.unibz.inf.isochrone.config.ConfigDataset; +import it.unibz.inf.isochrone.db.Database; import it.unibz.inf.isochrone.network.Link; import it.unibz.inf.isochrone.network.Node; import it.unibz.inf.isochrone.util.DistanceAlgorithm; @@ -28,11 +29,15 @@ public class MrneX extends Isochrone { // Constructors public MrneX(final ConfigDataset config, final Query query) throws AlgorithmException { - this(config, query, Integer.MAX_VALUE); + this(config, null, query, Integer.MAX_VALUE); } - public MrneX(final ConfigDataset config, final Query query, final int maxMemorySize) throws AlgorithmException { - super(config, query); + public MrneX(final ConfigDataset config, final Database db, final Query query) throws AlgorithmException { + this(config, db, query, Integer.MAX_VALUE); + } + + public MrneX(final ConfigDataset config, final Database db, final Query query, final int maxMemorySize) throws AlgorithmException { + super(config, db, query); adjList = new HashMap<Integer, List<Link>>(); loadedIERNodes = new HashMap<Integer, Node>(); @@ -46,7 +51,7 @@ public class MrneX extends Isochrone { @Override public Link getLink(final int linkId) { - final Link link = db.getLink(linkId, nodes); + final Link link = database.getLink(linkId, nodes); if (link == null) { throw new RuntimeException("LinkId not present: " + linkId); } @@ -58,7 +63,7 @@ public class MrneX extends Isochrone { public Node getNode(final int nodeId) { Node node = nodes.get(nodeId); if (node == null) { - node = db.getNode(nodeId); + node = database.getNode(nodeId); if (node == null) { throw new RuntimeException("NodeId not present: " + nodeId); } @@ -108,7 +113,7 @@ public class MrneX extends Isochrone { } if (node.getCoordinates() == null) { - node.setCoordinates(db.getCoordinates(nodeId)); + node.setCoordinates(database.getCoordinates(nodeId)); } if (unlimitedMemory()) { @@ -118,7 +123,7 @@ public class MrneX extends Isochrone { final int reservedMemorySize = calcAvailableMemorySize(loadedIERNodes.isEmpty() ? 0.5f : 1f); // CHECKSTYLE:ON MagicNumber - final double eDist = db.getRange(nodeId, reservedMemorySize); + final double eDist = database.getRange(nodeId, reservedMemorySize); node.setRadius(Math.min(calcRemainingDistance(node), eDist)); } @@ -200,7 +205,7 @@ public class MrneX extends Isochrone { * circle that should be loaded. */ private void loadLinksFromIER(final Node node, final Collection<Node> intersections) { - db.loadLinksFromIER(node, intersections, nodes, adjList); + database.loadLinksFromIER(node, intersections, nodes, adjList); } } diff --git a/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java b/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java index e5c140fc..eec36d95 100644 --- a/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java +++ b/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java @@ -471,8 +471,8 @@ public class ConfigDataset { private static Collection<String> filterInvalidDatasets(final Collection<String> datasets) { LOGGER.info("Filtering invalid datasets (e.g. which have no database tables)"); - final Collection<String> filteredList = new ArrayList<String>(datasets.size()); final ConfigIsochrone config = ConfigIsochrone.getInstance(); + final Collection<String> filteredList = new ArrayList<String>(datasets.size()); final Collection<String> allTables = config.getAllTables(); for (final String ds : datasets) { final ConfigDataset c = ConfigDataset.createInstance(ds); diff --git a/src/main/java/it/unibz/inf/isochrone/config/ConfigIsochrone.java b/src/main/java/it/unibz/inf/isochrone/config/ConfigIsochrone.java index f8649290..4ce45731 100644 --- a/src/main/java/it/unibz/inf/isochrone/config/ConfigIsochrone.java +++ b/src/main/java/it/unibz/inf/isochrone/config/ConfigIsochrone.java @@ -109,6 +109,8 @@ public final class ConfigIsochrone { public Connection getConnection() { try { return factory.getConnection(); + } catch (final NullPointerException e) { + e.printStackTrace(); } catch (final SQLException e) { e.printStackTrace(); } @@ -180,13 +182,18 @@ public final class ConfigIsochrone { } public Collection<String> getAllTables() { + final Connection connection = getConnection(); + if (connection == null) { + throw new NullPointerException("Connection to database could not be initialized"); + } + final Collection<String> result = new ArrayList<>(); final String query = "SELECT tablename FROM pg_tables WHERE schemaname='public'"; ResultSet rs = null; CallableStatement stmt = null; try { - stmt = getConnection().prepareCall(query); + stmt = connection.prepareCall(query); rs = stmt.executeQuery(); while (rs.next()) { result.add(rs.getString("tablename")); @@ -196,6 +203,7 @@ public final class ConfigIsochrone { } finally { DbUtils.closeQuietly(rs); DbUtils.closeQuietly(stmt); + DbUtils.closeQuietly(connection); } return result; diff --git a/src/main/java/it/unibz/inf/isochrone/db/ConnectionFactory.java b/src/main/java/it/unibz/inf/isochrone/db/ConnectionFactory.java index 8563c9dc..34251dce 100644 --- a/src/main/java/it/unibz/inf/isochrone/db/ConnectionFactory.java +++ b/src/main/java/it/unibz/inf/isochrone/db/ConnectionFactory.java @@ -16,10 +16,13 @@ import java.sql.SQLException; */ public class ConnectionFactory { private static final int MIN_CONNECTIONS = 5; - private Connection connection; - private BoneCP connectionPool; private final int maxConnections; private final boolean pooling; + private Connection connection; + private BoneCP connectionPool; + private String jdbcUrl; + private String username; + private String password; // Constructor @@ -46,7 +49,9 @@ public class ConnectionFactory { * @throws ClassNotFoundException thrown if the driver used for the database connection could not be found/loaded */ public void register(final String serverName, final String database, final int port, final String user, final String passwd) throws SQLException, ClassNotFoundException { - final String url = "jdbc:postgresql://" + serverName + ":" + port + "/" + database + "?binaryTransfer=true"; + this.jdbcUrl = "jdbc:postgresql://" + serverName + ":" + port + "/" + database + "?binaryTransfer=true"; + password = passwd; + username = user; // load the database driver Class.forName("org.postgresql.Driver"); @@ -56,14 +61,11 @@ public class ConnectionFactory { config.setDefaultAutoCommit(false); config.setUser(user); config.setPassword(passwd); - config.setJdbcUrl(url); + config.setJdbcUrl(jdbcUrl); config.setMinConnectionsPerPartition(Math.min(MIN_CONNECTIONS, maxConnections)); config.setMaxConnectionsPerPartition(maxConnections); config.setPartitionCount(1); connectionPool = new BoneCP(config); - } else { - connection = DriverManager.getConnection(url, user, passwd); - connection.setAutoCommit(false); } } @@ -75,9 +77,34 @@ public class ConnectionFactory { */ public Connection getConnection() throws SQLException { if (pooling) { - return connectionPool.getConnection(); + if (connectionPool == null) { + throw new NullPointerException("ConnectionFactory has not registered any connectionPool configurations"); + } + + return createConnection(); + } + + if (username == null || password == null) { + throw new NullPointerException("ConnectionFactory has not registered any connection configurations"); + } + + if (connection == null || connection.isClosed()) { + connection = createConnection(); } return connection; } + + // Private methods + + private Connection createConnection() throws SQLException { + if (pooling) { + return connectionPool.getConnection(); + } + + final Connection c = DriverManager.getConnection(jdbcUrl, username, password); + c.setAutoCommit(false); + + return c; + } } diff --git a/src/main/java/it/unibz/inf/isochrone/db/Database.java b/src/main/java/it/unibz/inf/isochrone/db/Database.java index ba92d986..006f0e1a 100644 --- a/src/main/java/it/unibz/inf/isochrone/db/Database.java +++ b/src/main/java/it/unibz/inf/isochrone/db/Database.java @@ -40,7 +40,7 @@ import org.apache.commons.dbutils.DbUtils; * @author Markus Innerebner * @version 2.2 */ -public class Database<T extends ConfigDataset> { +public class Database { protected static final byte NW_MODE_CONTINUOUS = 0; protected static final byte NW_MODE_DISCRETE = 1; @@ -60,14 +60,14 @@ public class Database<T extends ConfigDataset> { private final String queryGetLinksInRange; private final String queryGetRange; private final String queryLoadLinksFromIER; - protected final T config; + protected final ConfigDataset config; protected Mode mode; protected boolean isIncoming; protected Connection connection; // Constructor - public Database(final T config, final Mode mode, final Direction direction) { + public Database(final ConfigDataset config, final Mode mode, final Direction direction) { this.config = config; this.isIncoming = (direction == Direction.INCOMING); this.mode = mode; @@ -188,6 +188,8 @@ public class Database<T extends ConfigDataset> { for (final PreparedStatement pstmt : pstmtsCacheMap.values()) { DbUtils.closeQuietly(pstmt); } + + DbUtils.closeQuietly(connection); } /** @@ -616,8 +618,8 @@ public class Database<T extends ConfigDataset> { */ @Override protected void finalize() throws Throwable { - super.finalize(); close(); + super.finalize(); } // Protected methods diff --git a/src/main/java/it/unibz/inf/isochrone/util/Query.java b/src/main/java/it/unibz/inf/isochrone/util/Query.java index b35773ba..fad01ece 100644 --- a/src/main/java/it/unibz/inf/isochrone/util/Query.java +++ b/src/main/java/it/unibz/inf/isochrone/util/Query.java @@ -28,7 +28,7 @@ public class Query { private Long fromTime; private Boolean expireNodes; - // Constructor + // Constructors /** * Construct a query object with every field except the nodes and @@ -47,7 +47,7 @@ public class Query { setTime(time); } - // Public methods + // Getters public Direction getDir() { return dir; @@ -89,6 +89,8 @@ public class Query { return expireNodes; } + // Setters + public void setDuration(final Long duration) { this.duration = duration; } diff --git a/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java b/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java index 2512fd44..8457d483 100644 --- a/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java +++ b/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java @@ -41,7 +41,7 @@ import org.postgis.PGgeometry; * interface. (Mostly inserting vertices and links into the tables * used for the GeoServer) */ -public class DatabaseWeb extends Database<ConfigClient> { +public class DatabaseWeb extends Database { private final String queryGetIsoEdges; private final String queryStoreLinks; private final String queryStorePartialLinks; diff --git a/src/main/java/it/unibz/inf/isoga/db/DbUtility.java b/src/main/java/it/unibz/inf/isoga/db/DbUtility.java index 35f38a70..e7de60cc 100644 --- a/src/main/java/it/unibz/inf/isoga/db/DbUtility.java +++ b/src/main/java/it/unibz/inf/isoga/db/DbUtility.java @@ -42,49 +42,57 @@ public final class DbUtility { // Public static methods - public static void dropTable(final Connection connection, final String tableName, final boolean cascade) { + public static void createBufferTable(final Connection connection, final String tableName) { if (tableName == null || tableName.length() <= 0) { return; } - executeStatement(connection, "DROP TABLE IF EXISTS " + tableName + (cascade ? " CASCADE" : "")); + executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, CONSTRAINT pkey_" + tableName + " PRIMARY KEY (\"ID\"))"); } - public static void truncateTable(final Connection connection, final String tableName) { + public static void createEdgeTable(final Connection connection, final String tableName) { if (tableName == null || tableName.length() <= 0) { return; } - executeStatement(connection, "DELETE FROM " + tableName); + executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"SOURCE\" integer, \"TARGET\" integer, \"OFFSET\" double precision, \"LENGTH\" double precision)"); } - public static void dropIndex(final Connection connection, final String indexName) { + public static void createSpatialIndex(final Connection connection, final TableEntry tableEntry) { + final String indexName = tableEntry.getIndexName(); if (indexName == null || indexName.length() <= 0) { return; } - executeStatement(connection, "DROP INDEX IF EXISTS " + indexName); + final String tableName = tableEntry.getTableName(); + if (tableName == null || tableName.length() <= 0) { + return; + } + + executeStatement(connection, "CREATE INDEX " + indexName + " ON " + tableName + " USING GIST(\"GEOMETRY\")"); } - public static void createTargetEdgeTable(final Connection connection, final String tableName) { + public static void createVertexAnnotationTable(final Connection connection, final String tableName) { if (tableName == null || tableName.length() <= 0) { return; } - executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"SOURCE\" integer, \"TARGET\" integer, \"OFFSET\" double precision, \"LENGTH\" double precision)"); + executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"ROUTE_ID\" smallint,\"TIME_A\" integer,\"TIME_D\" integer)"); } - public static void insertGeometryMetadata(final Connection connection, final TableEntry tableEntry, final int serverSrid) { + public static void createVertexTable(final Connection connection, final String tableName) { + if (tableName == null || tableName.length() <= 0) { + return; + } + + executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"DISTANCE\" double precision, \"ROUTE_ID\" smallint, \"STATE\" VARCHAR(7), \"T_TYPE\" smallint)"); + } + + public static void deleteGeometryMetadata(final Connection connection, final String tableName) { CallableStatement prepareCall = null; try { - prepareCall = connection.prepareCall("{call addgeometrycolumn(?,?,?,?,?,true)}"); - // CHECKSTYLE:OFF MagicNumber - prepareCall.setString(1, tableEntry.getTableName()); - prepareCall.setString(2, "GEOMETRY"); - prepareCall.setInt(3, serverSrid); - prepareCall.setString(4, tableEntry.getGeometryType()); - prepareCall.setInt(5, 2); - // CHECKSTYLE:ON MagicNumber + prepareCall = connection.prepareCall("{call DropGeometryTable(?)}"); + prepareCall.setString(1, tableName); prepareCall.executeUpdate(); connection.commit(); } catch (final SQLException e) { @@ -99,18 +107,20 @@ public final class DbUtility { } } - public static void createSpatialIndex(final Connection connection, final TableEntry tableEntry) { - final String indexName = tableEntry.getIndexName(); + public static void dropIndex(final Connection connection, final String indexName) { if (indexName == null || indexName.length() <= 0) { return; } - final String tableName = tableEntry.getTableName(); + executeStatement(connection, "DROP INDEX IF EXISTS " + indexName); + } + + public static void dropTable(final Connection connection, final String tableName, final boolean cascade) { if (tableName == null || tableName.length() <= 0) { return; } - executeStatement(connection, "CREATE INDEX " + indexName + " ON " + tableName + " USING GIST(\"GEOMETRY\")"); + executeStatement(connection, "DROP TABLE IF EXISTS " + tableName + (cascade ? " CASCADE" : "")); } public static boolean dropTablesByRegexp(final Connection connection, final String regex) { @@ -134,13 +144,25 @@ public final class DbUtility { return false; } - public static void deleteGeometryMetadata(final Connection connection, final String tableName) { - CallableStatement prepareCall = null; + public static ResponsePoiFeature getPoiFeatures(final String sqlExpr, final ConfigDataset config) { + final ResponsePoiFeature result = new ResponsePoiFeature(); + if ("noResult".equals(sqlExpr)) { + result.setType("invalid"); + return result; + } + + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + + Statement stmt = null; + ResultSet rSet = null; try { - prepareCall = connection.prepareCall("{call DropGeometryTable(?)}"); - prepareCall.setString(1, tableName); - prepareCall.executeUpdate(); - connection.commit(); + stmt = connection.createStatement(); + rSet = stmt.executeQuery(sqlExpr); + + while (rSet.next()) { + result.addFeature(new PoiFeature(rSet.getString("category"), rSet.getString("GEOMETRY"))); + } + result.setType("FeatureCollection"); } catch (final SQLException e) { e.printStackTrace(); try { @@ -149,53 +171,30 @@ public final class DbUtility { e1.printStackTrace(); } } finally { - DbUtils.closeQuietly(prepareCall); - } - } - - public static void createVertexAnnotationTable(final Connection connection, final String tableName) { - if (tableName == null || tableName.length() <= 0) { - return; - } - - executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"ROUTE_ID\" smallint,\"TIME_A\" integer,\"TIME_D\" integer)"); - } - - public static void createTargetVertexTable(final Connection connection, final String tableName) { - if (tableName == null || tableName.length() <= 0) { - return; - } - - executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, \"DISTANCE\" double precision, \"ROUTE_ID\" smallint, \"STATE\" VARCHAR(7), \"T_TYPE\" smallint)"); - } - - public static void createTargetBufferTable(final Connection connection, final String tableName) { - if (tableName == null || tableName.length() <= 0) { - return; + DbUtils.closeQuietly(rSet); + DbUtils.closeQuietly(stmt); } - executeStatement(connection, "CREATE TABLE " + tableName + " (\"ID\" integer NOT NULL, CONSTRAINT pkey_" + tableName + " PRIMARY KEY (\"ID\"))"); + return result; } - public static ResponsePoiFeature getPoiFeatures(final String sqlExpr, final ConfigDataset config) { - final ResponsePoiFeature result = new ResponsePoiFeature(); - if ("noResult".equals(sqlExpr)) { - result.setType("invalid"); - return result; - } - + public static WpsStatistic getStatistics(final String sqlExpr, final boolean withSum, final ConfigDataset config) { final Connection connection = ConfigIsochrone.getInstance().getConnection(); + int sum = 0; + int count = 0; Statement stmt = null; ResultSet rSet = null; try { stmt = connection.createStatement(); rSet = stmt.executeQuery(sqlExpr); - while (rSet.next()) { - result.addFeature(new PoiFeature(rSet.getString("category"), rSet.getString("GEOMETRY"))); + if (rSet.next()) { + if (withSum) { + sum = rSet.getInt("sum"); + } + count = rSet.getInt("count"); } - result.setType("FeatureCollection"); } catch (final SQLException e) { e.printStackTrace(); try { @@ -208,7 +207,88 @@ public final class DbUtility { DbUtils.closeQuietly(stmt); } - return result; + return new WpsStatistic(count, sum); + } + + public static SortedMap<Calendar, RouteEntity> getVertexAnnotation(final ConfigClient config, final int vertexId, final Direction direction) { + final Comparator<Object> comp = (direction == Direction.INCOMING) ? Collections.reverseOrder() : null; + final SortedMap<Calendar, RouteEntity> schedules = new TreeMap<Calendar, RouteEntity>(comp); + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + + final String arrivalTimeStr = "to_char(to_timestamp(CAST(\"TIME_A\" AS text),'SSSSS'),'HH24:MI') \"ARRIVAL_TIME\""; + final String departureTimeStr = "to_char(to_timestamp(CAST(\"TIME_D\" AS text),'SSSSS'),'HH24:MI') \"DEPARTURE_TIME\""; + final String query = "SELECT R.ROUTE_ID, " + + arrivalTimeStr + ", " + + departureTimeStr + ", " + + "R.ROUTE_SHORT_NAME \"ROUTE_SHORT_NAME\", R.ROUTE_TYPE \"ROUTE_TYPE\" " + + "FROM ? V, ? R WHERE V.\"ID\"=? AND V.\"ROUTE_ID\"=R.ROUTE_ID"; + + PreparedStatement statement = null; + ResultSet resultSet = null; + try { + statement = connection.prepareStatement(query); + // CHECKSTYLE:OFF MagicNumber + statement.setString(1, config.getVertexAnnotatedTableEntry().getTableName()); + statement.setString(2, config.getTableRoutes()); + statement.setInt(3, vertexId); + // CHECKSTYLE:ON MagicNumber + + resultSet = statement.executeQuery(); + while (resultSet.next()) { + final int routeId = resultSet.getInt("ROUTE_ID"); + final String tArr = resultSet.getString("ARRIVAL_TIME"); + final String tDep = resultSet.getString("DEPARTURE_TIME"); + String time; + if (direction == Direction.INCOMING) { + time = tDep; + if (time.equals("00:00")) { + time = tArr; + } + } else { + time = tArr; + if (time.equals("00:00")) { + time = tDep; + } + } + + final String routeName = resultSet.getString("ROUTE_SHORT_NAME"); + final short routeType = resultSet.getShort("ROUTE_TYPE"); + final RouteEntity routeEntity = new RouteEntity(routeId, routeName, routeType, time); + schedules.put(routeEntity.getTime(), routeEntity); + } + } catch (final SQLException e) { + e.printStackTrace(); + } finally { + DbUtils.closeQuietly(resultSet); + DbUtils.closeQuietly(statement); + } + + return schedules; + } + + public static void insertGeometryMetadata(final Connection connection, final TableEntry tableEntry, final int serverSrid) { + CallableStatement prepareCall = null; + try { + prepareCall = connection.prepareCall("{call addgeometrycolumn(?,?,?,?,?,true)}"); + // CHECKSTYLE:OFF MagicNumber + prepareCall.setString(1, tableEntry.getTableName()); + prepareCall.setString(2, "GEOMETRY"); + prepareCall.setInt(3, serverSrid); + prepareCall.setString(4, tableEntry.getGeometryType()); + prepareCall.setInt(5, 2); + // CHECKSTYLE:ON MagicNumber + prepareCall.executeUpdate(); + connection.commit(); + } catch (final SQLException e) { + e.printStackTrace(); + try { + connection.rollback(); + } catch (final SQLException e1) { + e1.printStackTrace(); + } + } finally { + DbUtils.closeQuietly(prepareCall); + } } public static ResponseWps spatialIntersection2JSON(final String sqlExpr, final SqlQuery query, final ConfigDataset config) { @@ -299,92 +379,12 @@ public final class DbUtility { return result; } - public static WpsStatistic getStatistics(final String sqlExpr, final boolean withSum, final ConfigDataset config) { - final Connection connection = ConfigIsochrone.getInstance().getConnection(); - - int sum = 0; - int count = 0; - Statement stmt = null; - ResultSet rSet = null; - try { - stmt = connection.createStatement(); - rSet = stmt.executeQuery(sqlExpr); - - if (rSet.next()) { - if (withSum) { - sum = rSet.getInt("sum"); - } - count = rSet.getInt("count"); - } - } catch (final SQLException e) { - e.printStackTrace(); - try { - connection.rollback(); - } catch (final SQLException e1) { - e1.printStackTrace(); - } - } finally { - DbUtils.closeQuietly(rSet); - DbUtils.closeQuietly(stmt); - } - - return new WpsStatistic(count, sum); - } - - public static SortedMap<Calendar, RouteEntity> getVertexAnnotation(final ConfigClient config, final int vertexId, final Direction direction) { - final Comparator<Object> comp = (direction == Direction.INCOMING) ? Collections.reverseOrder() : null; - final SortedMap<Calendar, RouteEntity> schedules = new TreeMap<Calendar, RouteEntity>(comp); - final Connection connection = ConfigIsochrone.getInstance().getConnection(); - - final String arrivalTimeStr = "to_char(to_timestamp(CAST(\"TIME_A\" AS text),'SSSSS'),'HH24:MI') \"ARRIVAL_TIME\""; - final String departureTimeStr = "to_char(to_timestamp(CAST(\"TIME_D\" AS text),'SSSSS'),'HH24:MI') \"DEPARTURE_TIME\""; - final String query = "SELECT R.ROUTE_ID, " - + arrivalTimeStr + ", " - + departureTimeStr + ", " - + "R.ROUTE_SHORT_NAME \"ROUTE_SHORT_NAME\", R.ROUTE_TYPE \"ROUTE_TYPE\" " - + "FROM ? V, ? R WHERE V.\"ID\"=? AND V.\"ROUTE_ID\"=R.ROUTE_ID"; - - PreparedStatement statement = null; - ResultSet resultSet = null; - try { - statement = connection.prepareStatement(query); - // CHECKSTYLE:OFF MagicNumber - statement.setString(1, config.getVertexAnnotatedTableEntry().getTableName()); - statement.setString(2, config.getTableRoutes()); - statement.setInt(3, vertexId); - // CHECKSTYLE:ON MagicNumber - - resultSet = statement.executeQuery(); - while (resultSet.next()) { - final int routeId = resultSet.getInt("ROUTE_ID"); - final String tArr = resultSet.getString("ARRIVAL_TIME"); - final String tDep = resultSet.getString("DEPARTURE_TIME"); - String time; - if (direction == Direction.INCOMING) { - time = tDep; - if (time.equals("00:00")) { - time = tArr; - } - } else { - time = tArr; - if (time.equals("00:00")) { - time = tDep; - } - } - - final String routeName = resultSet.getString("ROUTE_SHORT_NAME"); - final short routeType = resultSet.getShort("ROUTE_TYPE"); - final RouteEntity routeEntity = new RouteEntity(routeId, routeName, routeType, time); - schedules.put(routeEntity.getTime(), routeEntity); - } - } catch (final SQLException e) { - e.printStackTrace(); - } finally { - DbUtils.closeQuietly(resultSet); - DbUtils.closeQuietly(statement); + public static void truncateTable(final Connection connection, final String tableName) { + if (tableName == null || tableName.length() <= 0) { + return; } - return schedules; + executeStatement(connection, "DELETE FROM " + tableName); } // Private static methods diff --git a/src/main/java/it/unibz/inf/isoga/service/AbstractService.java b/src/main/java/it/unibz/inf/isoga/service/AbstractService.java index ee5bfa4b..49fb4293 100644 --- a/src/main/java/it/unibz/inf/isoga/service/AbstractService.java +++ b/src/main/java/it/unibz/inf/isoga/service/AbstractService.java @@ -67,7 +67,7 @@ public abstract class AbstractService<T extends IRequest, U extends IResponse> i // register edge table and layer final TableEntry edgeTableEntry = configClient.getEdgeTableEntry(); DbUtility.deleteGeometryMetadata(connection, edgeTableEntry.getTableName()); - DbUtility.createTargetEdgeTable(connection, edgeTableEntry.getTableName()); + DbUtility.createEdgeTable(connection, edgeTableEntry.getTableName()); DbUtility.insertGeometryMetadata(connection, edgeTableEntry, serverSrid); DbUtility.createSpatialIndex(connection, edgeTableEntry); createdEntries.add(edgeTableEntry); @@ -92,7 +92,7 @@ public abstract class AbstractService<T extends IRequest, U extends IResponse> i // register vertex table and layer final TableEntry vertexTableEntry = configClient.getVertexTableEntry(); DbUtility.deleteGeometryMetadata(connection, vertexTableEntry.getTableName()); - DbUtility.createTargetVertexTable(connection, vertexTableEntry.getTableName()); + DbUtility.createVertexTable(connection, vertexTableEntry.getTableName()); DbUtility.insertGeometryMetadata(connection, vertexTableEntry, serverSrid); DbUtility.createSpatialIndex(connection, vertexTableEntry); createdEntries.add(vertexTableEntry); @@ -111,7 +111,7 @@ public abstract class AbstractService<T extends IRequest, U extends IResponse> i // register area buffer table and layer final TableEntry areaBufferTableEntry = configClient.getAreaBufferTableEntry(); DbUtility.deleteGeometryMetadata(connection, areaBufferTableEntry.getTableName()); - DbUtility.createTargetBufferTable(connection, areaBufferTableEntry.getTableName()); + DbUtility.createBufferTable(connection, areaBufferTableEntry.getTableName()); DbUtility.insertGeometryMetadata(connection, areaBufferTableEntry, serverSrid); DbUtility.createSpatialIndex(connection, areaBufferTableEntry); createdEntries.add(areaBufferTableEntry); diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java b/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java index 0de84182..299fcc35 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java @@ -68,7 +68,7 @@ public class ServiceIsochrone extends AbstractService<RequestIsochrone, Response truncateTables(config); final Query query = new Query(direction, request.getSpeed(), request.getDmax(), request.getDate(), true, request.getMode()); query.setStartLocations(locationsFromQueryNodes(request.getQueryNodes(), db)); - final Isochrone isochrone = getAlgorithm(request.getAlgorithm(), config, query); + final Isochrone isochrone = getAlgorithm(request.getAlgorithm(), config, db, query); final BBoxOutput output = isochrone.compute(new BBoxOutput(config, db, direction)); final long timeIsochrone = System.currentTimeMillis() - startComputationTiming; @@ -84,6 +84,8 @@ public class ServiceIsochrone extends AbstractService<RequestIsochrone, Response } } + db.close(); + final ResponseIsochrone response = new ResponseIsochrone(); response.setBoundingBox(output.getBoundingBox()); @@ -99,17 +101,17 @@ public class ServiceIsochrone extends AbstractService<RequestIsochrone, Response // Private methods - public Isochrone getAlgorithm(final Algorithm algorithm, final ConfigDataset config, final Query query) throws AlgorithmException { + public Isochrone getAlgorithm(final Algorithm algorithm, final ConfigDataset config, final DatabaseWeb db, final Query query) throws AlgorithmException { final Isochrone result; switch (algorithm) { case MINEX: - result = new MineX(config, query); + result = new MineX(config, db, query); break; case MRNEX: - result = new MrneX(config, query); + result = new MrneX(config, db, query); break; default: - result = new MDijkstra(config, query); + result = new MDijkstra(config, db, query); } return result; diff --git a/src/test/java/it/unibz/inf/isochrone/db/DatabaseTest.java b/src/test/java/it/unibz/inf/isochrone/db/DatabaseTest.java index 971b77f7..ee08f8c0 100644 --- a/src/test/java/it/unibz/inf/isochrone/db/DatabaseTest.java +++ b/src/test/java/it/unibz/inf/isochrone/db/DatabaseTest.java @@ -44,8 +44,9 @@ public class DatabaseTest { @Test public void testCreateDatabaseObject() { final ConfigDataset config = ConfigDataset.getInstance(TEST_DATASET); - final Database<ConfigDataset> db = new Database<>(config, Mode.MULTIMODAL, Direction.INCOMING); + final Database db = new Database(config, Mode.MULTIMODAL, Direction.INCOMING); Assert.assertNotNull(db, "Database object could not be created!"); + db.close(); } @Test @@ -54,28 +55,31 @@ public class DatabaseTest { final Map<Integer, Link> compareLinks = new LinkedHashMap<Integer, Link>(); fillHashMaps(compareNodes, compareLinks); - initDb(); - + final Database db = initDb(); Assert.assertEquals(nodes.get(NODE_ID), compareNodes.get(NODE_ID), "Nodes comparison"); Assert.assertEquals(links.get(LINK_ID), compareLinks.get(LINK_ID), "Links comparison"); + + db.close(); } @Test public void testCountEdges() { - initDb(); + final Database db = initDb(); // 2687 Doesn't correspond to the number of nodes in // the nodes table, but the number of distinct // target/source node in the edges table Assert.assertEquals(nodes.size(), EXPECTED_NODE_COUNT, "Node count was unexpected"); Assert.assertEquals(links.size(), EXPECTED_LINK_COUNT, "Link count was unexpected"); + + db.close(); } // Private methods - private Database<ConfigDataset> initDb() { + private Database initDb() { final ConfigDataset config = ConfigDataset.getInstance(TEST_DATASET); - final Database<ConfigDataset> db = new Database<>(config, Mode.MULTIMODAL, Direction.INCOMING); + final Database db = new Database(config, Mode.MULTIMODAL, Direction.INCOMING); db.readNetwork(nodes, links); return db; diff --git a/src/test/java/it/unibz/inf/isochrone/network/AlgorithmHelper.java b/src/test/java/it/unibz/inf/isochrone/network/AlgorithmHelper.java index 6a597d15..73adea3b 100644 --- a/src/test/java/it/unibz/inf/isochrone/network/AlgorithmHelper.java +++ b/src/test/java/it/unibz/inf/isochrone/network/AlgorithmHelper.java @@ -16,11 +16,11 @@ final class AlgorithmHelper { // Public static methods - public static void run(final Class<? extends Isochrone> algorithmClass, final TestParameters params) { - run(algorithmClass, params, true); + public static MemoryOutput run(final Class<? extends Isochrone> algorithmClass, final TestParameters params) { + return run(algorithmClass, params, true); } - public static void run(final Class<? extends Isochrone> algorithmClass, final TestParameters params, final boolean expireNodes) { + public static MemoryOutput run(final Class<? extends Isochrone> algorithmClass, final TestParameters params, final boolean expireNodes) { ConfigDataset c = ConfigDataset.getInstance(params.getDataset()); Query query = new Query(params.getDirection(), params.getWalkingSpeed(), params.getRuntime(), params.getDate(), expireNodes, params.getMode()); query.setStartNodeIds(params.getStartNodeId()); @@ -32,7 +32,10 @@ final class AlgorithmHelper { Assert.fail(e.getMessage()); } - algorithm.compute(); + final MemoryOutput o = algorithm.compute(); + algorithm.close(); + + return o; } diff --git a/src/test/java/it/unibz/inf/isochrone/network/ComparisonTest.java b/src/test/java/it/unibz/inf/isochrone/network/ComparisonTest.java index 215f47b5..9adf9d8c 100644 --- a/src/test/java/it/unibz/inf/isochrone/network/ComparisonTest.java +++ b/src/test/java/it/unibz/inf/isochrone/network/ComparisonTest.java @@ -12,6 +12,7 @@ import it.unibz.inf.isochrone.util.Query; import java.util.Calendar; import java.util.GregorianCalendar; +import java.util.Map; import org.testng.Assert; import org.testng.annotations.Test; @@ -35,7 +36,13 @@ public class ComparisonTest { queryMinex.setStartNodeIds(NODE_ID); final Isochrone mineX = new MineX(config, queryMinex); - Assert.assertEquals(mDijkstra.compute().getLinks(), mineX.compute().getLinks(), "Dijkstra != MineX"); + final Map<Integer, Link> linksDijkstra = mDijkstra.compute().getLinks(); + final Map<Integer, Link> linksMineX = mineX.compute().getLinks(); + + mDijkstra.close(); + mineX.close(); + + Assert.assertEquals(linksDijkstra, linksMineX, "Dijkstra != MineX"); } @Test @@ -50,7 +57,13 @@ public class ComparisonTest { queryMrneX.setStartNodeIds(NODE_ID); final Isochrone mrneX = new MrneX(config, queryMrneX); - Assert.assertEquals(mDijkstra.compute().getLinks(), mrneX.compute().getLinks(), "Dijkstra != MrneX"); + final Map<Integer, Link> linksDijkstra = mDijkstra.compute().getLinks(); + final Map<Integer, Link> linksMrneX = mrneX.compute().getLinks(); + + mDijkstra.close(); + mrneX.close(); + + Assert.assertEquals(linksDijkstra, linksMrneX, "Dijkstra != MrneX"); } @Test @@ -62,6 +75,12 @@ public class ComparisonTest { final Isochrone mineX = new MineX(config, query); final Isochrone mrneX = new MrneX(config, query); - Assert.assertEquals(mineX.compute().getLinks(), mrneX.compute().getLinks(), "MineX != MrneX"); + final Map<Integer, Link> linksMineX = mineX.compute().getLinks(); + final Map<Integer, Link> linksMrneX = mrneX.compute().getLinks(); + + mineX.close(); + mrneX.close(); + + Assert.assertEquals(linksMineX, linksMrneX, "MineX != MrneX"); } } -- GitLab