Module Spoc_framework_registry.Framework_cache

val debug_enabled : bool

Enable debug logging via environment variable

val debugf : ('a, Stdlib.out_channel, unit, unit, unit, unit) Stdlib.format6 -> 'a
val warnf : ('a, Stdlib.out_channel, unit, unit, unit, unit) Stdlib.format6 -> 'a
type stats = {
  1. mutable hits : int;
    (*

    Successful cache lookups

    *)
  2. mutable misses : int;
    (*

    Failed cache lookups

    *)
  3. mutable puts : int;
    (*

    Cache writes

    *)
  4. mutable errors : int;
    (*

    I/O errors

    *)
}

Cache statistics

val stats : stats
val get_stats : unit -> stats

Get current cache statistics

val reset_stats : unit -> unit

Reset statistics

val hit_rate : unit -> float

Calculate hit rate (0.0 - 1.0)

val print_stats : unit -> unit

Print statistics to stdout

val cache_dir_name : string
val enabled : unit -> bool

The on-disk cache is on unless SAREK_DISK_CACHE=0 (exactly the string 0). When off, get reports a miss without touching the disk or the statistics and put writes nothing. Read on every call so a test or a wrapper script can flip it per process.

val get_cache_dir : unit -> string

Get cache directory, creating it if needed

val untrusted_warned : bool Stdlib.Atomic.t
val warn_untrusted : ('a, Stdlib.out_channel, unit, unit, unit, unit) Stdlib.format6 -> 'a
val trusted_dir : unit -> string option

The directory entries may be read from and written to, or None when it cannot be trusted. Cached OpenCL entries are native device binaries that a driver loads, so a directory another user can write to would let them substitute code. Refused (one warning per process): no XDG_CACHE_HOME and no HOME (the only fallback is the shared temporary directory), a directory not owned by the current user, and a directory writable by group or others. A directory this module creates is mode 0o700.

val key_schema_version : string

On-disk key schema version. Bump this whenever the key inputs change so stale entries written under an older schema can never mis-hit - they simply become unreachable orphans (safe: just re-computed and rewritten under the new key). v2 adds the kernel/entry name to the digest (v1 keys omitted it, so two kernels sharing one source string collided).

val compute_key_with_options : options:(string * string) list -> dev_name:string -> driver_version:string -> name:string -> source:string -> string

Compute cache key from device, driver, kernel/entry name, and source.

name (the kernel/entry-point name) must be included: a single source string may define more than one kernel, and without the name in the key a second kernel compiled from the same source would return the first kernel's cached SPIR-V. The device identity is deliberately the device NAME + driver version (not an enumeration-order ordinal) so the key stays stable across process restarts where device enumeration order is not guaranteed.

Delegates to Compile_cache.make_key for the name/source component so this on-disk cache uses the same collision-resistant, digest-per-field join as every backend's in-memory compile cache. dev_name and driver_version are digested independently before being combined into the single device component make_key expects, so a value containing ':' in either field can never shift bytes between them (the same class of bug key_schema_version concatenation used to have). The key_schema_version prefix is preserved as an outer wrapper around the digest so schema bumps still invalidate stale on-disk entries.

This is compute_key for a backend whose binary also depends on a build-option string (OpenCL): options is forwarded to Compile_cache.make_key, so a different option set can never hit an entry built under another.

val compute_key : dev_name:string -> driver_version:string -> name:string -> source:string -> string

compute_key_with_options for a backend with no build options.

val get : key:string -> string option

Retrieve cached data by key; None when absent, when the cache is disabled (see enabled) or when its directory is not trusted (see trusted_dir).

val write_atomically : dir:string -> filename:string -> string -> unit

Write data to a fresh temporary file in dir and rename it onto filename. The temporary name is unique per call (Filename.temp_file: exclusive creation, random suffix), so concurrent writers (threads, domains or processes) never share a file; the rename is atomic on a POSIX filesystem, so a reader opening filename sees one complete entry, either the previous one or a new one.

val put : key:string -> data:string -> unit

Store data in cache with given key; see write_atomically for what a concurrent get can observe. No-op when the cache is disabled (see enabled) or its directory is not trusted (see trusted_dir).