Commit cef9f2ed authored by coin-server's avatar coin-server

Merge branch 'walletdb_improvemenmts' into 'master'

[FIX] - Wrong Boost Version, Possible Read/Write Collision

See merge request ProjectMerge/merge!9
parents c7710a38 cb04eea0
......@@ -382,7 +382,9 @@ std::string HelpMessage(HelpMessageMode mode)
#ifdef ENABLE_WALLET
strUsage += HelpMessageGroup(_("Wallet options:"));
strUsage += HelpMessageOpt("-backuppath=<dir|file>", _("Specify custom backup path to add a copy of any wallet backup. If set as dir, every backup generates a timestamped file. If set as file, will rewrite to that file every backup."));
strUsage += HelpMessageOpt("-createwalletbackups=<n>", _("Number of automatic wallet backups (default: 10)"));
strUsage += HelpMessageOpt("-custombackupthreshold=<n>", strprintf(_("Number of custom location backups to retain (default: %d)"), DEFAULT_CUSTOMBACKUPTHRESHOLD));
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100));
if (GetBoolArg("-help-debug", false))
......@@ -1003,7 +1005,7 @@ bool AppInit2(boost::thread_group& threadGroup)
sourceFile.make_preferred();
backupFile.make_preferred();
if (boost::filesystem::exists(sourceFile)) {
#if BOOST_VERSION >= 158000
#if BOOST_VERSION >= 105800
try {
boost::filesystem::copy_file(sourceFile, backupFile);
LogPrintf("Creating backup of %s -> %s\n", sourceFile, backupFile);
......
......@@ -17,6 +17,9 @@
#include "rpcclient.h"
#include "rpcserver.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif // ENABLE_WALLET
#include "json/json_spirit_value.h"
......@@ -251,6 +254,8 @@ RPCConsole::RPCConsole(QWidget* parent) : QDialog(parent),
// set library version labels
ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
#ifdef ENABLE_WALLET
std::string strPathCustom = GetArg("-backuppath", "");
int nCustomBackupThreshold = GetArg("-custombackupthreshold", DEFAULT_CUSTOMBACKUPTHRESHOLD);
ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
ui->wallet_path->setText(QString::fromStdString(GetDataDir().string() + QDir::separator().toLatin1() + GetArg("-wallet", "wallet.dat")));
#else
......
......@@ -207,6 +207,7 @@ public:
void unlockCoin(COutPoint& output);
void listLockedCoins(std::vector<COutPoint>& vOutpts);
string GetUniqueWalletBackupName();
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string& sAddress, const int64_t nId, const std::string& sRequest);
......
......@@ -3775,3 +3775,11 @@ bool CMerkleTx::IsTransactionLockTimedOut() const
return false;
}
string CWallet::GetUniqueWalletBackupName() const
{
stringstream ssDateTime;
std::string strWalletBackupName = strprintf("%s", DateTimeStrFormat(".%Y-%m-%d-%H-%M", GetTime()));
ssDateTime << strWalletBackupName;
return strprintf("wallet%s.dat%s","", DateTimeStrFormat(".%Y-%m-%d-%H-%M", GetTime()));
}
......@@ -55,6 +55,8 @@ static const CAmount DEFAULT_TRANSACTION_MAXFEE = 1 * COIN;
static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning;
//! Largest (in bytes) free transaction we're willing to create
static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
//! -custombackupthreshold default
static const int DEFAULT_CUSTOMBACKUPTHRESHOLD = 1;
// Zerocoin denomination which creates exactly one of each denominations:
// 6666 = 1*5000 + 1*1000 + 1*500 + 1*100 + 1*50 + 1*10 + 1*5 + 1
......@@ -209,6 +211,7 @@ public:
std::string ResetSpentZerocoin();
void ReconsiderZerocoins(std::list<CZerocoinMint>& listMintsRestored);
void ZPivBackupWallet();
string GetUniqueWalletBackupName() const;
/** Zerocin entry changed.
* @note called with lock cs_wallet held.
......
......@@ -566,7 +566,7 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW
if (pwallet->nMasterKeyMaxID < nID)
pwallet->nMasterKeyMaxID = nID;
} else if (strType == "ckey") {
vector<unsigned char> vchPubKey;
CPubKey vchPubKey;
ssKey >> vchPubKey;
vector<unsigned char> vchPrivKey;
ssValue >> vchPrivKey;
......@@ -895,11 +895,38 @@ void ThreadFlushWalletDB(const string& strFile)
}
}
}
bool BackupWallet(const CWallet& wallet, const string& strDest)
// TODO: Missing Function this is copied From PIVX Master left Commented out
// void NotifyBacked(const CWallet& wallet, bool fSuccess, string strMessage)
// This needs to get implemented in /src/qt/walletmodell.cpp
// {
// LogPrint(nullptr, strMessage.data());
// wallet.NotifyWalletBacked(fSuccess, strMessage);
// }
bool BackupWallet(const CWallet& wallet, const filesystem::path& strDest, bool fEnableCustom)
{
if (!wallet.fFileBacked)
filesystem::path pathCustom;
filesystem::path pathWithFile;
if (!wallet.fFileBacked) {
return false;
} else if(fEnableCustom) {
pathWithFile = GetArg("-backuppath", "");
if(!pathWithFile.empty()) {
if(!pathWithFile.has_extension()) {
pathCustom = pathWithFile;
pathWithFile /= wallet.GetUniqueWalletBackupName();
} else {
pathCustom = pathWithFile.parent_path();
}
try {
filesystem::create_directories(pathCustom);
} catch(const filesystem::filesystem_error& e) {
// FIXME: NotifyBacked(wallet, false, strprintf("%s\n", e.what()));
pathCustom = "";
}
}
}
while (true) {
{
LOCK(bitdb.cs_db);
......@@ -910,25 +937,72 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
bitdb.mapFileUseCount.erase(wallet.strWalletFile);
// Copy wallet.dat
filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
filesystem::path pathDest(strDest);
if (filesystem::is_directory(pathDest))
filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
if (filesystem::is_directory(pathDest)) {
// FIXME:This is From PIVX but i believe we should create the path
// Before we check for is_directory()
if(!exists(pathDest)) filesystem::create_directory(pathDest);
pathDest /= wallet.strWalletFile;
try {
#if BOOST_VERSION >= 158000
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
#else
std::ifstream src(pathSrc.string(), std::ios::binary);
std::ofstream dst(pathDest.string(), std::ios::binary);
dst << src.rdbuf();
#endif
LogPrintf("copied wallet.dat to %s\n", pathDest.string());
return true;
} catch (const filesystem::filesystem_error& e) {
LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string(), e.what());
return false;
}
bool defaultPath = AttemptBackupWallet(wallet, pathSrc.string(), pathDest.string());
if(defaultPath && !pathCustom.empty()) {
int nThreshold = GetArg("-custombackupthreshold", DEFAULT_CUSTOMBACKUPTHRESHOLD);
if (nThreshold > 0) {
typedef std::multimap<std::time_t, filesystem::path> folder_set_t;
folder_set_t folderSet;
filesystem::directory_iterator end_iter;
pathCustom.make_preferred();
// Build map of backup files for current(!) wallet sorted by last write time
filesystem::path currentFile;
for (filesystem::directory_iterator dir_iter(pathCustom); dir_iter != end_iter; ++dir_iter) {
// Only check regular files
if (filesystem::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() == wallet.strWalletFile) {
folderSet.insert(folder_set_t::value_type(filesystem::last_write_time(dir_iter->path()), *dir_iter));
}
}
}
int counter = 0; //TODO: add seconds to avoid naming conflicts
for (auto entry : folderSet) {
counter++;
if(entry.second == pathWithFile) {
pathWithFile += "(1)";
}
}
if (counter >= nThreshold) {
std::time_t oldestBackup = 0;
for(auto entry : folderSet) {
if(oldestBackup == 0 || entry.first < oldestBackup) {
oldestBackup = entry.first;
}
}
try {
auto entry = folderSet.find(oldestBackup);
if (entry != folderSet.end()) {
filesystem::remove(entry->second);
LogPrintf("Old backup deleted: %s\n", (*entry).second);
}
} catch (filesystem::filesystem_error& error) {
string strMessage = strprintf("Failed to delete backup %s\n", error.what());
LogPrint(nullptr, strMessage.data());
//FIXME: NotifyBacked(wallet, false, strMessage);
}
}
}
AttemptBackupWallet(wallet, pathSrc.string(), pathWithFile.string());
}
return defaultPath;
}
}
MilliSleep(100);
......@@ -936,6 +1010,38 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
return false;
}
bool AttemptBackupWallet(const CWallet& wallet, const filesystem::path& pathSrc, const filesystem::path& pathDest)
{
bool retStatus;
string strMessage;
try {
if (boost::filesystem::equivalent(pathSrc, pathDest)) {
LogPrintf("cannot backup to wallet source file %s\n", pathDest.string());
return false;
}
#if BOOST_VERSION >= 105800 /* BOOST_LIB_VERSION 1_58 */
filesystem::copy_file(pathSrc.c_str(), pathDest, filesystem::copy_option::overwrite_if_exists);
#else
std::ifstream src(pathSrc.c_str(), std::ios::binary | std::ios::in);
std::ofstream dst(pathDest.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
dst << src.rdbuf();
dst.flush();
src.close();
dst.close();
#endif
strMessage = strprintf("copied wallet.dat to %s\n", pathDest.string());
LogPrint(nullptr, strMessage.data());
retStatus = true;
} catch (const filesystem::filesystem_error& e) {
retStatus = false;
strMessage = strprintf("%s\n", e.what());
LogPrint(nullptr, strMessage.data());
}
// TODO: This Function is still commented out
//NotifyBacked(wallet, retStatus, strMessage);
return retStatus;
}
//
// Try to (very carefully!) recover wallet.dat if there is a problem.
//
......
......@@ -170,7 +170,10 @@ private:
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
};
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
// TODO: void NotifyBacked(const CWallet& wallet, bool fSuccess, string strMessage);
bool BackupWallet(const CWallet& wallet, const boost::filesystem::path& strDest, bool fEnableCustom = true);
bool AttemptBackupWallet(const CWallet& wallet, const boost::filesystem::path& pathSrc, const boost::filesystem::path& pathDest);
#endif // BITCOIN_WALLETDB_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment