Module B00.File_cache
File caches.
A file cache maps a key to a metadata hunk and an ordered list of file contents (filenames are irrelevant).
B0
uses file caches to capture the contents of files written by build operations, it also stores their exit code and standard outputs in the metadata. This allows to recreate the effect of a build operation without having to rerun it.
FIXME. The following notions use the file system information and can be inaccurate. It's a bit unclear whether it's a good idea to rely on them. They are only used for cache trimming.
- The access time of a key is the greatest access time to the file contents or metadata hunk it maps to.
- A key is unused if all its file contents are not referenced outside the cache. Key usage cannot be determined if the key file contents and their references do not live on the same file system device or if the file system does not support hard links, see
need_copy
. FIXME. Now that we allow keys to map to empty list of file contents, unused might not make much sense for trimming. Maybe refine the notion to unused content.
File caches
type feedback
=[
|
`File_cache_need_copy of B0_std.Fpath.t
]
The type for file cache feedback. See
create
.
val pp_feedback : feedback B0_std.Fmt.t
pp_feedback
formats file caches feedback.
type key
= string
The type for keys. A key maps to a metadata hunk and an ordered list of file contents. The module treats keys as sequence of bytes however since they are used as file names they should satisfy the
B0_std.Fpath.is_seg
predicate; this is not checked by the module.
val create : ?feedback:(feedback -> unit) -> B0_std.Fpath.t -> (t, string) Stdlib.result
create ~feedback dir
is a file cache using directorydir
for data storage. The full path todir
is created by the call if it doesn't exist.feedback
is invoked once if the cache switches to copying mode, seeneed_copy
for details (defaults is a nop).
val dir : t -> B0_std.Fpath.t
dir c
isc
's storage directory.
val need_copy : t -> B0_std.Fpath.t option
need_copy c
isSome file
iff the cache switched to copying mode because of an operation that involved the file pathfile
, external to the cache. This can happen due to one of the following conditions:- The cache directory
dir
andfile
live on different file system devices. - The underlying file system does not support hard links.
- Too many hard links exist on a file.
file
is also given to thenotify_need_copy
callback provided oncreate
as soon as the condition is detected (and before the actual copy occurs). Note that once a file did copy, all the remaining transfers from or to the cache do copy aswell, which may be slow.- The cache directory
Cache operations
Note. In general, whenever a cache operation modifies the file system and errors with Error _
the resulting file system state is undefined.
val add : t -> key -> string -> B0_std.Fpath.t list -> (bool, string) Stdlib.result
add c k m fs
, binds the metadatam
and the contents of the ordered list of filesfs
tok
inc
. The function returns:Ok true
if the operation succeeds.Ok false
if a file offs
could not be accessed. In this casek
is guaranteed to be unbound inc
.Error _
if an unexpected error occurs. In that case the resulting state of the cache for keyk
is undefined.
val rem : t -> key -> (bool, string) Stdlib.result
rem c k
removes the binding ofk
inc
.Ok true
is returned ifk
was bound inc
andOk false
otherwise.
val find : t -> key -> ((B0_std.Fpath.t * B0_std.Fpath.t list) option, string) Stdlib.result
find c k
isSome (mf, fs)
ifk
is bound inc
withmf
the file that holds the key metadata andfs
the files that hold the file contents of the key in the order given onadd
. The result isNone
ifk
is unbound inc
.
val revive : t -> key -> B0_std.Fpath.t list -> ((string * B0_std.Fpath.t list) option, string) Stdlib.result
revive c k fs
binds the file contents of keyk
to the inexistent file paths (directories are created) offs
. The function returns:Ok (Some (m, existed)
in case of success, withm
the metadata of the key andexisted
the files that already existed and were left untouched by the operation. Assuming no other process fiddles withfs
all these file paths now exist (but those ofexisted
might differ from the corresponding one in the cache).Ok None
if the length offs
does not match the sequence of files ofk
or ifk
is unbound inc
. In this case the file pathsfs
are left untouched.Error _
if an unexpected error occurs. In that case the resulting state of the file system for pathsfs
is undefined.
val fold : t -> (key -> B0_std.Fpath.t -> B0_std.Fpath.t list -> 'a -> 'a) -> 'a -> ('a, string) Stdlib.result
fold c f acc
foldsf
over the contents of each key ofc
starting withacc
.
val keys : t -> (key list, string) Stdlib.result
keys c
are the keys of cachec
.
val is_unused : t -> key -> (bool, string) Stdlib.result
is_unused c k
istrue
iffk
is bound inc
and its content is being unused. Warning For caches which are referenced across file system device or on file systems that do not support hard links this may returntrue
even though the key is actually in use.
val delete_unused : t -> (unit, string) Stdlib.result
delete_unused c
deletes unused keys ofc
.
val trim_size : t -> max_byte_size:int -> pct:int -> (unit, string) Stdlib.result
trim_size c max_byte_size ~pct
delete keys ofc
until they either weight at mostmax_byte_size
or arepct
of their current size; whichever is the smaller. The function deletes by order of increasing access time but unused keys are deleted first.
Cache statistics
module Stats : sig ... end
Cache statistics.