mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge #9227: Make nWalletDBUpdated atomic to avoid a potential race.
d63ff62
Make nWalletDBUpdated atomic to avoid a potential race. (Patrick Strateman)
This commit is contained in:
commit
02464da5e4
@ -24,9 +24,6 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
unsigned int nWalletDBUpdated;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CDB
|
// CDB
|
||||||
//
|
//
|
||||||
|
@ -23,8 +23,6 @@
|
|||||||
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
|
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
|
||||||
static const bool DEFAULT_WALLET_PRIVDB = true;
|
static const bool DEFAULT_WALLET_PRIVDB = true;
|
||||||
|
|
||||||
extern unsigned int nWalletDBUpdated;
|
|
||||||
|
|
||||||
class CDBEnv
|
class CDBEnv
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -3691,7 +3691,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
|
|||||||
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
||||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||||
walletInstance->SetBestChain(chainActive.GetLocator());
|
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||||
nWalletDBUpdated++;
|
CWalletDB::IncrementUpdateCounter();
|
||||||
|
|
||||||
// Restore wallet transaction metadata after -zapwallettxes=1
|
// Restore wallet transaction metadata after -zapwallettxes=1
|
||||||
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
@ -24,13 +26,15 @@ using namespace std;
|
|||||||
|
|
||||||
static uint64_t nAccountingEntryNumber = 0;
|
static uint64_t nAccountingEntryNumber = 0;
|
||||||
|
|
||||||
|
static std::atomic<unsigned int> nWalletDBUpdateCounter;
|
||||||
|
|
||||||
//
|
//
|
||||||
// CWalletDB
|
// CWalletDB
|
||||||
//
|
//
|
||||||
|
|
||||||
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(make_pair(string("name"), strAddress), strName);
|
return Write(make_pair(string("name"), strAddress), strName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,37 +42,37 @@ bool CWalletDB::EraseName(const string& strAddress)
|
|||||||
{
|
{
|
||||||
// This should only be used for sending addresses, never for receiving addresses,
|
// This should only be used for sending addresses, never for receiving addresses,
|
||||||
// receiving addresses must always have an address book entry if they're not change return.
|
// receiving addresses must always have an address book entry if they're not change return.
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(make_pair(string("name"), strAddress));
|
return Erase(make_pair(string("name"), strAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
|
bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(make_pair(string("purpose"), strAddress), strPurpose);
|
return Write(make_pair(string("purpose"), strAddress), strPurpose);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ErasePurpose(const string& strPurpose)
|
bool CWalletDB::ErasePurpose(const string& strPurpose)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(make_pair(string("purpose"), strPurpose));
|
return Erase(make_pair(string("purpose"), strPurpose));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseTx(uint256 hash)
|
bool CWalletDB::EraseTx(uint256 hash)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(std::make_pair(std::string("tx"), hash));
|
return Erase(std::make_pair(std::string("tx"), hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
|
|
||||||
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||||
keyMeta, false))
|
keyMeta, false))
|
||||||
@ -88,7 +92,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
|||||||
const CKeyMetadata &keyMeta)
|
const CKeyMetadata &keyMeta)
|
||||||
{
|
{
|
||||||
const bool fEraseUnencryptedKey = true;
|
const bool fEraseUnencryptedKey = true;
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
|
|
||||||
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||||
keyMeta))
|
keyMeta))
|
||||||
@ -106,31 +110,31 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
|||||||
|
|
||||||
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteWatchOnly(const CScript &dest)
|
bool CWalletDB::WriteWatchOnly(const CScript &dest)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
|
return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseWatchOnly(const CScript &dest)
|
bool CWalletDB::EraseWatchOnly(const CScript &dest)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
|
return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
|
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
|
||||||
return Write(std::string("bestblock_nomerkle"), locator);
|
return Write(std::string("bestblock_nomerkle"), locator);
|
||||||
}
|
}
|
||||||
@ -143,13 +147,13 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
|||||||
|
|
||||||
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::string("orderposnext"), nOrderPosNext);
|
return Write(std::string("orderposnext"), nOrderPosNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::string("defaultkey"), vchPubKey);
|
return Write(std::string("defaultkey"), vchPubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,13 +164,13 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
|
|||||||
|
|
||||||
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
|
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("pool"), nPool), keypool);
|
return Write(std::make_pair(std::string("pool"), nPool), keypool);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::ErasePool(int64_t nPool)
|
bool CWalletDB::ErasePool(int64_t nPool)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(std::make_pair(std::string("pool"), nPool));
|
return Erase(std::make_pair(std::string("pool"), nPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,20 +784,20 @@ void ThreadFlushWalletDB()
|
|||||||
if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
|
if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int nLastSeen = nWalletDBUpdated;
|
unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
|
||||||
unsigned int nLastFlushed = nWalletDBUpdated;
|
unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||||
int64_t nLastWalletUpdate = GetTime();
|
int64_t nLastWalletUpdate = GetTime();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
MilliSleep(500);
|
MilliSleep(500);
|
||||||
|
|
||||||
if (nLastSeen != nWalletDBUpdated)
|
if (nLastSeen != CWalletDB::GetUpdateCounter())
|
||||||
{
|
{
|
||||||
nLastSeen = nWalletDBUpdated;
|
nLastSeen = CWalletDB::GetUpdateCounter();
|
||||||
nLastWalletUpdate = GetTime();
|
nLastWalletUpdate = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
|
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
|
||||||
{
|
{
|
||||||
TRY_LOCK(bitdb.cs_db,lockDb);
|
TRY_LOCK(bitdb.cs_db,lockDb);
|
||||||
if (lockDb)
|
if (lockDb)
|
||||||
@ -815,7 +819,7 @@ void ThreadFlushWalletDB()
|
|||||||
if (_mi != bitdb.mapFileUseCount.end())
|
if (_mi != bitdb.mapFileUseCount.end())
|
||||||
{
|
{
|
||||||
LogPrint("db", "Flushing %s\n", strFile);
|
LogPrint("db", "Flushing %s\n", strFile);
|
||||||
nLastFlushed = nWalletDBUpdated;
|
nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||||
int64_t nStart = GetTimeMillis();
|
int64_t nStart = GetTimeMillis();
|
||||||
|
|
||||||
// Flush wallet file so it's self contained
|
// Flush wallet file so it's self contained
|
||||||
@ -922,19 +926,29 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
|
|||||||
|
|
||||||
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdateCounter++;
|
||||||
return Write(std::string("hdchain"), chain);
|
return Write(std::string("hdchain"), chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWalletDB::IncrementUpdateCounter()
|
||||||
|
{
|
||||||
|
nWalletDBUpdateCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CWalletDB::GetUpdateCounter()
|
||||||
|
{
|
||||||
|
return nWalletDBUpdateCounter;
|
||||||
|
}
|
||||||
|
@ -176,10 +176,11 @@ public:
|
|||||||
//! write the hdchain model (external chain child index counter)
|
//! write the hdchain model (external chain child index counter)
|
||||||
bool WriteHDChain(const CHDChain& chain);
|
bool WriteHDChain(const CHDChain& chain);
|
||||||
|
|
||||||
|
static void IncrementUpdateCounter();
|
||||||
|
static unsigned int GetUpdateCounter();
|
||||||
private:
|
private:
|
||||||
CWalletDB(const CWalletDB&);
|
CWalletDB(const CWalletDB&);
|
||||||
void operator=(const CWalletDB&);
|
void operator=(const CWalletDB&);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void ThreadFlushWalletDB();
|
void ThreadFlushWalletDB();
|
||||||
|
Loading…
Reference in New Issue
Block a user