@@ -175,23 +175,51 @@ instance_of_cinit;
175
175
*/
176
176
177
177
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
178
+
178
179
/* *
179
- * We use boost::call_once() to make sure these are initialized
180
- * in a thread-safe manner the first time called:
180
+ * We use boost::call_once() to make sure mutexDebugLog and
181
+ * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
182
+ *
183
+ * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
184
+ * are leaked on exit. This is ugly, but will be cleaned up by
185
+ * the OS/libc. When the shutdown sequence is fully audited and
186
+ * tested, explicit destruction of these objects can be implemented.
181
187
*/
182
188
static FILE* fileout = NULL ;
183
189
static boost::mutex* mutexDebugLog = NULL ;
190
+ static list<string> *vMsgsBeforeOpenLog;
191
+
192
+ static int FileWriteStr (const std::string &str, FILE *fp)
193
+ {
194
+ return fwrite (str.data (), 1 , str.size (), fp);
195
+ }
184
196
185
197
static void DebugPrintInit ()
186
198
{
187
- assert (fileout == NULL );
188
199
assert (mutexDebugLog == NULL );
200
+ mutexDebugLog = new boost::mutex ();
201
+ vMsgsBeforeOpenLog = new list<string>;
202
+ }
203
+
204
+ void OpenDebugLog ()
205
+ {
206
+ boost::call_once (&DebugPrintInit, debugPrintInitFlag);
207
+ boost::mutex::scoped_lock scoped_lock (*mutexDebugLog);
189
208
209
+ assert (fileout == NULL );
210
+ assert (vMsgsBeforeOpenLog);
190
211
boost::filesystem::path pathDebug = GetDataDir () / " debug.log" ;
191
212
fileout = fopen (pathDebug.string ().c_str (), " a" );
192
213
if (fileout) setbuf (fileout, NULL ); // unbuffered
193
214
194
- mutexDebugLog = new boost::mutex ();
215
+ // dump buffered messages from before we opened the log
216
+ while (!vMsgsBeforeOpenLog->empty ()) {
217
+ FileWriteStr (vMsgsBeforeOpenLog->front (), fileout);
218
+ vMsgsBeforeOpenLog->pop_front ();
219
+ }
220
+
221
+ delete vMsgsBeforeOpenLog;
222
+ vMsgsBeforeOpenLog = NULL ;
195
223
}
196
224
197
225
bool LogAcceptCategory (const char * category)
@@ -223,44 +251,67 @@ bool LogAcceptCategory(const char* category)
223
251
return true ;
224
252
}
225
253
254
+ /* *
255
+ * fStartedNewLine is a state variable held by the calling context that will
256
+ * suppress printing of the timestamp when multiple calls are made that don't
257
+ * end in a newline. Initialize it to true, and hold it, in the calling context.
258
+ */
259
+ static std::string LogTimestampStr (const std::string &str, bool *fStartedNewLine )
260
+ {
261
+ string strStamped;
262
+
263
+ if (!fLogTimestamps )
264
+ return str;
265
+
266
+ if (*fStartedNewLine )
267
+ strStamped = DateTimeStrFormat (" %Y-%m-%d %H:%M:%S" , GetTime ()) + ' ' + str;
268
+ else
269
+ strStamped = str;
270
+
271
+ if (!str.empty () && str[str.size ()-1 ] == ' \n ' )
272
+ *fStartedNewLine = true ;
273
+ else
274
+ *fStartedNewLine = false ;
275
+
276
+ return strStamped;
277
+ }
278
+
226
279
int LogPrintStr (const std::string &str)
227
280
{
228
281
int ret = 0 ; // Returns total number of characters written
282
+ static bool fStartedNewLine = true ;
229
283
if (fPrintToConsole )
230
284
{
231
285
// print to console
232
286
ret = fwrite (str.data (), 1 , str.size (), stdout);
233
287
fflush (stdout);
234
288
}
235
- else if (fPrintToDebugLog && AreBaseParamsConfigured () )
289
+ else if (fPrintToDebugLog )
236
290
{
237
- static bool fStartedNewLine = true ;
238
291
boost::call_once (&DebugPrintInit, debugPrintInitFlag);
239
-
240
- if (fileout == NULL )
241
- return ret;
242
-
243
292
boost::mutex::scoped_lock scoped_lock (*mutexDebugLog);
244
293
245
- // reopen the log file, if requested
246
- if (fReopenDebugLog ) {
247
- fReopenDebugLog = false ;
248
- boost::filesystem::path pathDebug = GetDataDir () / " debug.log" ;
249
- if (freopen (pathDebug.string ().c_str ()," a" ,fileout) != NULL )
250
- setbuf (fileout, NULL ); // unbuffered
251
- }
294
+ string strTimestamped = LogTimestampStr (str, &fStartedNewLine );
252
295
253
- // Debug print useful for profiling
254
- if (fLogTimestamps && fStartedNewLine )
255
- ret += fprintf (fileout, " %s " , DateTimeStrFormat (" %Y-%m-%d %H:%M:%S" , GetTime ()).c_str ());
256
- if (!str.empty () && str[str.size ()-1 ] == ' \n ' )
257
- fStartedNewLine = true ;
296
+ // buffer if we haven't opened the log yet
297
+ if (fileout == NULL ) {
298
+ assert (vMsgsBeforeOpenLog);
299
+ ret = strTimestamped.length ();
300
+ vMsgsBeforeOpenLog->push_back (strTimestamped);
301
+ }
258
302
else
259
- fStartedNewLine = false ;
260
-
261
- ret = fwrite (str.data (), 1 , str.size (), fileout);
303
+ {
304
+ // reopen the log file, if requested
305
+ if (fReopenDebugLog ) {
306
+ fReopenDebugLog = false ;
307
+ boost::filesystem::path pathDebug = GetDataDir () / " debug.log" ;
308
+ if (freopen (pathDebug.string ().c_str ()," a" ,fileout) != NULL )
309
+ setbuf (fileout, NULL ); // unbuffered
310
+ }
311
+
312
+ ret = FileWriteStr (strTimestamped, fileout);
313
+ }
262
314
}
263
-
264
315
return ret;
265
316
}
266
317
0 commit comments