diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -2193,7 +2193,7 @@ #ifdef ENABLE_WALLET if (pwalletMain) { - pwalletMain->postInitProcess(threadGroup); + pwalletMain->postInitProcess(scheduler); } #endif diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -2470,8 +2470,8 @@ std::bind(&CConnman::ThreadMessageHandler, this))); // Dump network addresses - scheduler.scheduleEvery(boost::bind(&CConnman::DumpData, this), - DUMP_ADDRESSES_INTERVAL); + scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), + DUMP_ADDRESSES_INTERVAL * 1000); return true; } diff --git a/src/scheduler.h b/src/scheduler.h --- a/src/scheduler.h +++ b/src/scheduler.h @@ -22,7 +22,7 @@ // // CScheduler* s = new CScheduler(); // s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { } -// s->scheduleFromNow(boost::bind(Class::func, this, argument), 3); +// s->scheduleFromNow(std::bind(Class::func, this, argument), 3); // boost::thread* t = new boost::thread(boost::bind(CScheduler::serviceQueue, // s)); // @@ -43,14 +43,14 @@ // Call func at/after time t void schedule(Function f, boost::chrono::system_clock::time_point t); - // Convenience method: call f once deltaSeconds from now - void scheduleFromNow(Function f, int64_t deltaSeconds); + // Convenience method: call f once deltaMilliSeconds from now + void scheduleFromNow(Function f, int64_t deltaMilliSeconds); - // Another convenience method: call f approximately every deltaSeconds - // forever, starting deltaSeconds from now. To be more precise: every time f - // is finished, it is rescheduled to run deltaSeconds later. If you need - // more accurate scheduling, don't use this method. - void scheduleEvery(Function f, int64_t deltaSeconds); + // Another convenience method: call f approximately every deltaMilliSeconds + // forever, starting deltaMilliSeconds from now. To be more precise: every + // time f is finished, it is rescheduled to run deltaMilliSeconds later. If + // you need more accurate scheduling, don't use this method. + void scheduleEvery(Function f, int64_t deltaMilliSeconds); // To keep things as simple as possible, there is no unschedule. diff --git a/src/scheduler.cpp b/src/scheduler.cpp --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -111,20 +111,24 @@ newTaskScheduled.notify_one(); } -void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds) { +void CScheduler::scheduleFromNow(CScheduler::Function f, + int64_t deltaMilliSeconds) { schedule(f, boost::chrono::system_clock::now() + - boost::chrono::seconds(deltaSeconds)); + boost::chrono::milliseconds(deltaMilliSeconds)); } static void Repeat(CScheduler *s, CScheduler::Function f, - int64_t deltaSeconds) { + int64_t deltaMilliSeconds) { f(); - s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds); + s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaMilliSeconds), + deltaMilliSeconds); } -void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds) { - scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds); +void CScheduler::scheduleEvery(CScheduler::Function f, + int64_t deltaMilliSeconds) { + scheduleFromNow(boost::bind(&Repeat, this, f, deltaMilliSeconds), + deltaMilliSeconds); } size_t diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -75,6 +75,7 @@ class COutput; class CReserveKey; class CScript; +class CScheduler; class CTxMemPool; class CWalletTx; @@ -555,7 +556,7 @@ */ class CWallet : public CCryptoKeyStore, public CValidationInterface { private: - static std::atomic fFlushThreadRunning; + static std::atomic fFlushScheduled; /** * Select a set of coins such that nValueRet >= nTargetValue and at least @@ -1038,7 +1039,7 @@ * Gives the wallet a chance to register repetitive tasks and complete * post-init tasks */ - void postInitProcess(boost::thread_group &threadGroup); + void postInitProcess(CScheduler &scheduler); /* Wallets parameter interaction */ static bool ParameterInteraction(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -18,6 +18,7 @@ #include "policy/policy.h" #include "primitives/block.h" #include "primitives/transaction.h" +#include "scheduler.h" #include "script/script.h" #include "script/sighashtype.h" #include "script/sign.h" @@ -4200,16 +4201,16 @@ return true; } -std::atomic CWallet::fFlushThreadRunning(false); +std::atomic CWallet::fFlushScheduled(false); -void CWallet::postInitProcess(boost::thread_group &threadGroup) { +void CWallet::postInitProcess(CScheduler &scheduler) { // Add wallet transactions that aren't already in a block to mempool. // Do this here as mempool requires genesis block to be loaded. ReacceptWalletTransactions(); // Run a thread to flush wallet periodically. - if (!CWallet::fFlushThreadRunning.exchange(true)) { - threadGroup.create_thread(ThreadFlushWalletDB); + if (!CWallet::fFlushScheduled.exchange(true)) { + scheduler.scheduleEvery(MaybeCompactWalletDB, 500); } } diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -211,6 +211,8 @@ void operator=(const CWalletDB &); }; -void ThreadFlushWalletDB(); +//! Compacts BDB state so that wallet.dat is self-contained (if there are +//! changes) +void MaybeCompactWalletDB(); #endif // BITCOIN_WALLET_WALLETDB_H diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -787,39 +787,32 @@ return DB_LOAD_OK; } -void ThreadFlushWalletDB() { - // Make this thread recognisable as the wallet flushing thread. - RenameThread("bitcoin-wallet"); - - static bool fOneThread; - if (fOneThread) { +void MaybeCompactWalletDB() { + static std::atomic fOneThread; + if (fOneThread.exchange(true)) { return; } - - fOneThread = true; if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { return; } - unsigned int nLastSeen = CWalletDB::GetUpdateCounter(); - unsigned int nLastFlushed = CWalletDB::GetUpdateCounter(); - int64_t nLastWalletUpdate = GetTime(); - while (true) { - MilliSleep(500); + static unsigned int nLastSeen = CWalletDB::GetUpdateCounter(); + static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter(); + static int64_t nLastWalletUpdate = GetTime(); - if (nLastSeen != CWalletDB::GetUpdateCounter()) { - nLastSeen = CWalletDB::GetUpdateCounter(); - nLastWalletUpdate = GetTime(); - } + if (nLastSeen != CWalletDB::GetUpdateCounter()) { + nLastSeen = CWalletDB::GetUpdateCounter(); + nLastWalletUpdate = GetTime(); + } - if (nLastFlushed != CWalletDB::GetUpdateCounter() && - GetTime() - nLastWalletUpdate >= 2) { - const std::string &strFile = pwalletMain->strWalletFile; - if (CDB::PeriodicFlush(strFile)) { - nLastFlushed = CWalletDB::GetUpdateCounter(); - } + if (nLastFlushed != CWalletDB::GetUpdateCounter() && + GetTime() - nLastWalletUpdate >= 2) { + const std::string &strFile = pwalletMain->strWalletFile; + if (CDB::PeriodicFlush(strFile)) { + nLastFlushed = CWalletDB::GetUpdateCounter(); } } + fOneThread = false; } //