better wallet.dat flush, consolidated QueryPerformanceCounter, PRI64d printf portability
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Thu, 29 Oct 2009 20:10:46 +0000 (20:10 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Thu, 29 Oct 2009 20:10:46 +0000 (20:10 +0000)
build.txt
db.cpp
db.h
main.cpp
main.h
makefile.vc
net.h
ui.cpp
util.cpp
util.h

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