Skip to content

feat: spool records to a file store with a CRC-16 at rest - #38

Merged
DavidCozens merged 1 commit into
mainfrom
stage/file-store
Jul 30, 2026
Merged

feat: spool records to a file store with a CRC-16 at rest#38
DavidCozens merged 1 commit into
mainfrom
stage/file-store

Conversation

@DavidCozens

@DavidCozens DavidCozens commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Pull request

What this stage adds

A SolidSyslogBlockStore over a FileBlockDevice over the library's FatFs port,
replacing the Null store. The service task drains the ring into the store and sends
from there, so a failed send costs a retry rather than the record.

Flash +11,576 B (+3,964 on the previous stage)
RAM +7,092 B (+1,212)
Log stack +448 B (unchanged)
Service +736 B (+64)

The log stack does not move: storing happens on the service task, and a task that
calls Log still knows nothing about what happens after it returns. The service
task's own high-water rises 64 bytes to 788, which the 2 KiB seam the buffered
stage sized absorbs, so no RAM moves with it.

The static RAM is pool allocation, not buffers. The 8192-byte block size is file
capacity — nothing holds a block in memory, so the store costs its handles rather
than its capacity.

CRC-16 is a checksum, not tamper-evidence: it catches a truncated write or bit-rot,
and anyone who can edit a stored record can recompute it. What it buys is knowing a
record came back the way it went in, which is the prerequisite for spooling at all.

One file per block, syslog00.log upward on the volume the device already mounts,
four blocks, oldest discarded when full — a device that cannot reach its collector
should keep the newest evidence rather than stop logging.

SolidSyslog::FatFs is a header-configured upstream, so it is named in
SOLIDSYSLOG_PLATFORMS and linked. The discard policy enumerator is
SOLIDSYSLOG_DISCARD_POLICY_OLDEST.

Files

 CMakeLists.txt              |  4 ++--
 README.md                   | 12 +++++++-----
 app/syslog/Syslog.c         | 22 ++++++++++++++++++----
 measurements/file-store.csv | 13 +++++++++++++
 measurements/stages.tsv     |  1 +
 run-report.md               | 38 +++++++++++++++++++-------------------
 6 files changed, 60 insertions(+), 30 deletions(-)

Checklist

  • The diff touches build infra (1 file(s)) — see Files above; deliberate for this stage.
  • measurements/file-store.csv committed.
  • Row added to measurements/stages.tsv.
  • README regenerated: python3 scripts/gen-cost-table.py.
  • ./run.sh green (build + QEMU + baseline self-check) — run-report.md committed.

Context for review: 11 of 21 sequential single-commit PRs replaying the integration on top of the Baseline root. Each lands green and reviewed before the next is built on it, because a change to an early commit would force every commit above it to be re-run and re-measured.

Summary by CodeRabbit

  • New Features

    • Added persistent store-and-forward logging, retaining records on the device when delivery fails and retrying them later.
    • Added CRC-16 integrity checks to detect corrupted records stored on the device.
    • Added support for file-backed logging storage on mounted volumes.
  • Documentation

    • Updated stage descriptions, cost estimates, and run measurements to document the new file-store behavior.

A SolidSyslogBlockStore over a FileBlockDevice over the library's FatFs port,
replacing the Null store. The service task drains the ring into the store and sends
from there, so a failed send costs a retry rather than the record.

  Flash      +11,576 B  (+3,964 on the previous stage)
  RAM         +7,092 B      (+1,212)
  Log stack     +448 B  (unchanged)
  Service       +736 B         (+64)

The log stack does not move: storing happens on the service task, and a task that
calls Log still knows nothing about what happens after it returns. The service
task's own high-water rises 64 bytes to 788, which the 2 KiB seam the buffered
stage sized absorbs, so no RAM moves with it.

The static RAM is pool allocation, not buffers. The 8192-byte block size is file
capacity — nothing holds a block in memory, so the store costs its handles rather
than its capacity.

CRC-16 is a checksum, not tamper-evidence: it catches a truncated write or bit-rot,
and anyone who can edit a stored record can recompute it. What it buys is knowing a
record came back the way it went in, which is the prerequisite for spooling at all.

One file per block, syslog00.log upward on the volume the device already mounts,
four blocks, oldest discarded when full — a device that cannot reach its collector
should keep the newest evidence rather than stop logging.

SolidSyslog::FatFs is a header-configured upstream, so it is named in
SOLIDSYSLOG_PLATFORMS and linked. The discard policy enumerator is
SOLIDSYSLOG_DISCARD_POLICY_OLDEST.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change enables FatFs, replaces the null syslog store with CRC16-protected file-backed block storage, and updates documentation and measurement reports for the file-store configuration.

Changes

File store integration

Layer / File(s) Summary
Enable FatFs platform
CMakeLists.txt
Adds FatFs to the enabled SolidSyslog platforms and links SolidSyslog::FatFs to baseline.
Configure persistent syslog store
app/syslog/Syslog.c
Configures file-backed storage with a mounted-volume prefix, bounded block count, oldest-record discard behavior, and CRC16 protection.
Document file-store results
README.md, run-report.md
Replaces the time-quality stage with file-store documentation and updates measured resource usage, size output, and self-check results.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Syslog_Start
  participant SolidSyslogBlockStore
  participant FatFsFileBlockDevice
  Syslog_Start->>FatFsFileBlockDevice: configure persistent block storage
  Syslog_Start->>SolidSyslogBlockStore: create store with discard-oldest and CRC16 policies
  SolidSyslogBlockStore-->>Syslog_Start: provide configured Store
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: file-store spooling with CRC-16 at rest.
Description check ✅ Passed The description matches the template with a stage summary and checklist, and it includes the required measurement and run-report updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stage/file-store

Comment @coderabbitai help to get the list of available commands.

@DavidCozens

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

The previous run on this PR came back rate limited rather than completed, so this PR has not actually been reviewed. Please run a full review.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

@DavidCozens: Understood — I’m rerunning a complete review of #38. 🐇🔍

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/syslog/Syslog.c (1)

125-137: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

Exercise the file-store failure paths in validation.

Add or confirm integration coverage for failed-send retry, reboot recovery, CRC rejection, and oldest-block discard when the four-block limit is reached. The supplied run output proves successful delivery and measurements, but not these persistence guarantees.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/syslog/Syslog.c` around lines 125 - 137, Extend integration validation
around SolidSyslogBlockStore_Create and the configured storeConfig to cover
failed-send retry, reboot recovery, CRC rejection, and oldest-block discard once
MaxBlocks reaches the four-block limit. Exercise each persistence scenario and
assert the expected retained, recovered, or rejected records rather than only
successful delivery and measurements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/syslog/Syslog.c`:
- Around line 125-137: Extend integration validation around
SolidSyslogBlockStore_Create and the configured storeConfig to cover failed-send
retry, reboot recovery, CRC rejection, and oldest-block discard once MaxBlocks
reaches the four-block limit. Exercise each persistence scenario and assert the
expected retained, recovered, or rejected records rather than only successful
delivery and measurements.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ff55e4c3-31cc-42a2-b586-9b3ca04f4f44

📥 Commits

Reviewing files that changed from the base of the PR and between f4724fc and 55a9192.

⛔ Files ignored due to path filters (2)
  • measurements/file-store.csv is excluded by !**/*.csv
  • measurements/stages.tsv is excluded by !**/*.tsv
📒 Files selected for processing (4)
  • CMakeLists.txt
  • README.md
  • app/syslog/Syslog.c
  • run-report.md

@DavidCozens
DavidCozens merged commit 8931a1e into main Jul 30, 2026
2 checks passed
@DavidCozens
DavidCozens deleted the stage/file-store branch July 30, 2026 05:41
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.

1 participant