diff options
Diffstat (limited to 'src/util.h')
-rw-r--r-- | src/util.h | 283 |
1 files changed, 217 insertions, 66 deletions
diff --git a/src/util.h b/src/util.h index 08b23a9d38..a4aaf29f91 100644 --- a/src/util.h +++ b/src/util.h @@ -1,81 +1,232 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef _SECP256K1_UTIL_H_ -#define _SECP256K1_UTIL_H_ +/** + * Server/client environment: argument handling, config file parsing, + * logging, thread wrappers + */ +#ifndef BITCOIN_UTIL_H +#define BITCOIN_UTIL_H -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" #endif -#include <stdlib.h> +#include "compat.h" +#include "tinyformat.h" +#include "utiltime.h" + +#include <exception> +#include <map> #include <stdint.h> -#include <stdio.h> +#include <string> +#include <vector> -#ifdef DETERMINISTIC -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s\n", msg); \ - abort(); \ -} while(0); -#else -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ - abort(); \ -} while(0) -#endif +#include <boost/filesystem/path.hpp> +#include <boost/thread/exceptions.hpp> -#ifndef HAVE_BUILTIN_EXPECT -#define EXPECT(x,c) __builtin_expect((x),(c)) -#else -#define EXPECT(x,c) (x) -#endif +extern std::map<std::string, std::string> mapArgs; +extern std::map<std::string, std::vector<std::string> > mapMultiArgs; +extern bool fDebug; +extern bool fPrintToConsole; +extern bool fPrintToDebugLog; +extern bool fServer; +extern std::string strMiscWarning; +extern bool fLogTimestamps; +extern bool fLogIPs; +extern volatile bool fReopenDebugLog; -#ifdef DETERMINISTIC -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed"); \ - } \ -} while(0) -#else -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed: " #cond); \ - } \ -} while(0) -#endif +void SetupEnvironment(); -/* Like assert(), but safe to use on expressions with side effects. */ -#ifndef NDEBUG -#define DEBUG_CHECK CHECK -#else -#define DEBUG_CHECK(cond) do { (void)(cond); } while(0) -#endif +/** Return true if log accepts specified category */ +bool LogAcceptCategory(const char* category); +/** Send a string to the log output */ +int LogPrintStr(const std::string &str); -/* Like DEBUG_CHECK(), but when VERIFY is defined instead of NDEBUG not defined. */ -#ifdef VERIFY -#define VERIFY_CHECK CHECK -#else -#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) +#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) + +/** + * When we switch to C++11, this can be switched to variadic templates instead + * of this macro-based construction (see tinyformat.h). + */ +#define MAKE_ERROR_AND_LOG_FUNC(n) \ + /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ + template<TINYFORMAT_ARGTYPES(n)> \ + static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ + { \ + if(!LogAcceptCategory(category)) return 0; \ + return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ + } \ + /** Log error and return false */ \ + template<TINYFORMAT_ARGTYPES(n)> \ + static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ + { \ + LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ + return false; \ + } + +TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) + +/** + * Zero-arg versions of logging and error, these are not covered by + * TINYFORMAT_FOREACH_ARGNUM + */ +static inline int LogPrint(const char* category, const char* format) +{ + if(!LogAcceptCategory(category)) return 0; + return LogPrintStr(format); +} +static inline bool error(const char* format) +{ + LogPrintStr(std::string("ERROR: ") + format + "\n"); + return false; +} + +void PrintExceptionContinue(std::exception* pex, const char* pszThread); +void ParseParameters(int argc, const char*const argv[]); +void FileCommit(FILE *fileout); +bool TruncateFile(FILE *file, unsigned int length); +int RaiseFileDescriptorLimit(int nMinFD); +void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); +bool TryCreateDirectory(const boost::filesystem::path& p); +boost::filesystem::path GetDefaultDataDir(); +const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +boost::filesystem::path GetConfigFile(); +#ifndef WIN32 +boost::filesystem::path GetPidFile(); +void CreatePidFile(const boost::filesystem::path &path, pid_t pid); +#endif +void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); +#ifdef WIN32 +boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif +boost::filesystem::path GetTempPath(); +void ShrinkDebugFile(); +void runCommand(std::string strCommand); -/* Macro for restrict, when available and not in a VERIFY build. */ -#if defined(SECP256K1_BUILD) && defined(VERIFY) -# define SECP256K1_RESTRICT +inline bool IsSwitchChar(char c) +{ +#ifdef WIN32 + return c == '-' || c == '/'; #else -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(3,0) -# define SECP256K1_RESTRICT __restrict__ -# elif (defined(_MSC_VER) && _MSC_VER >= 1400) -# define SECP256K1_RESTRICT __restrict -# else -# define SECP256K1_RESTRICT -# endif -# else -# define SECP256K1_RESTRICT restrict -# endif + return c == '-'; #endif +} -#endif +/** + * Return string argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. "1") + * @return command-line argument or default value + */ +std::string GetArg(const std::string& strArg, const std::string& strDefault); + +/** + * Return integer argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. 1) + * @return command-line argument (0 if invalid number) or default value + */ +int64_t GetArg(const std::string& strArg, int64_t nDefault); + +/** + * Return boolean argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (true or false) + * @return command-line argument or default value + */ +bool GetBoolArg(const std::string& strArg, bool fDefault); + +/** + * Set an argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValue Value (e.g. "1") + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, const std::string& strValue); + +/** + * Set a boolean argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param fValue Value (e.g. false) + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetBoolArg(const std::string& strArg, bool fValue); + +void SetThreadPriority(int nPriority); +void RenameThread(const char* name); + +/** + * Standard wrapper for do-something-forever thread functions. + * "Forever" really means until the thread is interrupted. + * Use it like: + * new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000)); + * or maybe: + * boost::function<void()> f = boost::bind(&FunctionWithArg, argument); + * threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds)); + */ +template <typename Callable> void LoopForever(const char* name, Callable func, int64_t msecs) +{ + std::string s = strprintf("bitcoin-%s", name); + RenameThread(s.c_str()); + LogPrintf("%s thread start\n", name); + try + { + while (1) + { + MilliSleep(msecs); + func(); + } + } + catch (boost::thread_interrupted) + { + LogPrintf("%s thread stop\n", name); + throw; + } + catch (std::exception& e) { + PrintExceptionContinue(&e, name); + throw; + } + catch (...) { + PrintExceptionContinue(NULL, name); + throw; + } +} + +/** + * .. and a wrapper that just calls func once + */ +template <typename Callable> void TraceThread(const char* name, Callable func) +{ + std::string s = strprintf("bitcoin-%s", name); + RenameThread(s.c_str()); + try + { + LogPrintf("%s thread start\n", name); + func(); + LogPrintf("%s thread exit\n", name); + } + catch (boost::thread_interrupted) + { + LogPrintf("%s thread interrupt\n", name); + throw; + } + catch (std::exception& e) { + PrintExceptionContinue(&e, name); + throw; + } + catch (...) { + PrintExceptionContinue(NULL, name); + throw; + } +} + +#endif // BITCOIN_UTIL_H |