Trimming old block online accounts signatures

There's still an existing issue where log entries like this appear:

  Unable to trim old online accounts signatures in repository

which is actually caused by:

  integrity constraint violation: unique constraint or index violation; SYS_PK_10092 table: BLOCKS

which seems to be a bug in the version of HSQLDB we use.
(Tested using synced-from-scratch DB).
It's not clear what the actual problem is at this point.

It might be possible to switch to v2.5.1 if our recent HSQLDB-related
commits have fixed/worked-around the OOM issues.

Move the inner method from BlockChain to Controller.
Remove blockchain lock as it's not needed because it's not an
HSQLDB "serialization failure" but constraint violation.

Trimming old online accounts signatures limited to batches of 1440
rows to reduce CPU and memory load.
This commit is contained in:
catbref 2020-09-11 15:57:12 +01:00
parent 5ea90f2fdd
commit d93e9d570f
3 changed files with 22 additions and 32 deletions

View File

@ -32,7 +32,6 @@ import org.qortal.repository.DataException;
import org.qortal.repository.Repository; import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager; import org.qortal.repository.RepositoryManager;
import org.qortal.settings.Settings; import org.qortal.settings.Settings;
import org.qortal.utils.NTP;
import org.qortal.utils.StringLongMapXmlAdapter; import org.qortal.utils.StringLongMapXmlAdapter;
/** /**
@ -578,33 +577,4 @@ public class BlockChain {
} }
} }
public static void trimOldOnlineAccountsSignatures() {
final Long now = NTP.getTime();
if (now == null)
return;
ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
if (!blockchainLock.tryLock())
// Too busy to trim right now, try again later
return;
try {
try (final Repository repository = RepositoryManager.tryRepository()) {
if (repository == null)
return;
int numBlocksTrimmed = repository.getBlockRepository().trimOldOnlineAccountsSignatures(now - BlockChain.getInstance().getOnlineAccountSignaturesMaxLifetime());
if (numBlocksTrimmed > 0)
LOGGER.debug(String.format("Trimmed old online accounts signatures from %d block%s", numBlocksTrimmed, (numBlocksTrimmed != 1 ? "s" : "")));
repository.saveChanges();
} catch (DataException e) {
LOGGER.warn(String.format("Repository issue trying to trim old online accounts signatures: %s", e.getMessage()));
}
} finally {
blockchainLock.unlock();
}
}
} }

View File

@ -1407,7 +1407,24 @@ public class Controller extends Thread {
sendOurOnlineAccountsInfo(); sendOurOnlineAccountsInfo();
// Trim blockchain by removing 'old' online accounts signatures // Trim blockchain by removing 'old' online accounts signatures
BlockChain.trimOldOnlineAccountsSignatures(); long upperMintedTimestamp = now - BlockChain.getInstance().getOnlineAccountSignaturesMaxLifetime();
trimOldOnlineAccountsSignatures(upperMintedTimestamp);
}
private void trimOldOnlineAccountsSignatures(long upperMintedTimestamp) {
try (final Repository repository = RepositoryManager.tryRepository()) {
if (repository == null)
return;
int numBlocksTrimmed = repository.getBlockRepository().trimOldOnlineAccountsSignatures(upperMintedTimestamp);
if (numBlocksTrimmed > 0)
LOGGER.debug(() -> String.format("Trimmed old online accounts signatures from %d block%s", numBlocksTrimmed, (numBlocksTrimmed != 1 ? "s" : "")));
repository.saveChanges();
} catch (DataException e) {
LOGGER.warn(String.format("Repository issue trying to trim old online accounts signatures: %s", e.getMessage()));
}
} }
private void sendOurOnlineAccountsInfo() { private void sendOurOnlineAccountsInfo() {

View File

@ -465,11 +465,14 @@ public class HSQLDBBlockRepository implements BlockRepository {
@Override @Override
public int trimOldOnlineAccountsSignatures(long timestamp) throws DataException { public int trimOldOnlineAccountsSignatures(long timestamp) throws DataException {
String sql = "UPDATE Blocks set online_accounts_signatures = NULL WHERE minted_when < ? AND online_accounts_signatures IS NOT NULL"; // We're often called so no need to trim all blocks in one go.
// Limit updates to reduce CPU and memory load.
String sql = "UPDATE Blocks set online_accounts_signatures = NULL WHERE minted_when < ? AND online_accounts_signatures IS NOT NULL LIMIT 1440";
try { try {
return this.repository.executeCheckedUpdate(sql, timestamp); return this.repository.executeCheckedUpdate(sql, timestamp);
} catch (SQLException e) { } catch (SQLException e) {
repository.examineException(e);
throw new DataException("Unable to trim old online accounts signatures in repository", e); throw new DataException("Unable to trim old online accounts signatures in repository", e);
} }
} }