wasm_file_cache (wasm v0.3.0)

View Source

A directory of files, bounded by total size, oldest first.

The policy behind both on-disk caches this runtime keeps: generated code in wasm_code_cache and snapshot images in wasm_snapshot_store. It was written once for the first and copied nowhere, which left the second growing without bound; it lives here now so there is one copy and one set of cases.

Plain module code, called from whichever process is storing. No server, no lock, no timer. Eviction happens on a store and nowhere else: a directory only grows when something is written to it, so that is the only moment it can need shrinking. A node that stores nothing never evicts, and a directory already over its cap stays over it until the next store.

What "oldest" means

Least recently used, not least recently written, because a reader calls touch/1 on a hit. That is the only thing separating the two, and it is worth knowing that without it eviction still looks correct: it stays under the cap, it just throws away the entries being used.

What it does when something goes wrong

Nothing raises and nothing is reported. An unreadable directory answers no entries and so evicts nothing. A failed delete is ignored, and drop/3 subtracts the size it expected to free either way, so a file that will not go cannot make the loop spin. Two processes evicting at once both enumerate, both delete, and the second delete fails with enoent: the result is over-eviction rather than corruption, and over-eviction costs a recompile or a recapture.

Summary

Functions

Every entry, oldest not first. [] for a directory that cannot be read.

Remove every entry and every temporary. For tests, and for a clean start.

Sweep stale temporaries, then drop oldest entries until the total fits.

Note that an entry was used, so eviction can tell which ones are.

Functions

entries(Dir, Suffix)

-spec entries(file:filename(), string()) -> [file:filename()].

Every entry, oldest not first. [] for a directory that cannot be read.

purge(Dir, Suffix)

-spec purge(file:filename(), string()) -> ok.

Remove every entry and every temporary. For tests, and for a clean start.

sweep_and_evict(Dir, Suffix, Max, Keep)

-spec sweep_and_evict(file:filename(), string(), non_neg_integer(), file:filename() | undefined) -> ok.

Sweep stale temporaries, then drop oldest entries until the total fits.

Suffix selects the entries, ".img" or ".beam". Temporaries are always *.tmp, are swept by age, and are counted as neither entries nor bytes.

Keep is a path that must not be dropped whatever its age, which a caller passes for the entry it has just written. Without it a store larger than the whole cap writes a file and immediately deletes it, and the caller is left believing it filed something.

touch(Path)

-spec touch(file:filename()) -> ok.

Note that an entry was used, so eviction can tell which ones are.

The result is dropped: a read-only directory degrades to least-recently-written rather than failing a lookup that otherwise worked.