Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file tree_intf.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447(*
* Copyright (c) 2013-2017 Thomas Gazagnaire <thomas@gazagnaire.org>
* Copyright (c) 2017 Grégoire Henry <gregoire.henry@ocamlpro.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)open!ImportmoduletypeS=sigtypekeytypesteptypemetadatatypecontentstypenodetypehash(** [Tree] provides immutable, in-memory partial mirror of the store, with
lazy reads and delayed writes.
Trees are like staging area in Git: they are immutable temporary
non-persistent areas (they disappear if the host crash), held in memory
for efficiency, where reads are done lazily and writes are done only when
needed on commit: if you modify a key twice, only the last change will be
written to the store when you commit. *)typet(** The type of trees. *)(** {1 Constructors} *)valempty:unit->t(** [empty ()] is the empty tree. The empty tree does not have associated
backend configuration values, as they can perform in-memory operation,
independently of any given backend. *)valof_contents:?metadata:metadata->contents->t(** [of_contents c] is the subtree built from the contents [c]. *)valof_node:node->t(** [of_node n] is the subtree built from the node [n]. *)typeelt=[`Nodeofnode|`Contentsofcontents*metadata](** The type for tree elements. *)valv:elt->t(** General-purpose constructor for trees. *)typekinded_hash=[`Contentsofhash*metadata|`Nodeofhash][@@derivingirmin]valpruned:kinded_hash->t(** [pruned h] is a purely in-memory tree with the hash [h]. Such trees can be
used as children of other in-memory tree nodes, for instance in order to
compute the hash of the parent, but they cannot be dereferenced.
Any operation that would require loading the contents of a pruned node
(e.g. calling {!find} on one of its children) will instead raise a
{!Pruned_hash} exception. Attempting to export a tree containing pruned
sub-trees to a repository will fail similarly. *)valkind:t->key->[`Contents|`Node]optionLwt.t(** [kind t k] is the type of [s] in [t]. It could either be a tree node or
some file contents. It is [None] if [k] is not present in [t]. *)valis_empty:t->bool(** [is_empty t] is true iff [t] is {!empty} (i.e. a tree node with no
children). Trees with {!kind} = [`Contents] are never considered empty. *)(** {1 Diffs} *)valdiff:t->t->(key*(contents*metadata)Diff.t)listLwt.t(** [diff x y] is the difference of contents between [x] and [y]. *)(** {1 Manipulating Contents} *)typeerror=[`Dangling_hashofhash|`Pruned_hashofhash](** The type for errors. *)type'aor_error=('a,error)result(** Operations on lazy nodes can fail if the underlying store does not contain
the expected hash. *)exceptionPruned_hashof{context:string;hash:hash}(** The exception raised by functions that attempt to load {!pruned} tree
nodes. *)(** Operations on lazy tree contents. *)moduleContents:sigtypet(** The type of lazy tree contents. *)valhash:?cache:bool->t->hash(** [hash t] is the hash of the {!contents} value returned when [t] is
{!force}d successfully.
{2 caching}
[cache] regulates the caching behaviour regarding the node's internal
data which are be lazily loaded from the backend.
[cache] defaults to [true] which may greatly reduce the IOs and the
runtime but may also grealy increase the memory consumption.
[cache = false] doesn't replace a call to [clear], it only prevents the
storing of new data, it doesn't discard the existing one. *)valforce:t->contentsor_errorLwt.t(** [force t] forces evaluation of the lazy content value [t], or returns an
error if no such value exists in the underlying repository. *)valforce_exn:t->contentsLwt.t(** Equivalent to {!force}, but raises an exception if the lazy content
value is not present in the underlying repository. *)valclear:t->unit(** [clear t] clears [t]'s cache. *)endvalmem:t->key->boolLwt.t(** [mem t k] is true iff [k] is associated to some contents in [t]. *)valfind_all:t->key->(contents*metadata)optionLwt.t(** [find_all t k] is [Some (b, m)] if [k] is associated to the contents [b]
and metadata [m] in [t] and [None] if [k] is not present in [t]. *)vallength:t->?cache:bool->key->intLwt.t(** [length t key] is the number of files and sub-nodes stored under [k] in
[t].
It is equivalent to [List.length (list t k)] but backends might optimise
this call: for instance it's a constant time operation in [irmin-pack].
[cache] defaults to [true], see {!caching} for an explanation of the
parameter.*)valfind:t->key->contentsoptionLwt.t(** [find] is similar to {!find_all} but it discards metadata. *)valget_all:t->key->(contents*metadata)Lwt.t(** Same as {!find_all} but raise [Invalid_arg] if [k] is not present in [t]. *)vallist:t->?offset:int->?length:int->?cache:bool->key->(step*t)listLwt.t(** [list t key] is the list of files and sub-nodes stored under [k] in [t].
The result order is not specified but is stable.
[offset] and [length] are used for pagination.
[cache] defaults to [true], see {!caching} for an explanation of the
parameter. *)valget:t->key->contentsLwt.t(** Same as {!get_all} but ignore the metadata. *)valadd:t->key->?metadata:metadata->contents->tLwt.t(** [add t k c] is the tree where the key [k] is bound to the contents [c] but
is similar to [t] for other bindings. *)valupdate:t->key->?metadata:metadata->(contentsoption->contentsoption)->tLwt.t(** [update t k f] is the tree [t'] that is the same as [t] for all keys
except [k], and whose binding for [k] is determined by [f (find t k)].
If [k] refers to an internal node of [t], [f] is called with [None] to
determine the value with which to replace it. *)valremove:t->key->tLwt.t(** [remove t k] is the tree where [k] bindings has been removed but is
similar to [t] for other bindings. *)(** {1 Manipulating Subtrees} *)valmem_tree:t->key->boolLwt.t(** [mem_tree t k] is false iff [find_tree k = None]. *)valfind_tree:t->key->toptionLwt.t(** [find_tree t k] is [Some v] if [k] is associated to [v] in [t]. It is
[None] if [k] is not present in [t]. *)valget_tree:t->key->tLwt.t(** [get_tree t k] is [v] if [k] is associated to [v] in [t]. Raise
[Invalid_arg] if [k] is not present in [t].*)valadd_tree:t->key->t->tLwt.t(** [add_tree t k v] is the tree where the key [k] is bound to the non-empty
tree [v] but is similar to [t] for other bindings.
If [v] is empty, this is equivalent to [remove t k]. *)valupdate_tree:t->key->(toption->toption)->tLwt.t(** [update_tree t k f] is the tree [t'] that is the same as [t] for all
subtrees except under [k], and whose subtree at [k] is determined by
[f (find_tree t k)].
[f] returning either [None] or [Some empty] causes the subtree at [k] to
be unbound (i.e. it is equivalent to [remove t k]). *)valmerge:tMerge.t(** [merge] is the 3-way merge function for trees. *)(** {1 Folds} *)valdestruct:t->[`Nodeofnode|`ContentsofContents.t*metadata](** General-purpose destructor for trees. *)typemarks(** The type for fold marks. *)valempty_marks:unit->marks(** [empty_marks ()] is an empty collection of marks. *)type'aforce=[`True|`Falseofkey->'a->'aLwt.t](** The type for {!fold}'s [force] parameter. [`True] forces the fold to read
the objects of the lazy nodes and contents. [`False f] is applying [f] on
every lazy node and content value instead. *)typeuniq=[`False|`True|`Marksofmarks](** The type for {!fold}'s [uniq] parameters. [`False] folds over all the
nodes. [`True] does not recurse on nodes already seen. [`Marks m] uses the
collection of marks [m] to store the cache of keys: the fold will modify
[m]. This can be used for incremental folds. *)type'anode_fn=key->steplist->'a->'aLwt.t(** The type for {!fold}'s [pre] and [post] parameters. *)typedepth=[`Eqofint|`Leofint|`Ltofint|`Geofint|`Gtofint][@@derivingirmin](** The type for fold depths.
- [Eq d] folds over nodes and contents of depth exactly [d].
- [Lt d] folds over nodes and contents of depth strictly less than [d].
- [Gt d] folds over nodes and contents of depth strictly more than [d].
[Le d] is [Eq d] and [Lt d]. [Ge d] is [Eq d] and [Gt d]. *)valfold:?order:[`Sorted|`Undefined|`RandomofRandom.State.t]->?force:'aforce->?cache:bool->?uniq:uniq->?pre:'anode_fn->?post:'anode_fn->?depth:depth->?contents:(key->contents->'a->'aLwt.t)->?node:(key->node->'a->'aLwt.t)->?tree:(key->t->'a->'aLwt.t)->t->'a->'aLwt.t(** [fold f t acc] folds [f] over [t]'s leafs.
For every node [n], ui [n] is a leaf node, call [f path n]. Otherwise:
- Call [pre path n]. By default [pre] is the identity;
- Recursively call [fold] on each children.
- Call [post path n]; By default [post] is the identity.
See {!force} for details about the [force] parameters. By default it is
[`True].
See {!uniq} for details about the [uniq] parameters. By default it is
[`False].
The fold depth is controlled by the [depth] parameter.
[cache] defaults to [false], see {!caching} for an explanation of the
parameter.
If [order] is [`Sorted] (the default), the elements are traversed in
lexicographic order of their keys. If [`Random state], they are traversed
in a random order. For large nodes, these two modes are memory-consuming,
use [`Undefined] for a more memory efficient [fold]. *)(** {1 Stats} *)typestats={nodes:int;(** Number of node. *)leafs:int;(** Number of leafs. *)skips:int;(** Number of lazy nodes. *)depth:int;(** Maximal depth. *)width:int;(** Maximal width. *)}[@@derivingirmin](** The type for tree stats. *)valstats:?force:bool->t->statsLwt.t(** [stats ~force t] are [t]'s statistics. If [force] is true, this will force
the reading of lazy nodes. By default it is [false]. *)(** {1 Concrete Trees} *)typeconcrete=[`Treeof(step*concrete)list|`Contentsofcontents*metadata][@@derivingirmin](** The type for concrete trees. *)valconcrete_t:concreteType.t(** The value-type for {!concrete}. *)valof_concrete:concrete->t(** [of_concrete c] is the subtree equivalent of the concrete tree [c].
@raise Invalid_argument
if [c] contains duplicate bindings for a given path. *)valto_concrete:t->concreteLwt.t(** [to_concrete t] is the concrete tree equivalent of the subtree [t]. *)(** {1 Proofs} *)moduleProof:sigincludeProof.Swithtypecontents:=contentsandtypehash:=hashandtypestep:=stepandtypemetadata:=metadatatypeirmin_treevalto_tree:treet->irmin_tree(** [to_tree p] is the tree [t] representing the tree proof [p]. Blinded
parts of the proof will raise [Dangling_hash] when traversed. *)endwithtypeirmin_tree:=t(** {1 Caches} *)valclear:?depth:int->t->unit(** [clear ?depth t] clears all caches in the tree [t] for subtrees with a
depth higher than [depth]. If [depth] is not set, all of the subtrees are
cleared.
A call to [clear] doesn't discard the subtrees of [t], only their cache
are discarded. Even the lazily loaded and unmodified subtrees remain. *)(** {1 Performance counters} *)typecounters={mutablecontents_hash:int;mutablecontents_find:int;mutablecontents_add:int;mutablenode_hash:int;mutablenode_mem:int;mutablenode_add:int;mutablenode_find:int;mutablenode_val_v:int;mutablenode_val_find:int;mutablenode_val_list:int;}valcounters:unit->countersvaldump_counters:unitFmt.tvalreset_counters:unit->unitvalinspect:t->[`Contents|`Nodeof[`Map|`Hash|`Value|`Pruned]](** / *)(** Internals Useful for testing purposes only. *)moduleEnv:sigtypet[@@derivingirmin]valis_empty:t->boolendvalget_env:t->Env.tendmoduletypeTree=sigmoduletypeS=sigincludeS(** @inline *)endmoduleMake(P:Private.S):sigincludeSwithtypekey=P.Node.Path.tandtypestep=P.Node.Path.stepandtypemetadata=P.Node.Metadata.tandtypecontents=P.Contents.valueandtypehash=P.Hash.ttypekinded_hash:=[`Contentsofhash*metadata|`Nodeofhash]valimport:P.Repo.t->kinded_hash->toptionLwt.tvalimport_no_check:P.Repo.t->kinded_hash->tvalexport:?clear:bool->P.Repo.t->[>write]P.Contents.t->[>read_write]P.Node.t->node->P.Node.keyLwt.tvaldump:tFmt.tvalequal:t->t->boolvalnode_t:nodeType.tvaltree_t:tType.tvalhash:?cache:bool->t->kinded_hashvalof_private_node:P.Repo.t->P.Node.value->nodevalto_private_node:node->P.Node.valueor_errorLwt.ttype('proof,'result)producer:=P.Repo.t->kinded_hash->(t->(t*'result)Lwt.t)->('proof*'result)Lwt.ttype('proof,'result)verifier:='proof->(t->(t*'result)Lwt.t)->(t*'result,[`Msgofstring])resultLwt.ttypetree_proof:=Proof.treeProof.tvalproduce_proof:(tree_proof,'a)producervalverify_proof:(tree_proof,'a)verifiertypestream_proof:=Proof.streamProof.tvalproduce_stream:(stream_proof,'a)producervalverify_stream:(stream_proof,'a)verifierendend