From 10a4aa4e6bcf3eddc1cfce7f104ec19f8f8c50f7 Mon Sep 17 00:00:00 2001 From: Nikolaus Krismer <niko@krismer.de> Date: Thu, 27 Mar 2014 15:29:19 +0100 Subject: [PATCH] reworked connection management (minimized open connections) --- .../it/unibz/inf/isochrone/db/Database.java | 23 +++++++++++-------- .../it/unibz/inf/isoga/db/DatabaseWeb.java | 15 +++++++----- .../java/it/unibz/inf/isoga/db/DbUtility.java | 17 ++++---------- .../unibz/inf/isoga/network/BBoxOutput.java | 6 ++--- .../isoga/service/ServiceConfiguration.java | 4 ++++ .../inf/isoga/service/ServiceFeatureInfo.java | 8 ++++++- .../inf/isoga/service/ServiceIsochrone.java | 13 ++++------- .../inf/isoga/service/ServicePoiFeature.java | 8 ++++++- .../unibz/inf/isoga/service/ServiceWps.java | 14 ++++++++--- .../it/unibz/inf/isoga/web/JsonWebsocket.java | 6 +++-- .../unibz/inf/isoga/web/StartupListener.java | 3 +++ 11 files changed, 72 insertions(+), 45 deletions(-) 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 006f0e1a..de4cd7c4 100644 --- a/src/main/java/it/unibz/inf/isochrone/db/Database.java +++ b/src/main/java/it/unibz/inf/isochrone/db/Database.java @@ -43,8 +43,6 @@ import org.apache.commons.dbutils.DbUtils; public class Database { protected static final byte NW_MODE_CONTINUOUS = 0; protected static final byte NW_MODE_DISCRETE = 1; - - private final Map<String, PreparedStatement> pstmtsCacheMap; private final String queryEarliestArrivalTimeHomo; private final String queryLatestDepartureTimeHomo; private final String queryGetAllEdges; @@ -63,8 +61,8 @@ public class Database { protected final ConfigDataset config; protected Mode mode; protected boolean isIncoming; - protected Connection connection; - + protected Connection connection; /** The connection the the database. It is lazy-loaded by {@link #getPstmt(String)} method. */ + private Map<String, PreparedStatement> pstmtsCacheMap; // Constructor public Database(final ConfigDataset config, final Mode mode, final Direction direction) { @@ -72,9 +70,6 @@ public class Database { this.isIncoming = (direction == Direction.INCOMING); this.mode = mode; - connection = ConfigIsochrone.getInstance().getConnection(); - pstmtsCacheMap = new HashMap<String, PreparedStatement>(); - final String configDatecodes = config.getTableDatecodes(); final String configEdges = config.getTableEdges(); final String configSchedule = config.getTableSchedule(); @@ -185,8 +180,10 @@ public class Database { * This should be called once you're done with the database. */ public void close() { - for (final PreparedStatement pstmt : pstmtsCacheMap.values()) { - DbUtils.closeQuietly(pstmt); + if (pstmtsCacheMap != null) { + for (final PreparedStatement pstmt : pstmtsCacheMap.values()) { + DbUtils.closeQuietly(pstmt); + } } DbUtils.closeQuietly(connection); @@ -636,6 +633,14 @@ public class Database { // FIXME: Find a fix for prepared statements with parameters // (we should NOT set strings in preparedStatemens just because we want to cache something) protected PreparedStatement getPstmt(final String query) { + if (connection == null) { + // lazy-loading of the database connection (so it is not created on object construction) + connection = ConfigIsochrone.getInstance().getConnection(); + } + if (pstmtsCacheMap == null) { + pstmtsCacheMap = new HashMap<String, PreparedStatement>(); + } + try { if (pstmtsCacheMap.containsKey(query) && !pstmtsCacheMap.get(query).isClosed()) { return pstmtsCacheMap.get(query); 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 8457d483..994ea7f6 100644 --- a/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java +++ b/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java @@ -428,7 +428,7 @@ public class DatabaseWeb extends Database { public Point transform(final Point p) { final String query = "SELECT ST_X(P.GEO) X, ST_Y(P.GEO) Y FROM (SELECT ST_Transform(ST_PointFromText(?,?),?) GEO ) P"; - return DatabaseWeb.transform(config, p, getPstmt(query)); + return DatabaseWeb.transform(connection, config, p, getPstmt(query)); } public void updateVertexTable() { @@ -447,15 +447,18 @@ public class DatabaseWeb extends Database { // Public static methods public static Point transform(final ConfigDataset config, final Point p) { - return transform(config, p, null); + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + final Point result = transform(connection, config, p, null); + DbUtils.closeQuietly(connection); + + return result; } // Private static methods - private static Point transform(final ConfigDataset config, final Point p, final PreparedStatement preparedStatement) { - final ConfigIsochrone configIso = ConfigIsochrone.getInstance(); + private static Point transform(final Connection connection, final ConfigDataset config, final Point p, final PreparedStatement preparedStatement) { final boolean openNewStatement = (preparedStatement == null); - final int clientSRID = configIso.getClientSRID(); + final int clientSRID = ConfigIsochrone.getInstance().getClientSRID(); if (clientSRID == config.getServerSRID()) { return p; } @@ -468,7 +471,7 @@ public class DatabaseWeb extends Database { try { if (openNewStatement) { final String query = "SELECT ST_X(P.GEO) X, ST_Y(P.GEO) Y FROM (SELECT ST_Transform(ST_PointFromText(?,?),?) GEO ) P"; - createdStatement = configIso.getConnection().prepareStatement(query); + createdStatement = connection.prepareStatement(query); stmt = createdStatement; } else { stmt = preparedStatement; 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 e7de60cc..c5de3e3a 100644 --- a/src/main/java/it/unibz/inf/isoga/db/DbUtility.java +++ b/src/main/java/it/unibz/inf/isoga/db/DbUtility.java @@ -1,7 +1,6 @@ package it.unibz.inf.isoga.db; import it.unibz.inf.isochrone.config.ConfigDataset; -import it.unibz.inf.isochrone.config.ConfigIsochrone; import it.unibz.inf.isochrone.util.EnumContainer.Direction; import it.unibz.inf.isochrone.util.EnumContainer.QueryType; import it.unibz.inf.isoga.config.ConfigClient; @@ -144,15 +143,13 @@ public final class DbUtility { return false; } - public static ResponsePoiFeature getPoiFeatures(final String sqlExpr, final ConfigDataset config) { + public static ResponsePoiFeature getPoiFeatures(final Connection connection, 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 { @@ -178,11 +175,10 @@ 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(); - + public static WpsStatistic getStatistics(final Connection connection, final String sqlExpr, final boolean withSum, final ConfigDataset config) { int sum = 0; int count = 0; + Statement stmt = null; ResultSet rSet = null; try { @@ -210,10 +206,9 @@ public final class DbUtility { return new WpsStatistic(count, sum); } - public static SortedMap<Calendar, RouteEntity> getVertexAnnotation(final ConfigClient config, final int vertexId, final Direction direction) { + public static SortedMap<Calendar, RouteEntity> getVertexAnnotation(final Connection connection, 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\""; @@ -291,15 +286,13 @@ public final class DbUtility { } } - public static ResponseWps spatialIntersection2JSON(final String sqlExpr, final SqlQuery query, final ConfigDataset config) { + public static ResponseWps spatialIntersection2JSON(final Connection connection, final String sqlExpr, final SqlQuery query, final ConfigDataset config) { final ResponseWps result = new ResponseWps(query.getQueryType().toString().toLowerCase()); if (sqlExpr.equals("noResult")) { result.setType("invalid"); return result; } - final Connection connection = ConfigIsochrone.getInstance().getConnection(); - Statement stmt = null; ResultSet rSet = null; try { diff --git a/src/main/java/it/unibz/inf/isoga/network/BBoxOutput.java b/src/main/java/it/unibz/inf/isoga/network/BBoxOutput.java index f7375287..edb8534a 100644 --- a/src/main/java/it/unibz/inf/isoga/network/BBoxOutput.java +++ b/src/main/java/it/unibz/inf/isoga/network/BBoxOutput.java @@ -83,15 +83,15 @@ public class BBoxOutput extends MemoryOutput { // Private methods private void calculateBoundingBox() { - final ConfigIsochrone configIso = ConfigIsochrone.getInstance(); - final Connection connection = configIso.getConnection(); + final int clientSRID = ConfigIsochrone.getInstance().getClientSRID(); + final Connection connection = db.getConnection(); PreparedStatement statement = null; ResultSet rSet = null; try { statement = connection.prepareStatement(query); statement.setInt(1, serverSRID); - statement.setInt(2, configIso.getClientSRID()); + statement.setInt(2, clientSRID); rSet = statement.executeQuery(); if (rSet.next()) { long minX = Math.round(rSet.getDouble("min_x")); diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java b/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java index 1b3542e0..823e5512 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java @@ -14,6 +14,8 @@ import java.util.Set; import javax.websocket.Session; +import org.apache.commons.dbutils.DbUtils; + /** * @author Nikolaus Krismer */ @@ -66,6 +68,8 @@ public class ServiceConfiguration extends AbstractService<RequestConfiguration, final ConfigClient configClient = ConfigClient.getInstance(clientId, dataset); registerTableAndLayers(connection, configClient); } + + DbUtils.closeQuietly(connection); } } diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java b/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java index b98c0297..8507e58b 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java @@ -1,6 +1,7 @@ package it.unibz.inf.isoga.service; +import it.unibz.inf.isochrone.config.ConfigIsochrone; import it.unibz.inf.isochrone.util.EnumContainer.Direction; import it.unibz.inf.isoga.config.ConfigClient; import it.unibz.inf.isoga.db.DbUtility; @@ -9,11 +10,14 @@ import it.unibz.inf.isoga.service.dto.RequestFeatureInfo; import it.unibz.inf.isoga.service.dto.ResponseFeatureInfo; import it.unibz.inf.isoga.service.dto.ResponseFeatureInfo.Entry; +import java.sql.Connection; import java.util.Calendar; import java.util.SortedMap; import javax.websocket.Session; +import org.apache.commons.dbutils.DbUtils; + /** * @author Nikolaus Krismer */ @@ -35,11 +39,13 @@ public class ServiceFeatureInfo extends AbstractService<RequestFeatureInfo, Resp final ConfigClient config = ConfigClient.getInstance(clientId, ds); final ResponseFeatureInfo result = new ResponseFeatureInfo(); - final SortedMap<Calendar, RouteEntity> schedules = DbUtility.getVertexAnnotation(config, stopId, direction); + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + final SortedMap<Calendar, RouteEntity> schedules = DbUtility.getVertexAnnotation(connection, config, stopId, direction); for (final RouteEntity routeEntity : schedules.values()) { result.addEntry(new Entry(routeEntity)); } + DbUtils.closeQuietly(connection); return result; } 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 299fcc35..5f36e40b 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java @@ -7,7 +7,6 @@ import it.unibz.inf.isochrone.algorithm.MDijkstra; import it.unibz.inf.isochrone.algorithm.MineX; import it.unibz.inf.isochrone.algorithm.MrneX; import it.unibz.inf.isochrone.config.ConfigDataset; -import it.unibz.inf.isochrone.config.ConfigIsochrone; import it.unibz.inf.isochrone.network.Location; import it.unibz.inf.isochrone.util.EnumContainer.Algorithm; import it.unibz.inf.isochrone.util.EnumContainer.CoverageMode; @@ -57,15 +56,15 @@ public class ServiceIsochrone extends AbstractService<RequestIsochrone, Response final ConfigClient config = ConfigClient.getInstance(clientId, dataset); // register layers which have not been pre-registered in ServiceConfiguration class + final long startComputationTiming = System.currentTimeMillis(); + final DatabaseWeb db = new DatabaseWeb(config, request.getMode(), direction); if (!config.isRegistered()) { - registerTableAndLayers(ConfigIsochrone.getInstance().getConnection(), config); + registerTableAndLayers(db.getConnection(), config); } // Timing start - final long startComputationTiming = System.currentTimeMillis(); - final DatabaseWeb db = new DatabaseWeb(config, request.getMode(), direction); - truncateTables(config); + truncateTables(db.getConnection(), 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, db, query); @@ -126,9 +125,7 @@ public class ServiceIsochrone extends AbstractService<RequestIsochrone, Response return locations; } - private void truncateTables(final ConfigDataset config) { - final Connection conn = ConfigIsochrone.getInstance().getConnection(); - + private void truncateTables(final Connection conn, final ConfigDataset config) { DbUtility.truncateTable(conn, config.getEdgeTableEntry().getTableName()); DbUtility.truncateTable(conn, config.getVertexTableEntry().getTableName()); DbUtility.dropIndex(conn, config.getVertexTableEntry().getIndexName()); diff --git a/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java b/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java index 06701581..63f7705d 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java @@ -7,8 +7,12 @@ import it.unibz.inf.isoga.db.DbUtility; import it.unibz.inf.isoga.service.dto.RequestPoiFeature; import it.unibz.inf.isoga.service.dto.ResponsePoiFeature; +import java.sql.Connection; + import javax.websocket.Session; +import org.apache.commons.dbutils.DbUtils; + /** * @author Nikolaus Krismer */ @@ -35,7 +39,9 @@ public class ServicePoiFeature extends AbstractService<RequestPoiFeature, Respon if (!sqlMessage.toUpperCase().startsWith("SELECT")) { poiFeatures.setType("No result"); } else { - poiFeatures = DbUtility.getPoiFeatures(sqlMessage, config); + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + poiFeatures = DbUtility.getPoiFeatures(connection, sqlMessage, config); + DbUtils.closeQuietly(connection); } return poiFeatures; diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java b/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java index f2d7b08e..eb32cb56 100644 --- a/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java +++ b/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java @@ -1,6 +1,7 @@ package it.unibz.inf.isoga.service; +import it.unibz.inf.isochrone.config.ConfigIsochrone; import it.unibz.inf.isochrone.util.EnumContainer.QueryType; import it.unibz.inf.isoga.config.ConfigClient; import it.unibz.inf.isoga.db.DbUtility; @@ -8,8 +9,12 @@ import it.unibz.inf.isoga.db.SqlQuery; import it.unibz.inf.isoga.service.dto.RequestWps; import it.unibz.inf.isoga.service.dto.ResponseWps; +import java.sql.Connection; + import javax.websocket.Session; +import org.apache.commons.dbutils.DbUtils; + /** * @author Nikolaus Krismer */ @@ -36,13 +41,16 @@ public class ServiceWps extends AbstractService<RequestWps, ResponseWps> { final String clientId = session.getId(); final ConfigClient config = ConfigClient.getInstance(clientId, ds); final String spatialQuery = query.getSpatialQueryString(config); - response = DbUtility.spatialIntersection2JSON(spatialQuery, query, config); + final Connection connection = ConfigIsochrone.getInstance().getConnection(); + + response = DbUtility.spatialIntersection2JSON(connection, spatialQuery, query, config); if (query.getQueryType().equals(QueryType.SELECT)) { - response.setStatistic(DbUtility.getStatistics(query.getStatistics(false), false, config)); + response.setStatistic(DbUtility.getStatistics(connection, query.getStatistics(false), false, config)); } else if (query.getQueryType().equals(QueryType.SUM)) { - response.setStatistic(DbUtility.getStatistics(query.getStatisticsWithSum(false), true, config)); + response.setStatistic(DbUtility.getStatistics(connection, query.getStatisticsWithSum(false), true, config)); } + DbUtils.closeQuietly(connection); return response; } diff --git a/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java b/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java index 23f7135f..dce87f7d 100644 --- a/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java +++ b/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java @@ -41,6 +41,7 @@ import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; +import org.apache.commons.dbutils.DbUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,14 +63,14 @@ public class JsonWebsocket { @OnClose public void onClose(final Session session, final CloseReason closeReason) { - final Connection connection = ConfigIsochrone.getInstance().getConnection(); - final ConfigGeoserver config = ConfigGeoserver.getInstance(); final String ws = config.getRenderServerWorkspace(); final GeoServerRESTPublisher publisher = config.getGeoServerPublisher(); final String clientId = session.getId(); final Collection<ConfigClient> allClientDatasetConfigs = ConfigClient.getAllConfigs(clientId); + + final Connection connection = ConfigIsochrone.getInstance().getConnection(); for (final ConfigClient clientDSetConfig : allClientDatasetConfigs) { if (clientDSetConfig.isRegistered()) { // unregister layers @@ -86,6 +87,7 @@ public class JsonWebsocket { } } } + DbUtils.closeQuietly(connection); publisher.reload(); LOGGER.debug("Websocket: Session \"" + clientId + "\" closed: " + closeReason); diff --git a/src/main/java/it/unibz/inf/isoga/web/StartupListener.java b/src/main/java/it/unibz/inf/isoga/web/StartupListener.java index 88465c08..108341d0 100644 --- a/src/main/java/it/unibz/inf/isoga/web/StartupListener.java +++ b/src/main/java/it/unibz/inf/isoga/web/StartupListener.java @@ -11,6 +11,7 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; +import org.apache.commons.dbutils.DbUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,6 +69,8 @@ public class StartupListener implements ServletContextListener { LOGGER.warn(" - table(s) \"" + regexp + "\" could not be dropped"); } } + + DbUtils.closeQuietly(connection); } /** -- GitLab