X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.cpp;h=c4464748fc83c6aab214fe8cf809b6fe2db74a52;hb=7a743148c999436840ab2ab249047f5f34e896b0;hp=049297706c59d6da743e0616f1f346bd11fd4e15;hpb=7bf8b7c25c944110dbe85ef9e4eebd858da34158;p=novacoin.git diff --git a/src/util.cpp b/src/util.cpp index 0492977..c446474 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,7 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. + #include "headers.h" #include "strlcpy.h" #include @@ -21,7 +22,6 @@ map > mapMultiArgs; bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugger = false; -char pszSetDataDir[MAX_PATH] = ""; bool fRequestShutdown = false; bool fShutdown = false; bool fDaemon = false; @@ -33,16 +33,6 @@ bool fNoListen = false; bool fLogTimestamps = false; CMedianFilter vTimeOffsets(200,0); - - -// Workaround for "multiple definition of `_tls_used'" -// http://svn.boost.org/trac/boost/ticket/4258 -extern "C" void tss_cleanup_implemented() { } - - - - - // Init openssl library multithreading support static boost::interprocess::interprocess_mutex** ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) @@ -174,10 +164,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...) if (!fileout) { - char pszFile[MAX_PATH+100]; - GetDataDir(pszFile); - strlcat(pszFile, "/debug.log", sizeof(pszFile)); - fileout = fopen(pszFile, "a"); + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + fileout = fopen(pathDebug.string().c_str(), "a"); if (fileout) setbuf(fileout, NULL); // unbuffered } if (fileout) @@ -205,8 +193,8 @@ inline int OutputDebugStringF(const char* pszFormat, ...) static CCriticalSection cs_OutputDebugStringF; // accumulate a line at a time - CRITICAL_BLOCK(cs_OutputDebugStringF) { + LOCK(cs_OutputDebugStringF); static char pszBuffer[50000]; static char* pend; if (pend == NULL) @@ -265,7 +253,7 @@ int my_snprintf(char* buffer, size_t limit, const char* format, ...) return ret; } -string strprintf(const std::string &format, ...) +string real_strprintf(const std::string &format, int dummy, ...) { char buffer[50000]; char* p = buffer; @@ -274,7 +262,7 @@ string strprintf(const std::string &format, ...) loop { va_list arg_ptr; - va_start(arg_ptr, format); + va_start(arg_ptr, dummy); ret = _vsnprintf(p, limit, format.c_str(), arg_ptr); va_end(arg_ptr); if (ret >= 0 && ret < limit) @@ -292,13 +280,13 @@ string strprintf(const std::string &format, ...) return str; } -bool error(const std::string &format, ...) +bool error(const char *format, ...) { char buffer[50000]; int limit = sizeof(buffer); va_list arg_ptr; va_start(arg_ptr, format); - int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr); + int ret = _vsnprintf(buffer, limit, format, arg_ptr); va_end(arg_ptr); if (ret < 0 || ret >= limit) { @@ -454,7 +442,22 @@ vector ParseHex(const string& str) return ParseHex(str.c_str()); } -void ParseParameters(int argc, char* argv[]) +static void InterpretNegativeSetting(string name, map& mapSettingsRet) +{ + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + if (name.find("-no") == 0) + { + std::string positive("-"); + positive.append(name.begin()+3, name.end()); + if (mapSettingsRet.count(positive) == 0) + { + bool value = !GetBoolArg(name); + mapSettingsRet[positive] = (value ? "1" : "0"); + } + } +} + +void ParseParameters(int argc, const char*const argv[]) { mapArgs.clear(); mapMultiArgs.clear(); @@ -475,9 +478,53 @@ void ParseParameters(int argc, char* argv[]) #endif if (psz[0] != '-') break; + mapArgs[psz] = pszValue; mapMultiArgs[psz].push_back(pszValue); } + + // New 0.6 features: + BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) + { + string name = entry.first; + + // interpret --foo as -foo (as long as both are not set) + if (name.find("--") == 0) + { + std::string singleDash(name.begin()+1, name.end()); + if (mapArgs.count(singleDash) == 0) + mapArgs[singleDash] = entry.second; + name = singleDash; + } + + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + InterpretNegativeSetting(name, mapArgs); + } +} + +std::string GetArg(const std::string& strArg, const std::string& strDefault) +{ + if (mapArgs.count(strArg)) + return mapArgs[strArg]; + return strDefault; +} + +int64 GetArg(const std::string& strArg, int64 nDefault) +{ + if (mapArgs.count(strArg)) + return atoi64(mapArgs[strArg]); + return nDefault; +} + +bool GetBoolArg(const std::string& strArg, bool fDefault) +{ + if (mapArgs.count(strArg)) + { + if (mapArgs[strArg].empty()) + return true; + return (atoi(mapArgs[strArg]) != 0); + } + return fDefault; } bool SoftSetArg(const std::string& strArg, const std::string& strValue) @@ -708,17 +755,6 @@ void PrintException(std::exception* pex, const char* pszThread) throw; } -void ThreadOneMessageBox(string strMessage) -{ - // Skip message boxes if one is already open - static bool fMessageBoxOpen; - if (fMessageBoxOpen) - return; - fMessageBoxOpen = true; - ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION); - fMessageBoxOpen = false; -} - void PrintExceptionContinue(std::exception* pex, const char* pszThread) { char pszMessage[10000]; @@ -728,128 +764,98 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) strMiscWarning = pszMessage; } - - - - - - - #ifdef WIN32 -typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate); - -string MyGetSpecialFolderPath(int nFolder, bool fCreate) +boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate) { - char pszPath[MAX_PATH+100] = ""; + namespace fs = boost::filesystem; - // SHGetSpecialFolderPath isn't always available on old Windows versions - HMODULE hShell32 = LoadLibraryA("shell32.dll"); - if (hShell32) + char pszPath[MAX_PATH] = ""; + if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) { - PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath = - (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA"); - if (pSHGetSpecialFolderPath) - (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate); - FreeModule(hShell32); + return fs::path(pszPath); } - - // Backup option - if (pszPath[0] == '\0') + else if (nFolder == CSIDL_STARTUP) { - if (nFolder == CSIDL_STARTUP) - { - strcpy(pszPath, getenv("USERPROFILE")); - strcat(pszPath, "\\Start Menu\\Programs\\Startup"); - } - else if (nFolder == CSIDL_APPDATA) - { - strcpy(pszPath, getenv("APPDATA")); - } + return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup"; } - - return pszPath; + else if (nFolder == CSIDL_APPDATA) + { + return fs::path(getenv("APPDATA")); + } + return fs::path(""); } #endif -string GetDefaultDataDir() +boost::filesystem::path GetDefaultDataDir() { + namespace fs = boost::filesystem; + // Windows: C:\Documents and Settings\username\Application Data\Bitcoin // Mac: ~/Library/Application Support/Bitcoin // Unix: ~/.bitcoin #ifdef WIN32 // Windows - return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin"; + return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "Bitcoin"; #else + fs::path pathRet; char* pszHome = getenv("HOME"); if (pszHome == NULL || strlen(pszHome) == 0) - pszHome = (char*)"/"; - string strHome = pszHome; - if (strHome[strHome.size()-1] != '/') - strHome += '/'; + pathRet = fs::path("/"); + else + pathRet = fs::path(pszHome); #ifdef MAC_OSX // Mac - strHome += "Library/Application Support/"; - filesystem::create_directory(strHome.c_str()); - return strHome + "Bitcoin"; + pathRet /= "Library" / "Application Support"; + filesystem::create_directory(pathRet); + return pathRet / "Bitcoin"; #else // Unix - return strHome + ".bitcoin"; + return pathRet / ".bitcoin"; #endif #endif } -void GetDataDir(char* pszDir) +const boost::filesystem::path &GetDataDir(bool fNetSpecific) { - // pszDir must be at least MAX_PATH length. - int nVariation; - if (pszSetDataDir[0] != 0) - { - strlcpy(pszDir, pszSetDataDir, MAX_PATH); - nVariation = 0; - } - 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. - static char pszCachedDir[MAX_PATH]; - if (pszCachedDir[0] == 0) - strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir)); - strlcpy(pszDir, pszCachedDir, MAX_PATH); - nVariation = 1; - } - if (fTestNet) - { - char* p = pszDir + strlen(pszDir); - if (p > pszDir && p[-1] != '/' && p[-1] != '\\') - *p++ = '/'; - strcpy(p, "testnet"); - nVariation += 2; - } - static bool pfMkdir[4]; - if (!pfMkdir[nVariation]) - { - pfMkdir[nVariation] = true; - boost::filesystem::create_directory(pszDir); + namespace fs = boost::filesystem; + + static fs::path pathCached[2]; + static CCriticalSection csPathCached; + static bool cachedPath[2] = {false, false}; + + fs::path &path = pathCached[fNetSpecific]; + + // This can be called during exceptions by printf, so we cache the + // value so we don't have to do memory allocations after that. + if (cachedPath[fNetSpecific]) + return path; + + LOCK(csPathCached); + + if (mapArgs.count("-datadir")) { + path = mapArgs["-datadir"]; + } else { + path = GetDefaultDataDir(); } -} + if (fNetSpecific && GetBoolArg("-testnet", false)) + path /= "testnet"; -string GetDataDir() -{ - char pszDir[MAX_PATH]; - GetDataDir(pszDir); - return pszDir; + fs::create_directory(path); + + cachedPath[fNetSpecific]=true; + return path; } -string GetConfigFile() +boost::filesystem::path GetConfigFile() { namespace fs = boost::filesystem; - fs::path pathConfig(GetArg("-conf", "bitcoin.conf")); - if (!pathConfig.is_complete()) - pathConfig = fs::path(GetDataDir()) / pathConfig; - return pathConfig.string(); + + fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf")); + if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + return pathConfigFile; } -void ReadConfigFile(map& mapSettingsRet, +bool ReadConfigFile(map& mapSettingsRet, map >& mapMultiSettingsRet) { namespace fs = boost::filesystem; @@ -857,33 +863,38 @@ void ReadConfigFile(map& mapSettingsRet, fs::ifstream streamConfig(GetConfigFile()); if (!streamConfig.good()) - return; + return true; // No bitcoin.conf file is OK set setOptions; setOptions.insert("*"); - + for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) { // Don't overwrite existing settings so command line settings override bitcoin.conf string strKey = string("-") + it->string_key; if (mapSettingsRet.count(strKey) == 0) + { mapSettingsRet[strKey] = it->value[0]; + // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) + InterpretNegativeSetting(strKey, mapSettingsRet); + } mapMultiSettingsRet[strKey].push_back(it->value[0]); } + return true; } -string GetPidFile() +boost::filesystem::path GetPidFile() { namespace fs = boost::filesystem; - fs::path pathConfig(GetArg("-pid", "bitcoind.pid")); - if (!pathConfig.is_complete()) - pathConfig = fs::path(GetDataDir()) / pathConfig; - return pathConfig.string(); + + fs::path pathPidFile(GetArg("-pid", "bitcoind.pid")); + if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; + return pathPidFile; } -void CreatePidFile(string pidFile, pid_t pid) +void CreatePidFile(const boost::filesystem::path &path, pid_t pid) { - FILE* file = fopen(pidFile.c_str(), "w"); + FILE* file = fopen(path.string().c_str(), "w"); if (file) { fprintf(file, "%d\n", pid); @@ -904,8 +915,8 @@ int GetFilesize(FILE* file) void ShrinkDebugFile() { // Scroll debug.log if it's getting too big - string strFile = GetDataDir() + "/debug.log"; - FILE* file = fopen(strFile.c_str(), "r"); + boost::filesystem::path pathLog = GetDataDir() / "debug.log"; + FILE* file = fopen(pathLog.string().c_str(), "r"); if (file && GetFilesize(file) > 10 * 1000000) { // Restart the file with some of the end @@ -914,7 +925,7 @@ void ShrinkDebugFile() int nBytes = fread(pch, 1, sizeof(pch), file); fclose(file); - file = fopen(strFile.c_str(), "w"); + file = fopen(pathLog.string().c_str(), "w"); if (file) { fwrite(pch, 1, nBytes, file); @@ -998,7 +1009,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime) string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly."); strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); - boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1)); + ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION); } } } @@ -1028,12 +1039,7 @@ string FormatVersion(int nVersion) string FormatFullVersion() { - string s = FormatVersion(CLIENT_VERSION); - if (VERSION_IS_BETA) { - s += "-"; - s += _("beta"); - } - return s; + return CLIENT_BUILD; } // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) @@ -1082,25 +1088,25 @@ private: int sourceLine; }; -typedef std::vector< std::pair > LockStack; +typedef std::vector< std::pair > LockStack; static boost::interprocess::interprocess_mutex dd_mutex; -static std::map, LockStack> lockorders; +static std::map, LockStack> lockorders; static boost::thread_specific_ptr lockstack; -static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) +static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) { printf("POTENTIAL DEADLOCK DETECTED\n"); printf("Previous lock order was:\n"); - BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2) { if (i.first == mismatch.first) printf(" (1)"); if (i.first == mismatch.second) printf(" (2)"); printf(" %s\n", i.second.ToString().c_str()); } printf("Current lock order is:\n"); - BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1) { if (i.first == mismatch.first) printf(" (1)"); if (i.first == mismatch.second) printf(" (2)"); @@ -1108,7 +1114,7 @@ static void potential_deadlock_detected(const std::pair p1 = std::make_pair(i.first, c); + std::pair p1 = std::make_pair(i.first, c); if (lockorders.count(p1)) continue; lockorders[p1] = (*lockstack); - std::pair p2 = std::make_pair(c, i.first); + std::pair p2 = std::make_pair(c, i.first); if (lockorders.count(p2)) { potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); @@ -1150,62 +1156,14 @@ static void pop_lock() dd_mutex.unlock(); } -void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine) -{ - push_lock(this, CLockLocation(pszName, pszFile, nLine)); -#ifdef DEBUG_LOCKCONTENTION - bool result = mutex.try_lock(); - if (!result) - { - printf("LOCKCONTENTION: %s\n", pszName); - printf("Locker: %s:%d\n", pszFile, nLine); - mutex.lock(); - printf("Locked\n"); - } -#else - mutex.lock(); -#endif -} -void CCriticalSection::Leave() +void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry) { - mutex.unlock(); - pop_lock(); -} -bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine) -{ - push_lock(this, CLockLocation(pszName, pszFile, nLine)); - bool result = mutex.try_lock(); - if (!result) pop_lock(); - return result; + push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry); } -#else - -void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine) +void LeaveCritical() { -#ifdef DEBUG_LOCKCONTENTION - bool result = mutex.try_lock(); - if (!result) - { - printf("LOCKCONTENTION: %s\n", pszName); - printf("Locker: %s:%d\n", pszFile, nLine); - mutex.lock(); - } -#else - mutex.lock(); -#endif -} - -void CCriticalSection::Leave() -{ - mutex.unlock(); -} - -bool CCriticalSection::TryEnter(const char*, const char*, int) -{ - bool result = mutex.try_lock(); - return result; + pop_lock(); } #endif /* DEBUG_LOCKORDER */ -