Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file store_intf.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384(*
* Copyright (c) 2018-2022 Tarides <contact@tarides.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!Import(** [Irmin-pack-unix]-specific extensions to the [Store] module type. *)moduletypeS=sig(** An [irmin-pack-unix] store. This provides the common {!Irmin} interface
with [irmin-pack-unix] specific extensions. *)includeIrmin.Generic_key.S(** @inline *)(** {1 Integrity Check} *)valintegrity_check:?ppf:Format.formatter->?heads:commitlist->auto_repair:bool->repo->([>`Fixedofint|`No_error],[>`Cannot_fixofstring|`Corruptedofint])resultLwt.t(** Checks the integrity of the repository. if [auto_repair] is [true], will
also try to fix the issues. [ppf] is a formatter for progressive
reporting. [`Fixed] and [`Corrupted] report the number of fixed/corrupted
entries. *)valintegrity_check_inodes:?heads:commitlist->repo->([>`No_error],[>`Cannot_fixofstring])resultLwt.tvaltraverse_pack_file:[`Reconstruct_indexof[`In_place|`Outputofstring]|`Check_index|`Check_and_fix_index]->Irmin.config->unitvaltest_traverse_pack_file:[`Reconstruct_indexof[`In_place|`Outputofstring]|`Check_index|`Check_and_fix_index]->Irmin.config->unit(** {1 Chunking} *)valsplit:repo->unit(** [split t] starts a fresh chunk file for appending data. Only allowed on
stores that allow gc.
Raises [RO_Not_Allowed] if called by a readonly instance.
Raises [Split_forbidden_during_batch] if called inside a batch operation.
Raises [Multiple_empty_chunks] if no data was added to the currently-used
chunk file.
Raises [Split_disallowed] if {!is_split_allowed} is false.
TODO: Detail exceptions raised. *)valis_split_allowed:repo->bool(** [is_split_allowed repo] returns if split is supported. Currently returns
the same value as {!Gc.is_allowed}. *)(** {1 Lower layer} *)valadd_volume:repo->unit(** [add_volume t] creates a new empty volume in the lower layer.
Raises [RO_Not_Allowed] if called by a readonly instance.
Raises [Add_volume_forbidden_during_gc] if called while a GC is running.
Raises [Multiple_empty_volumes] if there is already an empty volume. *)(** {1 On-disk} *)valreload:repo->unit(** [reload t] reloads a readonly pack with the files on disk. Raises
[invalid_argument] if called by a read-write pack.*)valflush:repo->unit(** [flush t] flush read-write pack on disk. Raises [RO_Not_Allowed] if called
by a readonly instance.*)valcreate_one_commit_store:repo->commit_key->string->unitLwt.t(** [create_one_commit_store t key path] creates a new store at [path] from
the existing one, containing only one commit, specified by the [key]. Note
that this operation is blocking.
It requires that the files existing on disk when the operation is
launched, remain on disk until the operation completes. In particular, a
Gc running in a different process could remove files from disk. *)(** {1 Garbage Collection} *)moduleGc:sigtypeprocess_state=[`Idle|`Running|`FinalisedofStats.Latest_gc.stats](** The state of the GC process after calling {!finalise_exn} *)(** {1 Low-level API} *)valstart_exn:?unlink:bool->repo->commit_key->boolLwt.t(** [start_exn] tries to start the GC process and returns true if the GC is
launched. If a GC is already running, a new one is not started.
The GC process will not be automatically finalised. The caller is
responsible for calling {!finalise_exn}.
If [unlink] is false then temporary files and files from the previous
generation will be kept on disk after the GC finished. This option is
useful for debugging. The default is [true].
TODO: Detail exceptions raised. *)valfinalise_exn:?wait:bool->repo->process_stateLwt.t(** [finalise_exn ?wait repo] waits for the GC process to finish in order to
finalise it. It returns the state of the GC process from the point of
view of the function call; subsequent calls of [finalise_exn] after a
return of [`Finalised] will return [`Idle].
Finalising consists of mutating [repo] so that it points to the new file
and to flush the internal caches that could be referencing GCed objects.
What is done with the discarded data depends on {!behaviour}.
If [wait = true] (the default), the call blocks until the GC process
finishes. If [wait = false], finalisation will occur if the process has
ended.
If there are no running GCs, the call is a no-op and it returns [`Idle].
TODO: Detail exceptions raised. *)(** {1 High-level API} *)typemsg=[`Msgofstring](** Pretty-print error messages meant for informational purposes, like
logging *)valrun:?finished:((Stats.Latest_gc.stats,msg)result->unitLwt.t)->repo->commit_key->(bool,msg)resultLwt.t(** [run repo commit_key] attempts to start a GC process for a [repo] by
discarding or archiving all data prior to [commit_key] (depending on
{!behaviour}. If a GC process is already running, a new one will not be
started.
[run] will also finalise the GC process automatically. For more detailed
control, see {!start_exn} and {!finalise_exn}.
When the GC process is finalised, [finished] is called with the result
of finalisation.
To monitor progress of GC, see {!wait} or {!is_finished}.
Returns whether a GC process successfully started or not.
All exceptions that [Irmin_pack] knows how to handle are caught and
returned as pretty-print error messages; others are re-raised. The error
messages should be used only for informational purposes, like logging. *)valwait:repo->(Stats.Latest_gc.statsoption,msg)resultLwt.t(** [wait repo] blocks until GC is finished or is idle.
If a GC finalises, its stats are returned.
All exceptions that [Irmin_pack] knows how to handle are caught and
returned as pretty-print error messages; others are re-raised. The error
messages should be used only for informational purposes, like logging. *)valcancel:repo->bool(** [cancel repo] aborts the current GC and returns [true], or returns
[false] if no GC was running. *)valis_finished:repo->bool(** [is_finished repo] is [true] if a GC is finished (or idle) and [false]
if a GC is running for the given [repo]. *)valbehaviour:repo->[`Archive|`Delete](** [behaviour repo] returns the behaviour that the GC will have during
finalization.
This depends on the presence of a lower layer in the store: if a lower
layer is present, the GC will archive old data into that lower layer.
Else, it will delete that data. *)valis_allowed:repo->bool(** [is_allowed repo] returns true if a gc can be run on the store. *)vallatest_gc_target:repo->commit_keyoption(** [latest_gc_target] returns the commit key on which the latest, finished
gc was called on. *)end(** {1 Snapshots} *)moduleSnapshot:sigtypekinded_hash=Contentsofhash*metadata|Nodeofhash[@@derivingirmin]typeentry={step:string;hash:kinded_hash}[@@derivingirmin]typeinode_tree={depth:int;length:int;pointers:(int*hash)list;}[@@derivingirmin]typev=Inode_treeofinode_tree|Inode_valueofentrylist[@@derivingirmin]typeinode={v:v;root:bool}[@@derivingirmin]typet=Inodeofinode|BlobofBackend.Contents.Val.t[@@derivingirmin]valexport:?on_disk:[`Pathofstring]->repo->(t->unitLwt.t)->root_key:Tree.kinded_key->intLwt.t(** [export ?on_disk repo f ~root_key] applies [f] to all inodes and
contents in a rooted tree, with root specified by [root_key].
The traversal requires an index to keep track of visited elements.
- if [on_disk] is not specified, the index is in memory.
- if [on_disk] is [`Path path], a temporary index is created at path.
The traversal order is stable. In [Inode_tree], it is lexicographic on
the [index] function (see {!Conf.inode_child_order}). In [Inode_value],
it is lexicographic on the steps.
[f] is called in post-order, that is [f] is first called on the leaves,
and the last call to [f] is on the root designated by [root_key].
The traversal skips objects that are structurally equal to objects that
were already traversed. In other words, [export] internally uses a hash
set in order to guarantee that all the objects passed to [f] don't hash
the same way.
Returns the total number of elements visited. *)moduleImport:sigtypeprocessvalv:?on_disk:[`Pathofstring|`Reuse]->repo->process(** [v ?on_disk repo] create a [snaphot] instance. The traversal requires
an index to keep track of visited elements.
- if [on_disk] is not specified, the index is in memory.
- if [on_disk] is [`Path path], a temporary index is created at path.
- if [on_disk] is [`Reuse] the store's index is reused. *)valsave_elt:process->t->node_keyLwt.t(** [save_elt snapshot elt] saves [elt] to the store. *)valclose:process->repo->unit(** [close snapshot] close the [snaphot] instance.*)endend(** {1 Statistics} *)valstats:dump_blob_paths_to:stringoption->commit:commit->repo->unitLwt.t(** {1 Internals} *)moduleInternal:sig(** Unstable internal API agnostic about the underlying storage. Use it only
to implement or test inodes. *)moduleIo=Io.UnixmoduleErrs:Io_errors.SwithmoduleIo=IomoduleIndex:Pack_index.Swithtypekey=hashmoduleFile_manager:File_manager.SwithmoduleIo=IoandmoduleErrs=ErrsandmoduleIndex=Indexvalfile_manager:repo->File_manager.tmoduleDict:Dict.Svaldict:repo->Dict.tmoduleDispatcher:Dispatcher.Svaldispatcher:repo->Dispatcher.tmoduleXKey:Pack_key.Swithtypehash=Schema.Hash.tvalsuffix_commit_mem:repo->XKey.t->boolvalsuffix_node_mem:repo->XKey.t->boolvalsuffix_contents_mem:repo->XKey.t->boolvalkill_gc:repo->boolendendmoduleS_is_a_store(X:S):Irmin.Generic_key.S=XmoduletypeMaker=sigtypeendpoint=unitincludeIrmin.Key.Store_spec.SmoduleMake(Schema:Irmin.Schema.Extended):S(* We can't have `with module Schema = Schema` here, since the Schema
on the RHS contains more information than the one on the LHS. We _want_
to do something like `with module Schema = (Schema : Irmin.Schema.S)`,
but this isn't supported.
TODO: extract these extensions as a separate functor argument instead. *)withtypeSchema.Hash.t=Schema.Hash.tandtypeSchema.Branch.t=Schema.Branch.tandtypeSchema.Metadata.t=Schema.Metadata.tandtypeSchema.Path.t=Schema.Path.tandtypeSchema.Path.step=Schema.Path.stepandtypeSchema.Contents.t=Schema.Contents.tandtypeSchema.Info.t=Schema.Info.tandtypecontents_key=(Schema.Hash.t,Schema.Contents.t)contents_keyandtypenode_key=Schema.Hash.tnode_keyandtypecommit_key=Schema.Hash.tcommit_keyandtypeBackend.Remote.endpoint=endpointendwithtype('h,_)contents_key='hPack_key.tandtype'hnode_key='hPack_key.tandtype'hcommit_key='hPack_key.tmoduletypeKV=sigtypeendpoint=unittypehash=Irmin.Schema.default_hashincludePack_key.Store_spectypemetadata=Irmin.Metadata.None.tmoduleMake(C:Irmin.Contents.S):SwithmoduleSchema.Contents=CandtypeSchema.Metadata.t=metadataandtypeBackend.Remote.endpoint=endpointandtypeSchema.Hash.t=hashandtypecontents_key=(hash,C.t)contents_keyandtypenode_key=hashnode_keyandtypecommit_key=hashcommit_keyandtypeSchema.Path.step=stringandtypeSchema.Path.t=stringlistandtypeSchema.Branch.t=stringendmoduletypeSigs=sigmoduletypeS=SmoduletypeMaker=MakermoduletypeKV=KVend