mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-11-16 15:58:08 +00:00
automatically restore backup cache if corrupt
This commit is contained in:
parent
2d0f200aa1
commit
a8e76fd720
2 changed files with 111 additions and 11 deletions
|
@ -40,10 +40,13 @@ import java.util.Scanner;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FileUtil {
|
public class FileUtil {
|
||||||
|
|
||||||
|
private static final String BACKUP_DIR = "backup";
|
||||||
|
|
||||||
public static void rollingBackup(File dir, String fileName, int numMaxBackupFiles) {
|
public static void rollingBackup(File dir, String fileName, int numMaxBackupFiles) {
|
||||||
if (numMaxBackupFiles <= 0) return;
|
if (numMaxBackupFiles <= 0) return;
|
||||||
if (dir.exists()) {
|
if (dir.exists()) {
|
||||||
File backupDir = new File(Paths.get(dir.getAbsolutePath(), "backup").toString());
|
File backupDir = new File(Paths.get(dir.getAbsolutePath(), BACKUP_DIR).toString());
|
||||||
if (!backupDir.exists())
|
if (!backupDir.exists())
|
||||||
if (!backupDir.mkdir())
|
if (!backupDir.mkdir())
|
||||||
log.warn("make dir failed.\nBackupDir=" + backupDir.getAbsolutePath());
|
log.warn("make dir failed.\nBackupDir=" + backupDir.getAbsolutePath());
|
||||||
|
@ -72,8 +75,21 @@ public class FileUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static File getLatestBackupFile(File dir, String fileName) {
|
||||||
|
File backupDir = new File(Paths.get(dir.getAbsolutePath(), BACKUP_DIR).toString());
|
||||||
|
if (!backupDir.exists()) return null;
|
||||||
|
String dirName = "backups_" + fileName;
|
||||||
|
if (dirName.contains(".")) dirName = dirName.replace(".", "_");
|
||||||
|
File backupFileDir = new File(Paths.get(backupDir.getAbsolutePath(), dirName).toString());
|
||||||
|
if (!backupFileDir.exists()) return null;
|
||||||
|
File[] files = backupFileDir.listFiles();
|
||||||
|
if (files == null || files.length == 0) return null;
|
||||||
|
Arrays.sort(files, Comparator.comparing(File::getName));
|
||||||
|
return files[files.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
public static void deleteRollingBackup(File dir, String fileName) {
|
public static void deleteRollingBackup(File dir, String fileName) {
|
||||||
File backupDir = new File(Paths.get(dir.getAbsolutePath(), "backup").toString());
|
File backupDir = new File(Paths.get(dir.getAbsolutePath(), BACKUP_DIR).toString());
|
||||||
if (!backupDir.exists()) return;
|
if (!backupDir.exists()) return;
|
||||||
String dirName = "backups_" + fileName;
|
String dirName = "backups_" + fileName;
|
||||||
if (dirName.contains(".")) dirName = dirName.replace(".", "_");
|
if (dirName.contains(".")) dirName = dirName.replace(".", "_");
|
||||||
|
|
|
@ -136,7 +136,6 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
private final WalletsSetup walletsSetup;
|
private final WalletsSetup walletsSetup;
|
||||||
|
|
||||||
private final File walletDir;
|
private final File walletDir;
|
||||||
private final File xmrWalletFile;
|
|
||||||
private final int rpcBindPort;
|
private final int rpcBindPort;
|
||||||
private final boolean useNativeXmrWallet;
|
private final boolean useNativeXmrWallet;
|
||||||
protected final CopyOnWriteArraySet<XmrBalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
|
protected final CopyOnWriteArraySet<XmrBalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
|
||||||
|
@ -181,7 +180,6 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
this.walletDir = walletDir;
|
this.walletDir = walletDir;
|
||||||
this.rpcBindPort = rpcBindPort;
|
this.rpcBindPort = rpcBindPort;
|
||||||
this.useNativeXmrWallet = useNativeXmrWallet;
|
this.useNativeXmrWallet = useNativeXmrWallet;
|
||||||
this.xmrWalletFile = new File(walletDir, MONERO_WALLET_NAME);
|
|
||||||
HavenoUtils.xmrWalletService = this;
|
HavenoUtils.xmrWalletService = this;
|
||||||
HavenoUtils.xmrConnectionService = xmrConnectionService;
|
HavenoUtils.xmrConnectionService = xmrConnectionService;
|
||||||
this.xmrConnectionService = xmrConnectionService; // TODO: super's is null unless set here from injection
|
this.xmrConnectionService = xmrConnectionService; // TODO: super's is null unless set here from injection
|
||||||
|
@ -1327,7 +1325,7 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
if (wallet == null) {
|
if (wallet == null) {
|
||||||
MoneroDaemonRpc daemon = xmrConnectionService.getDaemon();
|
MoneroDaemonRpc daemon = xmrConnectionService.getDaemon();
|
||||||
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
|
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
|
||||||
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
if (walletExists(MONERO_WALLET_NAME)) {
|
||||||
wallet = openWallet(MONERO_WALLET_NAME, rpcBindPort, isProxyApplied(wasWalletSynced));
|
wallet = openWallet(MONERO_WALLET_NAME, rpcBindPort, isProxyApplied(wasWalletSynced));
|
||||||
} else if (Boolean.TRUE.equals(xmrConnectionService.isConnected())) {
|
} else if (Boolean.TRUE.equals(xmrConnectionService.isConnected())) {
|
||||||
wallet = createWallet(MONERO_WALLET_NAME, rpcBindPort);
|
wallet = createWallet(MONERO_WALLET_NAME, rpcBindPort);
|
||||||
|
@ -1475,11 +1473,54 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
MoneroRpcConnection connection = new MoneroRpcConnection(xmrConnectionService.getConnection());
|
MoneroRpcConnection connection = new MoneroRpcConnection(xmrConnectionService.getConnection());
|
||||||
if (!applyProxyUri) connection.setProxyUri(null);
|
if (!applyProxyUri) connection.setProxyUri(null);
|
||||||
|
|
||||||
// open wallet
|
// try opening wallet
|
||||||
config.setNetworkType(getMoneroNetworkType());
|
config.setNetworkType(getMoneroNetworkType());
|
||||||
config.setServer(connection);
|
config.setServer(connection);
|
||||||
log.info("Opening full wallet " + config.getPath() + " with monerod=" + connection.getUri() + ", proxyUri=" + connection.getProxyUri());
|
log.info("Opening full wallet " + config.getPath() + " with monerod=" + connection.getUri() + ", proxyUri=" + connection.getProxyUri());
|
||||||
walletFull = MoneroWalletFull.openWallet(config);
|
try {
|
||||||
|
walletFull = MoneroWalletFull.openWallet(config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to open full wallet '{}', attempting to use backup cache, error={}", config.getPath(), e.getMessage());
|
||||||
|
boolean retrySuccessful = false;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// rename wallet cache to backup
|
||||||
|
String cachePath = walletDir.toString() + File.separator + MONERO_WALLET_NAME;
|
||||||
|
File originalCacheFile = new File(cachePath);
|
||||||
|
if (originalCacheFile.exists()) originalCacheFile.renameTo(new File(cachePath + ".backup"));
|
||||||
|
|
||||||
|
// copy latest wallet cache backup to main folder
|
||||||
|
File backupCacheFile = FileUtil.getLatestBackupFile(walletDir, MONERO_WALLET_NAME);
|
||||||
|
if (backupCacheFile != null) FileUtil.copyFile(backupCacheFile, new File(cachePath));
|
||||||
|
|
||||||
|
// retry opening wallet without original cache
|
||||||
|
try {
|
||||||
|
walletFull = MoneroWalletFull.openWallet(config);
|
||||||
|
log.info("Successfully opened full wallet using backup cache");
|
||||||
|
retrySuccessful = true;
|
||||||
|
} catch (Exception e2) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle success or failure
|
||||||
|
if (retrySuccessful) {
|
||||||
|
originalCacheFile.delete(); // delete original wallet cache backup
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// restore original wallet cache
|
||||||
|
log.warn("Failed to open full wallet using backup cache, restoring original cache");
|
||||||
|
File cacheFile = new File(cachePath);
|
||||||
|
if (cacheFile.exists()) cacheFile.delete();
|
||||||
|
File originalCacheBackup = new File(cachePath + ".backup");
|
||||||
|
if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath));
|
||||||
|
|
||||||
|
// throw exception
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} catch (Exception e2) {
|
||||||
|
throw e; // throw original exception
|
||||||
|
}
|
||||||
|
}
|
||||||
if (walletFull.getDaemonConnection() != null) walletFull.getDaemonConnection().setPrintStackTrace(PRINT_RPC_STACK_TRACE);
|
if (walletFull.getDaemonConnection() != null) walletFull.getDaemonConnection().setPrintStackTrace(PRINT_RPC_STACK_TRACE);
|
||||||
log.info("Done opening full wallet " + config.getPath());
|
log.info("Done opening full wallet " + config.getPath());
|
||||||
return walletFull;
|
return walletFull;
|
||||||
|
@ -1518,7 +1559,7 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
|
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
|
||||||
throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes, and restart Haveno.");
|
throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1537,17 +1578,60 @@ public class XmrWalletService extends XmrWalletBase {
|
||||||
MoneroRpcConnection connection = new MoneroRpcConnection(xmrConnectionService.getConnection());
|
MoneroRpcConnection connection = new MoneroRpcConnection(xmrConnectionService.getConnection());
|
||||||
if (!applyProxyUri) connection.setProxyUri(null);
|
if (!applyProxyUri) connection.setProxyUri(null);
|
||||||
|
|
||||||
// open wallet
|
// try opening wallet
|
||||||
log.info("Opening RPC wallet " + config.getPath() + " with monerod=" + connection.getUri() + ", proxyUri=" + connection.getProxyUri());
|
log.info("Opening RPC wallet " + config.getPath() + " with monerod=" + connection.getUri() + ", proxyUri=" + connection.getProxyUri());
|
||||||
config.setServer(connection);
|
config.setServer(connection);
|
||||||
walletRpc.openWallet(config);
|
try {
|
||||||
|
walletRpc.openWallet(config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to open RPC wallet '{}', attempting to use backup cache, error={}", config.getPath(), e.getMessage());
|
||||||
|
boolean retrySuccessful = false;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// rename wallet cache to backup
|
||||||
|
String cachePath = walletDir.toString() + File.separator + MONERO_WALLET_NAME;
|
||||||
|
File originalCacheFile = new File(cachePath);
|
||||||
|
if (originalCacheFile.exists()) originalCacheFile.renameTo(new File(cachePath + ".backup"));
|
||||||
|
|
||||||
|
// copy latest wallet cache backup to main folder
|
||||||
|
File backupCacheFile = FileUtil.getLatestBackupFile(walletDir, MONERO_WALLET_NAME);
|
||||||
|
if (backupCacheFile != null) FileUtil.copyFile(backupCacheFile, new File(cachePath));
|
||||||
|
|
||||||
|
// retry opening wallet without original cache
|
||||||
|
try {
|
||||||
|
walletRpc.openWallet(config);
|
||||||
|
log.info("Successfully opened RPC wallet using backup cache");
|
||||||
|
retrySuccessful = true;
|
||||||
|
} catch (Exception e2) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle success or failure
|
||||||
|
if (retrySuccessful) {
|
||||||
|
originalCacheFile.delete(); // delete original wallet cache backup
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// restore original wallet cache
|
||||||
|
log.warn("Failed to open RPC wallet using backup cache, restoring original cache");
|
||||||
|
File cacheFile = new File(cachePath);
|
||||||
|
if (cacheFile.exists()) cacheFile.delete();
|
||||||
|
File originalCacheBackup = new File(cachePath + ".backup");
|
||||||
|
if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath));
|
||||||
|
|
||||||
|
// throw exception
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} catch (Exception e2) {
|
||||||
|
throw e; // throw original exception
|
||||||
|
}
|
||||||
|
}
|
||||||
if (walletRpc.getDaemonConnection() != null) walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_RPC_STACK_TRACE);
|
if (walletRpc.getDaemonConnection() != null) walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_RPC_STACK_TRACE);
|
||||||
log.info("Done opening RPC wallet " + config.getPath());
|
log.info("Done opening RPC wallet " + config.getPath());
|
||||||
return walletRpc;
|
return walletRpc;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
|
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
|
||||||
throw new IllegalStateException("Could not open wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes, and restart Haveno.\n\nError message: " + e.getMessage());
|
throw new IllegalStateException("Could not open wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno.\n\nError message: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue