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

455
ui.cpp
View File

@@ -25,7 +25,6 @@ DEFINE_EVENT_TYPE(wxEVT_TABLEDELETED)
CMainFrame* pframeMain = NULL;
CMyTaskBarIcon* ptaskbaricon = NULL;
map<string, string> mapAddressBook;
map<string, string> mapArgs;
bool fRandSendTest = false;
void RandSend();
extern int g_isPainting;
@@ -283,7 +282,6 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
fRefreshListCtrl = false;
fRefreshListCtrlRunning = false;
fOnSetFocusAddress = false;
pindexBestLast = NULL;
m_choiceFilter->SetSelection(0);
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
m_listCtrl->SetFocus();
@@ -507,6 +505,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue;
wtx.nLinesDisplayed = 1;
nListViewUpdated++;
// Filter
if (wtx.IsCoinBase())
@@ -712,48 +711,6 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
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()
{
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)
{
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;
if (fOneThread)
return;
fOneThread = true;
Sleep(1000);
printf("DelayedRepaint()\n");
MainFrameRepaint();
fOneThread = false;
while (!fShutdown)
{
if (nLastRepaint != nNeedRepaint && GetTimeMillis() - nLastRepaintTime >= nRepaintInterval)
{
nLastRepaint = nNeedRepaint;
if (pframeMain)
{
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)
@@ -854,43 +894,54 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
if (ptaskbaricon)
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)
{
bool fInserted = false;
foreach(uint256 hash, vWalletUpdated)
fPaintedBalance = 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)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi != mapWallet.end())
fInserted |= InsertTransaction((*mi).second, false);
CWalletTx& wtx = (*it).second;
nTransactionCount += wtx.nLinesDisplayed;
}
vWalletUpdated.clear();
if (fInserted)
m_listCtrl->ScrollList(0, INT_MAX);
}
}
if (!vWalletUpdated.empty() || !fPaintedBalance)
nNeedRepaint++;
// Update status column of visible items only
RefreshStatus();
// 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;
}
}
RefreshStatusColumn();
// Update status bar
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);
m_statusBar->SetStatusText(strStatus, 2);
// mapWallet was locked, try again later
if (!vWalletUpdated.empty() || !fRefreshed)
_beginthread(DelayedRepaint, 0, NULL);
m_listCtrl->OnPaint(event);
}
void CrossThreadCall(wxCommandEvent& event)
{
if (pframeMain)
@@ -994,13 +1042,6 @@ void CMainFrame::OnMenuHelpAbout(wxCommandEvent& event)
void CMainFrame::OnButtonSend(wxCommandEvent& event)
{
/// debug test
if (fRandSendTest)
{
RandSend();
return;
}
// Toolbar: Send
CSendDialog dialog(this);
dialog.ShowModal();
@@ -1684,8 +1725,8 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
else
{
// Parse IP address
CAddress addr(strAddress.c_str());
if (addr.ip == 0)
CAddress addr(strAddress);
if (!addr.IsValid())
{
wxMessageBox("Invalid address ", "Send Coins");
return;
@@ -1818,14 +1859,6 @@ void CSendingDialog::OnPaint(wxPaintEvent& event)
wxMessageBox("Transfer cancelled ", "Sending...", wxOK, this);
}
event.Skip();
/// debug test
if (fRandSendTest && fWorkDone && fSuccess)
{
Close();
Sleep(1000);
RandSend();
}
}
@@ -3305,27 +3338,6 @@ bool CMyApp::OnInit()
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()
{
#ifdef _MSC_VER
@@ -3337,10 +3349,27 @@ bool CMyApp::OnInit2()
// Disable malfunctioning wxWidgets debug assertion
g_isPainting = 10000;
#endif
wxImage::AddHandler(new wxPNGHandler);
SetAppName("Bitcoin");
//// debug print
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());
ParseParameters(argc, argv);
if (mapArgs.count("-?") || mapArgs.count("--help"))
{
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
@@ -3382,31 +3411,31 @@ bool CMyApp::OnInit2()
//
// Parameters
//
wxImage::AddHandler(new wxPNGHandler);
mapArgs = ParseParameters(argc, argv);
if (mapArgs.count("-datadir"))
strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
if (mapArgs.count("/datadir"))
strSetDataDir = mapArgs["/datadir"];
if (mapArgs.count("/debug"))
if (mapArgs.count("-debug"))
fDebug = true;
if (mapArgs.count("/printtodebugger"))
if (mapArgs.count("-printtodebugger"))
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)
nDropMessagesTest = 20;
}
if (mapArgs.count("/loadblockindextest"))
if (mapArgs.count("-loadblockindextest"))
{
CTxDB txdb("r");
txdb.LoadBlockIndex();
PrintBlockTree();
ExitProcess(0);
exit(0);
}
//
@@ -3417,22 +3446,22 @@ bool CMyApp::OnInit2()
int64 nStart;
printf("Loading addresses...\n");
nStart = PerformanceCounter();
nStart = GetTimeMillis();
if (!LoadAddresses())
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");
nStart = PerformanceCounter();
nStart = GetTimeMillis();
if (!LoadBlockIndex())
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");
nStart = PerformanceCounter();
nStart = GetTimeMillis();
if (!LoadWallet(fFirstRun))
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");
@@ -3457,45 +3486,59 @@ bool CMyApp::OnInit2()
//
// Parameters
//
if (mapArgs.count("/printblockindex") || mapArgs.count("/printblocktree"))
if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
{
PrintBlockTree();
OnExit();
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;
addrProxy = CAddress(mapArgs["/proxy"].c_str());
if (addrProxy.ip == INADDR_NONE)
addrProxy = CAddress(mapArgs["-proxy"]);
if (!addrProxy.IsValid())
{
wxMessageBox("Invalid /proxy address", "Bitcoin");
wxMessageBox("Invalid -proxy address", "Bitcoin");
OnExit();
return false;
}
CWalletDB walletdb;
walletdb.WriteSetting("fUseProxy", fUseProxy);
walletdb.WriteSetting("addrProxy", addrProxy);
}
if (mapArgs.count("/gen"))
if (mapArgs.count("-addnode"))
{
if (mapArgs["/gen"].empty())
fGenerateBitcoins = true;
else
fGenerateBitcoins = atoi(mapArgs["/gen"].c_str());
CAddrDB addrdb;
foreach(string strAddr, mapMultiArgs["-addnode"])
{
CAddress addr(strAddr, NODE_NETWORK);
if (addr.IsValid())
AddAddress(addrdb, addr);
}
}
//
// Create the main frame window
//
pframeMain = new CMainFrame(NULL);
if (mapArgs.count("/min"))
if (mapArgs.count("-min"))
pframeMain->Iconize(true);
pframeMain->Show(true); // have to show first to get taskbar button to hide
pframeMain->Show(!fMinimizeToTray || !pframeMain->IsIconized());
ptaskbaricon->Show(fMinimizeToTray);
_beginthread(ThreadDelayedRepaint, 0, NULL);
if (!CheckDiskSpace())
{
OnExit();
@@ -3516,7 +3559,7 @@ bool CMyApp::OnInit2()
//
// Tests
//
if (argc >= 2 && stricmp(argv[1], "/send") == 0)
if (argc >= 2 && stricmp(argv[1], "-send") == 0)
{
int64 nValue = 1;
if (argc >= 3)
@@ -3525,7 +3568,7 @@ bool CMyApp::OnInit2()
string strAddress;
if (argc >= 4)
strAddress = argv[3];
CAddress addr(strAddress.c_str());
CAddress addr(strAddress);
CWalletTx wtx;
wtx.mapValue["to"] = strAddress;
@@ -3538,15 +3581,6 @@ bool CMyApp::OnInit2()
return false;
}
if (mapArgs.count("/randsendtest"))
{
if (!mapArgs["/randsendtest"].empty())
_beginthread(ThreadRandSendTest, 0, new string(mapArgs["/randsendtest"]));
else
fRandSendTest = true;
fDebug = 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);
@@ -3666,7 +3687,7 @@ string StartupShortcutPath()
bool GetStartOnSystemStartup()
{
return FileExists(StartupShortcutPath().c_str());
return wxFileExists(StartupShortcutPath());
}
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 ");
}