forked from Qortal/qortal
Don't rebuild repository or export node-local data during repository build if repository was 'pristine'.
Under certain conditions, e.g. non-existent database files, the repository would be created and then immediately be re-created. Not only was this unnecessary, but HSQLDBDatabaseUpdates would attempt to export the node-local data twice, which would cause an error due to existing .script files. The fix is three-pronged: 1. Don't immediately rebuild the repository if it's only just been built 2. Don't export the empty node-local data if repository has only just been built 3. Don't export the node-local data if it's empty
This commit is contained in:
parent
806baa6ae4
commit
1f409235e4
@ -531,7 +531,8 @@ public class BlockChain {
|
||||
|
||||
private static void rebuildBlockchain() throws DataException {
|
||||
// (Re)build repository
|
||||
RepositoryManager.rebuild();
|
||||
if (!RepositoryManager.wasPristineAtOpen())
|
||||
RepositoryManager.rebuild();
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
GenesisBlock genesisBlock = GenesisBlock.getInstance(repository);
|
||||
|
@ -2,6 +2,8 @@ package org.qortal.repository;
|
||||
|
||||
public interface RepositoryFactory {
|
||||
|
||||
public boolean wasPristineAtOpen();
|
||||
|
||||
public RepositoryFactory reopen() throws DataException;
|
||||
|
||||
public Repository getRepository() throws DataException;
|
||||
|
@ -8,6 +8,13 @@ public abstract class RepositoryManager {
|
||||
repositoryFactory = newRepositoryFactory;
|
||||
}
|
||||
|
||||
public static boolean wasPristineAtOpen() throws DataException {
|
||||
if (repositoryFactory == null)
|
||||
throw new DataException("No repository available");
|
||||
|
||||
return repositoryFactory.wasPristineAtOpen();
|
||||
}
|
||||
|
||||
public static Repository getRepository() throws DataException {
|
||||
if (repositoryFactory == null)
|
||||
throw new DataException("No repository available");
|
||||
|
@ -18,11 +18,16 @@ public class HSQLDBDatabaseUpdates {
|
||||
/**
|
||||
* Apply any incremental changes to database schema.
|
||||
*
|
||||
* @return true if database was non-existent/empty, false otherwise
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static void updateDatabase(Connection connection) throws SQLException {
|
||||
while (databaseUpdating(connection))
|
||||
public static boolean updateDatabase(Connection connection) throws SQLException {
|
||||
final boolean wasPristine = fetchDatabaseVersion(connection) == 0;
|
||||
|
||||
while (databaseUpdating(connection, wasPristine))
|
||||
incrementDatabaseVersion(connection);
|
||||
|
||||
return wasPristine;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,23 +45,21 @@ public class HSQLDBDatabaseUpdates {
|
||||
/**
|
||||
* Fetch current version of database schema.
|
||||
*
|
||||
* @return int, 0 if no schema yet
|
||||
* @return database version, or 0 if no schema yet
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static int fetchDatabaseVersion(Connection connection) throws SQLException {
|
||||
int databaseVersion = 0;
|
||||
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
if (stmt.execute("SELECT version FROM DatabaseInfo"))
|
||||
try (ResultSet resultSet = stmt.getResultSet()) {
|
||||
if (resultSet.next())
|
||||
databaseVersion = resultSet.getInt(1);
|
||||
return resultSet.getInt(1);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// empty database
|
||||
}
|
||||
|
||||
return databaseVersion;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,7 +68,7 @@ public class HSQLDBDatabaseUpdates {
|
||||
* @return true - if a schema update happened, false otherwise
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static boolean databaseUpdating(Connection connection) throws SQLException {
|
||||
private static boolean databaseUpdating(Connection connection, boolean wasPristine) throws SQLException {
|
||||
int databaseVersion = fetchDatabaseVersion(connection);
|
||||
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
@ -695,11 +698,24 @@ public class HSQLDBDatabaseUpdates {
|
||||
case 30:
|
||||
// Split AT state data off to new table for better performance/management.
|
||||
|
||||
if (!"mem".equals(HSQLDBRepository.getDbPathname(connection.getMetaData().getURL()))) {
|
||||
if (!wasPristine && !"mem".equals(HSQLDBRepository.getDbPathname(connection.getMetaData().getURL()))) {
|
||||
// First, backup node-local data in case user wants to avoid long reshape and use bootstrap instead
|
||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE MintingAccounts DATA TO 'MintingAccounts.script'");
|
||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE TradeBotStates DATA TO 'TradeBotStates.script'");
|
||||
LOGGER.info("Exported sensitive/node-local data: minting keys and trade bot states");
|
||||
try (ResultSet resultSet = stmt.executeQuery("SELECT COUNT(*) FROM MintingAccounts")) {
|
||||
int rowCount = resultSet.next() ? resultSet.getInt(1) : 0;
|
||||
if (rowCount > 0) {
|
||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE MintingAccounts DATA TO 'MintingAccounts.script'");
|
||||
LOGGER.info("Exported sensitive/node-local minting keys into MintingAccounts.script");
|
||||
}
|
||||
}
|
||||
|
||||
try (ResultSet resultSet = stmt.executeQuery("SELECT COUNT(*) FROM TradeBotStates")) {
|
||||
int rowCount = resultSet.next() ? resultSet.getInt(1) : 0;
|
||||
if (rowCount > 0) {
|
||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE TradeBotStates DATA TO 'TradeBotStates.script'");
|
||||
LOGGER.info("Exported sensitive/node-local trade-bot states into TradeBotStates.script");
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("If following reshape takes too long, use bootstrap and import node-local data using API's POST /admin/repository/data");
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
|
||||
private String connectionUrl;
|
||||
private HSQLDBPool connectionPool;
|
||||
private final boolean wasPristine;
|
||||
|
||||
/**
|
||||
* Constructs new RepositoryFactory using passed <tt>connectionUrl</tt>.
|
||||
@ -65,12 +66,17 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
|
||||
// Perform DB updates?
|
||||
try (final Connection connection = this.connectionPool.getConnection()) {
|
||||
HSQLDBDatabaseUpdates.updateDatabase(connection);
|
||||
this.wasPristine = HSQLDBDatabaseUpdates.updateDatabase(connection);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Repository initialization error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wasPristineAtOpen() {
|
||||
return this.wasPristine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryFactory reopen() throws DataException {
|
||||
return new HSQLDBRepositoryFactory(this.connectionUrl);
|
||||
|
Loading…
x
Reference in New Issue
Block a user