<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/src/util.h, branch main</title>
<subtitle>[no description]</subtitle>
<id>https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/atom?h=main</id>
<link rel='self' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/'/>
<updated>2026-09-03T21:49:35+00:00</updated>
<entry>
<title>merge: !10 fix/small-fixes into deploy/all-2026-08-24</title>
<updated>2026-09-03T21:49:35+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-03T21:49:35+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=424da766b76ba572cc9a93c4dd03736dace04d80'/>
<id>urn:sha1:424da766b76ba572cc9a93c4dd03736dace04d80</id>
<content type='text'>
</content>
</entry>
<entry>
<title>merge: !2 fix/log-rotation into deploy/all-2026-08-24</title>
<updated>2026-09-03T21:49:35+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-03T21:49:35+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=3c18a66ef601d90f08ea622021cb02bafab1601b'/>
<id>urn:sha1:3c18a66ef601d90f08ea622021cb02bafab1601b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>log: do not latch the roll off when logrotate won the race</title>
<updated>2026-09-02T16:44:57+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T16:44:57+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=74f1d8598a6f603fdfaf6c0487375c40166b76ec'/>
<id>urn:sha1:74f1d8598a6f603fdfaf6c0487375c40166b76ec</id>
<content type='text'>
The latch added in 456b3b4 treats every rename() failure as permanent. One
is not: if an external rotator moves debug.log between the size check and
the rename, the rename fails ENOENT. Nothing is wrong -- the file has just
been rotated by someone else, and the reopen above has already recreated
it -- but latching there would switch the cap off for the rest of the run
on a race the operator cannot see or fix.

Treat ENOENT as "already rotated" and carry on. It cannot loop: the reopen
leaves an empty file, so the next line's size check does not fire.
</content>
</entry>
<entry>
<title>log: stop a failed debug.log roll from repeating on every line</title>
<updated>2026-09-02T16:42:39+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T16:42:39+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=456b3b4a3372e7d13b764f41006bf2c15d92f46e'/>
<id>urn:sha1:456b3b4a3372e7d13b764f41006bf2c15d92f46e</id>
<content type='text'>
Neither remove() nor rename() was checked. When the rename fails -- a
read-only mount, permissions, EXDEV across a bind mount -- fopen() reopens
the same oversized file and writes the "grew past N MB" marker anyway. The
size never drops, so the next line takes the same branch, and every line
after that: the roll's own failure notice becomes unbounded growth, added
to the growth of issue #34 rather than replacing it.

Check rename(), and on failure latch the roll off for the rest of the run
after reporting it once -- on stderr as well as in the log, since whatever
blocked the rename may equally block the log write. An operator is told the
cap has stopped being enforced instead of learning it from the disk.
</content>
</entry>
<entry>
<title>log: measure the debug log with a size type that can hold it</title>
<updated>2026-09-02T16:36:42+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T16:36:42+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=123ae2e017d90fd18b291db3d76033781c1ead84'/>
<id>urn:sha1:123ae2e017d90fd18b291db3d76033781c1ead84</id>
<content type='text'>
GetFilesize() returned int while ftell() returns long, so a debug.log of
2 GiB or more came back negative. Its only caller is the -maxdebugfilesize
roll added in ae1c6a7, which skips the roll on a negative size: the
rotation written for issue #34 would have switched itself off permanently
at exactly the size it exists to prevent. Production was at 1.95 GiB
growing 51-129 MB/day, about a day short of crossing 2 GiB.

The same truncation capped the comparison at INT_MAX (2047.99 MB), so
-maxdebugfilesize=2048 or higher could never be exceeded and disabled
rotation outright. Both failures were silent.

Widen the return to int64 and seek with ftello/fseeko (_ftelli64 and
_fseeki64 on Windows). The roll in util.h is the function's only caller
in the tree, so no other behaviour changes. A 32-bit off_t would
reintroduce the same truncation, so its width is now a compile-time
assertion rather than a silent runtime surprise.
</content>
</entry>
<entry>
<title>payout: never collapse a log line that reports money moving</title>
<updated>2026-09-02T14:14:52+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T14:14:52+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=03a69ccfb36861948e11b0871bb9af8f0b280709'/>
<id>urn:sha1:03a69ccfb36861948e11b0871bb9af8f0b280709</id>
<content type='text'>
LogPrint()'s burst collapse is right for share and peer chatter and wrong
for anything that reports an irreversible change to money. A reorg voided
100 ledger entries totalling 4,950 BTF and the log carried one line, naming
one block and 49.49 BTF. The other 99 were counted and never printed, and
no "(N similar)" summary appeared either -- a summary was only ever flushed
when that same call site fired again, and after the reorg it never did. The
missing 4,950 BTF was found by counting entries in pending_payouts.json.

Add LogPrintAlways(), which skips the collapse entirely, and move the four
payout lines that report money to it: an obligation voided, an obligation
dropped, a payment sent, a payment that failed. All four are bursty by
nature -- one reorg voids every entry funded by the orphaned block, from a
single source line -- which is precisely why one line must not stand in for
all of them. Their volume is bounded by how much money moved, which is a
number worth the lines.

Also sweep expired windows for every call site rather than only the one
currently logging, so a burst that stops is still summarised, and report
the window's real elapsed time instead of a hardcoded 3s.
</content>
</entry>
<entry>
<title>util: initialise CCriticalSection's diagnostic fields at construction</title>
<updated>2026-09-02T06:51:07+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T06:51:07+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=a44c9402c20493f0964a1296dd38d313216fbd4d'/>
<id>urn:sha1:a44c9402c20493f0964a1296dd38d313216fbd4d</id>
<content type='text'>
pszFile/nLine were first written by CRITICAL_BLOCK on entry, so an
instance embedded in a dynamically allocated object (CNode::cs_vSend,
cs_vRecv, cs_inventory) held indeterminate values until its first
lock -- anything reading them for diagnostics dereferenced a wild
pointer.
</content>
</entry>
<entry>
<title>log: demote the four lines that were 90% of debug.log behind /debugrelay</title>
<updated>2026-09-02T05:31:22+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T05:31:22+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=2661de141e46dadfb2903bb12e72dc87c5a64375'/>
<id>urn:sha1:2661de141e46dadfb2903bb12e72dc87c5a64375</id>
<content type='text'>
A 13-hour production capture was ~71% "sending: tx", ~16% "Nostr:
discovered .btf peer", ~5% "Relaying wtx", and ~43% of raw lines were
CBlock/CTransaction dumps -- all already under -debug, which operators
run permanently, so -debug was useless as a filter.

The category mechanism gains a verbose tier: "relay" and
"nostrdiscovery" are accepted only with the new /debugrelay flag (which
implies /debug); everything else keeps its current gate. Demoted, with
message text unchanged for anyone grepping it:

  net.h     "sending: tx (N bytes)" (BeginMessage/EndMessage/
            AbortMessage all pick the category from the command, so no
            orphaned "(N bytes)" fragments leak into a plain -debug log)
  main.cpp  "Relaying wtx", "received block:" + CBlock::print, and the
            BitcoinMiner block dump
  nostr.cpp "Nostr: discovered .btf peer" -&gt; "nostrdiscovery"

Pool/worker/payout, [payout], BLOCK ORPHANED/ACCEPTED and share flow
lines are untouched. Because LogPrint dedup keys on category, demoted
lines also keep their burst collapse under /debugrelay.

Closes #35
</content>
</entry>
<entry>
<title>log: cap debug.log in-process, and ship a logrotate policy</title>
<updated>2026-09-02T05:26:51+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-09-02T05:26:51+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=ae1c6a7b49d9b4f8cf7218c0baec84f348eb5ef6'/>
<id>urn:sha1:ae1c6a7b49d9b4f8cf7218c0baec84f348eb5ef6</id>
<content type='text'>
debug.log grew without bound (production: 1.95 GiB, 51-129 MB/day).
Nothing shrank it once the process was up -- there is no
ShrinkDebugFile in this tree, and upstream's only ran at startup.

OutputDebugStringF now rolls the file to debug.log.old when it
passes -maxdebugfilesize (MB, default 1024, 0 disables). The write
path already opens and closes the file per line under one lock, so
the rename-and-reopen is a few lines inside that lock and no fd can
be stranded mid-roll.

contrib/logrotate/bitflash-debug.logrotate is the longer-term policy
(size 1G, rotate 4, compress, missingok, notifempty, copytruncate);
copytruncate keeps the writer's append handle valid across rotation.

Closes #34
</content>
</entry>
<entry>
<title>size thread pools by the cores we are allowed, not the ones the host has</title>
<updated>2026-08-23T04:37:36+00:00</updated>
<author>
<name>bitflash-maintainer</name>
<email>noreply@bitflash.invalid</email>
</author>
<published>2026-08-13T17:29:10+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1q9geyrch3feyczz242sxjaa05yczv50dlpug082sjln2kl0wrnxst0nrfa/bitflash/commit/?id=ee7613be2f1d679c7ea6e3948c44110313d230b1'/>
<id>urn:sha1:ee7613be2f1d679c7ea6e3948c44110313d230b1</id>
<content type='text'>
std::thread::hardware_concurrency() reports the MACHINE's core count. Inside a
container that is the wrong number: with --cpuset-cpus 0-5 on a 12-core host it
still answers 12, and every caller that sized a pool from it oversubscribed 2x.

Measured on the pool box:
  - the pool node logged "Mining with 11 thread(s) of 12 core(s)" while
    confined to 6 CPUs
  - a burst miner launched with /hashthreads=2 filled the ~2 GB RandomX
    dataset with 12 threads, alongside the pool node in the same 8 GB container

AvailableCoreCount() asks sched_getaffinity what the cpuset actually permits,
which is the number all of these meant. It cannot make the dataset build slower:
the CPU budget is identical either way, so fewer threads on the same cores is
the same work without the thrash. Falls back to hardware_concurrency where the
call is unavailable, and never returns 0 because callers subtract from it.

Not the cause of the burst miner dying -- that was a corrupt Berkeley DB
environment in the worker datadir -- but it is why the failure landed on the
dataset build, and it is wrong on its own terms.

(cherry picked from commit b3bee16f3eef8982bff1174bd9d0a9c21473732c)
</content>
</entry>
</feed>
