Table of Contents

Class DiskPatternClipCache

Namespace
EncDotNet.S100.Renderers.Mapsui
Assembly
EncDotNet.S100.Renderers.Mapsui.dll

Disk-backed IPatternClipCache: persists each computed S-101 pattern-fill priority clip result (see MapsuiDisplayListRenderer's PatternPriorityClipper) as a WKB sidecar file so that the cold first open of a previously-seen cell — including after a process restart — skips the multi-second NetTopologySuite overlay.

public sealed class DiskPatternClipCache : IPatternClipCache
Inheritance
DiskPatternClipCache
Implements
Inherited Members

Remarks

The in-memory InMemoryPatternClipCache (step 1) only eliminates re-clip cost for re-renders of the same already-open dataset (e.g. Day/Dusk/Night palette switches). It cannot help the very first open of a cell — nothing is cached yet — and its state is lost on close/restart. This implementation closes that gap by persisting the clip geometry to disk.

The clip geometry is palette-independent (the palette only recolours the raster tiles applied after clipping), so it is safe to persist and reuse across palette/display re-renders. To make the on-disk key globally unique — the GetOrCompute(string, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>) contract's key is only unique within one processor's single in-memory slot — the S-101 processor composes a fully-qualified key {datasetScope}|{portrayalKey} whose datasetScope deterministically encodes the dataset content hash, the clip parameters, the CRS, and the cache FormatVersion. Any change to dataset content, clip parameters, or the serialization format therefore yields a different filename and recomputes (auto-invalidation).

Robustness: any IO error, truncated/corrupt file, or FormatVersion mismatch is treated as a miss (the factory runs and overwrites the entry); failures never propagate to the caller. Writes are atomic (temp file + move) so a crash mid-write cannot leave a half-written entry that later deserializes incorrectly.

The cache is bounded by a total-bytes cap enforced with a least-recently-used eviction policy (see DiskCacheBudget). The cache directory is shared across every S-101 processor, so all instance methods are thread-safe; hits read and deserialize without a lock.

Constructors

DiskPatternClipCache(string, long)

Creates a disk-backed pattern-clip cache rooted at cacheDirectory.

public DiskPatternClipCache(string cacheDirectory, long maxBytes)

Parameters

cacheDirectory string

Directory under which clip sidecar files are stored. Created on first write if it does not exist. The directory is assumed to be private to this cache (the LRU sweep enumerates every *.clip file in it).

maxBytes long

Soft upper bound, in bytes, on the total size of all persisted clip files. After a write that exceeds it, the least-recently-used files are evicted until the total is at or below this cap. Must be positive.

Exceptions

ArgumentException

cacheDirectory is null or empty.

ArgumentOutOfRangeException

maxBytes is not positive.

Fields

FormatVersion

Version stamp for the on-disk serialization frame. It is written into every cache file and verified on read; a mismatch is treated as a miss. The S-101 processor also folds this value into the datasetScope component of the cache key, so bumping it both renames future files and rejects stale ones. Increment whenever the serialization frame or the clip algorithm changes in a way that invalidates persisted geometry.

public const int FormatVersion = 1

Field Value

int

Properties

Hits

Number of GetOrCompute(string, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>) calls served from the cache (the expensive clip overlay was skipped). Exposed for diagnostics and tests.

public long Hits { get; }

Property Value

long

MaxBytes

Soft upper bound, in bytes, on the total size of the persisted entries.

public long MaxBytes { get; }

Property Value

long

Misses

Number of GetOrCompute(string, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>) calls that ran the factory (cache miss). Exposed for diagnostics and tests.

public long Misses { get; }

Property Value

long

TotalBytes

The total size, in bytes, of the persisted entries. The first call reads the cache directory if no write has done so yet.

public long TotalBytes { get; }

Property Value

long

Methods

Contains(string)

Whether an entry is persisted for key. Checks only that the file exists: it neither reads nor validates the entry, and does not mark it used.

public bool Contains(string key)

Parameters

key string

A key as passed to GetOrCompute(string, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>).

Returns

bool

true when the entry's file exists.

GetOrCompute(string, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>)

Returns the cached clipped pattern geometry for key, invoking factory to compute and store it on a miss.

public IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)> GetOrCompute(string key, Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>> factory)

Parameters

key string

An opaque key that fully identifies the clip inputs (for S-101 this is the mariner + ECDIS display-state portrayal cache key). The same key must always map to the same clip result.

factory Func<IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>>

Computes the clipped pattern geometry when the key is not cached. Only invoked on a miss.

Returns

IReadOnlyList<(string PatternRef, int Priority, Geometry Geometry)>

The clipped pattern entries, each carrying its palette-independent pattern reference, drawing priority, and clipped geometry. On a hit the exact cached instances are returned.