From 7b056a832f335fcd4afc906d331f402c38d45d04 Mon Sep 17 00:00:00 2001 From: catbref Date: Mon, 2 Nov 2020 11:49:21 +0000 Subject: [PATCH] Turn off HSQLDB redo-log "blockchain.log" and periodically call "CHECKPOINT" instead. Checkpointing interval is 1 hour by default, changable in settings via "repositoryCheckpointInterval" plus corresponding "showCheckpointNotifications" SysTray flags (off by default). Added entries to SysTray_en i18n properties, and converted SysTray_ru to ISO-8559-1. --- .../org/qortal/controller/Controller.java | 14 ++++ .../org/qortal/repository/Repository.java | 2 + .../qortal/repository/RepositoryManager.java | 8 +++ .../hsqldb/HSQLDBDatabaseUpdates.java | 6 ++ .../repository/hsqldb/HSQLDBRepository.java | 9 +++ .../java/org/qortal/settings/Settings.java | 12 ++++ src/main/resources/i18n/SysTray_en.properties | 4 ++ src/main/resources/i18n/SysTray_ru.properties | 70 ++++++++----------- 8 files changed, 84 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index 4611e7f7..fc72475d 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -156,6 +156,7 @@ public class Controller extends Thread { }; private long repositoryBackupTimestamp = startTime; // ms + private long repositoryCheckpointTimestamp = startTime; // ms private long ntpCheckTimestamp = startTime; // ms private long deleteExpiredTimestamp = startTime + DELETE_EXPIRED_INTERVAL; // ms @@ -484,6 +485,7 @@ public class Controller extends Thread { Thread.currentThread().setName("Controller"); final long repositoryBackupInterval = Settings.getInstance().getRepositoryBackupInterval(); + final long repositoryCheckpointInterval = Settings.getInstance().getRepositoryCheckpointInterval(); ExecutorService trimExecutor = Executors.newCachedThreadPool(new DaemonThreadFactory()); trimExecutor.execute(new AtStatesTrimmer()); @@ -529,6 +531,18 @@ public class Controller extends Thread { final long requestMinimumTimestamp = now - ARBITRARY_REQUEST_TIMEOUT; arbitraryDataRequests.entrySet().removeIf(entry -> entry.getValue().getC() < requestMinimumTimestamp); + // Time to 'checkpoint' uncommitted repository writes? + if (now >= repositoryCheckpointTimestamp + repositoryCheckpointInterval) { + repositoryCheckpointTimestamp = now + repositoryCheckpointInterval; + + if (Settings.getInstance().getShowCheckpointNotification()) + SysTray.getInstance().showMessage(Translator.INSTANCE.translate("SysTray", "DB_CHECKPOINT"), + Translator.INSTANCE.translate("SysTray", "PERFORMING_DB_CHECKPOINT"), + MessageType.INFO); + + RepositoryManager.checkpoint(true); + } + // Give repository a chance to backup (if enabled) if (repositoryBackupInterval > 0 && now >= repositoryBackupTimestamp + repositoryBackupInterval) { repositoryBackupTimestamp = now + repositoryBackupInterval; diff --git a/src/main/java/org/qortal/repository/Repository.java b/src/main/java/org/qortal/repository/Repository.java index cc3a5336..cbfaab97 100644 --- a/src/main/java/org/qortal/repository/Repository.java +++ b/src/main/java/org/qortal/repository/Repository.java @@ -47,6 +47,8 @@ public interface Repository extends AutoCloseable { public void backup(boolean quick) throws DataException; + public void checkpoint(boolean quick) throws DataException; + public void performPeriodicMaintenance() throws DataException; } diff --git a/src/main/java/org/qortal/repository/RepositoryManager.java b/src/main/java/org/qortal/repository/RepositoryManager.java index e375be96..e3427954 100644 --- a/src/main/java/org/qortal/repository/RepositoryManager.java +++ b/src/main/java/org/qortal/repository/RepositoryManager.java @@ -35,6 +35,14 @@ public abstract class RepositoryManager { } } + public static void checkpoint(boolean quick) { + try (final Repository repository = getRepository()) { + repository.checkpoint(quick); + } catch (DataException e) { + // Checkpoint is best-effort so don't complain + } + } + public static void rebuild() throws DataException { RepositoryFactory oldRepositoryFactory = repositoryFactory; diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java index 60a611f8..3255c045 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBDatabaseUpdates.java @@ -685,6 +685,12 @@ public class HSQLDBDatabaseUpdates { + ")"); break; + case 29: + // Turn off HSQLDB redo-log "blockchain.log" and periodically call "CHECKPOINT" ourselves + stmt.execute("SET FILES LOG FALSE"); + stmt.execute("CHECKPOINT"); + break; + default: // nothing to do return false; diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java index d2623441..8391d7ae 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBRepository.java @@ -376,6 +376,15 @@ public class HSQLDBRepository implements Repository { } } + @Override + public void checkpoint(boolean quick) throws DataException { + try (Statement stmt = this.connection.createStatement()) { + stmt.execute(quick ? "CHECKPOINT" : "CHECKPOINT DEFRAG"); + } catch (SQLException e) { + throw new DataException("Unable to perform repositor checkpoint"); + } + } + @Override public void performPeriodicMaintenance() throws DataException { // Defrag DB - takes a while! diff --git a/src/main/java/org/qortal/settings/Settings.java b/src/main/java/org/qortal/settings/Settings.java index 94ffe839..1a989c2e 100644 --- a/src/main/java/org/qortal/settings/Settings.java +++ b/src/main/java/org/qortal/settings/Settings.java @@ -83,6 +83,10 @@ public class Settings { private long repositoryBackupInterval = 0; // ms /** Whether to show a notification when we backup repository. */ private boolean showBackupNotification = false; + /** How long between repository checkpoints (ms). */ + private long repositoryCheckpointInterval = 60 * 60 * 1000L; // 1 hour (ms) default + /** Whether to show a notification when we perform repository 'checkpoint'. */ + private boolean showCheckpointNotification = false; /** How long to keep old, full, AT state data (ms). */ private long atStatesMaxLifetime = 2 * 7 * 24 * 60 * 60 * 1000L; // milliseconds @@ -430,6 +434,14 @@ public class Settings { return this.showBackupNotification; } + public long getRepositoryCheckpointInterval() { + return this.repositoryCheckpointInterval; + } + + public boolean getShowCheckpointNotification() { + return this.showCheckpointNotification; + } + public long getAtStatesMaxLifetime() { return this.atStatesMaxLifetime; } diff --git a/src/main/resources/i18n/SysTray_en.properties b/src/main/resources/i18n/SysTray_en.properties index f41c1a32..e581335d 100644 --- a/src/main/resources/i18n/SysTray_en.properties +++ b/src/main/resources/i18n/SysTray_en.properties @@ -19,6 +19,8 @@ CREATING_BACKUP_OF_DB_FILES = Creating backup of database files... DB_BACKUP = Database Backup +DB_CHECKPOINT = Database Checkpoint + EXIT = Exit MINTING_DISABLED = NOT minting @@ -34,6 +36,8 @@ NTP_NAG_TEXT_WINDOWS = Select "Synchronize clock" from menu to fix. OPEN_UI = Open UI +PERFORMING_DB_CHECKPOINT = Saving uncommitted database changes... + SYNCHRONIZE_CLOCK = Synchronize clock SYNCHRONIZING_BLOCKCHAIN = Synchronizing diff --git a/src/main/resources/i18n/SysTray_ru.properties b/src/main/resources/i18n/SysTray_ru.properties index f7012034..9b93213e 100644 --- a/src/main/resources/i18n/SysTray_ru.properties +++ b/src/main/resources/i18n/SysTray_ru.properties @@ -1,41 +1,29 @@ -#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) -# SysTray pop-up menu - -APPLYING_UPDATE_AND_RESTARTING = Применение автоматического обновления и перезапуска... - -AUTO_UPDATE = Автоматическое обновление - -BLOCK_HEIGHT = Высота блока - -CHECK_TIME_ACCURACY = Проверка точного времени - -CONNECTING = Подключение - -CONNECTION = Соединение - -CONNECTIONS = Соединений - -CREATING_BACKUP_OF_DB_FILES = Создание резервной копии файлов базы данных... - -DB_BACKUP = Резервное копирование базы данных - -EXIT = Выход - -MINTING_DISABLED = Чеканка отключена - -MINTING_ENABLED = Чеканка активна - -# Nagging about lack of NTP time sync -NTP_NAG_CAPTION = Часы компьютера неточны! - -NTP_NAG_TEXT_UNIX = Установите службу NTP, чтобы получить точное время - -NTP_NAG_TEXT_WINDOWS = Выберите "Синхронизация времени" из меню, чтобы исправить - -OPEN_UI = Открыть пользовательский интерфейс - -SYNCHRONIZE_CLOCK = Синхронизировать время - -SYNCHRONIZING_BLOCKCHAIN = Синхронизация цепи - -SYNCHRONIZING_CLOCK = Проверка времени +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +# SysTray pop-up menu + +APPLYING_UPDATE_AND_RESTARTING = \u00D0\u009F\u00D1\u0080\u00D0\u00B8\u00D0\u00BC\u00D0\u00B5\u00D0\u00BD\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D0\u00B5 \u00D0\u00B0\u00D0\u00B2\u00D1\u0082\u00D0\u00BE\u00D0\u00BC\u00D0\u00B0\u00D1\u0082\u00D0\u00B8\u00D1\u0087\u00D0\u00B5\u00D1\u0081\u00D0\u00BA\u00D0\u00BE\u00D0\u00B3\u00D0\u00BE \u00D0\u00BE\u00D0\u00B1\u00D0\u00BD\u00D0\u00BE\u00D0\u00B2\u00D0\u00BB\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D1\u008F \u00D0\u00B8 \u00D0\u00BF\u00D0\u00B5\u00D1\u0080\u00D0\u00B5\u00D0\u00B7\u00D0\u00B0\u00D0\u00BF\u00D1\u0083\u00D1\u0081\u00D0\u00BA\u00D0\u00B0... + +AUTO_UPDATE = \u00D0\u0090\u00D0\u00B2\u00D1\u0082\u00D0\u00BE\u00D0\u00BC\u00D0\u00B0\u00D1\u0082\u00D0\u00B8\u00D1\u0087\u00D0\u00B5\u00D1\u0081\u00D0\u00BA\u00D0\u00BE\u00D0\u00B5 \u00D0\u00BE\u00D0\u00B1\u00D0\u00BD\u00D0\u00BE\u00D0\u00B2\u00D0\u00BB\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D0\u00B5 + +BLOCK_HEIGHT = \u00D0\u0092\u00D1\u008B\u00D1\u0081\u00D0\u00BE\u00D1\u0082\u00D0\u00B0 \u00D0\u00B1\u00D0\u00BB\u00D0\u00BE\u00D0\u00BA\u00D0\u00B0 + +CHECK_TIME_ACCURACY = \u00D0\u009F\u00D1\u0080\u00D0\u00BE\u00D0\u00B2\u00D0\u00B5\u00D1\u0080\u00D0\u00BA\u00D0\u00B0 \u00D1\u0082\u00D0\u00BE\u00D1\u0087\u00D0\u00BD\u00D0\u00BE\u00D0\u00B3\u00D0\u00BE \u00D0\u00B2\u00D1\u0080\u00D0\u00B5\u00D0\u00BC\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8 + +CONNECTING = \u00D0\u009F\u00D0\u00BE\u00D0\u00B4\u00D0\u00BA\u00D0\u00BB\u00D1\u008E\u00D1\u0087\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D0\u00B5 + +CONNECTION = \u00D0\u00A1\u00D0\u00BE\u00D0\u00B5\u00D0\u00B4\u00D0\u00B8\u00D0\u00BD\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D0\u00B5 + +CONNECTIONS = \u00D0\u00A1\u00D0\u00BE\u00D0\u00B5\u00D0\u00B4\u00D0\u00B8\u00D0\u00BD\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8\u00D0\u00B9 + +MINTING_DISABLED = \u00D0\u00A7\u00D0\u00B5\u00D0\u00BA\u00D0\u00B0\u00D0\u00BD\u00D0\u00BA\u00D0\u00B0 \u00D0\u00BE\u00D1\u0082\u00D0\u00BA\u00D0\u00BB\u00D1\u008E\u00D1\u0087\u00D0\u00B5\u00D0\u00BD\u00D0\u00B0 + +MINTING_ENABLED = \u00D0\u00A7\u00D0\u00B5\u00D0\u00BA\u00D0\u00B0\u00D0\u00BD\u00D0\u00BA\u00D0\u00B0 \u00D0\u00B0\u00D0\u00BA\u00D1\u0082\u00D0\u00B8\u00D0\u00B2\u00D0\u00BD\u00D0\u00B0 + +# Nagging about lack of NTP time sync +NTP_NAG_CAPTION = \u00D0\u00A7\u00D0\u00B0\u00D1\u0081\u00D1\u008B \u00D0\u00BA\u00D0\u00BE\u00D0\u00BC\u00D0\u00BF\u00D1\u008C\u00D1\u008E\u00D1\u0082\u00D0\u00B5\u00D1\u0080\u00D0\u00B0 \u00D0\u00BD\u00D0\u00B5\u00D1\u0082\u00D0\u00BE\u00D1\u0087\u00D0\u00BD\u00D1\u008B! + +NTP_NAG_TEXT_UNIX = \u00D0\u00A3\u00D1\u0081\u00D1\u0082\u00D0\u00B0\u00D0\u00BD\u00D0\u00BE\u00D0\u00B2\u00D0\u00B8\u00D1\u0082\u00D0\u00B5 \u00D1\u0081\u00D0\u00BB\u00D1\u0083\u00D0\u00B6\u00D0\u00B1\u00D1\u0083 NTP, \u00D1\u0087\u00D1\u0082\u00D0\u00BE\u00D0\u00B1\u00D1\u008B \u00D0\u00BF\u00D0\u00BE\u00D0\u00BB\u00D1\u0083\u00D1\u0087\u00D0\u00B8\u00D1\u0082\u00D1\u008C \u00D1\u0082\u00D0\u00BE\u00D1\u0087\u00D0\u00BD\u00D0\u00BE\u00D0\u00B5 \u00D0\u00B2\u00D1\u0080\u00D0\u00B5\u00D0\u00BC\u00D1\u008F + +OPEN_UI = \u00D0\u009E\u00D1\u0082\u00D0\u00BA\u00D1\u0080\u00D1\u008B\u00D1\u0082\u00D1\u008C \u00D0\u00BF\u00D0\u00BE\u00D0\u00BB\u00D1\u008C\u00D0\u00B7\u00D0\u00BE\u00D0\u00B2\u00D0\u00B0\u00D1\u0082\u00D0\u00B5\u00D0\u00BB\u00D1\u008C\u00D1\u0081\u00D0\u00BA\u00D0\u00B8\u00D0\u00B9 \u00D0\u00B8\u00D0\u00BD\u00D1\u0082\u00D0\u00B5\u00D1\u0080\u00D1\u0084\u00D0\u00B5\u00D0\u00B9\u00D1\u0081 + +SYNCHRONIZING_CLOCK = \u00D0\u009F\u00D1\u0080\u00D0\u00BE\u00D0\u00B2\u00D0\u00B5\u00D1\u0080\u00D0\u00BA\u00D0\u00B0 \u00D0\u00B2\u00D1\u0080\u00D0\u00B5\u00D0\u00BC\u00D0\u00B5\u00D0\u00BD\u00D0\u00B8