Skip to content

fix(amulegui): keep stats + Kad graphs populated across tab switches - #135

Merged
got3nks merged 2 commits into
amule-org:masterfrom
got3nks:fix/amulegui-stats-graph-background-poll
Jun 12, 2026
Merged

fix(amulegui): keep stats + Kad graphs populated across tab switches#135
got3nks merged 2 commits into
amule-org:masterfrom
got3nks:fix/amulegui-stats-graph-background-poll

Conversation

@got3nks

@got3nks got3nks commented Jun 12, 2026

Copy link
Copy Markdown

Fixes #134 (stats + Kad parts).

Two visible regressions on amulegui's Statistics tab and the Network → Kad sub-tab, both rooted in the same gap: COScopeCtrl::PlotHistory was an empty stub under CLIENT_GUI because the monolithic implementation calls theApp->m_statistics->GetHistory(...) which had no analogue on the remote-GUI side. Two symptoms:

  1. Background starvationCamuleRemoteGuiApp::OnPollTimer only fired statgraphs->DoRequery() and stattree->DoRequery() when the Statistics dialog was visible. CStatGraphRem::HandlePacket also feeds m_kademliawnd->UpdateGraph(), so leaving Statistics hidden also starved the Kad node-count graph. Switch off Stats → both graphs froze.
  2. Whole-graph resets — auto-rescale paths (SetRanges on Kad node count crossing a 50-step ceiling; SetRange on the Stats connection-scope nScale change) call RecreateGraph, which clears the bitmap and then calls PlotHistory(width, false, ...). Under CLIENT_GUI that was a no-op, so the bitmap stayed cleared and the entire line vanished.

What this PR does

Commit 1 — polling-gate fix. Both stats requests now run every step 2 cycle regardless of the active tab. Cost is unchanged in practice: the graph request is a delta (m_lastTimestamp lower bound; daemon returns only newer points or EC_OP_FAILED "No points for graph.") and the tree request is already throttled by thePrefs::GetStatsInterval().

Commit 2 — share PlotHistory with monolithic via a client-side history ring. Rather than duplicate the monolithic machinery, CPreciseRateCounter, CStatistics::GetHistory and CStatistics::ComputeAverages are lifted out of the #ifndef CLIENT_GUI gate alongside the already-shared HR struct. The CLIENT_GUI CStatistics now also carries listHR, the three m_graphRunningAvg* counters and hrInit. A new CLIENT_GUI-only producer AddHistoryRecord(const HR&) is called once per decoded point from CStatGraphRem::HandlePacket. The ring is capped at kHistoryCap = 1800 (~30 min @ 1 Hz, ≈150 KB across all four graphs). With listHR populated the shared PlotHistory body works under both builds and the CLIENT_GUI-specific empty stub is gone.

Field mapping in HandlePacket mirrors CStatistics::GetPointsForUpdate so the same GetHistory + ComputeAverages code reads it back correctly: kBytes{Received,Sent} and kadNodesTotal are stored as session-rate * timestamp, so ComputeAverages's kValueRun / sTimestamp recovers the session-avg trend [0] verbatim. Per-point timestamps are reconstructed from the batch by stepping back from m_lastTimestamp at the 1 s scale we request in DoRequery.

No EC protocol changes

The ring fills from the existing EC_OP_GET_STATSGRAPHS stream — no new tags, no version bump, fully backward compatible with old daemons.

Test plan

  • Statistics tab: graph stays continuous across Transfer / Search / Network switches; tree counters reflect current values on tab return.
  • Network → Kad sub-tab: graph populates while sitting on Kad; no whole-graph blank when node count crosses a 50-step ceiling.
  • Stats connection scope: no blank-out on nScale change.
  • Monolithic amule.app builds cleanly with BUILD_MONOLITHIC=YES BUILD_REMOTEGUI=YES BUILD_DAEMON=YES; no regression in monolithic graph behavior (history machinery is the same code paths, just no longer #ifdef-gated).
  • Long-session memory: listHR capped at 1800 records → bounded at ~150 KB total.

got3nks added 2 commits June 12, 2026 22:13
…dden

CamuleRemoteGuiApp::OnPollTimer only fired
stattree->DoRequery() / statgraphs->DoRequery() when the Statistics
dialog was the visible tab. Side effect: CStatGraphRem::HandlePacket
also calls m_kademliawnd->UpdateGraph(), so leaving Statistics hidden
also starved the Kad node-count graph on the Network -> Kad sub-tab.

Promote both polls out of the visibility gate; they run every step 2
cycle. Cost stays small because the graph request is a delta
(m_lastTimestamp lower bound) and the tree request is already
throttled by thePrefs::GetStatsInterval().

Reported in amule-project#134.
…ory ring

COScopeCtrl::PlotHistory had an empty stub under CLIENT_GUI because
the monolithic implementation called theApp->m_statistics->GetHistory
which had no analogue on the remote-GUI side. Two visible regressions
fell out of that gap:

  * Switching off the Stats / Kad tab and back left a gap on the graph
    -- the OnPaint "come out of hiding" catch-up via PlotHistory was a
    no-op, so the bitmap never refilled the hidden interval.
  * Auto-rescale events (Kad node count crossing a 50-step ceiling,
    Stats connection scope changing scale) called RecreateGraph which
    cleared the bitmap and then called the empty PlotHistory, blanking
    the entire graph.

Share the monolithic machinery instead of duplicating it. The HR
struct was already outside the #ifndef CLIENT_GUI gate; lift
CPreciseRateCounter, CStatistics::GetHistory and
CStatistics::ComputeAverages out alongside it. The CLIENT_GUI
CStatistics now also carries listHR + the three m_graphRunningAvg*
counters + hrInit, plus a new CLIENT_GUI-only producer
AddHistoryRecord that CStatGraphRem::HandlePacket calls once per
decoded point. The ring is capped at kHistoryCap=1800 (~30 min @ 1Hz)
so memory stays bounded across long sessions. With listHR populated,
the shared PlotHistory body works for both builds and the
CLIENT_GUI-specific stub is gone.

Field mapping in HandlePacket mirrors CStatistics::GetPointsForUpdate
so the same GetHistory + ComputeAverages code reads it back correctly:
kBytes{Received,Sent} and kadNodesTotal are stored as
(session-rate * timestamp), so ComputeAverages's "kValueRun /
sTimestamp" recovers the session-avg trend ([0]) verbatim. Per-point
timestamps are reconstructed from the batch by stepping back from
m_lastTimestamp at the 1s scale we request in DoRequery.

Statistics.h gains "#include GetTickCount.h" because the now-shared
CPreciseRateCounter inline ctor calls GetTickCount64 and was
previously only instantiated under #ifndef CLIENT_GUI where transitive
includes covered it.

Verified locally on macOS that monolithic amule and amulegui both
build cleanly (BUILD_MONOLITHIC=YES BUILD_REMOTEGUI=YES
BUILD_DAEMON=YES).

Reported in amule-project#134.
@got3nks
got3nks merged commit b2d7186 into amule-org:master Jun 12, 2026
10 checks passed
@got3nks
got3nks deleted the fix/amulegui-stats-graph-background-poll branch June 12, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: stats and kad graphing in amulegui

1 participant