You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

util.h 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright (c) 2009-2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2016 The Starwels developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. /**
  6. * Server/client environment: argument handling, config file parsing,
  7. * logging, thread wrappers, startup time
  8. */
  9. #ifndef STARWELS_UTIL_H
  10. #define STARWELS_UTIL_H
  11. #if defined(HAVE_CONFIG_H)
  12. #include "config/starwels-config.h"
  13. #endif
  14. #include "compat.h"
  15. #include "fs.h"
  16. #include "sync.h"
  17. #include "tinyformat.h"
  18. #include "utiltime.h"
  19. #include <atomic>
  20. #include <exception>
  21. #include <map>
  22. #include <stdint.h>
  23. #include <string>
  24. #include <vector>
  25. #include <boost/signals2/signal.hpp>
  26. // Application startup time (used for uptime calculation)
  27. int64_t GetStartupTime();
  28. static const bool DEFAULT_LOGTIMEMICROS = false;
  29. static const bool DEFAULT_LOGIPS = false;
  30. static const bool DEFAULT_LOGTIMESTAMPS = true;
  31. /** Signals for translation. */
  32. class CTranslationInterface
  33. {
  34. public:
  35. /** Translate a message to the native language of the user. */
  36. boost::signals2::signal<std::string (const char* psz)> Translate;
  37. };
  38. extern bool fPrintToConsole;
  39. extern bool fPrintToDebugLog;
  40. extern bool fLogTimestamps;
  41. extern bool fLogTimeMicros;
  42. extern bool fLogIPs;
  43. extern std::atomic<bool> fReopenDebugLog;
  44. extern CTranslationInterface translationInterface;
  45. extern const char * const STARWELS_CONF_FILENAME;
  46. extern const char * const STARWELS_PID_FILENAME;
  47. extern std::atomic<uint32_t> logCategories;
  48. /**
  49. * Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
  50. * If no translation slot is registered, nothing is returned, and simply return the input.
  51. */
  52. inline std::string _(const char* psz)
  53. {
  54. boost::optional<std::string> rv = translationInterface.Translate(psz);
  55. return rv ? (*rv) : psz;
  56. }
  57. void SetupEnvironment();
  58. bool SetupNetworking();
  59. struct CLogCategoryActive
  60. {
  61. std::string category;
  62. bool active;
  63. };
  64. namespace BCLog {
  65. enum LogFlags : uint32_t {
  66. NONE = 0,
  67. NET = (1 << 0),
  68. TOR = (1 << 1),
  69. MEMPOOL = (1 << 2),
  70. HTTP = (1 << 3),
  71. BENCH = (1 << 4),
  72. ZMQ = (1 << 5),
  73. DB = (1 << 6),
  74. RPC = (1 << 7),
  75. ESTIMATEFEE = (1 << 8),
  76. ADDRMAN = (1 << 9),
  77. SELECTCOINS = (1 << 10),
  78. REINDEX = (1 << 11),
  79. CMPCTBLOCK = (1 << 12),
  80. RAND = (1 << 13),
  81. PRUNE = (1 << 14),
  82. PROXY = (1 << 15),
  83. MEMPOOLREJ = (1 << 16),
  84. LIBEVENT = (1 << 17),
  85. COINDB = (1 << 18),
  86. QT = (1 << 19),
  87. LEVELDB = (1 << 20),
  88. ALL = ~(uint32_t)0,
  89. };
  90. }
  91. /** Return true if log accepts specified category */
  92. static inline bool LogAcceptCategory(uint32_t category)
  93. {
  94. return (logCategories.load(std::memory_order_relaxed) & category) != 0;
  95. }
  96. /** Returns a string with the log categories. */
  97. std::string ListLogCategories();
  98. /** Returns a vector of the active log categories. */
  99. std::vector<CLogCategoryActive> ListActiveLogCategories();
  100. /** Return true if str parses as a log category and set the flags in f */
  101. bool GetLogCategory(uint32_t *f, const std::string *str);
  102. /** Send a string to the log output */
  103. int LogPrintStr(const std::string &str);
  104. /** Get format string from VA_ARGS for error reporting */
  105. template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
  106. static inline void MarkUsed() {}
  107. template<typename T, typename... Args> static inline void MarkUsed(const T& t, const Args&... args)
  108. {
  109. (void)t;
  110. MarkUsed(args...);
  111. }
  112. #ifdef USE_COVERAGE
  113. #define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0)
  114. #define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0)
  115. #else
  116. #define LogPrintf(...) do { \
  117. std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
  118. try { \
  119. _log_msg_ = tfm::format(__VA_ARGS__); \
  120. } catch (tinyformat::format_error &fmterr) { \
  121. /* Original format string will have newline so don't add one here */ \
  122. _log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
  123. } \
  124. LogPrintStr(_log_msg_); \
  125. } while(0)
  126. #define LogPrint(category, ...) do { \
  127. if (LogAcceptCategory((category))) { \
  128. LogPrintf(__VA_ARGS__); \
  129. } \
  130. } while(0)
  131. #endif
  132. template<typename... Args>
  133. bool error(const char* fmt, const Args&... args)
  134. {
  135. LogPrintStr("ERROR: " + tfm::format(fmt, args...) + "\n");
  136. return false;
  137. }
  138. void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
  139. void FileCommit(FILE *file);
  140. bool TruncateFile(FILE *file, unsigned int length);
  141. int RaiseFileDescriptorLimit(int nMinFD);
  142. void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
  143. bool RenameOver(fs::path src, fs::path dest);
  144. bool TryCreateDirectories(const fs::path& p);
  145. fs::path GetDefaultDataDir();
  146. const fs::path &GetDataDir(bool fNetSpecific = true);
  147. void ClearDatadirCache();
  148. fs::path GetConfigFile(const std::string& confPath);
  149. #ifndef WIN32
  150. fs::path GetPidFile();
  151. void CreatePidFile(const fs::path &path, pid_t pid);
  152. #endif
  153. #ifdef WIN32
  154. fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
  155. #endif
  156. void OpenDebugLog();
  157. void ShrinkDebugFile();
  158. void runCommand(const std::string& strCommand);
  159. inline bool IsSwitchChar(char c)
  160. {
  161. #ifdef WIN32
  162. return c == '-' || c == '/';
  163. #else
  164. return c == '-';
  165. #endif
  166. }
  167. class ArgsManager
  168. {
  169. protected:
  170. CCriticalSection cs_args;
  171. std::map<std::string, std::string> mapArgs;
  172. std::map<std::string, std::vector<std::string> > mapMultiArgs;
  173. public:
  174. void ParseParameters(int argc, const char*const argv[]);
  175. void ReadConfigFile(const std::string& confPath);
  176. std::vector<std::string> GetArgs(const std::string& strArg);
  177. /**
  178. * Return true if the given argument has been manually set
  179. *
  180. * @param strArg Argument to get (e.g. "-foo")
  181. * @return true if the argument has been set
  182. */
  183. bool IsArgSet(const std::string& strArg);
  184. /**
  185. * Return string argument or default value
  186. *
  187. * @param strArg Argument to get (e.g. "-foo")
  188. * @param strDefault (e.g. "1")
  189. * @return command-line argument or default value
  190. */
  191. std::string GetArg(const std::string& strArg, const std::string& strDefault);
  192. /**
  193. * Return integer argument or default value
  194. *
  195. * @param strArg Argument to get (e.g. "-foo")
  196. * @param nDefault (e.g. 1)
  197. * @return command-line argument (0 if invalid number) or default value
  198. */
  199. int64_t GetArg(const std::string& strArg, int64_t nDefault);
  200. /**
  201. * Return boolean argument or default value
  202. *
  203. * @param strArg Argument to get (e.g. "-foo")
  204. * @param fDefault (true or false)
  205. * @return command-line argument or default value
  206. */
  207. bool GetBoolArg(const std::string& strArg, bool fDefault);
  208. /**
  209. * Set an argument if it doesn't already have a value
  210. *
  211. * @param strArg Argument to set (e.g. "-foo")
  212. * @param strValue Value (e.g. "1")
  213. * @return true if argument gets set, false if it already had a value
  214. */
  215. bool SoftSetArg(const std::string& strArg, const std::string& strValue);
  216. /**
  217. * Set a boolean argument if it doesn't already have a value
  218. *
  219. * @param strArg Argument to set (e.g. "-foo")
  220. * @param fValue Value (e.g. false)
  221. * @return true if argument gets set, false if it already had a value
  222. */
  223. bool SoftSetBoolArg(const std::string& strArg, bool fValue);
  224. // Forces an arg setting. Called by SoftSetArg() if the arg hasn't already
  225. // been set. Also called directly in testing.
  226. void ForceSetArg(const std::string& strArg, const std::string& strValue);
  227. };
  228. extern ArgsManager gArgs;
  229. /**
  230. * Format a string to be used as group of options in help messages
  231. *
  232. * @param message Group name (e.g. "RPC server options:")
  233. * @return the formatted string
  234. */
  235. std::string HelpMessageGroup(const std::string& message);
  236. /**
  237. * Format a string to be used as option description in help messages
  238. *
  239. * @param option Option message (e.g. "-rpcuser=<user>")
  240. * @param message Option description (e.g. "Username for JSON-RPC connections")
  241. * @return the formatted string
  242. */
  243. std::string HelpMessageOpt(const std::string& option, const std::string& message);
  244. /**
  245. * Return the number of physical cores available on the current system.
  246. * @note This does not count virtual cores, such as those provided by HyperThreading
  247. * when boost is newer than 1.56.
  248. */
  249. int GetNumCores();
  250. void RenameThread(const char* name);
  251. /**
  252. * .. and a wrapper that just calls func once
  253. */
  254. template <typename Callable> void TraceThread(const char* name, Callable func)
  255. {
  256. std::string s = strprintf("starwels-%s", name);
  257. RenameThread(s.c_str());
  258. try
  259. {
  260. LogPrintf("%s thread start\n", name);
  261. func();
  262. LogPrintf("%s thread exit\n", name);
  263. }
  264. catch (const boost::thread_interrupted&)
  265. {
  266. LogPrintf("%s thread interrupt\n", name);
  267. throw;
  268. }
  269. catch (const std::exception& e) {
  270. PrintExceptionContinue(&e, name);
  271. throw;
  272. }
  273. catch (...) {
  274. PrintExceptionContinue(nullptr, name);
  275. throw;
  276. }
  277. }
  278. std::string CopyrightHolders(const std::string& strPrefix);
  279. #endif // STARWELS_UTIL_H