forked from Qortal/qortal
Disable archiving and pruning if the AtStatesHeightIndex is missing, and log it so that the user knows they should bootstrap or resync.
This commit is contained in:
parent
1f79d88840
commit
4c171df848
@ -27,6 +27,13 @@ public class BlockArchiver implements Runnable {
|
|||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
int startHeight = repository.getBlockArchiveRepository().getBlockArchiveHeight();
|
int startHeight = repository.getBlockArchiveRepository().getBlockArchiveHeight();
|
||||||
|
|
||||||
|
// Don't attempt to archive if we have no ATStatesHeightIndex, as it will be too slow
|
||||||
|
boolean hasAtStatesHeightIndex = repository.getATRepository().hasAtStatesHeightIndex();
|
||||||
|
if (!hasAtStatesHeightIndex) {
|
||||||
|
LOGGER.info("Unable to start block archiver due to missing ATStatesHeightIndex. Bootstrapping is recommended.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't even start building until initial rush has ended
|
// Don't even start building until initial rush has ended
|
||||||
Thread.sleep(INITIAL_SLEEP_PERIOD);
|
Thread.sleep(INITIAL_SLEEP_PERIOD);
|
||||||
|
|
||||||
|
@ -34,6 +34,13 @@ public class BlockPruner implements Runnable {
|
|||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
int pruneStartHeight = repository.getBlockRepository().getBlockPruneHeight();
|
int pruneStartHeight = repository.getBlockRepository().getBlockPruneHeight();
|
||||||
|
|
||||||
|
// Don't attempt to prune if we have no ATStatesHeightIndex, as it will be too slow
|
||||||
|
boolean hasAtStatesHeightIndex = repository.getATRepository().hasAtStatesHeightIndex();
|
||||||
|
if (!hasAtStatesHeightIndex) {
|
||||||
|
LOGGER.info("Unable to start block pruner due to missing ATStatesHeightIndex. Bootstrapping is recommended.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (!Controller.isStopping()) {
|
while (!Controller.isStopping()) {
|
||||||
repository.discardChanges();
|
repository.discardChanges();
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.qortal.repository;
|
package org.qortal.repository;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -146,6 +148,10 @@ public interface ATRepository {
|
|||||||
public int pruneAtStates(int minHeight, int maxHeight) throws DataException;
|
public int pruneAtStates(int minHeight, int maxHeight) throws DataException;
|
||||||
|
|
||||||
|
|
||||||
|
/** Checks for the presence of the ATStatesHeightIndex in repository */
|
||||||
|
public boolean hasAtStatesHeightIndex() throws DataException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save ATStateData into repository.
|
* Save ATStateData into repository.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -61,11 +61,16 @@ public abstract class RepositoryManager {
|
|||||||
public static boolean archive() {
|
public static boolean archive() {
|
||||||
// Bulk archive the database the first time we use archive mode
|
// Bulk archive the database the first time we use archive mode
|
||||||
if (Settings.getInstance().isArchiveEnabled()) {
|
if (Settings.getInstance().isArchiveEnabled()) {
|
||||||
try {
|
if (RepositoryManager.canArchiveOrPrune()) {
|
||||||
return HSQLDBDatabaseArchiving.buildBlockArchive();
|
try {
|
||||||
|
return HSQLDBDatabaseArchiving.buildBlockArchive();
|
||||||
|
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
LOGGER.info("Unable to bulk prune AT states. The database may have been left in an inconsistent state.");
|
LOGGER.info("Unable to build block archive. The database may have been left in an inconsistent state.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOGGER.info("Unable to build block archive due to missing ATStatesHeightIndex. Bootstrapping is recommended.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -75,18 +80,23 @@ public abstract class RepositoryManager {
|
|||||||
// Bulk prune the database the first time we use pruning mode
|
// Bulk prune the database the first time we use pruning mode
|
||||||
if (Settings.getInstance().isPruningEnabled() ||
|
if (Settings.getInstance().isPruningEnabled() ||
|
||||||
Settings.getInstance().isArchiveEnabled()) {
|
Settings.getInstance().isArchiveEnabled()) {
|
||||||
try {
|
if (RepositoryManager.canArchiveOrPrune()) {
|
||||||
boolean prunedATStates = HSQLDBDatabasePruning.pruneATStates();
|
try {
|
||||||
boolean prunedBlocks = HSQLDBDatabasePruning.pruneBlocks();
|
boolean prunedATStates = HSQLDBDatabasePruning.pruneATStates();
|
||||||
|
boolean prunedBlocks = HSQLDBDatabasePruning.pruneBlocks();
|
||||||
|
|
||||||
// Perform repository maintenance to shrink the db size down
|
// Perform repository maintenance to shrink the db size down
|
||||||
if (prunedATStates && prunedBlocks) {
|
if (prunedATStates && prunedBlocks) {
|
||||||
HSQLDBDatabasePruning.performMaintenance();
|
HSQLDBDatabasePruning.performMaintenance();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException | DataException e) {
|
||||||
|
LOGGER.info("Unable to bulk prune AT states. The database may have been left in an inconsistent state.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (SQLException | DataException e) {
|
else {
|
||||||
LOGGER.info("Unable to bulk prune AT states. The database may have been left in an inconsistent state.");
|
LOGGER.info("Unable to prune blocks due to missing ATStatesHeightIndex. Bootstrapping is recommended.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -118,4 +128,12 @@ public abstract class RepositoryManager {
|
|||||||
return SQLException.class.isInstance(cause) && repositoryFactory.isDeadlockException((SQLException) cause);
|
return SQLException.class.isInstance(cause) && repositoryFactory.isDeadlockException((SQLException) cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canArchiveOrPrune() {
|
||||||
|
try (final Repository repository = getRepository()) {
|
||||||
|
return repository.getATRepository().hasAtStatesHeightIndex();
|
||||||
|
} catch (DataException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -798,6 +798,19 @@ public class HSQLDBATRepository implements ATRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAtStatesHeightIndex() throws DataException {
|
||||||
|
String sql = "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.SYSTEM_INDEXINFO where INDEX_NAME='ATSTATESHEIGHTINDEX'";
|
||||||
|
|
||||||
|
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
|
||||||
|
return resultSet != null;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to check for ATStatesHeightIndex in repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(ATStateData atStateData) throws DataException {
|
public void save(ATStateData atStateData) throws DataException {
|
||||||
// We shouldn't ever save partial ATStateData
|
// We shouldn't ever save partial ATStateData
|
||||||
|
@ -17,6 +17,7 @@ import org.qortal.data.transaction.DeployAtTransactionData;
|
|||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
import org.qortal.group.Group;
|
import org.qortal.group.Group;
|
||||||
import org.qortal.repository.*;
|
import org.qortal.repository.*;
|
||||||
|
import org.qortal.repository.hsqldb.HSQLDBRepository;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
import org.qortal.test.common.AtUtils;
|
import org.qortal.test.common.AtUtils;
|
||||||
import org.qortal.test.common.BlockUtils;
|
import org.qortal.test.common.BlockUtils;
|
||||||
@ -33,6 +34,7 @@ import java.io.IOException;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -487,6 +489,29 @@ public class BlockArchiveTests extends Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Many nodes are missing an ATStatesHeightIndex due to an earlier bug
|
||||||
|
* In these cases we disable archiving and pruning as this index is a
|
||||||
|
* very essential component in these processes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMissingAtStatesHeightIndex() throws DataException, SQLException {
|
||||||
|
try (final HSQLDBRepository repository = (HSQLDBRepository) RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
// Firstly check that we're able to prune or archive when the index exists
|
||||||
|
assertTrue(repository.getATRepository().hasAtStatesHeightIndex());
|
||||||
|
assertTrue(RepositoryManager.canArchiveOrPrune());
|
||||||
|
|
||||||
|
// Delete the index
|
||||||
|
repository.prepareStatement("DROP INDEX ATSTATESHEIGHTINDEX").execute();
|
||||||
|
|
||||||
|
// Ensure check that we're unable to prune or archive when the index doesn't exist
|
||||||
|
assertFalse(repository.getATRepository().hasAtStatesHeightIndex());
|
||||||
|
assertFalse(RepositoryManager.canArchiveOrPrune());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void deleteArchiveDirectory() {
|
private void deleteArchiveDirectory() {
|
||||||
// Delete archive directory if exists
|
// Delete archive directory if exists
|
||||||
Path archivePath = Paths.get(Settings.getInstance().getRepositoryPath(), "archive").toAbsolutePath();
|
Path archivePath = Paths.get(Settings.getInstance().getRepositoryPath(), "archive").toAbsolutePath();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user