lib.FcCache: Add a write-through read cache #145

Merged
Jan Lindemann merged 2 commits from jan/feature/20261017-lib-fccache-add-a-write-through-read-cache into master 2026-10-17 12:26:32 +02:00 AGit
Owner

This PR adds a write-through read cache in front of a file context. The two commits build on each other: FcWrapper first establishes the delegation base — a context that adopts the identity of the wrapped context and forwards every primitive, so a derived context overrides only what it cares about — and FcCache then implements the cache on top of it, so repeated stat() and get() calls on a path pay the cache instead of the wrapped context, and warm() pre-fills the cache with a single host command when the wrapped context is an exec context:

lib.FcWrapper: Add a delegating file context wrapper

Add a file context that sits in front of another one and delegates every primitive call to it.

The wrapper adopts the identity of the wrapped context: uri, root, chroot flag, and the chroot path composition are the wrapped context's, so a path composed by the wrapper composes identically in the wrapped context. Every primitive is forwarded to the wrapped context's primitives, which receive the already-composed path; open() and close() are forwarded to the wrapped context's public methods, so the open count is kept in one place.

The point is to give derived contexts a stable base: a caching context, or any other filter, overrides the primitives it cares about and inherits the rest, instead of re-deriving the chroot bookkeeping of every method.

lib.FcCache: Add a write-through read cache

Add a write-through read cache in front of a file context.

stat() and get() results are cached: stat per (path, follow_symlinks), get per (path, wd, throw). Successful stats and FileNotFoundErrors are cached; other errors are re-probed, so a transient transport failure does not poison the cache. Writes pass through to the wrapped context and drop the cache entries of the affected paths. The existence and directory checks are rerouted through the cached stat, so they pay the cache instead of the wrapped context's own fast path.

warm() fills the stat cache of a set of paths, as file_exists() would stat them, without following symlinks. If the wrapped context is an exec context, one host command stats all of the paths; otherwise, one stat per path runs.

The GNU stat format of ExecContext is lifted to the module constant STAT_GNU_FORMAT, and the field parser is exported as parse_stat_fields(), so warm() fills entries that are indistinguishable from a real stat().

This PR adds a write-through read cache in front of a file context. The two commits build on each other: `FcWrapper` first establishes the delegation base — a context that adopts the identity of the wrapped context and forwards every primitive, so a derived context overrides only what it cares about — and `FcCache` then implements the cache on top of it, so repeated `stat()` and `get()` calls on a path pay the cache instead of the wrapped context, and `warm()` pre-fills the cache with a single host command when the wrapped context is an exec context: #### lib.FcWrapper: Add a delegating file context wrapper Add a file context that sits in front of another one and delegates every primitive call to it. The wrapper adopts the identity of the wrapped context: uri, root, chroot flag, and the chroot path composition are the wrapped context's, so a path composed by the wrapper composes identically in the wrapped context. Every primitive is forwarded to the wrapped context's primitives, which receive the already-composed path; `open()` and `close()` are forwarded to the wrapped context's public methods, so the open count is kept in one place. The point is to give derived contexts a stable base: a caching context, or any other filter, overrides the primitives it cares about and inherits the rest, instead of re-deriving the chroot bookkeeping of every method. #### lib.FcCache: Add a write-through read cache Add a write-through read cache in front of a file context. `stat()` and `get()` results are cached: stat per (path, `follow_symlinks`), get per (path, wd, throw). Successful stats and `FileNotFoundErrors` are cached; other errors are re-probed, so a transient transport failure does not poison the cache. Writes pass through to the wrapped context and drop the cache entries of the affected paths. The existence and directory checks are rerouted through the cached stat, so they pay the cache instead of the wrapped context's own fast path. `warm()` fills the stat cache of a set of paths, as `file_exists()` would stat them, without following symlinks. If the wrapped context is an exec context, one host command stats all of the paths; otherwise, one stat per path runs. The GNU stat format of `ExecContext` is lifted to the module constant `STAT_GNU_FORMAT`, and the field parser is exported as `parse_stat_fields()`, so `warm()` fills entries that are indistinguishable from a real `stat()`.
Add a file context that sits in front of another one and delegates every
primitive call to it.

The wrapper adopts the identity of the wrapped context: uri, root, chroot
flag, and the chroot path composition are the wrapped context's, so a path
composed by the wrapper composes identically in the wrapped context. Every
primitive is forwarded to the wrapped context's primitives, which receive
the already-composed path; open() and close() are forwarded to the wrapped
context's public methods, so the open count is kept in one place.

The point is to give derived contexts a stable base: a caching context, or
any other filter, overrides the primitives it cares about and inherits the
rest, instead of re-deriving the chroot bookkeeping of every method.

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v1.1.0
Signed-off-by: Jan Lindemann <jan@janware.com>
lib.FcCache: Add a write-through read cache
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m23s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m44s
CI / Packaging test (pull_request) Successful in 0s
CI / Packaging - Kali Linux (push) Successful in 4m55s
CI / Packaging - OpenSUSE Tumbleweed (push) Successful in 4m54s
CI / Packaging test (push) Successful in 0s
e02f724808
Add a write-through read cache in front of a file context.

stat() and get() results are cached: stat per (path, follow_symlinks), get
per (path, wd, throw). Successful stats and FileNotFoundErrors are cached;
other errors are re-probed, so a transient transport failure does not
poison the cache. Writes pass through to the wrapped context and drop the
cache entries of the affected paths. The existence and directory checks are
rerouted through the cached stat, so they pay the cache instead of the
wrapped context's own fast path.

warm() fills the stat cache of a set of paths, as file_exists() would stat
them, without following symlinks. If the wrapped context is an exec
context, one host command stats all of the paths; otherwise, one stat per
path runs.

The GNU stat format of ExecContext is lifted to the module constant
STAT_GNU_FORMAT, and the field parser is exported as parse_stat_fields(),
so warm() fills entries that are indistinguishable from a real stat().

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v1.1.0
Signed-off-by: Jan Lindemann <jan@janware.com>
Jan Lindemann scheduled this pull request to auto merge when all checks succeed 2026-10-17 12:17:23 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
janware/jw-pkg!145
No description provided.