Skip to content

Commit

Permalink
[Refactor] Break up Auto-backup monolithic code in init.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
random-zebra committed May 7, 2021
1 parent 6ab142b commit 1270ef8
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 78 deletions.
75 changes: 4 additions & 71 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
#include "net_processing.h"
#include "policy/feerate.h"
#include "policy/policy.h"
#include "reverse_iterate.h"
#include "rpc/register.h"
#include "rpc/server.h"
#include "script/sigcache.h"
Expand Down Expand Up @@ -87,9 +86,6 @@
#endif


#ifdef ENABLE_WALLET
int nWalletBackups = 10;
#endif
volatile bool fFeeEstimatesInitialized = false;
volatile bool fRestartRequested = false; // true: restart false: shutdown
static const bool DEFAULT_PROXYRANDOMIZE = true;
Expand Down Expand Up @@ -1305,74 +1301,11 @@ bool AppInitMain()

// ********************************************************* Step 5: Backup wallet and verify wallet database integrity
#ifdef ENABLE_WALLET
if (!InitAutoBackupWallet()) {
return false;
}

// not fixing indentation as this block of code will be moved away from here in the following commits
fs::path backupDir = GetDataDir() / "backups";
if (!fs::exists(backupDir)) {
// Always create backup folder to not confuse the operating system's file browser
fs::create_directories(backupDir);
}
nWalletBackups = gArgs.GetArg("-createwalletbackups", DEFAULT_CREATEWALLETBACKUPS);
nWalletBackups = std::max(0, std::min(10, nWalletBackups));
if (nWalletBackups > 0) {
if (fs::exists(backupDir)) {
// Create backup of the wallet
std::string dateTimeStr = FormatISO8601DateTimeForBackup(GetTime());
std::string backupPathStr = backupDir.string();
backupPathStr += "/" + strWalletFile;
std::string sourcePathStr = GetDataDir().string();
sourcePathStr += "/" + strWalletFile;
fs::path sourceFile = sourcePathStr;
fs::path backupFile = backupPathStr + dateTimeStr;
sourceFile.make_preferred();
backupFile.make_preferred();
if (fs::exists(sourceFile)) {
#if BOOST_VERSION >= 105800
try {
fs::copy_file(sourceFile, backupFile);
LogPrintf("Creating backup of %s -> %s\n", sourceFile, backupFile);
} catch (const fs::filesystem_error& error) {
LogPrintf("Failed to create backup %s\n", error.what());
}
#else
std::ifstream src(sourceFile.string(), std::ios::binary);
std::ofstream dst(backupFile.string(), std::ios::binary);
dst << src.rdbuf();
#endif
}
// Keep only the last 10 backups, including the new one of course
typedef std::multimap<std::time_t, fs::path> folder_set_t;
folder_set_t folder_set;
fs::directory_iterator end_iter;
fs::path backupFolder = backupDir.string();
backupFolder.make_preferred();
// Build map of backup files for current(!) wallet sorted by last write time
fs::path currentFile;
for (fs::directory_iterator dir_iter(backupFolder); dir_iter != end_iter; ++dir_iter) {
// Only check regular files
if (fs::is_regular_file(dir_iter->status())) {
currentFile = dir_iter->path().filename();
// Only add the backups for the current wallet, e.g. wallet.dat.*
if (dir_iter->path().stem().string() == strWalletFile) {
folder_set.insert(folder_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
}
}
}
// Loop backward through backup files and keep the N newest ones (1 <= N <= 10)
int counter = 0;
for (std::pair<const std::time_t, fs::path> file : reverse_iterate(folder_set)) {
counter++;
if (counter > nWalletBackups) {
// More than nWalletBackups backups: delete oldest one(s)
try {
fs::remove(file.second);
LogPrintf("Old backup deleted: %s\n", file.second);
} catch (const fs::filesystem_error& error) {
LogPrintf("Failed to delete backup %s\n", error.what());
}
}
}
}
}

if (gArgs.GetBoolArg("-resync", false)) {
uiInterface.InitMessage(_("Preparing for resync..."));
Expand Down
21 changes: 19 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2009-2021 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2020 The PIVX developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -4856,3 +4856,20 @@ const CWDestination* CAddressBookIterator::GetDestKey()
CStakeableOutput::CStakeableOutput(const CWalletTx* txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn,
const CBlockIndex*& _pindex) : COutput(txIn, iIn, nDepthIn, fSpendableIn, fSolvableIn),
pindex(_pindex) {}

bool InitAutoBackupWallet()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
return true;
}

std::string strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT);

std::string strWarning, strError;
if(!AutoBackupWallet(strWalletFile, strWarning, strError)) {
if (!strWarning.empty()) UIWarning(strWarning);
if (!strError.empty()) return UIError(strError);
}

return true;
}
13 changes: 8 additions & 5 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2009-2021 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2020 The PIVX developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_WALLET_H
#define BITCOIN_WALLET_H
#ifndef PIVX_WALLET_H
#define PIVX_WALLET_H

#include "addressbook.h"
#include "amount.h"
Expand Down Expand Up @@ -1267,4 +1267,7 @@ class WalletRescanReserver
}
};

#endif // BITCOIN_WALLET_H
// !TODO: move to wallet/init.*
bool InitAutoBackupWallet();

#endif // PIVX_WALLET_H
92 changes: 92 additions & 0 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "base58.h"
#include "protocol.h"
#include "reverse_iterate.h"
#include "sapling/key_io_sapling.h"
#include "serialize.h"
#include "sync.h"
Expand Down Expand Up @@ -870,6 +871,97 @@ std::pair<fs::path, fs::path> GetBackupPath(const CWallet& wallet)
return {pathCustom, pathWithFile};
}

bool AutoBackupWallet(const std::string& strWalletFile, std::string& strBackupWarning, std::string& strBackupError)
{
strBackupWarning = strBackupError = "";

int nWalletBackups = gArgs.GetArg("-createwalletbackups", DEFAULT_CREATEWALLETBACKUPS);
nWalletBackups = std::max(0, std::min(10, nWalletBackups));

if (nWalletBackups == 0) {
LogPrintf("Automatic wallet backups are disabled!\n");
return false;
}

fs::path backupsDir = GetDataDir() / "backups";
if (!fs::exists(backupsDir)) {
// Always create backup folder to not confuse the operating system's file browser
LogPrintf("Creating backup folder %s\n", backupsDir.string());
if(!fs::create_directories(backupsDir)) {
// smth is wrong, we shouldn't continue until it's resolved
strBackupError = strprintf(_("Wasn't able to create wallet backup folder %s!"), backupsDir.string());
LogPrintf("%s\n", strBackupError);
nWalletBackups = -1;
return false;
}
}
// Create backup of the ...
std::string dateTimeStr = FormatISO8601DateTimeForBackup(GetTime());

// ... strWalletFile file
fs::path sourceFile = GetDataDir() / strWalletFile;
fs::path backupFile = backupsDir / (strWalletFile + dateTimeStr);
sourceFile.make_preferred();
backupFile.make_preferred();
if (fs::exists(backupFile)) {
strBackupWarning = _("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this.");
LogPrintf("%s\n", strBackupWarning);
return false;
}
if(fs::exists(sourceFile)) {
#if BOOST_VERSION >= 105800
try {
fs::copy_file(sourceFile, backupFile);
LogPrintf("Creating backup of %s -> %s\n", sourceFile.string(), backupFile.string());
} catch(fs::filesystem_error &error) {
strBackupWarning = strprintf(_("Failed to create backup, error: %s"), error.what());
LogPrintf("%s\n", strBackupWarning);
nWalletBackups = -1;
return false;
}
#else
std::ifstream src(sourceFile.string(), std::ios::binary);
std::ofstream dst(backupFile.string(), std::ios::binary);
dst << src.rdbuf();
#endif
}

// Keep only the last 10 backups, including the new one of course
typedef std::multimap<std::time_t, fs::path> folder_set_t;
folder_set_t folder_set;
fs::directory_iterator end_iter;
backupsDir.make_preferred();
// Build map of backup files for current(!) wallet sorted by last write time
fs::path currentFile;
for (fs::directory_iterator dir_iter(backupsDir); dir_iter != end_iter; ++dir_iter) {
// Only check regular files
if ( fs::is_regular_file(dir_iter->status())) {
currentFile = dir_iter->path().filename();
// Only add the backups for the current wallet, e.g. wallet.dat.*
if(dir_iter->path().stem().string() == strWalletFile) {
folder_set.insert(folder_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
}
}
}
// Loop backward through backup files and keep the N newest ones (1 <= N <= 10)
int counter = 0;
for (std::pair<const std::time_t, fs::path> file : reverse_iterate(folder_set)) {
counter++;
if (counter > nWalletBackups) {
// More than nWalletBackups backups: delete oldest one(s)
try {
fs::remove(file.second);
LogPrintf("Old backup deleted: %s\n", file.second);
} catch(fs::filesystem_error &error) {
strBackupWarning = strprintf(_("Failed to delete backup, error: %s"), error.what());
LogPrintf("%s\n", strBackupWarning);
return false;
}
}
}
return true;
}

void MultiBackup(const CWallet& wallet, fs::path pathCustom, fs::path pathWithFile, const fs::path& pathSrc)
{
int nThreshold = gArgs.GetArg("-custombackupthreshold", DEFAULT_CUSTOMBACKUPTHRESHOLD);
Expand Down
3 changes: 3 additions & 0 deletions src/wallet/walletdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ void NotifyBacked(const CWallet& wallet, bool fSuccess, std::string strMessage);
bool BackupWallet(const CWallet& wallet, const fs::path& strDest);
bool AttemptBackupWallet(const CWallet& wallet, const fs::path& pathSrc, const fs::path& pathDest);

//! Called during init: Automatic backups of wallet not running (just copying and renaming dat file)
bool AutoBackupWallet(const std::string& strWalletFile, std::string& strBackupWarning, std::string& strBackupError);

//! Compacts BDB state so that wallet.dat is self-contained (if there are changes)
void MaybeCompactWalletDB();

Expand Down

0 comments on commit 1270ef8

Please sign in to comment.