\r
Compilers Supported\r
-------------------\r
-MinGW GCC (currently v3.4.5)\r
+MinGW GCC\r
Microsoft Visual C++ 6.0 SP6\r
\r
\r
\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
\r
#include "headers.h"\r
\r
+void ThreadFlushWalletDB(void* parg);\r
\r
\r
+unsigned int nWalletDBUpdated;\r
+\r
\r
\r
\r
{\r
if (!fDbEnvInit)\r
{\r
+ if (fShutdown)\r
+ return;\r
string strAppDir = GetAppDir();\r
string strLogDir = strAppDir + "\\database";\r
_mkdir(strLogDir.c_str());\r
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
// 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
\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
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
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
\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
\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
\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
\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
\r
bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)\r
{\r
+ nWalletDBUpdated++;\r
return Write(string("defaultkey"), vchPubKey);\r
}\r
\r
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
\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
}\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
{\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
\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
// 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
//\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
return;\r
}\r
\r
- loop\r
+ while (!fShutdown)\r
{\r
Sleep(GetRand(30) * 1000 + 100);\r
\r
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
// randsendtest to any connected node\r
void RandSend()\r
{\r
- CWalletTx wtx;\r
-\r
while (vNodes.empty())\r
Sleep(1000);\r
CAddress addr;\r
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
}\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
\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
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
{\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
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
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
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
/// 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
#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
#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
\r
\r
\r
-\r
-\r
extern bool fDebug;\r
extern bool fPrintToDebugger;\r
extern bool fPrintToConsole;\r
\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
}\r
}\r
\r
+#ifdef __WXMSW__\r
if (fPrintToDebugger)\r
{\r
// accumulate a line at a time\r
}\r
}\r
#endif\r
+#endif\r
\r
if (fPrintToConsole)\r
{\r
\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
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
\r
\r
\r
+\r
template<typename T1>\r
inline uint256 Hash(const T1 pbegin, const T1 pend)\r
{\r