forked from
gazagnaire.org/irmin
Persistent store with Git semantics: lazy reads, delayed writes, content-addressing
1(** Storage backends for Irmin.
2
3 Backends are records of functions, NOT functors. This makes them composable
4 and easy to create without functor application. *)
5
6(** {1 Backend Interface} *)
7
8type 'hash t = {
9 read : 'hash -> string option;
10 (** [read hash] retrieves the object with the given hash. *)
11 write : 'hash -> string -> unit;
12 (** [write hash data] stores [data] at [hash]. Caller computes the hash.
13 *)
14 exists : 'hash -> bool; (** [exists hash] checks if an object exists. *)
15 get_ref : string -> 'hash option;
16 (** [get_ref name] reads a reference (branch/tag). *)
17 set_ref : string -> 'hash -> unit;
18 (** [set_ref name hash] sets a reference. *)
19 test_and_set_ref : string -> test:'hash option -> set:'hash option -> bool;
20 (** [test_and_set_ref name ~test ~set] atomically updates a reference if
21 its current value matches [test]. *)
22 list_refs : unit -> string list;
23 (** [list_refs ()] returns all reference names. *)
24 write_batch : ('hash * string) list -> unit;
25 (** [write_batch [(h1, d1); ...]] writes multiple objects efficiently. *)
26 flush : unit -> unit; (** [flush ()] ensures all writes are persisted. *)
27 close : unit -> unit; (** [close ()] releases resources. *)
28}
29
30(** {1 Memory Backend} *)
31
32module Memory : sig
33 val create_with_hash : ('h -> string) -> ('h -> 'h -> bool) -> 'h t
34 (** [create_with_hash to_hex equal] creates an in-memory backend. Caller
35 computes hashes; backend just stores (hash, data) pairs. *)
36
37 val create_sha1 : unit -> Hash.sha1 t
38 (** Create an in-memory SHA-1 backend. *)
39
40 val create_sha256 : unit -> Hash.sha256 t
41 (** Create an in-memory SHA-256 backend. *)
42end
43
44(** {1 Backend Combinators} *)
45
46val cached : ?capacity:int -> 'h t -> 'h t
47(** [cached ?capacity backend] wraps a backend with an LRU cache (default:
48 100 000 entries). Reads are served from cache when possible, and writes
49 populate the cache. *)
50
51val readonly : 'h t -> 'h t
52(** [readonly backend] makes a backend read-only. Write operations raise
53 [Invalid_argument]. *)
54
55val layered : upper:'h t -> lower:'h t -> 'h t
56(** [layered ~upper ~lower] creates a layered backend. Reads check upper first,
57 then lower. Writes go to upper only. Used for garbage collection
58 (upper=live, lower=frozen). *)
59
60(** {1 Disk Backend} *)
61
62module Disk : sig
63 val create_with_hash :
64 sw:Eio.Switch.t ->
65 Eio.Fs.dir_ty Eio.Path.t ->
66 ('h -> string) ->
67 (string -> ('h, [ `Msg of string ]) result) ->
68 ('h -> 'h -> bool) ->
69 'h t
70 (** [create_with_hash ~sw root to_hex of_hex equal] creates a disk-based
71 backend at [root]. Uses append-only storage for objects with an index file
72 for lookups.
73
74 Storage layout:
75 - objects.data: append-only file containing all objects
76 - objects.idx: index mapping hex hash to (offset, length)
77 - refs/: directory with one file per ref *)
78
79 val create_sha1 : sw:Eio.Switch.t -> Eio.Fs.dir_ty Eio.Path.t -> Hash.sha1 t
80 (** Create a disk-based SHA-1 backend. *)
81
82 val create_sha256 :
83 sw:Eio.Switch.t -> Eio.Fs.dir_ty Eio.Path.t -> Hash.sha256 t
84 (** Create a disk-based SHA-256 backend. *)
85end
86
87(** {1 Statistics} *)
88
89type stats = { reads : int; writes : int; cache_hits : int; cache_misses : int }
90
91val stats : _ t -> stats option
92(** [stats backend] returns statistics if the backend tracks them. *)