aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2017-03-08 11:48:58 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2017-04-20 17:15:30 +0200
commit71afe3c0995592ff17968816a833a8ed3ce05bf2 (patch)
tree84df1ac80d58db77464e500bf152a41bace9a4ac
parent987a6c09562e1e1e9d6623b999ae9de268490e4b (diff)
downloadbitcoin-71afe3c0995592ff17968816a833a8ed3ce05bf2.tar.xz
wallet: Introduce database handle wrapper
Abstract database handle from explicit strFilename into CWalletDBWrapper. Also move CWallet::Backup to db.cpp - as it deals with representation details this is a database specific operation.
-rw-r--r--src/qt/test/wallettests.cpp3
-rw-r--r--src/wallet/db.cpp58
-rw-r--r--src/wallet/db.h36
-rw-r--r--src/wallet/rpcwallet.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp3
-rw-r--r--src/wallet/wallet.cpp129
-rw-r--r--src/wallet/wallet.h24
-rw-r--r--src/wallet/walletdb.cpp5
-rw-r--r--src/wallet/walletdb.h8
9 files changed, 171 insertions, 97 deletions
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index f794b6b382..a0dce3d997 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -86,7 +86,8 @@ void WalletTests::walletTests()
TestChain100Setup test;
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
bitdb.MakeMock();
- CWallet wallet("wallet_test.dat");
+ std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat"));
+ CWallet wallet(std::move(dbw));
bool firstRun;
wallet.LoadWallet(firstRun);
{
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index f47fc92b57..cdf785a957 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -359,13 +359,12 @@ void CDBEnv::CheckpointLSN(const std::string& strFile)
}
-CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL)
+CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL)
{
int ret;
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
fFlushOnClose = fFlushOnCloseIn;
- if (strFilename.empty())
- return;
+ const std::string& strFilename = dbw.strFile;
bool fCreate = strchr(pszMode, 'c') != NULL;
unsigned int nFlags = DB_THREAD;
@@ -472,8 +471,12 @@ bool CDBEnv::RemoveDb(const std::string& strFile)
return (rc == 0);
}
-bool CDB::Rewrite(const std::string& strFile, const char* pszSkip)
+bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip)
{
+ if (!dbw.env) {
+ return true;
+ }
+ const std::string& strFile = dbw.strFile;
while (true) {
{
LOCK(bitdb.cs_db);
@@ -487,7 +490,7 @@ bool CDB::Rewrite(const std::string& strFile, const char* pszSkip)
LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile);
std::string strFileRes = strFile + ".rewrite";
{ // surround usage of db with extra {}
- CDB db(strFile.c_str(), "r");
+ CDB db(dbw, "r");
Db* pdbCopy = new Db(bitdb.dbenv, 0);
int ret = pdbCopy->open(NULL, // Txn pointer
@@ -596,9 +599,10 @@ void CDBEnv::Flush(bool fShutdown)
}
}
-bool CDB::PeriodicFlush(std::string strFile)
+bool CDB::PeriodicFlush(CWalletDBWrapper& dbw)
{
bool ret = false;
+ const std::string& strFile = dbw.strFile;
TRY_LOCK(bitdb.cs_db,lockDb);
if (lockDb)
{
@@ -633,3 +637,45 @@ bool CDB::PeriodicFlush(std::string strFile)
return ret;
}
+
+bool CWalletDBWrapper::Rewrite(const char* pszSkip)
+{
+ return CDB::Rewrite(*this, pszSkip);
+}
+
+bool CWalletDBWrapper::Backup(const std::string& strDest)
+{
+ if (!env) {
+ return false;
+ }
+ while (true)
+ {
+ {
+ LOCK(bitdb.cs_db);
+ if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0)
+ {
+ // Flush log data to the dat file
+ bitdb.CloseDb(strFile);
+ bitdb.CheckpointLSN(strFile);
+ bitdb.mapFileUseCount.erase(strFile);
+
+ // Copy wallet file
+ fs::path pathSrc = GetDataDir() / strFile;
+ fs::path pathDest(strDest);
+ if (fs::is_directory(pathDest))
+ pathDest /= strFile;
+
+ try {
+ fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists);
+ LogPrintf("copied %s to %s\n", strFile, pathDest.string());
+ return true;
+ } catch (const fs::filesystem_error& e) {
+ LogPrintf("error copying %s to %s - %s\n", strFile, pathDest.string(), e.what());
+ return false;
+ }
+ }
+ }
+ MilliSleep(100);
+ }
+ return false;
+}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 9f912f9a1a..f6d0d54114 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -86,6 +86,36 @@ public:
extern CDBEnv bitdb;
+/** An instance of this class represents one database.
+ * For BerkeleyDB this is just a (env, strFile) tuple.
+ **/
+class CWalletDBWrapper
+{
+ friend class CDB;
+public:
+ CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in):
+ env(env_in), strFile(strFile_in)
+ {
+ }
+
+ /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
+ */
+ bool Rewrite(const char* pszSkip=nullptr);
+
+ /** Back up the entire database to a file.
+ */
+ bool Backup(const std::string& strDest);
+
+ /** Get a name for this database, for debugging etc.
+ */
+ std::string GetName() const { return strFile; }
+
+private:
+ /** BerkeleyDB specific */
+ CDBEnv *env;
+ std::string strFile;
+};
+
/** RAII class that provides access to a Berkeley database */
class CDB
@@ -97,7 +127,7 @@ protected:
bool fReadOnly;
bool fFlushOnClose;
- explicit CDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
+ explicit CDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
~CDB() { Close(); }
public:
@@ -107,7 +137,7 @@ public:
/* flush the wallet passively (TRY_LOCK)
ideal to be called periodically */
- static bool PeriodicFlush(std::string strFile);
+ static bool PeriodicFlush(CWalletDBWrapper& dbw);
/* verifies the database environment */
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr);
/* verifies the database file */
@@ -310,7 +340,7 @@ public:
return Write(std::string("version"), nVersion);
}
- bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
+ bool static Rewrite(CWalletDBWrapper& dbw, const char* pszSkip = NULL);
};
#endif // BITCOIN_WALLET_DB_H
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 665d856df5..7408806b7d 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2076,7 +2076,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
int64_t nSleepTime = request.params[1].get_int64();
pwallet->nRelockTime = GetTime() + nSleepTime;
- RPCRunLater(strprintf("lockwallet(%s)", pwallet->strWalletFile), boost::bind(LockWallet, pwallet), nSleepTime);
+ RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime);
return NullUniValue;
}
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index a76db37617..1989bf8d9b 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -14,7 +14,8 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
bitdb.MakeMock();
bool fFirstRun;
- pwalletMain = new CWallet("wallet_test.dat");
+ std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat"));
+ pwalletMain = new CWallet(std::move(dbw));
pwalletMain->LoadWallet(fFirstRun);
RegisterValidationInterface(pwalletMain);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index b5e26e26d3..5b03b00179 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -161,7 +161,7 @@ void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool inter
secret = childKey.key;
metadata.hdMasterKeyID = hdChain.masterKeyID;
// update the chain model in the database
- if (!CWalletDB(strWalletFile).WriteHDChain(hdChain))
+ if (!CWalletDB(*dbw).WriteHDChain(hdChain))
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
}
@@ -183,7 +183,7 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
if (!fFileBacked)
return true;
if (!IsCrypted()) {
- return CWalletDB(strWalletFile).WriteKey(pubkey,
+ return CWalletDB(*dbw).WriteKey(pubkey,
secret.GetPrivKey(),
mapKeyMetadata[pubkey.GetID()]);
}
@@ -204,7 +204,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
vchCryptedSecret,
mapKeyMetadata[vchPubKey.GetID()]);
else
- return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
+ return CWalletDB(*dbw).WriteCryptedKey(vchPubKey,
vchCryptedSecret,
mapKeyMetadata[vchPubKey.GetID()]);
}
@@ -242,7 +242,7 @@ bool CWallet::AddCScript(const CScript& redeemScript)
return false;
if (!fFileBacked)
return true;
- return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
+ return CWalletDB(*dbw).WriteCScript(Hash160(redeemScript), redeemScript);
}
bool CWallet::LoadCScript(const CScript& redeemScript)
@@ -270,7 +270,7 @@ bool CWallet::AddWatchOnly(const CScript& dest)
NotifyWatchonlyChanged(true);
if (!fFileBacked)
return true;
- return CWalletDB(strWalletFile).WriteWatchOnly(dest, meta);
+ return CWalletDB(*dbw).WriteWatchOnly(dest, meta);
}
bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
@@ -287,7 +287,7 @@ bool CWallet::RemoveWatchOnly(const CScript &dest)
if (!HaveWatchOnly())
NotifyWatchonlyChanged(false);
if (fFileBacked)
- if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
+ if (!CWalletDB(*dbw).EraseWatchOnly(dest))
return false;
return true;
@@ -353,7 +353,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
return false;
- CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
+ CWalletDB(*dbw).WriteMasterKey(pMasterKey.first, pMasterKey.second);
if (fWasLocked)
Lock();
return true;
@@ -366,7 +366,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
void CWallet::SetBestChain(const CBlockLocator& loc)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
walletdb.WriteBestBlock(loc);
}
@@ -387,7 +387,7 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn,
if (fFileBacked)
{
- CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
+ CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(*dbw);
if (nWalletVersion > 40000)
pwalletdb->WriteMinVersion(nWalletVersion);
if (!pwalletdbIn)
@@ -597,7 +597,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (fFileBacked)
{
assert(!pwalletdbEncryption);
- pwalletdbEncryption = new CWalletDB(strWalletFile);
+ pwalletdbEncryption = new CWalletDB(*dbw);
if (!pwalletdbEncryption->TxnBegin()) {
delete pwalletdbEncryption;
pwalletdbEncryption = NULL;
@@ -651,7 +651,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// Need to completely rewrite the wallet file; if we don't, bdb might keep
// bits of the unencrypted private key in slack space in the database file.
- CDB::Rewrite(strWalletFile);
+ dbw->Rewrite();
}
NotifyStatusChanged(this);
@@ -662,7 +662,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
DBErrors CWallet::ReorderTransactions()
{
LOCK(cs_wallet);
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
// Old wallets didn't have any defined order for transactions
// Probably a bad idea to change the output of this
@@ -743,14 +743,14 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
if (pwalletdb) {
pwalletdb->WriteOrderPosNext(nOrderPosNext);
} else {
- CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
+ CWalletDB(*dbw).WriteOrderPosNext(nOrderPosNext);
}
return nRet;
}
bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
if (!walletdb.TxnBegin())
return false;
@@ -784,7 +784,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun
bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
CAccount account;
walletdb.ReadAccount(strAccount, account);
@@ -845,7 +845,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
wtx.mapValue["replaced_by_txid"] = newHash.ToString();
- CWalletDB walletdb(strWalletFile, "r+");
+ CWalletDB walletdb(*dbw, "r+");
bool success = true;
if (!walletdb.WriteTx(wtx)) {
@@ -862,7 +862,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
{
LOCK(cs_wallet);
- CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose);
+ CWalletDB walletdb(*dbw, "r+", fFlushOnClose);
uint256 hash = wtxIn.GetHash();
@@ -1006,7 +1006,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
{
LOCK2(cs_main, cs_wallet);
- CWalletDB walletdb(strWalletFile, "r+");
+ CWalletDB walletdb(*dbw, "r+");
std::set<uint256> todo;
std::set<uint256> done;
@@ -1078,7 +1078,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
return;
// Do not flush the wallet here for performance reasons
- CWalletDB walletdb(strWalletFile, "r+", false);
+ CWalletDB walletdb(*dbw, "r+", false);
std::set<uint256> todo;
std::set<uint256> done;
@@ -1361,7 +1361,7 @@ bool CWallet::SetHDMasterKey(const CPubKey& pubkey, CHDChain *possibleOldChain)
bool CWallet::SetHDChain(const CHDChain& chain, bool memonly)
{
LOCK(cs_wallet);
- if (!memonly && !CWalletDB(strWalletFile).WriteHDChain(chain))
+ if (!memonly && !CWalletDB(*dbw).WriteHDChain(chain))
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
hdChain = chain;
@@ -2758,13 +2758,13 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
}
void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries) {
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
return walletdb.ListAccountCreditDebit(strAccount, entries);
}
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
return AddAccountingEntry(acentry, &walletdb);
}
@@ -2819,10 +2819,10 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
if (!fFileBacked)
return DB_LOAD_OK;
fFirstRunRet = false;
- DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
+ DBErrors nLoadWalletRet = CWalletDB(*dbw,"cr+").LoadWallet(this);
if (nLoadWalletRet == DB_NEED_REWRITE)
{
- if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ if (dbw->Rewrite("\x04pool"))
{
LOCK(cs_wallet);
setKeyPool.clear();
@@ -2847,13 +2847,13 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
return DB_LOAD_OK;
AssertLockHeld(cs_wallet); // mapWallet
vchDefaultKey = CPubKey();
- DBErrors nZapSelectTxRet = CWalletDB(strWalletFile,"cr+").ZapSelectTx(vHashIn, vHashOut);
+ DBErrors nZapSelectTxRet = CWalletDB(*dbw,"cr+").ZapSelectTx(vHashIn, vHashOut);
for (uint256 hash : vHashOut)
mapWallet.erase(hash);
if (nZapSelectTxRet == DB_NEED_REWRITE)
{
- if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ if (dbw->Rewrite("\x04pool"))
{
setKeyPool.clear();
// Note: can't top-up keypool here, because wallet is locked.
@@ -2876,10 +2876,10 @@ DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
if (!fFileBacked)
return DB_LOAD_OK;
vchDefaultKey = CPubKey();
- DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(vWtx);
+ DBErrors nZapWalletTxRet = CWalletDB(*dbw,"cr+").ZapWalletTx(vWtx);
if (nZapWalletTxRet == DB_NEED_REWRITE)
{
- if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ if (dbw->Rewrite("\x04pool"))
{
LOCK(cs_wallet);
setKeyPool.clear();
@@ -2911,9 +2911,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
if (!fFileBacked)
return false;
- if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
+ if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
return false;
- return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
+ return CWalletDB(*dbw).WriteName(CBitcoinAddress(address).ToString(), strName);
}
bool CWallet::DelAddressBook(const CTxDestination& address)
@@ -2927,7 +2927,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
std::string strAddress = CBitcoinAddress(address).ToString();
BOOST_FOREACH(const PAIRTYPE(std::string, std::string) &item, mapAddressBook[address].destdata)
{
- CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
+ CWalletDB(*dbw).EraseDestData(strAddress, item.first);
}
}
mapAddressBook.erase(address);
@@ -2937,15 +2937,15 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
if (!fFileBacked)
return false;
- CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
- return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
+ CWalletDB(*dbw).ErasePurpose(CBitcoinAddress(address).ToString());
+ return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString());
}
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
{
if (fFileBacked)
{
- if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
+ if (!CWalletDB(*dbw).WriteDefaultKey(vchPubKey))
return false;
}
vchDefaultKey = vchPubKey;
@@ -2960,7 +2960,7 @@ bool CWallet::NewKeyPool()
{
{
LOCK(cs_wallet);
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
BOOST_FOREACH(int64_t nIndex, setKeyPool)
walletdb.ErasePool(nIndex);
setKeyPool.clear();
@@ -2981,7 +2981,7 @@ size_t CWallet::KeypoolCountExternalKeys()
if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT))
return setKeyPool.size();
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
// count amount of external keys
size_t amountE = 0;
@@ -3024,7 +3024,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
missingInternal = 0;
}
bool internal = false;
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
for (int64_t i = missingInternal + missingExternal; i--;)
{
int64_t nEnd = 1;
@@ -3055,7 +3055,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool int
if(setKeyPool.empty())
return;
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
// try to find a key that matches the internal/external filter
for(const int64_t& id : setKeyPool)
@@ -3083,7 +3083,7 @@ void CWallet::KeepKey(int64_t nIndex)
// Remove from key pool
if (fFileBacked)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
walletdb.ErasePool(nIndex);
}
LogPrintf("keypool keep %d\n", nIndex);
@@ -3127,7 +3127,7 @@ int64_t CWallet::GetOldestKeyPoolTime()
return GetTime();
CKeyPool keypool;
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT))
{
@@ -3295,7 +3295,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter)
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
}
@@ -3375,7 +3375,7 @@ void CWallet::GetAllReserveKeys(std::set<CKeyID>& setAddress) const
{
setAddress.clear();
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(*dbw);
LOCK2(cs_main, cs_wallet);
BOOST_FOREACH(const int64_t& id, setKeyPool)
@@ -3599,7 +3599,7 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
if (!fFileBacked)
return true;
- return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
+ return CWalletDB(*dbw).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
}
bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
@@ -3608,7 +3608,7 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
return false;
if (!fFileBacked)
return true;
- return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
+ return CWalletDB(*dbw).EraseDestData(CBitcoinAddress(dest).ToString(), key);
}
bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
@@ -3678,7 +3678,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
if (GetBoolArg("-zapwallettxes", false)) {
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
- CWallet *tempWallet = new CWallet(walletFile);
+ std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, walletFile));
+ CWallet *tempWallet = new CWallet(std::move(dbw));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DB_LOAD_OK) {
InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
@@ -3693,7 +3694,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- CWallet *walletInstance = new CWallet(walletFile);
+ std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, walletFile));
+ CWallet *walletInstance = new CWallet(std::move(dbw));
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DB_LOAD_OK)
{
@@ -3784,7 +3786,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
CBlockIndex *pindexRescan = chainActive.Genesis();
if (!GetBoolArg("-rescan", false))
{
- CWalletDB walletdb(walletFile);
+ CWalletDB walletdb(*walletInstance->dbw);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
@@ -3817,7 +3819,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
{
- CWalletDB walletdb(walletFile);
+ CWalletDB walletdb(*walletInstance->dbw);
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
{
@@ -3979,36 +3981,7 @@ bool CWallet::BackupWallet(const std::string& strDest)
{
if (!fFileBacked)
return false;
- while (true)
- {
- {
- LOCK(bitdb.cs_db);
- if (!bitdb.mapFileUseCount.count(strWalletFile) || bitdb.mapFileUseCount[strWalletFile] == 0)
- {
- // Flush log data to the dat file
- bitdb.CloseDb(strWalletFile);
- bitdb.CheckpointLSN(strWalletFile);
- bitdb.mapFileUseCount.erase(strWalletFile);
-
- // Copy wallet file
- fs::path pathSrc = GetDataDir() / strWalletFile;
- fs::path pathDest(strDest);
- if (fs::is_directory(pathDest))
- pathDest /= strWalletFile;
-
- try {
- fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists);
- LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string());
- return true;
- } catch (const fs::filesystem_error& e) {
- LogPrintf("error copying %s to %s - %s\n", strWalletFile, pathDest.string(), e.what());
- return false;
- }
- }
- }
- MilliSleep(100);
- }
- return false;
+ return dbw->Backup(strDest);
}
CKeyPool::CKeyPool()
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 06e7e14990..318aa2bf97 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -715,17 +715,35 @@ private:
*/
bool AddWatchOnly(const CScript& dest) override;
+ std::unique_ptr<CWalletDBWrapper> dbw;
+
public:
/*
* Main wallet lock.
* This lock protects all the fields added by CWallet
* except for:
* fFileBacked (immutable after instantiation)
- * strWalletFile (immutable after instantiation)
*/
mutable CCriticalSection cs_wallet;
- const std::string strWalletFile;
+ /** Get database handle used by this wallet. Ideally this function would
+ * not be necessary.
+ */
+ CWalletDBWrapper& GetDBHandle()
+ {
+ return *dbw;
+ }
+
+ /** Get a name for this wallet for logging/debugging purposes.
+ */
+ std::string GetName() const
+ {
+ if (dbw) {
+ return dbw->GetName();
+ } else {
+ return "dummy";
+ }
+ }
void LoadKeyPool(int nIndex, const CKeyPool &keypool)
{
@@ -752,7 +770,7 @@ public:
SetNull();
}
- CWallet(const std::string& strWalletFileIn) : strWalletFile(strWalletFileIn)
+ CWallet(std::unique_ptr<CWalletDBWrapper> dbw_in) : dbw(std::move(dbw_in))
{
SetNull();
fFileBacked = true;
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index ceff2d36e3..6921c9900b 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -797,9 +797,9 @@ void MaybeCompactWalletDB()
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
{
- const std::string& strFile = pwalletMain->strWalletFile;
- if (CDB::PeriodicFlush(strFile))
+ if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) {
nLastFlushed = CWalletDB::GetUpdateCounter();
+ }
}
fOneThread = false;
}
@@ -880,3 +880,4 @@ unsigned int CWalletDB::GetUpdateCounter()
{
return nWalletDBUpdateCounter;
}
+
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index b94f341b2e..c0135a6292 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -118,11 +118,15 @@ public:
}
};
-/** Access to the wallet database */
+/** Access to the wallet database.
+ * This should really be named CWalletDBBatch, as it represents a single transaction at the
+ * database. It will be committed when the object goes out of scope.
+ * Optionally (on by default) it will flush to disk as well.
+ */
class CWalletDB : public CDB
{
public:
- CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool _fFlushOnClose = true) : CDB(strFilename, pszMode, _fFlushOnClose)
+ CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : CDB(dbw, pszMode, _fFlushOnClose)
{
}