]>
Commit | Line | Data |
---|---|---|
1f2e0df8 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
57702541 | 2 | // Copyright (c) 2009-2014 The Bitcoin developers |
c63a73d1 | 3 | // Distributed under the MIT software license, see the accompanying |
3a25a2b9 | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
51ed9ec9 | 5 | |
ad49c256 WL |
6 | /** |
7 | * Server/client environment: argument handling, config file parsing, | |
8 | * logging, thread wrappers | |
9 | */ | |
1f2e0df8 WL |
10 | #ifndef BITCOIN_UTIL_H |
11 | #define BITCOIN_UTIL_H | |
12 | ||
51ed9ec9 | 13 | #if defined(HAVE_CONFIG_H) |
f3967bcc | 14 | #include "config/bitcoin-config.h" |
51ed9ec9 BD |
15 | #endif |
16 | ||
17 | #include "compat.h" | |
b77dfdc9 | 18 | #include "tinyformat.h" |
611116d4 | 19 | #include "utiltime.h" |
1f2e0df8 | 20 | |
51ed9ec9 | 21 | #include <exception> |
51ed9ec9 | 22 | #include <map> |
51ed9ec9 BD |
23 | #include <stdint.h> |
24 | #include <string> | |
51ed9ec9 | 25 | #include <vector> |
65ec9eab | 26 | |
ee12c3d6 | 27 | #include <boost/filesystem/path.hpp> |
ad49c256 | 28 | #include <boost/thread/exceptions.hpp> |
1f2e0df8 | 29 | |
1f2e0df8 WL |
30 | extern std::map<std::string, std::string> mapArgs; |
31 | extern std::map<std::string, std::vector<std::string> > mapMultiArgs; | |
32 | extern bool fDebug; | |
33 | extern bool fPrintToConsole; | |
9e9056cd | 34 | extern bool fPrintToDebugLog; |
1f2e0df8 | 35 | extern bool fServer; |
1f2e0df8 | 36 | extern std::string strMiscWarning; |
1f2e0df8 | 37 | extern bool fLogTimestamps; |
2e36866f | 38 | extern bool fLogIPs; |
ee337423 | 39 | extern volatile bool fReopenDebugLog; |
1f2e0df8 | 40 | |
5248ff40 | 41 | void SetupEnvironment(); |
e51321fb | 42 | |
c63a73d1 | 43 | /** Return true if log accepts specified category */ |
b77dfdc9 | 44 | bool LogAcceptCategory(const char* category); |
c63a73d1 | 45 | /** Send a string to the log output */ |
b77dfdc9 WL |
46 | int LogPrintStr(const std::string &str); |
47 | ||
881a85a2 | 48 | #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) |
52d3a481 | 49 | |
c63a73d1 MF |
50 | /** |
51 | * When we switch to C++11, this can be switched to variadic templates instead | |
b77dfdc9 | 52 | * of this macro-based construction (see tinyformat.h). |
b0a90fbb | 53 | */ |
b77dfdc9 | 54 | #define MAKE_ERROR_AND_LOG_FUNC(n) \ |
c63a73d1 | 55 | /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ |
b77dfdc9 WL |
56 | template<TINYFORMAT_ARGTYPES(n)> \ |
57 | static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ | |
58 | { \ | |
59 | if(!LogAcceptCategory(category)) return 0; \ | |
60 | return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ | |
61 | } \ | |
c63a73d1 | 62 | /** Log error and return false */ \ |
b77dfdc9 WL |
63 | template<TINYFORMAT_ARGTYPES(n)> \ |
64 | static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ | |
65 | { \ | |
2383e488 | 66 | LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ |
b77dfdc9 WL |
67 | return false; \ |
68 | } | |
69 | ||
70 | TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) | |
71 | ||
c63a73d1 MF |
72 | /** |
73 | * Zero-arg versions of logging and error, these are not covered by | |
b77dfdc9 WL |
74 | * TINYFORMAT_FOREACH_ARGNUM |
75 | */ | |
76 | static inline int LogPrint(const char* category, const char* format) | |
77 | { | |
78 | if(!LogAcceptCategory(category)) return 0; | |
79 | return LogPrintStr(format); | |
80 | } | |
81 | static inline bool error(const char* format) | |
82 | { | |
2383e488 | 83 | LogPrintStr(std::string("ERROR: ") + format + "\n"); |
b77dfdc9 WL |
84 | return false; |
85 | } | |
b0a90fbb | 86 | |
1f2e0df8 | 87 | void PrintExceptionContinue(std::exception* pex, const char* pszThread); |
3ae07355 | 88 | void ParseParameters(int argc, const char*const argv[]); |
768e5d52 | 89 | void FileCommit(FILE *fileout); |
1eb57879 | 90 | bool TruncateFile(FILE *file, unsigned int length); |
ba29a559 | 91 | int RaiseFileDescriptorLimit(int nMinFD); |
bba89aa8 | 92 | void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); |
768e5d52 | 93 | bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); |
2b7709dc | 94 | bool TryCreateDirectory(const boost::filesystem::path& p); |
ee12c3d6 PW |
95 | boost::filesystem::path GetDefaultDataDir(); |
96 | const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); | |
97 | boost::filesystem::path GetConfigFile(); | |
a034c7eb | 98 | #ifndef WIN32 |
d6712db3 | 99 | boost::filesystem::path GetPidFile(); |
ee12c3d6 | 100 | void CreatePidFile(const boost::filesystem::path &path, pid_t pid); |
a034c7eb | 101 | #endif |
f4203de3 | 102 | void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); |
3e468840 PK |
103 | #ifdef WIN32 |
104 | boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); | |
105 | #endif | |
597fa4cd | 106 | boost::filesystem::path GetTempPath(); |
1f2e0df8 | 107 | void ShrinkDebugFile(); |
429039d4 | 108 | void runCommand(std::string strCommand); |
1f2e0df8 | 109 | |
1f2e0df8 WL |
110 | inline bool IsSwitchChar(char c) |
111 | { | |
6853e627 | 112 | #ifdef WIN32 |
1f2e0df8 WL |
113 | return c == '-' || c == '/'; |
114 | #else | |
115 | return c == '-'; | |
116 | #endif | |
117 | } | |
118 | ||
3ae07355 GA |
119 | /** |
120 | * Return string argument or default value | |
121 | * | |
122 | * @param strArg Argument to get (e.g. "-foo") | |
123 | * @param default (e.g. "1") | |
124 | * @return command-line argument or default value | |
125 | */ | |
126 | std::string GetArg(const std::string& strArg, const std::string& strDefault); | |
1f2e0df8 | 127 | |
3ae07355 GA |
128 | /** |
129 | * Return integer argument or default value | |
130 | * | |
131 | * @param strArg Argument to get (e.g. "-foo") | |
132 | * @param default (e.g. 1) | |
133 | * @return command-line argument (0 if invalid number) or default value | |
134 | */ | |
51ed9ec9 | 135 | int64_t GetArg(const std::string& strArg, int64_t nDefault); |
1f2e0df8 | 136 | |
3ae07355 GA |
137 | /** |
138 | * Return boolean argument or default value | |
139 | * | |
140 | * @param strArg Argument to get (e.g. "-foo") | |
141 | * @param default (true or false) | |
142 | * @return command-line argument or default value | |
143 | */ | |
3260b4c0 | 144 | bool GetBoolArg(const std::string& strArg, bool fDefault); |
1f2e0df8 | 145 | |
0fcf91ea GA |
146 | /** |
147 | * Set an argument if it doesn't already have a value | |
148 | * | |
149 | * @param strArg Argument to set (e.g. "-foo") | |
150 | * @param strValue Value (e.g. "1") | |
151 | * @return true if argument gets set, false if it already had a value | |
152 | */ | |
153 | bool SoftSetArg(const std::string& strArg, const std::string& strValue); | |
154 | ||
155 | /** | |
156 | * Set a boolean argument if it doesn't already have a value | |
157 | * | |
158 | * @param strArg Argument to set (e.g. "-foo") | |
159 | * @param fValue Value (e.g. false) | |
160 | * @return true if argument gets set, false if it already had a value | |
161 | */ | |
7bf8b7c2 | 162 | bool SoftSetBoolArg(const std::string& strArg, bool fValue); |
1f2e0df8 | 163 | |
610a8c07 | 164 | void SetThreadPriority(int nPriority); |
96931d6f | 165 | void RenameThread(const char* name); |
1f2e0df8 | 166 | |
c63a73d1 MF |
167 | /** |
168 | * Standard wrapper for do-something-forever thread functions. | |
169 | * "Forever" really means until the thread is interrupted. | |
170 | * Use it like: | |
171 | * new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000)); | |
172 | * or maybe: | |
173 | * boost::function<void()> f = boost::bind(&FunctionWithArg, argument); | |
174 | * threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds)); | |
175 | */ | |
51ed9ec9 | 176 | template <typename Callable> void LoopForever(const char* name, Callable func, int64_t msecs) |
72f14d26 GA |
177 | { |
178 | std::string s = strprintf("bitcoin-%s", name); | |
179 | RenameThread(s.c_str()); | |
881a85a2 | 180 | LogPrintf("%s thread start\n", name); |
72f14d26 GA |
181 | try |
182 | { | |
183 | while (1) | |
184 | { | |
72f14d26 | 185 | MilliSleep(msecs); |
c43da3f1 | 186 | func(); |
72f14d26 GA |
187 | } |
188 | } | |
189 | catch (boost::thread_interrupted) | |
190 | { | |
881a85a2 | 191 | LogPrintf("%s thread stop\n", name); |
72f14d26 GA |
192 | throw; |
193 | } | |
194 | catch (std::exception& e) { | |
44235713 WL |
195 | PrintExceptionContinue(&e, name); |
196 | throw; | |
72f14d26 GA |
197 | } |
198 | catch (...) { | |
44235713 WL |
199 | PrintExceptionContinue(NULL, name); |
200 | throw; | |
72f14d26 GA |
201 | } |
202 | } | |
c63a73d1 MF |
203 | |
204 | /** | |
205 | * .. and a wrapper that just calls func once | |
206 | */ | |
72f14d26 GA |
207 | template <typename Callable> void TraceThread(const char* name, Callable func) |
208 | { | |
209 | std::string s = strprintf("bitcoin-%s", name); | |
210 | RenameThread(s.c_str()); | |
211 | try | |
212 | { | |
881a85a2 | 213 | LogPrintf("%s thread start\n", name); |
72f14d26 | 214 | func(); |
881a85a2 | 215 | LogPrintf("%s thread exit\n", name); |
72f14d26 GA |
216 | } |
217 | catch (boost::thread_interrupted) | |
218 | { | |
881a85a2 | 219 | LogPrintf("%s thread interrupt\n", name); |
72f14d26 GA |
220 | throw; |
221 | } | |
222 | catch (std::exception& e) { | |
44235713 WL |
223 | PrintExceptionContinue(&e, name); |
224 | throw; | |
72f14d26 GA |
225 | } |
226 | catch (...) { | |
44235713 WL |
227 | PrintExceptionContinue(NULL, name); |
228 | throw; | |
72f14d26 GA |
229 | } |
230 | } | |
231 | ||
093303a8 | 232 | #endif // BITCOIN_UTIL_H |