From 7be46ce487e2f3c6e145b9bc56cc37d8de97df9e Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Thu, 29 Oct 2009 20:10:46 +0000 Subject: [PATCH] better wallet.dat flush, consolidated QueryPerformanceCounter, PRI64d printf portability --- build.txt | 3 ++- db.cpp | 76 +++++++++++++++++++++++++++++++++++++---------------- db.h | 12 ++++++++- main.cpp | 6 ++--- main.h | 2 +- makefile.vc | 4 +-- net.h | 2 +- ui.cpp | 26 +++++++++--------- util.cpp | 22 +++++++--------- util.h | 43 ++++++++++++++++++------------ 10 files changed, 121 insertions(+), 75 deletions(-) diff --git a/build.txt b/build.txt index f51005576..67b03fe24 100644 --- a/build.txt +++ b/build.txt @@ -10,7 +10,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com). Compilers Supported ------------------- -MinGW GCC (currently v3.4.5) +MinGW GCC Microsoft Visual C++ 6.0 SP6 @@ -20,6 +20,7 @@ Libraries you need to obtain separately to build: default path download wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/ + or prebuilt: http://wxpack.sourceforge.net OpenSSL \openssl http://www.openssl.org/source/ Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html Boost \boost http://www.boost.org/users/download/ diff --git a/db.cpp b/db.cpp index 315e93b73..699a94f2e 100644 --- a/db.cpp +++ b/db.cpp @@ -4,8 +4,11 @@ #include "headers.h" +void ThreadFlushWalletDB(void* parg); +unsigned int nWalletDBUpdated; + @@ -56,6 +59,8 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL) { if (!fDbEnvInit) { + if (fShutdown) + return; string strAppDir = GetAppDir(); string strLogDir = strAppDir + "\\database"; _mkdir(strLogDir.c_str()); @@ -121,12 +126,10 @@ void CDB::Close() pdb->close(0); delete pdb; pdb = NULL; + dbenv.txn_checkpoint(0, 0, 0); CRITICAL_BLOCK(cs_db) - { - dbenv.txn_checkpoint(0, 0, 0); --mapFileUseCount[strFile]; - } RandAddSeed(); } @@ -499,25 +502,6 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector& vReviews) // CWalletDB // -CWalletDB::~CWalletDB() -{ - // Flush whenever all handles to wallet.dat are closed - CRITICAL_BLOCK(cs_db) - { - Close(); // close includes a txn_checkpoint - map::iterator mi = mapFileUseCount.find(strFile); - if (mi != mapFileUseCount.end()) - { - int nRefCount = (*mi).second; - if (nRefCount == 0) - { - dbenv.lsn_reset(strFile.c_str(), 0); - mapFileUseCount.erase(mi++); - } - } - } -} - bool CWalletDB::LoadWallet(vector& vchDefaultKeyRet) { vchDefaultKeyRet.clear(); @@ -610,7 +594,7 @@ bool CWalletDB::LoadWallet(vector& vchDefaultKeyRet) printf("fShowGenerated = %d\n", fShowGenerated); printf("fGenerateBitcoins = %d\n", fGenerateBitcoins); - printf("nTransactionFee = %I64d\n", nTransactionFee); + printf("nTransactionFee = %"PRI64d"\n", nTransactionFee); printf("addrIncoming = %s\n", addrIncoming.ToString().c_str()); printf("fMinimizeToTray = %d\n", fMinimizeToTray); printf("fMinimizeOnClose = %d\n", fMinimizeOnClose); @@ -655,5 +639,51 @@ bool LoadWallet(bool& fFirstRunRet) CWalletDB().WriteDefaultKey(keyUser.GetPubKey()); } + _beginthread(ThreadFlushWalletDB, 0, NULL); return true; } + +void ThreadFlushWalletDB(void* parg) +{ + static bool fOneThread; + if (fOneThread) + return; + fOneThread = true; + + unsigned int nLastSeen = nWalletDBUpdated; + unsigned int nLastFlushed = nWalletDBUpdated; + int64 nLastWalletUpdate = GetTime(); + while (!fShutdown) + { + Sleep(500); + + if (nLastSeen != nWalletDBUpdated) + { + nLastSeen = nWalletDBUpdated; + nLastWalletUpdate = GetTime(); + } + + if (nLastFlushed != nWalletDBUpdated && nLastWalletUpdate < GetTime() - 1) + { + TRY_CRITICAL_BLOCK(cs_db) + { + string strFile = "wallet.dat"; + map::iterator mi = mapFileUseCount.find(strFile); + if (mi != mapFileUseCount.end()) + { + int nRefCount = (*mi).second; + if (nRefCount == 0 && !fShutdown) + { + // Flush wallet.dat so it's self contained + nLastFlushed == nWalletDBUpdated; + int64 nStart = PerformanceCounter(); + dbenv.txn_checkpoint(0, 0, 0); + dbenv.lsn_reset(strFile.c_str(), 0); + printf("Flushed wallet.dat %15"PRI64d"\n", PerformanceCounter() - nStart); + mapFileUseCount.erase(mi++); + } + } + } + } + } +} diff --git a/db.h b/db.h index 496146875..d11b397eb 100644 --- a/db.h +++ b/db.h @@ -17,7 +17,10 @@ extern map mapAddressBook; extern bool fClient; +extern unsigned int nWalletDBUpdated; extern DbEnv dbenv; + + extern void DBFlush(bool fShutdown); @@ -334,11 +337,11 @@ bool LoadAddresses(); + class CWalletDB : public CDB { public: CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { } - ~CWalletDB(); private: CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); @@ -351,12 +354,14 @@ public: bool WriteName(const string& strAddress, const string& strName) { + nWalletDBUpdated++; mapAddressBook[strAddress] = strName; return Write(make_pair(string("name"), strAddress), strName); } bool EraseName(const string& strAddress) { + nWalletDBUpdated++; mapAddressBook.erase(strAddress); return Erase(make_pair(string("name"), strAddress)); } @@ -368,11 +373,13 @@ public: bool WriteTx(uint256 hash, const CWalletTx& wtx) { + nWalletDBUpdated++; return Write(make_pair(string("tx"), hash), wtx); } bool EraseTx(uint256 hash) { + nWalletDBUpdated++; return Erase(make_pair(string("tx"), hash)); } @@ -384,6 +391,7 @@ public: bool WriteKey(const vector& vchPubKey, const CPrivKey& vchPrivKey) { + nWalletDBUpdated++; return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false); } @@ -395,6 +403,7 @@ public: bool WriteDefaultKey(const vector& vchPubKey) { + nWalletDBUpdated++; return Write(string("defaultkey"), vchPubKey); } @@ -407,6 +416,7 @@ public: template bool WriteSetting(const string& strKey, const T& value) { + nWalletDBUpdated++; return Write(make_pair(string("setting"), strKey), value); } diff --git a/main.cpp b/main.cpp index 710b78920..4194333d8 100644 --- a/main.cpp +++ b/main.cpp @@ -2518,8 +2518,7 @@ bool BitcoinMiner() int64 GetBalance() { - int64 nStart, nEnd; - QueryPerformanceCounter((LARGE_INTEGER*)&nStart); + int64 nStart = PerformanceCounter(); int64 nTotal = 0; CRITICAL_BLOCK(cs_mapWallet) @@ -2533,8 +2532,7 @@ int64 GetBalance() } } - QueryPerformanceCounter((LARGE_INTEGER*)&nEnd); - ///printf(" GetBalance() time = %16I64d\n", nEnd - nStart); + ///printf(" GetBalance() time = %15"PRI64d"\n", PerformanceCounter() - nStart); return nTotal; } diff --git a/main.h b/main.h index 958f7a5f1..fcfd33d13 100644 --- a/main.h +++ b/main.h @@ -344,7 +344,7 @@ public: { if (scriptPubKey.size() < 6) return "CTxOut(error)"; - return strprintf("CTxOut(nValue=%I64d.%08I64d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str()); + return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str()); } void print() const diff --git a/makefile.vc b/makefile.vc index c3bd0c4bc..fb7f3086e 100644 --- a/makefile.vc +++ b/makefile.vc @@ -13,8 +13,8 @@ DEBUGFLAGS=/Zi /Od /D__WXDEBUG__ -INCLUDEPATHS=/I"/boost" /I"/DB/build_windows" /I"/OpenSSL/include" /I"/wxWidgets/lib/vc_lib/mswd" /I"/wxWidgets/include" -LIBPATHS=/LIBPATH:"/DB/build_windows/$(BUILD)" /LIBPATH:"/OpenSSL/out" /LIBPATH:"/wxWidgets/lib/vc_lib" +INCLUDEPATHS=/I"/boost" /I"/db/build_windows" /I"/openssl/include" /I"/wxwidgets/lib/vc_lib/mswd" /I"/wxwidgets/include" +LIBPATHS=/LIBPATH:"/db/build_windows/$(BUILD)" /LIBPATH:"/openssl/out" /LIBPATH:"/wxwidgets/lib/vc_lib" LIBS= \ libdb47s$(D).lib \ libeay32.lib \ diff --git a/net.h b/net.h index 5995ac334..4011a3ef7 100644 --- a/net.h +++ b/net.h @@ -589,7 +589,7 @@ public: // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64& nRequestTime = mapAlreadyAskedFor[inv]; - printf("askfor %s %I64d\n", inv.ToString().c_str(), nRequestTime); + printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime); // Make sure not to reuse time indexes to keep things in the same order int64 nNow = (GetTime() - 1) * 1000000; diff --git a/ui.cpp b/ui.cpp index 917c64b44..ce287e391 100644 --- a/ui.cpp +++ b/ui.cpp @@ -3414,28 +3414,25 @@ bool CMyApp::OnInit2() // bool fFirstRun; string strErrors; - int64 nStart, nEnd; + int64 nStart; printf("Loading addresses...\n"); - QueryPerformanceCounter((LARGE_INTEGER*)&nStart); + nStart = PerformanceCounter(); if (!LoadAddresses()) strErrors += "Error loading addr.dat \n"; - QueryPerformanceCounter((LARGE_INTEGER*)&nEnd); - printf(" addresses %20I64d\n", nEnd - nStart); + printf(" addresses %15"PRI64d"\n", PerformanceCounter() - nStart); printf("Loading block index...\n"); - QueryPerformanceCounter((LARGE_INTEGER*)&nStart); + nStart = PerformanceCounter(); if (!LoadBlockIndex()) strErrors += "Error loading blkindex.dat \n"; - QueryPerformanceCounter((LARGE_INTEGER*)&nEnd); - printf(" block index %20I64d\n", nEnd - nStart); + printf(" block index %15"PRI64d"\n", PerformanceCounter() - nStart); printf("Loading wallet...\n"); - QueryPerformanceCounter((LARGE_INTEGER*)&nStart); + nStart = PerformanceCounter(); if (!LoadWallet(fFirstRun)) strErrors += "Error loading wallet.dat \n"; - QueryPerformanceCounter((LARGE_INTEGER*)&nEnd); - printf(" wallet %20I64d\n", nEnd - nStart); + printf(" wallet %15"PRI64d"\n", PerformanceCounter() - nStart); printf("Done loading\n"); @@ -3742,7 +3739,7 @@ void ThreadRandSendTest(void* parg) return; } - loop + while (!fShutdown) { Sleep(GetRand(30) * 1000 + 100); @@ -3767,6 +3764,8 @@ void ThreadRandSendTest(void* parg) CScript scriptPubKey; scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + if (fShutdown) + return; if (!SendMoney(scriptPubKey, nValue, wtx)) return; } @@ -3776,8 +3775,6 @@ void ThreadRandSendTest(void* parg) // randsendtest to any connected node void RandSend() { - CWalletTx wtx; - while (vNodes.empty()) Sleep(1000); CAddress addr; @@ -3785,6 +3782,7 @@ void RandSend() addr = vNodes[GetRand(vNodes.size())]->addr; // Message + CWalletTx wtx; wtx.mapValue["to"] = addr.ToString(); wtx.mapValue["from"] = addrLocalHost.ToString(); static int nRep; @@ -3799,6 +3797,8 @@ void RandSend() } // Send to IP address + if (fShutdown) + return; CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx); if (!pdialog->Show()) wxMessageBox("ShowModal Failed "); diff --git a/util.cpp b/util.cpp index bdf899d78..ef950920f 100644 --- a/util.cpp +++ b/util.cpp @@ -14,8 +14,7 @@ bool fPrintToConsole = false; // Init openssl library multithreading support static wxMutex** ppmutexOpenSSL; - -void win32_locking_callback(int mode, int i, const char* file, int line) +void locking_callback(int mode, int i, const char* file, int line) { if (mode & CRYPTO_LOCK) ppmutexOpenSSL[i]->Lock(); @@ -33,7 +32,7 @@ public: ppmutexOpenSSL = (wxMutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(wxMutex*)); for (int i = 0; i < CRYPTO_num_locks(); i++) ppmutexOpenSSL[i] = new wxMutex(); - CRYPTO_set_locking_callback(win32_locking_callback); + CRYPTO_set_locking_callback(locking_callback); // Seed random number generator with screen scrape and other hardware sources RAND_screen(); @@ -45,7 +44,7 @@ public: { // Shutdown openssl library multithreading support CRYPTO_set_locking_callback(NULL); - for (int i =0 ; i < CRYPTO_num_locks(); i++) + for (int i = 0; i < CRYPTO_num_locks(); i++) delete ppmutexOpenSSL[i]; OPENSSL_free(ppmutexOpenSSL); } @@ -62,10 +61,9 @@ instance_of_cinit; void RandAddSeed() { // Seed with CPU performance counter - LARGE_INTEGER PerformanceCount; - QueryPerformanceCounter(&PerformanceCount); - RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5); - memset(&PerformanceCount, 0, sizeof(PerformanceCount)); + int64 nCounter = PerformanceCounter(); + RAND_add(&nCounter, sizeof(nCounter), 1.5); + memset(&nCounter, 0, sizeof(nCounter)); } void RandAddSeedPerfmon() @@ -196,7 +194,7 @@ void ParseString(const string& str, char c, vector& v) string FormatMoney(int64 n, bool fPlus) { n /= CENT; - string str = strprintf("%I64d.%02I64d", (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100); + string str = strprintf("%"PRI64d".%02"PRI64d, (n > 0 ? n : -n)/100, (n > 0 ? n : -n)%100); for (int i = 6; i < str.size(); i += 4) if (isdigit(str[str.size() - i - 1])) str.insert(str.size() - i, 1, ','); @@ -435,7 +433,7 @@ void AddTimeData(unsigned int ip, int64 nTime) if (vTimeOffsets.empty()) vTimeOffsets.push_back(0); vTimeOffsets.push_back(nOffsetSample); - printf("Added time data, samples %d, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60); + printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60); if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { sort(vTimeOffsets.begin(), vTimeOffsets.end()); @@ -449,7 +447,7 @@ void AddTimeData(unsigned int ip, int64 nTime) /// to make sure it doesn't get changed again } foreach(int64 n, vTimeOffsets) - printf("%+I64d ", n); - printf("| nTimeOffset = %+I64d (%+I64d minutes)\n", nTimeOffset, nTimeOffset/60); + printf("%+"PRI64d" ", n); + printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60); } } diff --git a/util.h b/util.h index 436281c90..1c7215d29 100644 --- a/util.h +++ b/util.h @@ -13,7 +13,6 @@ typedef unsigned long long uint64; #if defined(_MSC_VER) && _MSC_VER < 1300 #define for if (false) ; else for #endif - #ifndef _MSC_VER #define __forceinline inline #endif @@ -25,25 +24,22 @@ typedef unsigned long long uint64; #define UBEGIN(a) ((unsigned char*)&(a)) #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) - -#ifdef _WINDOWS #define printf OutputDebugStringF -#endif #ifdef snprintf #undef snprintf #endif #define snprintf my_snprintf -#ifndef PRId64 +#ifndef PRI64d #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__) -#define PRId64 "I64d" -#define PRIu64 "I64u" -#define PRIx64 "I64x" +#define PRI64d "I64d" +#define PRI64u "I64u" +#define PRI64x "I64x" #else -#define PRId64 "lld" -#define PRIu64 "llu" -#define PRIx64 "llx" +#define PRI64d "lld" +#define PRI64u "llu" +#define PRI64x "llx" #endif #endif @@ -64,8 +60,6 @@ inline T& REF(const T& val) - - extern bool fDebug; extern bool fPrintToDebugger; extern bool fPrintToConsole; @@ -101,9 +95,7 @@ void AddTimeData(unsigned int ip, int64 nTime); - -// Wrapper to automatically initialize critical section -// Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection +// Wrapper to automatically initialize critical sections class CCriticalSection { #ifdef __WXMSW__ @@ -191,6 +183,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...) } } +#ifdef __WXMSW__ if (fPrintToDebugger) { // accumulate a line at a time @@ -230,6 +223,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...) pend -= (p1 - pszBuffer); } } +#endif #endif if (fPrintToConsole) @@ -254,7 +248,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...) inline string i64tostr(int64 n) { - return strprintf("%"PRId64, n); + return strprintf("%"PRI64d, n); } inline string itostr(int n) @@ -328,6 +322,20 @@ inline void PrintHex(vector vch, const char* pszFormat="%s", bool printf(pszFormat, HexStr(vch, fSpaces).c_str()); } +inline int64 PerformanceCounter() +{ + int64 nCounter = 0; + QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); + return nCounter; +} + +#ifndef __WXMSW__ +inline void Sleep(unsigned int nMilliseconds) +{ + wxMilliSleep(nMilliseconds); +} +#endif + @@ -370,6 +378,7 @@ inline void heapchk() + template inline uint256 Hash(const T1 pbegin, const T1 pend) {