forked from Qortal/qortal
Merge branch 'master' into prioritize-peers
This commit is contained in:
commit
3022cb22d6
@ -547,7 +547,7 @@ public class AdminResource {
|
|||||||
blockchainLock.lockInterruptibly();
|
blockchainLock.lockInterruptibly();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
repository.exportNodeLocalData();
|
repository.exportNodeLocalData(true);
|
||||||
return "true";
|
return "true";
|
||||||
} finally {
|
} finally {
|
||||||
blockchainLock.unlock();
|
blockchainLock.unlock();
|
||||||
|
@ -797,7 +797,7 @@ public class Controller extends Thread {
|
|||||||
actionText = Translator.INSTANCE.translate("SysTray", "MINTING_DISABLED");
|
actionText = Translator.INSTANCE.translate("SysTray", "MINTING_DISABLED");
|
||||||
}
|
}
|
||||||
|
|
||||||
String tooltip = String.format("%s - %d %s - %s %d", actionText, numberOfPeers, connectionsText, heightText, height);
|
String tooltip = String.format("%s - %d %s - %s %d", actionText, numberOfPeers, connectionsText, heightText, height) + "\n" + String.format("Build version: %s", this.buildVersion);
|
||||||
SysTray.getInstance().setToolTipText(tooltip);
|
SysTray.getInstance().setToolTipText(tooltip);
|
||||||
|
|
||||||
this.callbackExecutor.execute(() -> {
|
this.callbackExecutor.execute(() -> {
|
||||||
|
@ -211,6 +211,9 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
|
|
||||||
TradeBot.updateTradeBotState(repository, tradeBotData, () -> String.format("Built AT %s. Waiting for deployment", atAddress));
|
TradeBot.updateTradeBotState(repository, tradeBotData, () -> String.format("Built AT %s. Waiting for deployment", atAddress));
|
||||||
|
|
||||||
|
// Attempt to backup the trade bot data
|
||||||
|
TradeBot.backupTradeBotData(repository);
|
||||||
|
|
||||||
// Return to user for signing and broadcast as we don't have their Qortal private key
|
// Return to user for signing and broadcast as we don't have their Qortal private key
|
||||||
try {
|
try {
|
||||||
return DeployAtTransactionTransformer.toBytes(deployAtTransactionData);
|
return DeployAtTransactionTransformer.toBytes(deployAtTransactionData);
|
||||||
@ -283,6 +286,9 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
tradeForeignPublicKey, tradeForeignPublicKeyHash,
|
tradeForeignPublicKey, tradeForeignPublicKeyHash,
|
||||||
crossChainTradeData.expectedForeignAmount, xprv58, null, lockTimeA, receivingPublicKeyHash);
|
crossChainTradeData.expectedForeignAmount, xprv58, null, lockTimeA, receivingPublicKeyHash);
|
||||||
|
|
||||||
|
// Attempt to backup the trade bot data
|
||||||
|
TradeBot.backupTradeBotData(repository);
|
||||||
|
|
||||||
// Check we have enough funds via xprv58 to fund P2SH to cover expectedForeignAmount
|
// Check we have enough funds via xprv58 to fund P2SH to cover expectedForeignAmount
|
||||||
long p2shFee;
|
long p2shFee;
|
||||||
try {
|
try {
|
||||||
|
@ -7,6 +7,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -267,6 +268,22 @@ public class TradeBot implements Listener {
|
|||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ static void backupTradeBotData(Repository repository) {
|
||||||
|
// Attempt to backup the trade bot data. This an optional step and doesn't impact trading, so don't throw an exception on failure
|
||||||
|
try {
|
||||||
|
LOGGER.info("About to backup trade bot data...");
|
||||||
|
ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
|
||||||
|
blockchainLock.lockInterruptibly();
|
||||||
|
try {
|
||||||
|
repository.exportNodeLocalData(true);
|
||||||
|
} finally {
|
||||||
|
blockchainLock.unlock();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | DataException e) {
|
||||||
|
LOGGER.info(String.format("Failed to obtain blockchain lock when exporting trade bot data: %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Updates trade-bot entry to new state, with current timestamp, logs message and notifies state-change listeners. */
|
/** Updates trade-bot entry to new state, with current timestamp, logs message and notifies state-change listeners. */
|
||||||
/*package*/ static void updateTradeBotState(Repository repository, TradeBotData tradeBotData,
|
/*package*/ static void updateTradeBotState(Repository repository, TradeBotData tradeBotData,
|
||||||
String newState, int newStateValue, Supplier<String> logMessageSupplier) throws DataException {
|
String newState, int newStateValue, Supplier<String> logMessageSupplier) throws DataException {
|
||||||
|
@ -49,7 +49,7 @@ public interface Repository extends AutoCloseable {
|
|||||||
|
|
||||||
public void performPeriodicMaintenance() throws DataException;
|
public void performPeriodicMaintenance() throws DataException;
|
||||||
|
|
||||||
public void exportNodeLocalData() throws DataException;
|
public void exportNodeLocalData(boolean keepArchivedCopy) throws DataException;
|
||||||
|
|
||||||
public void importDataFromFile(String filename) throws DataException;
|
public void importDataFromFile(String filename) throws DataException;
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ import org.qortal.repository.TransactionRepository;
|
|||||||
import org.qortal.repository.VotingRepository;
|
import org.qortal.repository.VotingRepository;
|
||||||
import org.qortal.repository.hsqldb.transaction.HSQLDBTransactionRepository;
|
import org.qortal.repository.hsqldb.transaction.HSQLDBTransactionRepository;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
import org.qortal.utils.NTP;
|
||||||
|
|
||||||
public class HSQLDBRepository implements Repository {
|
public class HSQLDBRepository implements Repository {
|
||||||
|
|
||||||
@ -459,10 +460,44 @@ public class HSQLDBRepository implements Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exportNodeLocalData() throws DataException {
|
public void exportNodeLocalData(boolean keepArchivedCopy) throws DataException {
|
||||||
|
|
||||||
|
// Create the qortal-backup folder if it doesn't exist
|
||||||
|
Path backupPath = Paths.get("qortal-backup");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(backupPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.info("Unable to create backup folder");
|
||||||
|
throw new DataException("Unable to create backup folder");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to rename or delete an existing TradeBotStates backup before creating a new one
|
||||||
|
File tradeBotStatesBackupFile = new File("qortal-backup/TradeBotStates.script");
|
||||||
|
if (tradeBotStatesBackupFile.exists()) {
|
||||||
|
if (keepArchivedCopy) {
|
||||||
|
// Rename existing TradeBotStates backup, to make sure that we're not overwriting any keys
|
||||||
|
File archivedBackupFile = new File(String.format("qortal-backup/TradeBotStates-archive-%d.script", NTP.getTime()));
|
||||||
|
if (tradeBotStatesBackupFile.renameTo(archivedBackupFile))
|
||||||
|
LOGGER.info(String.format("Moved existing TradeBotStates backup file to %s", archivedBackupFile.getPath()));
|
||||||
|
else
|
||||||
|
throw new DataException("Unable to rename existing TradeBotStates backup");
|
||||||
|
} else {
|
||||||
|
// Delete existing copy
|
||||||
|
LOGGER.info("Deleting existing TradeBotStates backup because it is being replaced with a new one");
|
||||||
|
tradeBotStatesBackupFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's currently no need to take an archived copy of the MintingAccounts data - just delete the old one if it exists
|
||||||
|
File mintingAccountsBackupFile = new File("qortal-backup/MintingAccounts.script");
|
||||||
|
if (mintingAccountsBackupFile.exists()) {
|
||||||
|
LOGGER.info("Deleting existing MintingAccounts backup because it is being replaced with a new one");
|
||||||
|
mintingAccountsBackupFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
try (Statement stmt = this.connection.createStatement()) {
|
try (Statement stmt = this.connection.createStatement()) {
|
||||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE MintingAccounts DATA TO 'MintingAccounts.script'");
|
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE MintingAccounts DATA TO 'qortal-backup/MintingAccounts.script'");
|
||||||
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE TradeBotStates DATA TO 'TradeBotStates.script'");
|
stmt.execute("PERFORM EXPORT SCRIPT FOR TABLE TradeBotStates DATA TO 'qortal-backup/TradeBotStates.script'");
|
||||||
LOGGER.info("Exported sensitive/node-local data: minting keys and trade bot states");
|
LOGGER.info("Exported sensitive/node-local data: minting keys and trade bot states");
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to export sensitive/node-local data from repository");
|
throw new DataException("Unable to export sensitive/node-local data from repository");
|
||||||
@ -475,12 +510,12 @@ public class HSQLDBRepository implements Repository {
|
|||||||
LOGGER.info(() -> String.format("Importing data into repository from %s", filename));
|
LOGGER.info(() -> String.format("Importing data into repository from %s", filename));
|
||||||
|
|
||||||
String escapedFilename = stmt.enquoteLiteral(filename);
|
String escapedFilename = stmt.enquoteLiteral(filename);
|
||||||
stmt.execute("PERFORM IMPORT SCRIPT DATA FROM " + escapedFilename + " STOP ON ERROR");
|
stmt.execute("PERFORM IMPORT SCRIPT DATA FROM " + escapedFilename + " CONTINUE ON ERROR");
|
||||||
|
|
||||||
LOGGER.info(() -> String.format("Imported data into repository from %s", filename));
|
LOGGER.info(() -> String.format("Imported data into repository from %s", filename));
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
LOGGER.info(() -> String.format("Failed to import data into repository from %s: %s", filename, e.getMessage()));
|
LOGGER.info(() -> String.format("Failed to import data into repository from %s: %s", filename, e.getMessage()));
|
||||||
throw new DataException("Unable to export sensitive/node-local data from repository: " + e.getMessage());
|
throw new DataException("Unable to import sensitive/node-local data to repository: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +716,7 @@ public class HSQLDBRepository implements Repository {
|
|||||||
/**
|
/**
|
||||||
* Execute PreparedStatement and return changed row count.
|
* Execute PreparedStatement and return changed row count.
|
||||||
*
|
*
|
||||||
* @param preparedStatement
|
* @param sql
|
||||||
* @param objects
|
* @param objects
|
||||||
* @return number of changed rows
|
* @return number of changed rows
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
@ -693,8 +728,8 @@ public class HSQLDBRepository implements Repository {
|
|||||||
/**
|
/**
|
||||||
* Execute batched PreparedStatement
|
* Execute batched PreparedStatement
|
||||||
*
|
*
|
||||||
* @param preparedStatement
|
* @param sql
|
||||||
* @param objects
|
* @param batchedObjects
|
||||||
* @return number of changed rows
|
* @return number of changed rows
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
@ -818,7 +853,7 @@ public class HSQLDBRepository implements Repository {
|
|||||||
*
|
*
|
||||||
* @param tableName
|
* @param tableName
|
||||||
* @param whereClause
|
* @param whereClause
|
||||||
* @param objects
|
* @param batchedObjects
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public int deleteBatch(String tableName, String whereClause, List<Object[]> batchedObjects) throws SQLException {
|
public int deleteBatch(String tableName, String whereClause, List<Object[]> batchedObjects) throws SQLException {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user