move debug.log and db.log to data dir, portable GetDataDir, optimize GetBalance, fix repaint bogdown, -addnode and -? switches

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@25 1a98c847-1fd6-4fd8-948a-caf3550aa51b
This commit is contained in:
s_nakamoto 2009-11-01 01:16:51 +00:00
parent 5750932cdf
commit 4ac57f013e
12 changed files with 415 additions and 381 deletions

View File

@ -10,7 +10,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com).
Compilers Supported Compilers Supported
------------------- -------------------
MinGW GCC MinGW GCC (v3.4.5)
Microsoft Visual C++ 6.0 SP6 Microsoft Visual C++ 6.0 SP6

19
db.cpp
View File

@ -61,18 +61,19 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
{ {
if (fShutdown) if (fShutdown)
return; return;
string strAppDir = GetAppDir(); string strDataDir = GetDataDir();
string strLogDir = strAppDir + "\\database"; string strLogDir = strDataDir + "\\database";
_mkdir(strLogDir.c_str()); _mkdir(strLogDir.c_str());
printf("dbenv.open strAppDir=%s\n", strAppDir.c_str()); string strErrorFile = strDataDir + "\\db.log";
printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
dbenv.set_lg_dir(strLogDir.c_str()); dbenv.set_lg_dir(strLogDir.c_str());
dbenv.set_lg_max(10000000); dbenv.set_lg_max(10000000);
dbenv.set_lk_max_locks(10000); dbenv.set_lk_max_locks(10000);
dbenv.set_lk_max_objects(10000); dbenv.set_lk_max_objects(10000);
dbenv.set_errfile(fopen("db.log", "a")); /// debug dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug
///dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); /// causes corruption ///dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); /// causes corruption
ret = dbenv.open(strAppDir.c_str(), ret = dbenv.open(strDataDir.c_str(),
DB_CREATE | DB_CREATE |
DB_INIT_LOCK | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_LOG |
@ -139,6 +140,8 @@ void DBFlush(bool fShutdown)
// Flush log data to the actual data file // Flush log data to the actual data file
// on all files that are not in use // on all files that are not in use
printf("DBFlush(%s)\n", fShutdown ? "true" : "false"); printf("DBFlush(%s)\n", fShutdown ? "true" : "false");
if (!fDbEnvInit)
return;
CRITICAL_BLOCK(cs_db) CRITICAL_BLOCK(cs_db)
{ {
dbenv.txn_checkpoint(0, 0, 0); dbenv.txn_checkpoint(0, 0, 0);
@ -421,7 +424,7 @@ bool CAddrDB::LoadAddresses()
while (fgets(psz, sizeof(psz), filein)) while (fgets(psz, sizeof(psz), filein))
{ {
CAddress addr(psz, NODE_NETWORK); CAddress addr(psz, NODE_NETWORK);
if (addr.ip != 0) if (addr.IsValid())
{ {
AddAddress(*this, addr); AddAddress(*this, addr);
mapIRCAddresses.insert(make_pair(addr.GetKey(), addr)); mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
@ -676,10 +679,10 @@ void ThreadFlushWalletDB(void* parg)
{ {
// Flush wallet.dat so it's self contained // Flush wallet.dat so it's self contained
nLastFlushed == nWalletDBUpdated; nLastFlushed == nWalletDBUpdated;
int64 nStart = PerformanceCounter(); int64 nStart = GetTimeMillis();
dbenv.txn_checkpoint(0, 0, 0); dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0); dbenv.lsn_reset(strFile.c_str(), 0);
printf("Flushed wallet.dat %15"PRI64d"\n", PerformanceCounter() - nStart); printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
mapFileUseCount.erase(mi++); mapFileUseCount.erase(mi++);
} }
} }

View File

@ -40,7 +40,7 @@ bool DecodeAddress(string str, CAddress& addr)
return false; return false;
memcpy(&tmp, &vch[0], sizeof(tmp)); memcpy(&tmp, &vch[0], sizeof(tmp));
addr = CAddress(tmp.ip, tmp.port); addr = CAddress(tmp.ip, tmp.port, NODE_NETWORK);
return true; return true;
} }
@ -163,6 +163,7 @@ void ThreadIRCSeed(void* parg)
int nErrorWait = 10; int nErrorWait = 10;
int nRetryWait = 10; int nRetryWait = 10;
// IRC server blocks TOR users
if (fUseProxy && addrProxy.port == htons(9050)) if (fUseProxy && addrProxy.port == htons(9050))
return; return;
@ -237,14 +238,14 @@ void ThreadIRCSeed(void* parg)
{ {
// index 7 is limited to 16 characters // index 7 is limited to 16 characters
// could get full length name at index 10, but would be different from join messages // could get full length name at index 10, but would be different from join messages
strcpy(pszName, vWords[7].c_str()); strlcpy(pszName, vWords[7].c_str(), sizeof(pszName));
printf("IRC got who\n"); printf("IRC got who\n");
} }
if (vWords[1] == "JOIN" && vWords[0].size() > 1) if (vWords[1] == "JOIN" && vWords[0].size() > 1)
{ {
// :username!username@50000007.F000000B.90000002.IP JOIN :#channelname // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname
strcpy(pszName, vWords[0].c_str() + 1); strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
if (strchr(pszName, '!')) if (strchr(pszName, '!'))
*strchr(pszName, '!') = '\0'; *strchr(pszName, '!') = '\0';
printf("IRC got join\n"); printf("IRC got join\n");

5
irc.h
View File

@ -2,11 +2,6 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef __WXMSW__
#define closesocket(s) close(s)
typedef u_int SOCKET;
#endif
extern bool RecvLine(SOCKET hSocket, string& strLine); extern bool RecvLine(SOCKET hSocket, string& strLine);
extern void ThreadIRCSeed(void* parg); extern void ThreadIRCSeed(void* parg);
extern bool fRestartIRCSeed; extern bool fRestartIRCSeed;

View File

@ -42,7 +42,6 @@ map<uint160, vector<unsigned char> > mapPubKeys;
CCriticalSection cs_mapKeys; CCriticalSection cs_mapKeys;
CKey keyUser; CKey keyUser;
string strSetDataDir;
int nDropMessagesTest = 0; int nDropMessagesTest = 0;
// Settings // Settings
@ -1361,52 +1360,17 @@ bool ScanMessageStart(Stream& s)
} }
} }
string GetAppDir()
{
string strDir;
if (!strSetDataDir.empty())
{
strDir = strSetDataDir;
}
else if (getenv("APPDATA"))
{
strDir = strprintf("%s\\Bitcoin", getenv("APPDATA"));
}
else if (getenv("USERPROFILE"))
{
string strAppData = strprintf("%s\\Application Data", getenv("USERPROFILE"));
static bool fMkdirDone;
if (!fMkdirDone)
{
fMkdirDone = true;
_mkdir(strAppData.c_str());
}
strDir = strprintf("%s\\Bitcoin", strAppData.c_str());
}
else
{
return ".";
}
static bool fMkdirDone;
if (!fMkdirDone)
{
fMkdirDone = true;
_mkdir(strDir.c_str());
}
return strDir;
}
bool CheckDiskSpace(int64 nAdditionalBytes) bool CheckDiskSpace(int64 nAdditionalBytes)
{ {
wxLongLong nFreeBytesAvailable = 0; wxLongLong nFreeBytesAvailable = 0;
if (!wxGetDiskSpace(wxStandardPaths::Get().GetDataDir(), NULL, &nFreeBytesAvailable)) if (!wxGetDiskSpace(GetDataDir(), NULL, &nFreeBytesAvailable))
{ {
printf("ERROR: wxGetDiskSpace() failed\n"); printf("ERROR: wxGetDiskSpace() failed\n");
return true; return true;
} }
// Check for 15MB because database could create another 10MB log file at any time // Check for 15MB because database could create another 10MB log file at any time
if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes) if (nFreeBytesAvailable.GetValue() < (int64)15000000 + nAdditionalBytes)
{ {
fShutdown = true; fShutdown = true;
wxMessageBox("Warning: Your disk space is low ", "Bitcoin", wxICON_EXCLAMATION); wxMessageBox("Warning: Your disk space is low ", "Bitcoin", wxICON_EXCLAMATION);
@ -1420,7 +1384,7 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM
{ {
if (nFile == -1) if (nFile == -1)
return NULL; return NULL;
FILE* file = fopen(strprintf("%s\\blk%04d.dat", GetAppDir().c_str(), nFile).c_str(), pszMode); FILE* file = fopen(strprintf("%s\\blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
if (!file) if (!file)
return NULL; return NULL;
if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w')) if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
@ -1719,7 +1683,7 @@ bool ProcessMessages(CNode* pfrom)
if (strstr(e.what(), "CDataStream::read() : end of data")) if (strstr(e.what(), "CDataStream::read() : end of data"))
{ {
// Allow exceptions from underlength message on vRecv // Allow exceptions from underlength message on vRecv
LogException(&e, "ProcessMessage()"); printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
} }
else else
PrintException(&e, "ProcessMessage()"); PrintException(&e, "ProcessMessage()");
@ -2512,7 +2476,7 @@ bool BitcoinMiner()
int64 GetBalance() int64 GetBalance()
{ {
int64 nStart = PerformanceCounter(); int64 nStart = GetTimeMillis();
int64 nTotal = 0; int64 nTotal = 0;
CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(cs_mapWallet)
@ -2522,11 +2486,11 @@ int64 GetBalance()
CWalletTx* pcoin = &(*it).second; CWalletTx* pcoin = &(*it).second;
if (!pcoin->IsFinal() || pcoin->fSpent) if (!pcoin->IsFinal() || pcoin->fSpent)
continue; continue;
nTotal += pcoin->GetCredit(); nTotal += pcoin->GetCredit(true);
} }
} }
///printf(" GetBalance() time = %15"PRI64d"\n", PerformanceCounter() - nStart); //printf("GetBalance() %"PRI64d"ms\n", GetTimeMillis() - nStart);
return nTotal; return nTotal;
} }

20
main.h
View File

@ -34,7 +34,6 @@ extern int nBestHeight;
extern uint256 hashBestChain; extern uint256 hashBestChain;
extern CBlockIndex* pindexBest; extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated; extern unsigned int nTransactionsUpdated;
extern string strSetDataDir;
extern int nDropMessagesTest; extern int nDropMessagesTest;
// Settings // Settings
@ -50,7 +49,6 @@ extern int nLimitProcessors;
string GetAppDir();
bool CheckDiskSpace(int64 nAdditionalBytes=0); bool CheckDiskSpace(int64 nAdditionalBytes=0);
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
FILE* AppendBlockFile(unsigned int& nFileRet); FILE* AppendBlockFile(unsigned int& nFileRet);
@ -405,10 +403,10 @@ public:
{ {
// Time based nLockTime implemented in 0.1.6, // Time based nLockTime implemented in 0.1.6,
// do not use time based until most 0.1.5 nodes have upgraded. // do not use time based until most 0.1.5 nodes have upgraded.
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if (nLockTime == 0) if (nLockTime == 0)
return true; return true;
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime)) if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))
return true; return true;
foreach(const CTxIn& txin, vin) foreach(const CTxIn& txin, vin)
@ -627,6 +625,8 @@ public:
// memory only // memory only
mutable bool fMerkleVerified; mutable bool fMerkleVerified;
mutable bool fGetCreditCached;
mutable int64 nGetCreditCached;
CMerkleTx() CMerkleTx()
@ -644,14 +644,22 @@ public:
hashBlock = 0; hashBlock = 0;
nIndex = -1; nIndex = -1;
fMerkleVerified = false; fMerkleVerified = false;
fGetCreditCached = false;
nGetCreditCached = 0;
} }
int64 GetCredit() const int64 GetCredit(bool fUseCache=false) const
{ {
// Must wait until coinbase is safely deep enough in the chain before valuing it // Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0) if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0; return 0;
return CTransaction::GetCredit();
// GetBalance can assume transactions in mapWallet won't change
if (fUseCache && fGetCreditCached)
return nGetCreditCached;
nGetCreditCached = CTransaction::GetCredit();
fGetCreditCached = true;
return nGetCreditCached;
} }
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE

34
net.cpp
View File

@ -21,8 +21,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
bool fClient = false; bool fClient = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices); CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices)); CNode* pnodeLocalHost = NULL;
CNode* pnodeLocalHost = &nodeLocalHost;
uint64 nLocalHostNonce = 0; uint64 nLocalHostNonce = 0;
bool fShutdown = false; bool fShutdown = false;
array<int, 10> vnThreadsRunning; array<int, 10> vnThreadsRunning;
@ -129,7 +128,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
strLine = wxString(strLine).Trim(); strLine = wxString(strLine).Trim();
CAddress addr(strLine.c_str()); CAddress addr(strLine.c_str());
printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
if (addr.ip == 0 || !addr.IsRoutable()) if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
return false; return false;
ipRet = addr.ip; ipRet = addr.ip;
return true; return true;
@ -740,10 +739,29 @@ void ThreadOpenConnections2(void* parg)
printf("ThreadOpenConnections started\n"); printf("ThreadOpenConnections started\n");
// Connect to one specified address // Connect to one specified address
while (mapArgs.count("/connect")) while (mapArgs.count("-connect"))
{ {
OpenNetworkConnection(CAddress(mapArgs["/connect"].c_str())); OpenNetworkConnection(CAddress(mapArgs["-connect"]));
Sleep(10000); for (int i = 0; i < 10; i++)
{
Sleep(1000);
CheckForShutdown(1);
}
}
// Connect to manually added nodes first
if (mapArgs.count("-addnode"))
{
foreach(string strAddr, mapMultiArgs["-addnode"])
{
CAddress addr(strAddr, NODE_NETWORK);
if (addr.IsValid())
{
OpenNetworkConnection(addr);
Sleep(1000);
CheckForShutdown(1);
}
}
} }
// Initiate network connections // Initiate network connections
@ -967,6 +985,8 @@ void ThreadMessageHandler2(void* parg)
bool StartNode(string& strError) bool StartNode(string& strError)
{ {
if (pnodeLocalHost == NULL)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
strError = ""; strError = "";
// Sockets startup // Sockets startup
@ -1031,7 +1051,7 @@ bool StartNode(string& strError)
printf("%s\n", strError.c_str()); printf("%s\n", strError.c_str());
return false; return false;
} }
printf("bound to addrLocalHost = %s\n\n", addrLocalHost.ToString().c_str()); printf("bound to addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
// Listen for incoming connections // Listen for incoming connections
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)

78
net.h
View File

@ -2,12 +2,6 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef __WXMSW__
#define closesocket(s) close(s)
#define INVALID_SOCKET (SOCKET)(~0)
typedef u_int SOCKET;
#endif
class CMessageHeader; class CMessageHeader;
class CAddress; class CAddress;
class CInv; class CInv;
@ -148,61 +142,73 @@ public:
CAddress() CAddress()
{ {
nServices = 0; Init();
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = 0;
port = DEFAULT_PORT;
nTime = GetAdjustedTime();
nLastFailed = 0;
} }
CAddress(unsigned int ipIn, unsigned short portIn=DEFAULT_PORT, uint64 nServicesIn=0) CAddress(unsigned int ipIn, unsigned short portIn=DEFAULT_PORT, uint64 nServicesIn=NODE_NETWORK)
{ {
nServices = nServicesIn; Init();
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = ipIn; ip = ipIn;
port = portIn; port = portIn;
nTime = GetAdjustedTime(); nServices = nServicesIn;
nLastFailed = 0;
} }
explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=0) explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK)
{ {
nServices = nServicesIn; Init();
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = sockaddr.sin_addr.s_addr; ip = sockaddr.sin_addr.s_addr;
port = sockaddr.sin_port; port = sockaddr.sin_port;
nTime = GetAdjustedTime(); nServices = nServicesIn;
nLastFailed = 0;
} }
explicit CAddress(const char* pszIn, uint64 nServicesIn=0) explicit CAddress(const char* pszIn, uint64 nServicesIn=NODE_NETWORK)
{ {
Init();
SetAddress(pszIn);
nServices = nServicesIn; nServices = nServicesIn;
}
explicit CAddress(string strIn, uint64 nServicesIn=NODE_NETWORK)
{
Init();
SetAddress(strIn.c_str());
nServices = nServicesIn;
}
void Init()
{
nServices = NODE_NETWORK;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = INADDR_NONE; ip = INADDR_NONE;
port = DEFAULT_PORT; port = DEFAULT_PORT;
nTime = GetAdjustedTime(); nTime = GetAdjustedTime();
nLastFailed = 0; nLastFailed = 0;
}
bool SetAddress(const char* pszIn)
{
ip = INADDR_NONE;
port = DEFAULT_PORT;
char psz[100]; char psz[100];
if (strlen(pszIn) > ARRAYLEN(psz)-1) strlcpy(psz, pszIn, sizeof(psz));
return;
strcpy(psz, pszIn);
unsigned int a=0, b=0, c=0, d=0, e=0; unsigned int a=0, b=0, c=0, d=0, e=0;
if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4) if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
return; return false;
char* pszPort = strchr(psz, ':'); char* pszPort = strchr(psz, ':');
if (pszPort) if (pszPort)
{ {
*pszPort++ = '\0'; *pszPort++ = '\0';
port = htons(atoi(pszPort)); port = htons(atoi(pszPort));
if (atoi(pszPort) > USHRT_MAX) if (atoi(pszPort) < 0 || atoi(pszPort) > USHRT_MAX)
port = htons(USHRT_MAX); port = htons(USHRT_MAX);
if (atoi(pszPort) < 0)
port = htons(0);
} }
ip = inet_addr(psz); ip = inet_addr(psz);
return IsValid();
}
bool SetAddress(string strIn)
{
return SetAddress(strIn.c_str());
} }
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE
@ -274,7 +280,17 @@ public:
bool IsRoutable() const bool IsRoutable() const
{ {
return !(GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168) || GetByte(3) == 127 || GetByte(3) == 0); return !(GetByte(3) == 10 ||
(GetByte(3) == 192 && GetByte(2) == 168) ||
GetByte(3) == 127 ||
GetByte(3) == 0 ||
ip == 0 ||
ip == INADDR_NONE);
}
bool IsValid() const
{
return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
} }
unsigned char GetByte(int n) const unsigned char GetByte(int n) const

455
ui.cpp
View File

@ -25,7 +25,6 @@ DEFINE_EVENT_TYPE(wxEVT_TABLEDELETED)
CMainFrame* pframeMain = NULL; CMainFrame* pframeMain = NULL;
CMyTaskBarIcon* ptaskbaricon = NULL; CMyTaskBarIcon* ptaskbaricon = NULL;
map<string, string> mapAddressBook; map<string, string> mapAddressBook;
map<string, string> mapArgs;
bool fRandSendTest = false; bool fRandSendTest = false;
void RandSend(); void RandSend();
extern int g_isPainting; extern int g_isPainting;
@ -283,7 +282,6 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
fRefreshListCtrl = false; fRefreshListCtrl = false;
fRefreshListCtrlRunning = false; fRefreshListCtrlRunning = false;
fOnSetFocusAddress = false; fOnSetFocusAddress = false;
pindexBestLast = NULL;
m_choiceFilter->SetSelection(0); m_choiceFilter->SetSelection(0);
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " "); m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
m_listCtrl->SetFocus(); m_listCtrl->SetFocus();
@ -507,6 +505,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
string strStatus = FormatTxStatus(wtx); string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue; map<string, string> mapValue = wtx.mapValue;
wtx.nLinesDisplayed = 1; wtx.nLinesDisplayed = 1;
nListViewUpdated++;
// Filter // Filter
if (wtx.IsCoinBase()) if (wtx.IsCoinBase())
@ -712,48 +711,6 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
return true; return true;
} }
void CMainFrame::RefreshStatus()
{
static int nLastTop;
int nTop = max((int)m_listCtrl->GetTopItem(), 0);
if (nTop == nLastTop && pindexBestLast == pindexBest)
return;
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
int nStart = nTop;
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
if (pindexBestLast == pindexBest)
{
if (nStart >= nLastTop && nStart < nLastTop + 100)
nStart = nLastTop + 100;
if (nEnd >= nLastTop && nEnd < nLastTop + 100)
nEnd = nLastTop;
}
nLastTop = nTop;
pindexBestLast = pindexBest;
for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
{
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi == mapWallet.end())
{
printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
continue;
}
CWalletTx& wtx = (*mi).second;
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
{
if (!InsertTransaction(wtx, false, nIndex))
m_listCtrl->DeleteItem(nIndex--);
}
else
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
}
}
}
void CMainFrame::RefreshListCtrl() void CMainFrame::RefreshListCtrl()
{ {
fRefreshListCtrl = true; fRefreshListCtrl = true;
@ -832,21 +789,104 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
} }
} }
void CMainFrame::RefreshStatusColumn()
{
static int nLastTop;
static CBlockIndex* pindexLastBest;
static unsigned int nLastRefreshed;
int nTop = max((int)m_listCtrl->GetTopItem(), 0);
if (nTop == nLastTop && pindexLastBest == pindexBest)
return;
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
int nStart = nTop;
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
if (pindexLastBest == pindexBest && nLastRefreshed == nListViewUpdated)
{
// If no updates, only need to do the part that moved onto the screen
if (nStart >= nLastTop && nStart < nLastTop + 100)
nStart = nLastTop + 100;
if (nEnd >= nLastTop && nEnd < nLastTop + 100)
nEnd = nLastTop;
}
nLastTop = nTop;
pindexLastBest = pindexBest;
nLastRefreshed = nListViewUpdated;
for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
{
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi == mapWallet.end())
{
printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n");
continue;
}
CWalletTx& wtx = (*mi).second;
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
{
if (!InsertTransaction(wtx, false, nIndex))
m_listCtrl->DeleteItem(nIndex--);
}
else
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
}
}
}
void CMainFrame::OnPaint(wxPaintEvent& event) void CMainFrame::OnPaint(wxPaintEvent& event)
{ {
event.Skip(); event.Skip();
} }
void DelayedRepaint(void* parg)
unsigned int nNeedRepaint = 0;
unsigned int nLastRepaint = 0;
int64 nLastRepaintTime = 0;
int64 nRepaintInterval = 500;
void ThreadDelayedRepaint(void* parg)
{ {
static bool fOneThread; while (!fShutdown)
if (fOneThread) {
return; if (nLastRepaint != nNeedRepaint && GetTimeMillis() - nLastRepaintTime >= nRepaintInterval)
fOneThread = true; {
Sleep(1000); nLastRepaint = nNeedRepaint;
printf("DelayedRepaint()\n"); if (pframeMain)
MainFrameRepaint(); {
fOneThread = false; printf("DelayedRepaint\n");
wxPaintEvent event;
pframeMain->Refresh();
pframeMain->AddPendingEvent(event);
}
}
Sleep(nRepaintInterval);
}
}
void MainFrameRepaint()
{
// This is called by network code that shouldn't access pframeMain
// directly because it could still be running after the UI is closed.
if (pframeMain)
{
// Don't repaint too often
static int64 nLastRepaintRequest;
if (GetTimeMillis() - nLastRepaintRequest < 100)
{
nNeedRepaint++;
return;
}
nLastRepaintRequest = GetTimeMillis();
printf("MainFrameRepaint\n");
wxPaintEvent event;
pframeMain->Refresh();
pframeMain->AddPendingEvent(event);
}
} }
void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
@ -854,43 +894,54 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
if (ptaskbaricon) if (ptaskbaricon)
ptaskbaricon->UpdateTooltip(); ptaskbaricon->UpdateTooltip();
// Update listctrl contents //
if (!vWalletUpdated.empty()) // Slower stuff
//
static int nTransactionCount;
bool fPaintedBalance = false;
if (GetTimeMillis() - nLastRepaintTime >= nRepaintInterval)
{ {
nLastRepaint = nNeedRepaint;
nLastRepaintTime = GetTimeMillis();
// Update listctrl contents
if (!vWalletUpdated.empty())
{
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
bool fInserted = false;
foreach(uint256 hash, vWalletUpdated)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi != mapWallet.end())
fInserted |= InsertTransaction((*mi).second, false);
}
vWalletUpdated.clear();
if (fInserted)
m_listCtrl->ScrollList(0, INT_MAX);
}
}
// Balance total
TRY_CRITICAL_BLOCK(cs_mapWallet) TRY_CRITICAL_BLOCK(cs_mapWallet)
{ {
bool fInserted = false; fPaintedBalance = true;
foreach(uint256 hash, vWalletUpdated) m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
// Count hidden and multi-line transactions
nTransactionCount = 0;
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); CWalletTx& wtx = (*it).second;
if (mi != mapWallet.end()) nTransactionCount += wtx.nLinesDisplayed;
fInserted |= InsertTransaction((*mi).second, false);
} }
vWalletUpdated.clear();
if (fInserted)
m_listCtrl->ScrollList(0, INT_MAX);
} }
} }
if (!vWalletUpdated.empty() || !fPaintedBalance)
nNeedRepaint++;
// Update status column of visible items only // Update status column of visible items only
RefreshStatus(); RefreshStatusColumn();
// Balance total
bool fRefreshed = false;
static int nTransactionCount;
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
fRefreshed = true;
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
// Count hidden and multi-line transactions
nTransactionCount = 0;
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
CWalletTx& wtx = (*it).second;
nTransactionCount += wtx.nLinesDisplayed;
}
}
// Update status bar // Update status bar
string strGen = ""; string strGen = "";
@ -903,13 +954,10 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount); string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
m_statusBar->SetStatusText(strStatus, 2); m_statusBar->SetStatusText(strStatus, 2);
// mapWallet was locked, try again later
if (!vWalletUpdated.empty() || !fRefreshed)
_beginthread(DelayedRepaint, 0, NULL);
m_listCtrl->OnPaint(event); m_listCtrl->OnPaint(event);
} }
void CrossThreadCall(wxCommandEvent& event) void CrossThreadCall(wxCommandEvent& event)
{ {
if (pframeMain) if (pframeMain)
@ -994,13 +1042,6 @@ void CMainFrame::OnMenuHelpAbout(wxCommandEvent& event)
void CMainFrame::OnButtonSend(wxCommandEvent& event) void CMainFrame::OnButtonSend(wxCommandEvent& event)
{ {
/// debug test
if (fRandSendTest)
{
RandSend();
return;
}
// Toolbar: Send // Toolbar: Send
CSendDialog dialog(this); CSendDialog dialog(this);
dialog.ShowModal(); dialog.ShowModal();
@ -1684,8 +1725,8 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
else else
{ {
// Parse IP address // Parse IP address
CAddress addr(strAddress.c_str()); CAddress addr(strAddress);
if (addr.ip == 0) if (!addr.IsValid())
{ {
wxMessageBox("Invalid address ", "Send Coins"); wxMessageBox("Invalid address ", "Send Coins");
return; return;
@ -1818,14 +1859,6 @@ void CSendingDialog::OnPaint(wxPaintEvent& event)
wxMessageBox("Transfer cancelled ", "Sending...", wxOK, this); wxMessageBox("Transfer cancelled ", "Sending...", wxOK, this);
} }
event.Skip(); event.Skip();
/// debug test
if (fRandSendTest && fWorkDone && fSuccess)
{
Close();
Sleep(1000);
RandSend();
}
} }
@ -3305,27 +3338,6 @@ bool CMyApp::OnInit()
return false; return false;
} }
map<string, string> ParseParameters(int argc, char* argv[])
{
map<string, string> mapArgs;
for (int i = 0; i < argc; i++)
{
char psz[10000];
strcpy(psz, argv[i]);
char* pszValue = "";
if (strchr(psz, '='))
{
pszValue = strchr(psz, '=');
*pszValue++ = '\0';
}
strlwr(psz);
if (psz[0] == '-')
psz[0] = '/';
mapArgs[psz] = pszValue;
}
return mapArgs;
}
bool CMyApp::OnInit2() bool CMyApp::OnInit2()
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
@ -3337,10 +3349,27 @@ bool CMyApp::OnInit2()
// Disable malfunctioning wxWidgets debug assertion // Disable malfunctioning wxWidgets debug assertion
g_isPainting = 10000; g_isPainting = 10000;
#endif #endif
wxImage::AddHandler(new wxPNGHandler);
SetAppName("Bitcoin");
//// debug print ParseParameters(argc, argv);
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); if (mapArgs.count("-?") || mapArgs.count("--help"))
printf("Bitcoin version %d, Windows version %08x\n", VERSION, GetVersion()); {
string strUsage =
"Usage: bitcoin [options]\t\t\t\t\t\t\n"
"Options:\n"
" -gen\t\t Generate coins\n"
" -gen=0\t\t Don't generate coins\n"
" -min\t\t Start minimized\n"
" -datadir=<dir>\t Specify data directory\n"
" -proxy=<ip:port>\t Connect through socks4 proxy,\n"
" \t\t e.g. -proxy=127.0.0.1:9050 to use TOR\n"
" -addnode=<ip>\t Add a node to connect to\n"
" -connect=<ip>\t Connect only to the specified node\n"
" -?\t\t This help message\n";
wxMessageBox(strUsage, "Bitcoin", wxOK);
exit(0);
}
// //
// Limit to single instance per user // Limit to single instance per user
@ -3382,31 +3411,31 @@ bool CMyApp::OnInit2()
// //
// Parameters // Parameters
// //
wxImage::AddHandler(new wxPNGHandler); if (mapArgs.count("-datadir"))
mapArgs = ParseParameters(argc, argv); strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
if (mapArgs.count("/datadir")) if (mapArgs.count("-debug"))
strSetDataDir = mapArgs["/datadir"];
if (mapArgs.count("/debug"))
fDebug = true; fDebug = true;
if (mapArgs.count("/printtodebugger")) if (mapArgs.count("-printtodebugger"))
fPrintToDebugger = true; fPrintToDebugger = true;
if (mapArgs.count("/dropmessages")) printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Bitcoin version %d, Windows version %08x\n", VERSION, GetVersion());
if (mapArgs.count("-dropmessages"))
{ {
nDropMessagesTest = atoi(mapArgs["/dropmessages"]); nDropMessagesTest = atoi(mapArgs["-dropmessages"]);
if (nDropMessagesTest == 0) if (nDropMessagesTest == 0)
nDropMessagesTest = 20; nDropMessagesTest = 20;
} }
if (mapArgs.count("/loadblockindextest")) if (mapArgs.count("-loadblockindextest"))
{ {
CTxDB txdb("r"); CTxDB txdb("r");
txdb.LoadBlockIndex(); txdb.LoadBlockIndex();
PrintBlockTree(); PrintBlockTree();
ExitProcess(0); exit(0);
} }
// //
@ -3417,22 +3446,22 @@ bool CMyApp::OnInit2()
int64 nStart; int64 nStart;
printf("Loading addresses...\n"); printf("Loading addresses...\n");
nStart = PerformanceCounter(); nStart = GetTimeMillis();
if (!LoadAddresses()) if (!LoadAddresses())
strErrors += "Error loading addr.dat \n"; strErrors += "Error loading addr.dat \n";
printf(" addresses %15"PRI64d"\n", PerformanceCounter() - nStart); printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading block index...\n"); printf("Loading block index...\n");
nStart = PerformanceCounter(); nStart = GetTimeMillis();
if (!LoadBlockIndex()) if (!LoadBlockIndex())
strErrors += "Error loading blkindex.dat \n"; strErrors += "Error loading blkindex.dat \n";
printf(" block index %15"PRI64d"\n", PerformanceCounter() - nStart); printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading wallet...\n"); printf("Loading wallet...\n");
nStart = PerformanceCounter(); nStart = GetTimeMillis();
if (!LoadWallet(fFirstRun)) if (!LoadWallet(fFirstRun))
strErrors += "Error loading wallet.dat \n"; strErrors += "Error loading wallet.dat \n";
printf(" wallet %15"PRI64d"\n", PerformanceCounter() - nStart); printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Done loading\n"); printf("Done loading\n");
@ -3457,45 +3486,59 @@ bool CMyApp::OnInit2()
// //
// Parameters // Parameters
// //
if (mapArgs.count("/printblockindex") || mapArgs.count("/printblocktree")) if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
{ {
PrintBlockTree(); PrintBlockTree();
OnExit(); OnExit();
return false; return false;
} }
if (mapArgs.count("/proxy")) if (mapArgs.count("-gen"))
{
if (mapArgs["-gen"].empty())
fGenerateBitcoins = true;
else
fGenerateBitcoins = atoi(mapArgs["-gen"].c_str());
}
if (mapArgs.count("-proxy"))
{ {
fUseProxy = true; fUseProxy = true;
addrProxy = CAddress(mapArgs["/proxy"].c_str()); addrProxy = CAddress(mapArgs["-proxy"]);
if (addrProxy.ip == INADDR_NONE) if (!addrProxy.IsValid())
{ {
wxMessageBox("Invalid /proxy address", "Bitcoin"); wxMessageBox("Invalid -proxy address", "Bitcoin");
OnExit(); OnExit();
return false;
} }
CWalletDB walletdb; CWalletDB walletdb;
walletdb.WriteSetting("fUseProxy", fUseProxy); walletdb.WriteSetting("fUseProxy", fUseProxy);
walletdb.WriteSetting("addrProxy", addrProxy); walletdb.WriteSetting("addrProxy", addrProxy);
} }
if (mapArgs.count("/gen")) if (mapArgs.count("-addnode"))
{ {
if (mapArgs["/gen"].empty()) CAddrDB addrdb;
fGenerateBitcoins = true; foreach(string strAddr, mapMultiArgs["-addnode"])
else {
fGenerateBitcoins = atoi(mapArgs["/gen"].c_str()); CAddress addr(strAddr, NODE_NETWORK);
if (addr.IsValid())
AddAddress(addrdb, addr);
}
} }
// //
// Create the main frame window // Create the main frame window
// //
pframeMain = new CMainFrame(NULL); pframeMain = new CMainFrame(NULL);
if (mapArgs.count("/min")) if (mapArgs.count("-min"))
pframeMain->Iconize(true); pframeMain->Iconize(true);
pframeMain->Show(true); // have to show first to get taskbar button to hide pframeMain->Show(true); // have to show first to get taskbar button to hide
pframeMain->Show(!fMinimizeToTray || !pframeMain->IsIconized()); pframeMain->Show(!fMinimizeToTray || !pframeMain->IsIconized());
ptaskbaricon->Show(fMinimizeToTray); ptaskbaricon->Show(fMinimizeToTray);
_beginthread(ThreadDelayedRepaint, 0, NULL);
if (!CheckDiskSpace()) if (!CheckDiskSpace())
{ {
OnExit(); OnExit();
@ -3516,7 +3559,7 @@ bool CMyApp::OnInit2()
// //
// Tests // Tests
// //
if (argc >= 2 && stricmp(argv[1], "/send") == 0) if (argc >= 2 && stricmp(argv[1], "-send") == 0)
{ {
int64 nValue = 1; int64 nValue = 1;
if (argc >= 3) if (argc >= 3)
@ -3525,7 +3568,7 @@ bool CMyApp::OnInit2()
string strAddress; string strAddress;
if (argc >= 4) if (argc >= 4)
strAddress = argv[3]; strAddress = argv[3];
CAddress addr(strAddress.c_str()); CAddress addr(strAddress);
CWalletTx wtx; CWalletTx wtx;
wtx.mapValue["to"] = strAddress; wtx.mapValue["to"] = strAddress;
@ -3538,15 +3581,6 @@ bool CMyApp::OnInit2()
return false; return false;
} }
if (mapArgs.count("/randsendtest"))
{
if (!mapArgs["/randsendtest"].empty())
_beginthread(ThreadRandSendTest, 0, new string(mapArgs["/randsendtest"]));
else
fRandSendTest = true;
fDebug = true;
}
return true; return true;
} }
@ -3610,19 +3644,6 @@ void CMyApp::OnFatalException()
void MainFrameRepaint()
{
// This is called by network code that shouldn't access pframeMain
// directly because it could still be running after the UI is closed.
if (pframeMain)
{
printf("MainFrameRepaint()\n");
wxPaintEvent event;
pframeMain->Refresh();
pframeMain->AddPendingEvent(event);
}
}
typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate); typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
@ -3666,7 +3687,7 @@ string StartupShortcutPath()
bool GetStartOnSystemStartup() bool GetStartOnSystemStartup()
{ {
return FileExists(StartupShortcutPath().c_str()); return wxFileExists(StartupShortcutPath());
} }
void SetStartOnSystemStartup(bool fAutoStart) void SetStartOnSystemStartup(bool fAutoStart)
@ -3727,79 +3748,3 @@ void SetStartOnSystemStartup(bool fAutoStart)
// randsendtest to bitcoin address
void ThreadRandSendTest(void* parg)
{
string strAddress = *(string*)parg;
uint160 hash160;
if (!AddressToHash160(strAddress, hash160))
{
wxMessageBox(strprintf("ThreadRandSendTest: Bitcoin address '%s' not valid ", strAddress.c_str()));
return;
}
while (!fShutdown)
{
Sleep(GetRand(30) * 1000 + 100);
// Message
CWalletTx wtx;
wtx.mapValue["to"] = strAddress;
wtx.mapValue["from"] = addrLocalHost.ToString();
static int nRep;
wtx.mapValue["message"] = strprintf("randsendtest %d\n", ++nRep);
// Value
int64 nValue = (GetRand(9) + 1) * 100 * CENT;
if (GetBalance() < nValue)
{
wxMessageBox("Out of money ");
while (GetBalance() < 1000)
Sleep(1000);
}
nValue += (nRep % 100) * CENT;
// Send to bitcoin address
CScript scriptPubKey;
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
if (fShutdown)
return;
if (!SendMoney(scriptPubKey, nValue, wtx))
return;
}
}
// randsendtest to any connected node
void RandSend()
{
while (vNodes.empty())
Sleep(1000);
CAddress addr;
CRITICAL_BLOCK(cs_vNodes)
addr = vNodes[GetRand(vNodes.size())]->addr;
// Message
CWalletTx wtx;
wtx.mapValue["to"] = addr.ToString();
wtx.mapValue["from"] = addrLocalHost.ToString();
static int nRep;
wtx.mapValue["message"] = strprintf("randsendtest %d\n", ++nRep);
// Value
int64 nValue = (GetRand(999) + 1) * CENT;
if (GetBalance() < nValue)
{
wxMessageBox("Out of money ");
return;
}
// Send to IP address
if (fShutdown)
return;
CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx);
if (!pdialog->Show())
wxMessageBox("ShowModal Failed ");
}

5
ui.h
View File

@ -83,15 +83,14 @@ public:
bool fRefreshListCtrl; bool fRefreshListCtrl;
bool fRefreshListCtrlRunning; bool fRefreshListCtrlRunning;
bool fOnSetFocusAddress; bool fOnSetFocusAddress;
CBlockIndex* pindexBestLast; unsigned int nListViewUpdated;
set<uint256> setUnmaturedDisplayed;
void OnCrossThreadCall(wxCommandEvent& event); void OnCrossThreadCall(wxCommandEvent& event);
void InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5); void InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5);
bool DeleteLine(uint256 hashKey); bool DeleteLine(uint256 hashKey);
bool InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1); bool InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
void RefreshListCtrl(); void RefreshListCtrl();
void RefreshStatus(); void RefreshStatusColumn();
}; };

View File

@ -5,9 +5,13 @@
#include "headers.h" #include "headers.h"
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
bool fDebug = false; bool fDebug = false;
bool fPrintToDebugger = false; bool fPrintToDebugger = false;
bool fPrintToConsole = false; bool fPrintToConsole = false;
char pszSetDataDir[MAX_PATH] = "";
@ -68,6 +72,8 @@ void RandAddSeed()
void RandAddSeedPerfmon() void RandAddSeedPerfmon()
{ {
#ifdef __WXMSW__
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// This can take up to 2 seconds, so only do it every 10 minutes // This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon; static int64 nLastPerfmon;
if (GetTime() < nLastPerfmon + 10 * 60) if (GetTime() < nLastPerfmon + 10 * 60)
@ -95,6 +101,7 @@ void RandAddSeedPerfmon()
strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime); strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime);
printf("%s RandAddSeed() %d bytes\n", pszTime, nSize); printf("%s RandAddSeed() %d bytes\n", pszTime, nSize);
} }
#endif
} }
@ -304,6 +311,32 @@ vector<unsigned char> ParseHex(const std::string& str)
} }
void ParseParameters(int argc, char* argv[])
{
mapArgs.clear();
mapMultiArgs.clear();
for (int i = 0; i < argc; i++)
{
char psz[10000];
strlcpy(psz, argv[i], sizeof(psz));
char* pszValue = "";
if (strchr(psz, '='))
{
pszValue = strchr(psz, '=');
*pszValue++ = '\0';
}
strlwr(psz);
#ifdef __WXMSW__
if (psz[0] == '/')
psz[0] = '-';
#endif
mapArgs[psz] = pszValue;
mapMultiArgs[psz].push_back(pszValue);
}
}
@ -346,15 +379,6 @@ void PrintException(std::exception* pex, const char* pszThread)
bool FileExists(const char* psz)
{
#ifdef WIN32
return GetFileAttributes(psz) != -1;
#else
return access(psz, 0) != -1;
#endif
}
int GetFilesize(FILE* file) int GetFilesize(FILE* file)
{ {
int nSavePos = ftell(file); int nSavePos = ftell(file);
@ -365,6 +389,46 @@ int GetFilesize(FILE* file)
return nFilesize; return nFilesize;
} }
void GetDataDir(char* pszDir)
{
// pszDir must be at least MAX_PATH length.
if (pszSetDataDir[0] != 0)
{
strlcpy(pszDir, pszSetDataDir, MAX_PATH);
static bool fMkdirDone;
if (!fMkdirDone)
{
fMkdirDone = true;
_mkdir(pszDir);
}
}
else
{
// This can be called during exceptions by printf, so we cache the
// value so we don't have to do memory allocations after that.
// wxStandardPaths::GetUserDataDir
// Return the directory for the user-dependent application data files:
// Unix: ~/.appname
// Windows: C:\Documents and Settings\username\Application Data\appname
// Mac: ~/Library/Application Support/appname
static char pszCachedDir[MAX_PATH];
if (pszCachedDir[0] == 0)
{
strlcpy(pszCachedDir, wxStandardPaths::Get().GetUserDataDir().c_str(), sizeof(pszCachedDir));
_mkdir(pszCachedDir);
}
strlcpy(pszDir, pszCachedDir, MAX_PATH);
}
}
string GetDataDir()
{
char pszDir[MAX_PATH];
GetDataDir(pszDir);
return pszDir;
}

35
util.h
View File

@ -54,16 +54,23 @@ inline T& REF(const T& val)
return (T&)val; return (T&)val;
} }
#ifndef __WXMSW__
#define closesocket(s) close(s)
#define INVALID_SOCKET (SOCKET)(~0)
typedef u_int SOCKET;
#endif
extern map<string, string> mapArgs;
extern map<string, vector<string> > mapMultiArgs;
extern bool fDebug; extern bool fDebug;
extern bool fPrintToDebugger; extern bool fPrintToDebugger;
extern bool fPrintToConsole; extern bool fPrintToConsole;
extern map<string, string> mapArgs; extern char pszSetDataDir[MAX_PATH];
void RandAddSeed(); void RandAddSeed();
void RandAddSeedPerfmon(); void RandAddSeedPerfmon();
@ -77,8 +84,10 @@ string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const char* pszIn, int64& nRet); bool ParseMoney(const char* pszIn, int64& nRet);
vector<unsigned char> ParseHex(const char* psz); vector<unsigned char> ParseHex(const char* psz);
vector<unsigned char> ParseHex(const std::string& str); vector<unsigned char> ParseHex(const std::string& str);
bool FileExists(const char* psz); void ParseParameters(int argc, char* argv[]);
int GetFilesize(FILE* file); int GetFilesize(FILE* file);
void GetDataDir(char* pszDirRet);
string GetDataDir();
uint64 GetRand(uint64 nMax); uint64 GetRand(uint64 nMax);
int64 GetTime(); int64 GetTime();
int64 GetAdjustedTime(); int64 GetAdjustedTime();
@ -172,9 +181,14 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
if (!fPrintToConsole) if (!fPrintToConsole)
{ {
// print to debug.log // print to debug.log
FILE* fileout = fopen("debug.log", "a"); char pszFile[MAX_PATH+100];
GetDataDir(pszFile);
strlcat(pszFile, "\\debug.log", sizeof(pszFile));
FILE* fileout = fopen(pszFile, "a");
if (fileout) if (fileout)
{ {
//// Debug print useful for profiling
//fprintf(fileout, " %"PRI64d" ", wxGetLocalTimeMillis().GetValue());
va_list arg_ptr; va_list arg_ptr;
va_start(arg_ptr, pszFormat); va_start(arg_ptr, pszFormat);
ret = vfprintf(fileout, pszFormat, arg_ptr); ret = vfprintf(fileout, pszFormat, arg_ptr);
@ -322,21 +336,24 @@ inline void PrintHex(vector<unsigned char> vch, const char* pszFormat="%s", bool
printf(pszFormat, HexStr(vch, fSpaces).c_str()); printf(pszFormat, HexStr(vch, fSpaces).c_str());
} }
inline int64 PerformanceCounter() inline int64 PerformanceCounter()
{ {
int64 nCounter = 0; int64 nCounter = 0;
#ifdef __WXMSW__ #ifdef __WXMSW__
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else #else
// this could be changed to reading /dev/urandom timeval t;
timeval t; gettimeofday(&t, NULL);
gettimeofday(&t, NULL); nCounter = t.tv_sec * 1000000 + t.tv_usec;
nCounter += t.tv_sec * 1000000 + t.tv_usec;
#endif #endif
return nCounter; return nCounter;
} }
inline int64 GetTimeMillis()
{
return wxGetLocalTimeMillis().GetValue();
}
#ifndef __WXMSW__ #ifndef __WXMSW__
inline void Sleep(unsigned int nMilliseconds) inline void Sleep(unsigned int nMilliseconds)
{ {
@ -354,8 +371,10 @@ inline void Sleep(unsigned int nMilliseconds)
inline void heapchk() inline void heapchk()
{ {
#ifdef __WXMSW__
if (_heapchk() != _HEAPOK) if (_heapchk() != _HEAPOK)
DebugBreak(); DebugBreak();
#endif
} }
// Randomize the stack to help protect against buffer overrun exploits // Randomize the stack to help protect against buffer overrun exploits