upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/util.h
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-06 01:53:03 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-06 01:53:03 +0000
commitef9f06d43fc6577c15df2256abbb25b20d4227b8 (patch)
tree7e9132aa871fdc01cb95268d2f5ea3bb11853ddf /src/util.h
parentbe63e83d79e7e00e6b8ca889a70e6a19886aa1d8 (diff)
parentceae3d076b5ad11ee84729ae43f14e9312896646 (diff)
Merge branch 'chore/main-catchup-2026-08-26' into 'main'HEADmain
Bring main onto the line this project actually ships (incl. the 1.2.23 compactblock port) Closes #6, #7, #8, #11, #35, #34, #29, #28, #27, and #16 See merge request !16
Diffstat (limited to 'src/util.h')
-rw-r--r--src/util.h93
1 files changed, 87 insertions, 6 deletions
diff --git a/src/util.h b/src/util.h
index d72518b..dfe7511 100644
--- a/src/util.h
+++ b/src/util.h
@@ -87,6 +87,15 @@ inline T& REF(const T& val)
87 87
88extern bool fDebug; 88extern bool fDebug;
89 89
90// /debugrelay: the per-message firehose ("relay" and "nostrdiscovery"
91// categories) that even -debug keeps off. See LogAcceptsCategory().
92extern bool fDebugRelay;
93
94// debug.log is rolled to debug.log.old once it grows past this many bytes
95// (set from -maxdebugfilesize, in MB; 0 disables the check). See the roll
96// site in OutputDebugStringF() below.
97extern int64 nMaxDebugFileSize;
98
90// --------------------------------------------------------------------------- 99// ---------------------------------------------------------------------------
91// Categorized, burst-collapsing logging 100// Categorized, burst-collapsing logging
92// 101//
@@ -106,15 +115,29 @@ extern bool fDebug;
106// 2. Burst collapse: repeated LogPrint() calls from the *same source line* 115// 2. Burst collapse: repeated LogPrint() calls from the *same source line*
107// only emit one line per DEDUP_WINDOW_SECS; if more calls land inside 116// only emit one line per DEDUP_WINDOW_SECS; if more calls land inside
108// that window they're counted instead of reprinted, and the count is 117// that window they're counted instead of reprinted, and the count is
109// flushed as a single "(xN similar in Ws)" line the moment the window 118// flushed as a single "(xN similar in Ws)" line once the window expires
110// rolls over. A loop discovering 500 peers by address now produces a 119// -- whether or not that call site ever fires again. A loop discovering
111// small, bounded number of lines instead of 500 -- log growth is capped 120// 500 peers by address now produces a small, bounded number of lines
112// by elapsed time, not by how many similar events happen to fire. 121// instead of 500 -- log growth is capped by elapsed time, not by how
122// many similar events happen to fire.
123//
124// Use LogPrintAlways() instead for anything that reports an irreversible
125// change to money: an obligation voided, a payment sent, a payment that
126// failed. One line standing in for an unknown number of identical events is
127// a tidy report of peer chatter and a false report of a ledger. A reorg
128// voiding 100 entries hits one source line 100 times inside one window;
129// under LogPrint() that read as a single block losing a single 49.49 BTF
130// payment, while 4,950 BTF of obligations were actually destroyed, and the
131// discrepancy was only found by counting entries in pending_payouts.json
132// (issue #3). Bounded log growth is not worth that ambiguity here.
113// --------------------------------------------------------------------------- 133// ---------------------------------------------------------------------------
114bool LogAcceptsCategory(const char* category); 134bool LogAcceptsCategory(const char* category);
115void LogPrintDedup(const char* category, const char* file, int line, const std::string& msg); 135void LogPrintDedup(const char* category, const char* file, int line, const std::string& msg);
136void LogPrintNoCollapse(const char* category, const std::string& msg);
116#define LogPrint(category, ...) \ 137#define LogPrint(category, ...) \
117 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0) 138 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0)
139#define LogPrintAlways(category, ...) \
140 do { if (LogAcceptsCategory(category)) LogPrintNoCollapse((category), strprintf(__VA_ARGS__)); } while (0)
118 141
119// Every format string in this project goes through one of the four functions 142// Every format string in this project goes through one of the four functions
120// below -- `printf` itself is remapped to OutputDebugStringF just above, and 143// below -- `printf` itself is remapped to OutputDebugStringF just above, and
@@ -145,7 +168,7 @@ void ParseString(const string& str, char c, vector<string>& v);
145string FormatMoney(int64 n, bool fPlus=false); 168string FormatMoney(int64 n, bool fPlus=false);
146bool ParseMoney(const char* pszIn, int64& nRet); 169bool ParseMoney(const char* pszIn, int64& nRet);
147bool FileExists(const char* psz); 170bool FileExists(const char* psz);
148int GetFilesize(FILE* file); 171int64 GetFilesize(FILE* file);
149uint64 GetRand(uint64 nMax); 172uint64 GetRand(uint64 nMax);
150int64 GetTime(); 173int64 GetTime();
151int64 GetAdjustedTime(); 174int64 GetAdjustedTime();
@@ -199,7 +222,7 @@ protected:
199public: 222public:
200 char* pszFile; 223 char* pszFile;
201 int nLine; 224 int nLine;
202 explicit CCriticalSection() { InitializeCriticalSection(&cs); } 225 explicit CCriticalSection() : pszFile(NULL), nLine(0) { InitializeCriticalSection(&cs); }
203 ~CCriticalSection() { DeleteCriticalSection(&cs); } 226 ~CCriticalSection() { DeleteCriticalSection(&cs); }
204 void Enter() { EnterCriticalSection(&cs); } 227 void Enter() { EnterCriticalSection(&cs); }
205 void Leave() { LeaveCriticalSection(&cs); } 228 void Leave() { LeaveCriticalSection(&cs); }
@@ -390,7 +413,65 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
390 else 413 else
391 strDebugFile = "debug.log"; 414 strDebugFile = "debug.log";
392 } 415 }
416 // Latched by a failed rename in the roll below, which cannot be
417 // retried usefully and must not be retried endlessly.
418 static bool fRollDisabled = false;
393 FILE* fileout = fopen(strDebugFile.c_str(), "a"); 419 FILE* fileout = fopen(strDebugFile.c_str(), "a");
420 if (fileout && nMaxDebugFileSize > 0 && !fRollDisabled)
421 {
422 // Roll an overgrown debug.log before adding to it. Nothing in the
423 // tree shrinks this file once the process is running (there is no
424 // ShrinkDebugFile, and even Bitcoin's only ran at startup), so a
425 // node that stays up for months grows the log without bound --
426 // production hit ~2 GiB. The file is opened and closed per line,
427 // so a rename is safe here: the next line simply reopens the
428 // path. One generation is kept as debug.log.old; logrotate
429 // (contrib/logrotate/) handles anything longer-term.
430 int64 nSize = GetFilesize(fileout);
431 if (nSize >= 0 && nSize > nMaxDebugFileSize)
432 {
433 fclose(fileout);
434 string strOldFile = strDebugFile + ".old";
435 remove(strOldFile.c_str()); // rename() won't clobber on Windows
436 bool fRolled = (rename(strDebugFile.c_str(), strOldFile.c_str()) == 0);
437 int nRenameErrno = errno; // before fopen() can overwrite it
438 fileout = fopen(strDebugFile.c_str(), "a");
439 if (fRolled)
440 {
441 if (fileout)
442 fprintf(fileout,
443 "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n",
444 (long long)(nMaxDebugFileSize / 1024 / 1024));
445 }
446 else if (nRenameErrno == ENOENT)
447 {
448 // The file went away between the size check and the
449 // rename, so an external rotator (logrotate) got there
450 // first. Nothing left to roll and nothing wrong: the
451 // fopen above has already recreated it. Latching on this
452 // would let a benign race with logrotate switch the cap
453 // off for the rest of the run.
454 }
455 else
456 {
457 // The file is still over the cap, so this branch would be
458 // reached again on the next line and every line after it.
459 // Unlatched, the complaint about failing to roll becomes
460 // the runaway growth the roll exists to prevent. Say it
461 // once and stop trying -- on stderr too, because whatever
462 // blocked the rename (read-only mount, permissions, EXDEV
463 // across a bind mount) may equally block the log write.
464 fRollDisabled = true;
465 fprintf(stderr,
466 "cannot roll %s (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n",
467 strDebugFile.c_str(), strerror(nRenameErrno));
468 if (fileout)
469 fprintf(fileout,
470 "cannot roll debug.log (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n",
471 strerror(nRenameErrno));
472 }
473 }
474 }
394 if (fileout) 475 if (fileout)
395 { 476 {
396 va_list arg_ptr; 477 va_list arg_ptr;