diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java index 760d1ebc..da69d767 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -208,7 +209,7 @@ public class HSQLDBRepository implements Repository { this.savepoints.clear(); // Before clearing statements so we can log what led to assertion error - assertEmptyTransaction("transaction commit"); + assertEmptyTransaction("transaction rollback"); if (this.sqlStatements != null) this.sqlStatements.clear(); @@ -298,11 +299,12 @@ public class HSQLDBRepository implements Repository { Path oldRepoDirPath = Paths.get(dbPathname).getParent(); // Delete old repository files - Files.walk(oldRepoDirPath) - .sorted(Comparator.reverseOrder()) + try (Stream paths = Files.walk(oldRepoDirPath)) { + paths.sorted(Comparator.reverseOrder()) .map(Path::toFile) .filter(file -> file.getPath().startsWith(dbPathname)) .forEach(File::delete); + } } } catch (NoSuchFileException e) { // Nothing to remove @@ -342,11 +344,12 @@ public class HSQLDBRepository implements Repository { Path backupDirPath = Paths.get(backupPathname).getParent(); String backupDirPathname = backupDirPath.toString(); - Files.walk(backupDirPath) - .sorted(Comparator.reverseOrder()) + try (Stream paths = Files.walk(backupDirPath)) { + paths.sorted(Comparator.reverseOrder()) .map(Path::toFile) .filter(file -> file.getPath().startsWith(backupDirPathname)) .forEach(File::delete); + } } catch (NoSuchFileException e) { // Nothing to remove } catch (SQLException | IOException e) { @@ -411,11 +414,12 @@ public class HSQLDBRepository implements Repository { LOGGER.info("Attempting repository recovery using backup"); // Move old repository files out the way - Files.walk(oldRepoDirPath) - .sorted(Comparator.reverseOrder()) + try (Stream paths = Files.walk(oldRepoDirPath)) { + paths.sorted(Comparator.reverseOrder()) .map(Path::toFile) .filter(file -> file.getPath().startsWith(dbPathname)) .forEach(File::delete); + } try (Statement stmt = connection.createStatement()) { // Now "backup" the backup back to original repository location (the parent). @@ -455,6 +459,10 @@ public class HSQLDBRepository implements Repository { if (this.sqlStatements != null) this.sqlStatements.add(sql); + return cachePreparedStatement(sql); + } + + private PreparedStatement cachePreparedStatement(String sql) throws SQLException { /* * We cache a duplicate PreparedStatement for this SQL string, * which we never close, which means HSQLDB also caches a parsed, @@ -799,7 +807,7 @@ public class HSQLDBRepository implements Repository { /** Logs other HSQLDB sessions then returns passed exception */ public SQLException examineException(SQLException e) { - LOGGER.error(String.format("HSQLDB error (session %d): %s", this.sessionId, e.getMessage()), e); + LOGGER.error(() -> String.format("HSQLDB error (session %d): %s", this.sessionId, e.getMessage()), e); logStatements(); @@ -833,14 +841,19 @@ public class HSQLDBRepository implements Repository { } private void assertEmptyTransaction(String context) throws DataException { - try (Statement stmt = this.connection.createStatement()) { + String sql = "SELECT transaction, transaction_size FROM information_schema.system_sessions WHERE session_id = ?"; + + try { + PreparedStatement stmt = this.cachePreparedStatement(sql); + stmt.setLong(1, this.sessionId); + // Diagnostic check for uncommitted changes - if (!stmt.execute("SELECT transaction, transaction_size FROM information_schema.system_sessions WHERE session_id = " + this.sessionId)) // TRANSACTION_SIZE() broken? + if (!stmt.execute()) // TRANSACTION_SIZE() broken? throw new DataException("Unable to check repository status after " + context); try (ResultSet resultSet = stmt.getResultSet()) { if (resultSet == null || !resultSet.next()) { - LOGGER.warn(String.format("Unable to check repository status after %s", context)); + LOGGER.warn(() -> String.format("Unable to check repository status after %s", context)); return; } @@ -848,7 +861,11 @@ public class HSQLDBRepository implements Repository { int transactionCount = resultSet.getInt(2); if (inTransaction && transactionCount != 0) { - LOGGER.warn(String.format("Uncommitted changes (%d) after %s, session [%d]", transactionCount, context, this.sessionId), new Exception("Uncommitted repository changes")); + LOGGER.warn(() -> String.format("Uncommitted changes (%d) after %s, session [%d]", + transactionCount, + context, + this.sessionId), + new Exception("Uncommitted repository changes")); logStatements(); } }