Skip to main content

Crate gsym_cache

Crate gsym_cache 

Source
Expand description

Concurrent, process-safe storage for immutable [LLVM GSYM] files.

gsym-cache separates the profiler’s read path from the machinery that creates and maintains cached files. A lookup takes no lock and performs no write. Optional features add debounced recency markers, nonblocking population ownership, verified atomic publication, negative caching, and bounded maintenance.

Conversion, downloads, worker scheduling, and resource limits remain with the application.

§Quick start

Open a cache without creating it, then look up a binary build identifier:

use gsym_cache::{BuildId, Cache, CacheEpoch};

let cache = Cache::open("/var/cache/my-profiler/gsym", CacheEpoch::new(1))?;
let build_id: BuildId = "1212121212121212121212121212121212121212".parse()?;
if let Some(entry) = cache.lookup(&build_id)? {
    println!("cached GSYM: {} bytes", entry.len());
}

Population is an explicit, nonblocking state machine:

use std::fs::File;
use std::io;
use gsym_cache::{BuildId, Cache, CacheEpoch, PopulationOutcome};

let cache = Cache::open("/var/cache/my-profiler/gsym", CacheEpoch::new(1))?;
let build_id = BuildId::new([0x12; 20])?;

match cache.try_begin_population(&build_id)? {
    PopulationOutcome::Present(entry) => drop(entry),
    PopulationOutcome::Acquired(population) => {
        let mut source = File::open("artifact.gsym")?;
        let mut writer = population.into_writer()?;
        io::copy(&mut source, &mut writer)?;
        drop(writer.publish()?.into_entry());
    }
    PopulationOutcome::Suppressed(failure) => {
        eprintln!("retry after {:?}", failure.expires_at());
    }
    PopulationOutcome::Busy => eprintln!("another process owns population"),
}

§Choosing an entry point

To …UseNotes
use an explicit cache rootCache::opensuitable for services and privileged applications
follow the XDG cache conventionCache::open_xdgvalidates the cache home and application component
read an immutable entryCache::lookuplock-free and deliberately does not decode GSYM
record coarse recencyCache::record_accessaccess feature; call only after a hit
coordinate a cache missCache::try_begin_populationmanage feature; never waits
enforce capacity or age limitsCache::prunemanage feature; uses 80% low-watermark hysteresis
verify and repair stored stateCache::scrubmanage feature; checks complete GSYM files

§Usage notes

  • A BuildId is an opaque cache key, not proof that input is trustworthy. Keep one private root per trust domain and isolate converters that consume untrusted binaries.

  • CacheEpoch versions the application’s conversion policy. Increment it when the same build ID could produce different bytes. Old epochs are separate namespaces and can be removed after their workers stop.

  • Cache::lookup verifies ownership and file type, but not GSYM contents. Managed publication and scrubbing perform complete GSYM verification so the profiler-facing path stays small.

  • Directory descriptors are pinned after they are opened. Create a new Cache after replacing a cache namespace directory.

  • Durability and no-clobber behavior assume a private cache root on a local Linux filesystem with advisory flock, atomic rename, and directory fsync semantics.

§Feature flags

FeatureDefaultAdds
lookupyesbuild IDs, cache opening, and lock-free lookup
accessnodebounced access markers; implies lookup
managenopopulation, negative caching, pruning, and scrubbing; implies access

Read-only use needs only the default feature:

[dependencies]
gsym-cache = "0.1"

§Errors

Fallible entry points return Result<T>. Error distinguishes I/O, unsafe directory or entry layouts, invalid GSYM, build-ID mismatch, and invalid negative-cache lifetimes. It is #[non_exhaustive], so exhaustive matches need a fallback arm.

Cache misses, active population, and active maintenance are ordinary outcomes, not errors.

§Guides

Modules§

docs
Deployment and operations guides.

Structs§

BuildId
A validated, owned binary build identifier.
BuildIdMismatchError
GSYM build-identifier mismatch with bounded diagnostic data.
ByteLimit
Nonzero cache-size limit in bytes.
Cache
A configured GSYM filesystem cache.
CacheEntry
An opened, immutable cache entry.
CacheEpoch
Version of the conversion policy used to create cached GSYM files.
CacheStats
Current size of the recognized object tree.
CachedFailure
An unexpired persistent population failure.
EntryLimit
Nonzero cache-entry limit.
InvalidGsymError
Invalid GSYM file with its cache path.
Population
Exclusive population capability for one build identifier.
PopulationWriter
Exclusive write-only owner of a staged GSYM file.
PrunePolicy
Size, count, and age policy for cache pruning.
PruneReport
Measurements from a completed prune pass.
ScrubReport
Measurements from a completed scrub pass.

Enums§

AccessUpdate
Whether access-marker write traffic was required.
BuildIdError
Build identifier validation error.
Error
Cache operation failure.
FailureKind
Stable class of a population failure.
PopulationOutcome
Outcome of trying to acquire population ownership.
PruneOutcome
Outcome of nonblocking cache pruning.
PublishOutcome
Result of publishing a verified staged file.
ScrubOutcome
Outcome of nonblocking cache scrubbing.

Constants§

MAX_FAILURE_TTL
Longest accepted negative-cache lifetime.

Type Aliases§

Result
Result type used by this crate.