C# header: one function decides it for every writer; a store's own ids are the only source
CacheBackingStore.HeaderFor(holdsIds, existingHeader, wholeStore, directoryStore) replaces FormatFor, DirectoryFormatFor and the writers' private marker logic. A writer that rewrites the whole store decides by content; a writer that touches part of it keeps a header already marked. Flush, unconditional and conditional commit, the directory store and CultMesh's single-file write all call it. A typed CultMesh write replaces the file with a document it can see, so it decides by content; a raw payload is opaque and keeps a marked file marked. A record's HoldsIds is what its stored form persists: a load keeps a variant's delta as read, so the ids a load mints in an override exist only in memory and no longer mark the store. A conditional commit onto the file no longer reads this cache's view of what the file held, so a stale view cannot over-mark it. IdPlan.HoldsIds is derived from HeldIds and the fills. Reverts InternalsVisibleTo GameCult.Caching.MessagePack and the public DirectoryFormatV4/V5 constants: the directory store reaches the decision through the protected member it inherits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
591eeff70d
commit
41d0dd9bfb
7 changed files with 164 additions and 70 deletions
|
|
@ -15,8 +15,9 @@ namespace GameCult.Caching.MessagePack;
|
|||
// A small hot manifest indexes the store; each record lives in one cold content-addressed page.
|
||||
public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
|
||||
{
|
||||
private const string IndexedFormatVersion = CultPersistedStoreSnapshot.DirectoryFormatV4;
|
||||
private const string IndexedFormatVersionWithIds = CultPersistedStoreSnapshot.DirectoryFormatV5;
|
||||
// The two manifest headers; the shared header decision names them.
|
||||
private static readonly string IndexedFormatVersion = HeaderFor(holdsIds: false, existingHeader: null, wholeStore: true, directoryStore: true);
|
||||
private static readonly string IndexedFormatVersionWithIds = HeaderFor(holdsIds: true, existingHeader: null, wholeStore: true, directoryStore: true);
|
||||
// An unleased load that has not settled after this many attempts throws.
|
||||
private const int UnleasedLoadAttempts = 5;
|
||||
private readonly FileInfo _manifestFile;
|
||||
|
|
@ -284,12 +285,15 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
|
|||
pagePayload);
|
||||
}
|
||||
|
||||
// A manifest already marked stays marked: pages it names may hold ids this cache cannot read.
|
||||
var carriesIds = string.Equals(currentManifest.FormatVersion, IndexedFormatVersionWithIds, StringComparison.Ordinal) ||
|
||||
keysToWrite.Any(key => Entries.TryGetValue(key, out var written) && written.HoldsIds);
|
||||
// The directory store writes only its dirty pages, so it keeps a manifest already marked.
|
||||
var header = HeaderFor(
|
||||
keysToWrite.Any(key => Entries.TryGetValue(key, out var written) && written.HoldsIds),
|
||||
currentManifest.FormatVersion,
|
||||
wholeStore: false,
|
||||
directoryStore: true);
|
||||
WriteManifest(targetCatalog, currentIndex.Values
|
||||
.OrderBy(record => record.Key, StringComparer.Ordinal)
|
||||
.ToArray(), carriesIds);
|
||||
.ToArray(), header);
|
||||
|
||||
DeleteUnreferencedRecordPages(currentIndex.Values);
|
||||
|
||||
|
|
@ -299,11 +303,11 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
|
|||
MarkFlushSucceeded();
|
||||
}
|
||||
|
||||
private void WriteManifest(CultSchemaCatalogEntry[] catalog, CultPersistedRecord[] index, bool carriesElementIds)
|
||||
private void WriteManifest(CultSchemaCatalogEntry[] catalog, CultPersistedRecord[] index, string header)
|
||||
{
|
||||
var manifest = new CultPersistedStoreSnapshot
|
||||
{
|
||||
FormatVersion = CultPersistedStoreSnapshot.DirectoryFormatFor(carriesElementIds),
|
||||
FormatVersion = header,
|
||||
SchemaCatalog = catalog,
|
||||
Records = index
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue