Mercurial > dive4elements > framework
changeset 541:3b1e48d22ce0
Experimentally let database cleaner and backend share the same sql executor.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 03 Sep 2015 15:34:07 +0200 |
parents | 91b1435fb9ea |
children | 9497f58484a0 |
files | artifact-database/src/main/java/org/dive4elements/artifactdatabase/App.java artifact-database/src/main/java/org/dive4elements/artifactdatabase/Backend.java artifact-database/src/main/java/org/dive4elements/artifactdatabase/DatabaseCleaner.java artifact-database/src/main/java/org/dive4elements/artifactdatabase/db/SQLExecutor.java |
diffstat | 4 files changed, 179 insertions(+), 139 deletions(-) [+] |
line wrap: on
line diff
--- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/App.java Thu Sep 03 11:46:24 2015 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/App.java Thu Sep 03 15:34:07 2015 +0200 @@ -70,7 +70,10 @@ bootstrap, backend); DatabaseCleaner cleaner = new DatabaseCleaner( - bootstrap.getContext(), backend, backend.getConfig()); + bootstrap.getContext(), + backend, + backend.getSQLExecutor(), + backend.getConfig()); HTTPServer httpServer = bootstrap.getHTTPServer();
--- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/Backend.java Thu Sep 03 11:46:24 2015 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/Backend.java Thu Sep 03 15:34:07 2015 +0200 @@ -273,6 +273,10 @@ setupSQL(config.getSQL()); } + public SQLExecutor getSQLExecutor() { + return sqlExecutor; + } + /** * Constructor to create a backend with a link to the database cleaner. * @param cleaner The clean which periodically removes outdated @@ -706,6 +710,7 @@ final int [] id = new int[1]; SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override public boolean doIt() throws SQLException { prepareStatement(SQL_NEXT_ID); result = stmnt.executeQuery();
--- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/DatabaseCleaner.java Thu Sep 03 11:46:24 2015 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/DatabaseCleaner.java Thu Sep 03 15:34:07 2015 +0200 @@ -14,6 +14,7 @@ import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifactdatabase.db.SQL; +import org.dive4elements.artifactdatabase.db.SQLExecutor; import org.dive4elements.artifactdatabase.db.DBConnection; import java.sql.Connection; @@ -135,7 +136,7 @@ */ protected ArtifactReviver reviver; - protected DBConnection dbConnection; + protected SQLExecutor sqlExecutor; /** * Default constructor. @@ -149,12 +150,17 @@ * @param context The global context of the artifact database * @param reviver The reviver to awake artifact one last time. */ - public DatabaseCleaner(Object context, ArtifactReviver reviver, DBConfig config) { + public DatabaseCleaner( + Object context, + ArtifactReviver reviver, + SQLExecutor sqlExecutor, + DBConfig config + ) { setDaemon(true); sleepTime = getSleepTime(); this.context = context; this.reviver = reviver; - this.dbConnection = config.getDBConnection(); + this.sqlExecutor = sqlExecutor; setupSQL(config.getSQL()); } @@ -249,155 +255,154 @@ protected void cleanup() { logger.info("database cleanup"); - Connection connection = null; - PreparedStatement fetchIds = null; - PreparedStatement stmnt = null; - ResultSet result = null; - - DataSource dataSource = dbConnection.getDataSource(); - - Set<Integer> lockedIds = lockedIdsProvider != null + final Set<Integer> lockedIds = lockedIdsProvider != null ? lockedIdsProvider.getLockedIds() : EMPTY_IDS; - String questionMarks = lockedIds.isEmpty() + final String questionMarks = lockedIds.isEmpty() ? "-666" // XXX: A bit hackish. : StringUtils.repeat('?', lockedIds.size(), ','); - List<String> deletedCollections = new ArrayList<String>(); - List<String> deletedArtifacts = new ArrayList<String>(); - - try { - connection = dataSource.getConnection(); - connection.setAutoCommit(false); - - fetchIds = connection.prepareStatement( - SQL_OUTDATED.replace("$LOCKED_IDS$", questionMarks)); - - // some dbms like derby do not support LIMIT - // in SQL statements. - fetchIds.setMaxRows(MAX_ROWS); - - // Fetch ids of outdated collections - stmnt = connection.prepareStatement( - SQL_OUTDATED_COLLECTIONS.replace( - "$LOCKED_IDS$", questionMarks)); - - // fill in the locked ids - int idx = 1; - for (Integer id: lockedIds) { - fetchIds.setInt(idx, id); - stmnt .setInt(idx, id); - ++idx; - } - - ArrayList<IdIdentifier> cs = new ArrayList<IdIdentifier>(); - result = stmnt.executeQuery(); - while (result.next()) { - cs.add(new IdIdentifier( - result.getInt(1), - result.getString(2))); - } - - result.close(); result = null; - stmnt.close(); stmnt = null; - - // delete collection items - stmnt = connection.prepareStatement(SQL_DELETE_COLLECTION_ITEMS); - - for (IdIdentifier id: cs) { - logger.debug("Mark collection for deletion: " + id.id); - stmnt.setInt(1, id.id); - stmnt.execute(); - } - - stmnt.close(); stmnt = null; - - // delete collections - stmnt = connection.prepareStatement(SQL_DELETE_COLLECTION); + final List<String> deletedCollections = new ArrayList<String>(); + final List<String> deletedArtifacts = new ArrayList<String>(); - for (IdIdentifier id: cs) { - stmnt.setInt(1, id.id); - stmnt.execute(); - deletedCollections.add(id.identifier); - } - - stmnt.close(); stmnt = null; - connection.commit(); - - cs = null; - - // remove artifacts - stmnt = connection.prepareStatement(SQL_DELETE_ARTIFACT); - - for (;;) { - List<IdData> ids = new ArrayList<IdData>(); - - result = fetchIds.executeQuery(); - - while (result.next()) { - ids.add(new IdData( - result.getInt(1), - result.getString(2), - result.getBytes(3), - result.getString(4))); - } + SQLExecutor.Instance exec = sqlExecutor.new Instance() { - result.close(); result = null; - - if (ids.isEmpty()) { - break; - } - - for (int i = ids.size()-1; i >= 0; --i) { - IdData idData = ids.get(i); - Artifact artifact = reviver.reviveArtifact( - idData.factoryName, idData.data); - idData.data = null; + @Override + public boolean doIt() throws SQLException { - logger.debug("Prepare Artifact (id=" - + idData.id + ") for deletion."); - - stmnt.setInt(1, idData.id); - stmnt.execute(); - connection.commit(); + PreparedStatement fetchIds = null; + PreparedStatement stmnt = null; + ResultSet result = null; - try { - if (artifact != null) { - logger.debug("Call endOfLife for Artifact: " - + artifact.identifier()); + try { + fetchIds = conn.prepareStatement( + SQL_OUTDATED.replace("$LOCKED_IDS$", questionMarks)); - artifact.endOfLife(context); - } - } - catch (Exception e) { - logger.error(e.getMessage(), e); + // some dbms like derby do not support LIMIT + // in SQL statements. + fetchIds.setMaxRows(MAX_ROWS); + + // Fetch ids of outdated collections + stmnt = conn.prepareStatement( + SQL_OUTDATED_COLLECTIONS.replace( + "$LOCKED_IDS$", questionMarks)); + + // fill in the locked ids + int idx = 1; + for (Integer id: lockedIds) { + fetchIds.setInt(idx, id); + stmnt .setInt(idx, id); + ++idx; } - deletedArtifacts.add(idData.identifier); - } // for all fetched data - } - } - catch (SQLException sqle) { - logger.error(sqle.getLocalizedMessage(), sqle); - } - finally { - if (result != null) { - try { result.close(); } - catch (SQLException sqle) {} + ArrayList<IdIdentifier> cs = new ArrayList<IdIdentifier>(); + result = stmnt.executeQuery(); + while (result.next()) { + cs.add(new IdIdentifier( + result.getInt(1), + result.getString(2))); + } + + result.close(); result = null; + stmnt.close(); stmnt = null; + + // delete collection items + stmnt = conn.prepareStatement(SQL_DELETE_COLLECTION_ITEMS); + + for (IdIdentifier id: cs) { + logger.debug("Mark collection for deletion: " + id.id); + stmnt.setInt(1, id.id); + stmnt.execute(); + } + + stmnt.close(); stmnt = null; + + // delete collections + stmnt = conn.prepareStatement(SQL_DELETE_COLLECTION); + + for (IdIdentifier id: cs) { + stmnt.setInt(1, id.id); + stmnt.execute(); + deletedCollections.add(id.identifier); + } + + stmnt.close(); stmnt = null; + conn.commit(); + + cs = null; + + // remove artifacts + stmnt = conn.prepareStatement(SQL_DELETE_ARTIFACT); + + for (;;) { + List<IdData> ids = new ArrayList<IdData>(); + + result = fetchIds.executeQuery(); + + while (result.next()) { + ids.add(new IdData( + result.getInt(1), + result.getString(2), + result.getBytes(3), + result.getString(4))); + } + + result.close(); result = null; + + if (ids.isEmpty()) { + break; + } + + for (int i = ids.size()-1; i >= 0; --i) { + IdData idData = ids.get(i); + Artifact artifact = reviver.reviveArtifact( + idData.factoryName, idData.data); + idData.data = null; + + logger.debug("Prepare Artifact (id=" + + idData.id + ") for deletion."); + + stmnt.setInt(1, idData.id); + stmnt.execute(); + conn.commit(); + + try { + if (artifact != null) { + logger.debug("Call endOfLife for Artifact: " + + artifact.identifier()); + + artifact.endOfLife(context); + } + } + catch (Exception e) { + logger.error(e.getMessage(), e); + } + + deletedArtifacts.add(idData.identifier); + } // for all fetched data + } + } + finally { + if (result != null) { + try { result.close(); } + catch (SQLException sqle) {} + } + if (stmnt != null) { + try { stmnt.close(); } + catch (SQLException sqle) {} + } + if (fetchIds != null) { + try { fetchIds.close(); } + catch (SQLException sqle) {} + } + } + return true; } - if (stmnt != null) { - try { stmnt.close(); } - catch (SQLException sqle) {} - } - if (fetchIds != null) { - try { fetchIds.close(); } - catch (SQLException sqle) {} - } - if (connection != null) { - try { connection.close(); } - catch (SQLException sqle) {} - } + }; + + if (!exec.runWriteNoRollback()) { + logger.error("Deleting artifacts failed."); } if (!deletedCollections.isEmpty()) {
--- a/artifact-database/src/main/java/org/dive4elements/artifactdatabase/db/SQLExecutor.java Thu Sep 03 11:46:24 2015 +0200 +++ b/artifact-database/src/main/java/org/dive4elements/artifactdatabase/db/SQLExecutor.java Thu Sep 03 15:34:07 2015 +0200 @@ -55,6 +55,33 @@ } } + public boolean runWriteNoRollback() { + rwLock.writeLock().lock(); + try { + DataSource dataSource = dbConnection.getDataSource(); + try { + conn = dataSource.getConnection(); + try { + conn.setAutoCommit(false); + return doIt(); + } + catch (SQLException sqle) { + throw sqle; + } + } + catch (SQLException sqle) { + logger.error(sqle.getLocalizedMessage(), sqle); + } + finally { + close(); + } + return false; + } + finally { + rwLock.writeLock().unlock(); + } + } + public boolean runWrite() { rwLock.writeLock().lock(); try {