Synchronized LatestATStates, to make rebuildLatestAtStates() thread safe.

This commit is contained in:
CalDescent 2021-08-28 11:00:49 +01:00
parent dc030a42bb
commit 87595fd704
2 changed files with 90 additions and 71 deletions

View File

@ -604,6 +604,11 @@ public class HSQLDBATRepository implements ATRepository {
@Override @Override
public void rebuildLatestAtStates() throws DataException { public void rebuildLatestAtStates() throws DataException {
// latestATStatesLock is to prevent concurrent updates on LatestATStates
// that could result in one process using a partial or empty dataset
// because it was in the process of being rebuilt by another thread
synchronized (this.repository.latestATStatesLock) {
// Rebuild cache of latest AT states that we can't trim // Rebuild cache of latest AT states that we can't trim
String deleteSql = "DELETE FROM LatestATStates"; String deleteSql = "DELETE FROM LatestATStates";
try { try {
@ -628,6 +633,7 @@ public class HSQLDBATRepository implements ATRepository {
throw new DataException("Unable to populate temporary latest AT states cache in repository", e); throw new DataException("Unable to populate temporary latest AT states cache in repository", e);
} }
} }
}
@Override @Override
@ -666,6 +672,11 @@ public class HSQLDBATRepository implements ATRepository {
if (minHeight >= maxHeight) if (minHeight >= maxHeight)
return 0; return 0;
// latestATStatesLock is to prevent concurrent updates on LatestATStates
// that could result in one process using a partial or empty dataset
// because it was in the process of being rebuilt by another thread
synchronized (this.repository.latestATStatesLock) {
// We're often called so no need to trim all states in one go. // We're often called so no need to trim all states in one go.
// Limit updates to reduce CPU and memory load. // Limit updates to reduce CPU and memory load.
String sql = "DELETE FROM ATStatesData " String sql = "DELETE FROM ATStatesData "
@ -684,6 +695,7 @@ public class HSQLDBATRepository implements ATRepository {
throw new DataException("Unable to trim AT states in repository", e); throw new DataException("Unable to trim AT states in repository", e);
} }
} }
}
@Override @Override
@ -719,9 +731,14 @@ public class HSQLDBATRepository implements ATRepository {
@Override @Override
public int pruneAtStates(int minHeight, int maxHeight) throws DataException { public int pruneAtStates(int minHeight, int maxHeight) throws DataException {
// latestATStatesLock is to prevent concurrent updates on LatestATStates
// that could result in one process using a partial or empty dataset
// because it was in the process of being rebuilt by another thread
synchronized (this.repository.latestATStatesLock) {
int deletedCount = 0; int deletedCount = 0;
for (int height=minHeight; height<maxHeight; height++) { for (int height = minHeight; height < maxHeight; height++) {
// Give up if we're stopping // Give up if we're stopping
if (Controller.isStopping()) { if (Controller.isStopping()) {
@ -771,6 +788,7 @@ public class HSQLDBATRepository implements ATRepository {
return deletedCount; return deletedCount;
} }
}
@Override @Override

View File

@ -69,6 +69,7 @@ public class HSQLDBRepository implements Repository {
protected final Map<String, PreparedStatement> preparedStatementCache = new HashMap<>(); protected final Map<String, PreparedStatement> preparedStatementCache = new HashMap<>();
// We want the same object corresponding to the actual DB // We want the same object corresponding to the actual DB
protected final Object trimHeightsLock = RepositoryManager.getRepositoryFactory(); protected final Object trimHeightsLock = RepositoryManager.getRepositoryFactory();
protected final Object latestATStatesLock = RepositoryManager.getRepositoryFactory();
private final ATRepository atRepository = new HSQLDBATRepository(this); private final ATRepository atRepository = new HSQLDBATRepository(this);
private final AccountRepository accountRepository = new HSQLDBAccountRepository(this); private final AccountRepository accountRepository = new HSQLDBAccountRepository(this);