aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-10-29 20:10:46 +0000
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-10-29 20:10:46 +0000
commite8474beb6f2c5e2654f8ebc671b3dbf5fae78563 (patch)
tree31faa0f74ff1541946f6d0d5d8764be8e2564a66
parentdc73b326f97f2ed7ec7b7e8485ebc9eb46e05ddb (diff)
downloadbitcoin-e8474beb6f2c5e2654f8ebc671b3dbf5fae78563.tar.xz
better wallet.dat flush, consolidated QueryPerformanceCounter, PRI64d printf portability
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@20 1a98c847-1fd6-4fd8-948a-caf3550aa51b
-rw-r--r--build.txt3
-rw-r--r--db.cpp76
-rw-r--r--db.h12
-rw-r--r--main.cpp6
-rw-r--r--main.h2
-rw-r--r--makefile.vc4
-rw-r--r--net.h2
-rw-r--r--ui.cpp26
-rw-r--r--util.cpp22
-rw-r--r--util.h43
10 files changed, 121 insertions, 75 deletions
diff --git a/build.txt b/build.txt
index f510055767..67b03fe24a 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 315e93b73a..699a94f2ea 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<CReview>& vReviews)
// CWalletDB
//
-CWalletDB::~CWalletDB()
-{
- // Flush whenever all handles to wallet.dat are closed
- CRITICAL_BLOCK(cs_db)
- {
- Close(); // close includes a txn_checkpoint
- map<string, int>::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<unsigned char>& vchDefaultKeyRet)
{
vchDefaultKeyRet.clear();
@@ -610,7 +594,7 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& 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<string, int>::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 4961468759..d11b397eba 100644
--- a/db.h
+++ b/db.h
@@ -17,7 +17,10 @@ extern map<string, string> 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<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
{
+ nWalletDBUpdated++;
return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
}
@@ -395,6 +403,7 @@ public:
bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
{
+ nWalletDBUpdated++;
return Write(string("defaultkey"), vchPubKey);
}
@@ -407,6 +416,7 @@ public:
template<typename T>
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 710b789200..4194333d84 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 958f7a5f1c..fcfd33d134 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 c3bd0c4bcd..fb7f3086e3 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 5995ac3343..4011a3ef75 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 917c64b445..ce287e3911 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 bdf899d78e..ef950920fd 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<string>& 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 436281c90a..1c7215d29d 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
@@ -231,6 +224,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
}
}
#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<unsigned char> 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<typename T1>
inline uint256 Hash(const T1 pbegin, const T1 pend)
{