Superbol_cache.StoreStorage the cache is built upon.
Like Cobol_common.Platform, this is a record of operations rather than a set of direct system calls, so that the library itself needs no dependency on Unix: cobol_lsp links against a platform that performs no I/O at all, and the concrete implementation is injected at startup by superbol_platform. It also lets the test suite run the whole cache against in_memory, with no file-system involved.
Every path handed to a store is relative to the cache root.
The cache directory may sit on a network mount, and may be written to by several users at once. An implementation is therefore required to:
TYPES.store.publish atomic and non-destructive: a reader either sees nothing at the given path or sees the complete contents, never a prefix; and, unless asked to replace it, publishing over an existing path leaves that path alone and reports success. Publishing is expected to stage the item under Layout.tmp, which shares the target's file-system, followed by a hard link --- link fails with EEXIST exactly when someone else has already published the same item, which is the wanted behaviour and is reliable over NFS. rename is only fit for replacing a target, or as a fallback where hard links are unavailable and the target was just seen to be absent: it silently overwrites, and some SMB shares refuse to replace with it at all.Error, which the cache turns into a miss.TYPES.store.touch and TYPES.store.remove as best-effort. Refreshing the hit date of an entry owned by another user may be refused, and removing an item another process holds open fails on Windows; neither is worth reporting.Conversely, an implementation is not required to make TYPES.store.stat accurate: attribute caching makes sizes and dates stale over NFS. The cache never relies on them for correctness, only for pruning and monitoring.
module TYPES : sig ... endA store on which nothing can be stored. Every lookup against it misses and every write is dropped, which is precisely how the cache behaves when caching is turned off.
val entries_under : TYPES.store -> string -> (string * string) listentries_under store dir lists the items held under the two-level fanout at dir, as pairs of an item's name and its path. Both the manifests and the values are laid out that way, and both the monitoring API and the pruner need to walk them.
val in_memory : ?now:(unit -> float) -> unit -> TYPES.storein_memory ?now () is a store backed by a hash table. Intended for testing: it honours the same contract as a file-system store, including the non-destructive behaviour of TYPES.store.publish.