From 1715a7bc9ad990910f767a6714ab10821075bacf Mon Sep 17 00:00:00 2001 From: Craig Ferguson Date: Wed, 8 Dec 2021 19:04:37 +0000 Subject: [PATCH 1/3] irmin-pack: add support for user-defined indexing strategies Now that internal references between pack entries can be resolved without use of the index, it is no longer necessary to index every object for correctness of the store. The index is now used to de-duplicate exported (concrete) values, which impacts only the size of the store and not its consistency. This commit allows the user to define their own indexing strategy, with two pre-provided strategies: - `always`: equivalent to the old behaviour; - `minimal`: index only the objects that are necessary for store correctness (currently just commit objects). The `irmin-pack` test suite is now run twice, once for each of these pre-provided strategies. --- src/irmin-pack/conf.ml | 17 +++++++- src/irmin-pack/conf.mli | 9 +++- src/irmin-pack/ext.ml | 25 +++++++---- src/irmin-pack/inode_intf.ml | 1 + src/irmin-pack/irmin_pack_intf.ml | 1 + src/irmin-pack/pack_store.ml | 69 +++++++++++++++++++++++++------ src/irmin-pack/pack_store_intf.ml | 39 ++++++++++++++--- test/irmin-pack/common.ml | 9 ++-- test/irmin-pack/test_inode.ml | 9 ++-- test/irmin-pack/test_pack.ml | 24 ++++++++--- 10 files changed, 161 insertions(+), 42 deletions(-) diff --git a/src/irmin-pack/conf.ml b/src/irmin-pack/conf.ml index aa42fda713..8bfddf7ab3 100644 --- a/src/irmin-pack/conf.ml +++ b/src/irmin-pack/conf.ml @@ -29,6 +29,7 @@ module Default = struct let readonly = false let merge_throttle = `Block_writes let freeze_throttle = `Block_writes + let indexing_strategy = Pack_store.Indexing_strategy.always end open Irmin.Backend.Conf @@ -67,6 +68,17 @@ module Key = struct freeze_throttle_t Default.freeze_throttle let root = root spec + + let indexing_strategy = + let serialisable_t = [%typ: [ `Always | `Minimal ]] in + key ~spec ~doc:"Strategy to use for adding objects to the index" + "indexing-strategy" + (Irmin.Type.map serialisable_t + (function + | `Always -> Pack_store.Indexing_strategy.always + | `Minimal -> Pack_store.Indexing_strategy.minimal) + (fun _ -> Fmt.failwith "Can't serialise indexing strategy")) + Default.indexing_strategy end let fresh config = get config Key.fresh @@ -76,11 +88,13 @@ let index_log_size config = get config Key.index_log_size let merge_throttle config = get config Key.merge_throttle let freeze_throttle config = get config Key.freeze_throttle let root config = get config Key.root +let indexing_strategy config = get config Key.indexing_strategy let init ?(fresh = Default.fresh) ?(readonly = Default.readonly) ?(lru_size = Default.lru_size) ?(index_log_size = Default.index_log_size) ?(merge_throttle = Default.merge_throttle) - ?(freeze_throttle = Default.freeze_throttle) root = + ?(freeze_throttle = Default.freeze_throttle) + ?(indexing_strategy = Default.indexing_strategy) root = let config = empty spec in let config = add config Key.root root in let config = add config Key.fresh fresh in @@ -89,4 +103,5 @@ let init ?(fresh = Default.fresh) ?(readonly = Default.readonly) let config = add config Key.readonly readonly in let config = add config Key.merge_throttle merge_throttle in let config = add config Key.freeze_throttle freeze_throttle in + let config = add config Key.indexing_strategy indexing_strategy in verify config diff --git a/src/irmin-pack/conf.mli b/src/irmin-pack/conf.mli index 005dda45bc..3417636178 100644 --- a/src/irmin-pack/conf.mli +++ b/src/irmin-pack/conf.mli @@ -27,7 +27,11 @@ module type S = sig - [Some `Varint]: the length header is a LEB128-encoded integer at the very beginning of the encoded value. - - [None]: there is no length header, and values have unknown size. *) + - [None]: there is no length header, and values have unknown size. NOTE: + when using [irmin-pack] in this mode, the selected indexing strategy + {i must} index all contents values (as recovering contents values from + the store will require referring to the index for their length + information). *) end val spec : Irmin.Backend.Conf.Spec.t @@ -43,6 +47,7 @@ module Key : sig val root : string Irmin.Backend.Conf.key val merge_throttle : merge_throttle Irmin.Backend.Conf.key val freeze_throttle : freeze_throttle Irmin.Backend.Conf.key + val indexing_strategy : Pack_store.Indexing_strategy.t Irmin.Backend.Conf.key end val fresh : Irmin.Backend.Conf.t -> bool @@ -52,6 +57,7 @@ val readonly : Irmin.Backend.Conf.t -> bool val merge_throttle : Irmin.Backend.Conf.t -> merge_throttle val freeze_throttle : Irmin.Backend.Conf.t -> freeze_throttle val root : Irmin.Backend.Conf.t -> string +val indexing_strategy : Irmin.Backend.Conf.t -> Pack_store.Indexing_strategy.t val init : ?fresh:bool -> @@ -60,5 +66,6 @@ val init : ?index_log_size:int -> ?merge_throttle:merge_throttle -> ?freeze_throttle:freeze_throttle -> + ?indexing_strategy:Pack_store.Indexing_strategy.t -> string -> Irmin.config diff --git a/src/irmin-pack/ext.ml b/src/irmin-pack/ext.ml index 27396602ed..3b37a48b79 100644 --- a/src/irmin-pack/ext.ml +++ b/src/irmin-pack/ext.ml @@ -136,12 +136,13 @@ module Maker (Config : Conf.S) = struct f contents node commit))) let unsafe_v config = - let root = Conf.root config in - let fresh = Conf.fresh config in - let lru_size = Conf.lru_size config in - let readonly = Conf.readonly config in - let log_size = Conf.index_log_size config in - let throttle = Conf.merge_throttle config in + let root = Conf.root config + and fresh = Conf.fresh config + and lru_size = Conf.lru_size config + and readonly = Conf.readonly config + and log_size = Conf.index_log_size config + and throttle = Conf.merge_throttle config + and indexing_strategy = Conf.indexing_strategy config in let f = ref (fun () -> ()) in let index = Index.v @@ -150,10 +151,16 @@ module Maker (Config : Conf.S) = struct ~fresh ~readonly ~throttle ~log_size root in let* contents = - Contents.CA.v ~fresh ~readonly ~lru_size ~index root + Contents.CA.v ~fresh ~readonly ~lru_size ~index ~indexing_strategy + root + in + let* node = + Node.CA.v ~fresh ~readonly ~lru_size ~index ~indexing_strategy root + in + let* commit = + Commit.CA.v ~fresh ~readonly ~lru_size ~index ~indexing_strategy + root in - let* node = Node.CA.v ~fresh ~readonly ~lru_size ~index root in - let* commit = Commit.CA.v ~fresh ~readonly ~lru_size ~index root in let+ branch = Branch.v ~fresh ~readonly root in (* Stores share instances in memory, one flush is enough. In case of a system crash, the flush_callback might not make with the disk. In diff --git a/src/irmin-pack/inode_intf.ml b/src/irmin-pack/inode_intf.ml index a040e402cc..7e86d3d0c5 100644 --- a/src/irmin-pack/inode_intf.ml +++ b/src/irmin-pack/inode_intf.ml @@ -64,6 +64,7 @@ module type Persistent = sig ?readonly:bool -> ?lru_size:int -> index:index -> + indexing_strategy:Pack_store.Indexing_strategy.t -> string -> read t Lwt.t diff --git a/src/irmin-pack/irmin_pack_intf.ml b/src/irmin-pack/irmin_pack_intf.ml index ae7856f157..78167a65cb 100644 --- a/src/irmin-pack/irmin_pack_intf.ml +++ b/src/irmin-pack/irmin_pack_intf.ml @@ -35,6 +35,7 @@ module type Sigs = sig ?index_log_size:int -> ?merge_throttle:Conf.merge_throttle -> ?freeze_throttle:Conf.freeze_throttle -> + ?indexing_strategy:Pack_store.Indexing_strategy.t -> string -> Irmin.config (** Configuration options for stores. diff --git a/src/irmin-pack/pack_store.ml b/src/irmin-pack/pack_store.ml index b0aa76a385..068efb4934 100644 --- a/src/irmin-pack/pack_store.ml +++ b/src/irmin-pack/pack_store.ml @@ -1,6 +1,36 @@ open! Import include Pack_store_intf +module Indexing_strategy = struct + type t = value_length:int -> Pack_value.Kind.t -> bool + + let always ~value_length:_ _ = true + + let minimal : t = + fun ~value_length:_ -> function + | Commit_v2 -> + (* Commits must be indexed as the branch store contains only their + hashes. All {i internal} references to V1 commits are via offset + (from other V1 commit objects). *) + true + | Inode_v2_root -> + (* It's safe not to index V1 root inodes because they are never + referenced by V0 commit objects (only V1 commit objects, which + contain direct pointers rather than hashes).*) + false + | Inode_v2_nonroot -> false + | Contents -> false + | Commit_v1 | Inode_v1_unstable | Inode_v1_stable -> + (* We never append new V0 values, so this choice is irrelevant to the + store implementation, but we do assume that existing V0 objects are + indexed (as they may be referenced via hash by other V0 objects), and + this must be accounted for when reconstructing the index. *) + true +end + +module type S = S with type indexing_strategy := Indexing_strategy.t +module type Maker = Maker with type indexing_strategy := Indexing_strategy.t + module Table (K : Irmin.Hash.S) = Hashtbl.Make (struct type t = K.t @@ -45,6 +75,7 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : type 'a t = { mutable block : IO.t; index : Index.t; + indexing_strategy : Indexing_strategy.t; dict : Dict.t; mutable open_instances : int; } @@ -55,7 +86,7 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : true) else false - let unsafe_v ~index ~fresh ~readonly file = + let unsafe_v ~index ~indexing_strategy ~fresh ~readonly file = let root = Filename.dirname file in let dict = Dict.v ~fresh ~readonly root in let block = @@ -64,12 +95,12 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : let version = Some selected_version in IO.v ~version ~fresh ~readonly file in - { block; index; dict; open_instances = 1 } + { block; index; indexing_strategy; dict; open_instances = 1 } let IO_cache.{ v } = IO_cache.memoize ~valid ~clear:(fun t -> IO.truncate t.block) - ~v:(fun index -> unsafe_v ~index) + ~v:(fun (index, indexing_strategy) -> unsafe_v ~index ~indexing_strategy) Layout.pack let close t = @@ -132,17 +163,18 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : if index_merge then Index.merge t.pack.index; Dict.flush t.pack.dict; IO.flush t.pack.block; - if index then Index.flush ~no_callback:() t.pack.index; + if index then Index.flush t.pack.index; Tbl.clear t.staging - let unsafe_v_no_cache ~fresh ~readonly ~lru_size ~index root = - let pack = v index ~fresh ~readonly root in + let unsafe_v_no_cache ~fresh ~readonly ~lru_size ~index ~indexing_strategy + root = + let pack = v (index, indexing_strategy) ~fresh ~readonly root in let staging = Tbl.create 127 in let lru = Lru.create lru_size in { staging; lru; pack; open_instances = 1; readonly } let unsafe_v ?(fresh = false) ?(readonly = false) ?(lru_size = 10_000) - ~index root = + ~index ~indexing_strategy root = try let t = Hashtbl.find roots (root, readonly) in if valid t then ( @@ -152,13 +184,18 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : Hashtbl.remove roots (root, readonly); raise Not_found) with Not_found -> - let t = unsafe_v_no_cache ~fresh ~readonly ~lru_size ~index root in + let t = + unsafe_v_no_cache ~fresh ~readonly ~lru_size ~index ~indexing_strategy + root + in if fresh then unsafe_clear t; Hashtbl.add roots (root, readonly) t; t - let v ?fresh ?readonly ?lru_size ~index root = - let t = unsafe_v ?fresh ?readonly ?lru_size ~index root in + let v ?fresh ?readonly ?lru_size ~index ~indexing_strategy root = + let t = + unsafe_v ?fresh ?readonly ?lru_size ~index ~indexing_strategy root + in Lwt.return t let io_read_and_decode_hash ~off t = @@ -445,7 +482,12 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : Val.encode_bin ~offset_of_key ~dict hash v (IO.append t.pack.block); let len = Int63.to_int (IO.offset t.pack.block -- off) in let key = Pack_key.v_direct ~hash ~offset:off ~length:len in - Index.add ~overcommit t.pack.index hash (off, len, kind); + let () = + let kind = Val.kind v in + let should_index = t.pack.indexing_strategy ~value_length:len kind in + if should_index then + Index.add ~overcommit t.pack.index hash (off, len, kind) + in if Tbl.length t.staging >= auto_flush then flush t else Tbl.add t.staging hash v; Lru.add t.lru hash v; @@ -500,8 +542,9 @@ module Maker (Index : Pack_index.S) (K : Irmin.Hash.S with type t = Index.key) : module Inner = Make_without_close_checks (Val) include Indexable.Closeable (Inner) - let v ?fresh ?readonly ?lru_size ~index path = - Inner.v ?fresh ?readonly ?lru_size ~index path >|= make_closeable + let v ?fresh ?readonly ?lru_size ~index ~indexing_strategy path = + Inner.v ?fresh ?readonly ?lru_size ~index ~indexing_strategy path + >|= make_closeable let sync t = Inner.sync (get_open_exn t) diff --git a/src/irmin-pack/pack_store_intf.ml b/src/irmin-pack/pack_store_intf.ml index af5b56e6d6..6a180beca5 100644 --- a/src/irmin-pack/pack_store_intf.ml +++ b/src/irmin-pack/pack_store_intf.ml @@ -1,19 +1,22 @@ open! Import -(** A [Pack_store.S] is a closeable, persistent implementation of - {!Content_addressable.S} that uses an append-only file of variable-length - data blocks. The data file is indexed by hash via {!Pack_index.S} - implementation. *) +(** A [Pack_store.S] is a closeable, persistent implementation of {!Indexable.S} + that uses an append-only file of variable-length data blocks. + + Certain values in the data file are indexed by hash via a {!Pack_index.S} + implementation, but not all of them need be. *) module type S = sig include Indexable.S type index + type indexing_strategy val v : ?fresh:bool -> ?readonly:bool -> ?lru_size:int -> index:index -> + indexing_strategy:indexing_strategy -> string -> read t Lwt.t @@ -35,6 +38,7 @@ end module type Maker = sig type hash type index + type indexing_strategy (** Save multiple kind of values in the same pack file. Values will be distinguished using [V.magic], so they have to all be different. *) @@ -48,11 +52,34 @@ module type Maker = sig and type hash = hash and type value = V.t and type index := index + and type indexing_strategy := indexing_strategy end module type Sigs = sig - module type S = S - module type Maker = Maker + module Indexing_strategy : sig + type t = value_length:int -> Pack_value.Kind.t -> bool + (** The type of configurations for [irmin-pack]'s indexing strategy, which + dictates whether or not newly-appended pack entries should also be added + to the index. Strategies are parameterised over: + + - the length of the binary encoding of the {i object} inside the pack + entry (i.e. not accounting for the encoded hash and kind character); + - the kind of the pack object having been added. + + Indexing more than the {!minimal} strategy only impacts performance and + not correctness: more indexing results in a larger index and a smaller + pack file. *) + + val always : t + (** The strategy that indexes all objects. *) + + val minimal : t + (** The strategy that indexes as few objects as possible while still + maintaing store integrity. *) + end + + module type S = S with type indexing_strategy := Indexing_strategy.t + module type Maker = Maker with type indexing_strategy := Indexing_strategy.t val selected_version : Version.t diff --git a/test/irmin-pack/common.ml b/test/irmin-pack/common.ml index 7d2bb8c47e..c90a80dfd7 100644 --- a/test/irmin-pack/common.ml +++ b/test/irmin-pack/common.ml @@ -118,14 +118,17 @@ struct let index = Index.v ~flush_callback:(fun () -> !f ()) ~log_size ~fresh:true name in - let+ pack = Pack.v ~fresh:true ~lru_size ~index name in + let indexing_strategy = Irmin_pack.Pack_store.Indexing_strategy.always in + let+ pack = Pack.v ~fresh:true ~lru_size ~index ~indexing_strategy name in (f := fun () -> Pack.flush ~index:false pack); let clone_pack ~readonly = - Pack.v ~lru_size ~fresh:false ~readonly ~index name + Pack.v ~lru_size ~fresh:false ~readonly ~index ~indexing_strategy name in let clone_index_pack ~readonly = let index = Index.v ~log_size ~fresh:false ~readonly name in - let+ pack = Pack.v ~lru_size ~fresh:false ~readonly ~index name in + let+ pack = + Pack.v ~lru_size ~fresh:false ~readonly ~index ~indexing_strategy name + in (index, pack) in { index; pack; clone_pack; clone_index_pack } diff --git a/test/irmin-pack/test_inode.ml b/test/irmin-pack/test_inode.ml index 3886638939..1a0efec6e6 100644 --- a/test/irmin-pack/test_inode.ml +++ b/test/irmin-pack/test_inode.ml @@ -75,9 +75,12 @@ struct [%log.app "Constructing a fresh context for use by the test"]; rm_dir root; let index = Index.v ~log_size ~fresh:true root in - let* store = Inode.v ~fresh:true ~lru_size ~index root in + let indexing_strategy = Irmin_pack.Pack_store.Indexing_strategy.always in + let* store = + Inode.v ~fresh:true ~lru_size ~index ~indexing_strategy root + in let* store_contents = - Contents_store.v ~fresh:false ~lru_size ~index root + Contents_store.v ~fresh:false ~lru_size ~index ~indexing_strategy root in let+ foo, bar = Contents_store.batch store_contents (fun writer -> @@ -86,7 +89,7 @@ struct Lwt.return (foo, bar)) in let clone ~readonly = - Inode.v ~lru_size ~fresh:false ~readonly ~index root + Inode.v ~lru_size ~fresh:false ~readonly ~index ~indexing_strategy root in [%log.app "Test context constructed"]; { index; store; store_contents; clone; foo; bar } diff --git a/test/irmin-pack/test_pack.ml b/test/irmin-pack/test_pack.ml index e8008e297a..b9c6a2e7b7 100644 --- a/test/irmin-pack/test_pack.ml +++ b/test/irmin-pack/test_pack.ml @@ -36,9 +36,11 @@ module Irmin_pack_store : Irmin_test.Generic_key = struct end) end -let suite_pack = +let suite_pack name_suffix indexing_strategy = let store = (module Irmin_pack_store : Irmin_test.Generic_key) in - let config = Irmin_pack.config ~fresh:false ~lru_size:0 test_dir in + let config = + Irmin_pack.config ~fresh:false ~lru_size:0 ~indexing_strategy test_dir + in let init () = rm_dir test_dir; Lwt.return_unit @@ -47,8 +49,9 @@ let suite_pack = rm_dir test_dir; Lwt.return_unit in - Irmin_test.Suite.create_generic_key ~name:"PACK" ~clear_supported:false - ~import_supported:false ~init ~store ~config ~clean ~layered_store:None () + Irmin_test.Suite.create_generic_key ~name:("PACK" ^ name_suffix) + ~clear_supported:false ~import_supported:false ~init ~store ~config ~clean + ~layered_store:None () module Irmin_pack_mem_maker : Irmin_test.Generic_key = struct open Irmin_pack_mem.Maker (Config) @@ -67,7 +70,13 @@ let suite_mem = Irmin_test.Suite.create_generic_key ~import_supported:false ~name:"PACK MEM" ~store ~config ~layered_store:None () -let suite = [ suite_pack; suite_mem ] +let suite = + let module Index = Irmin_pack.Pack_store.Indexing_strategy in + [ + suite_pack " { index = always }" Index.always; + suite_pack " { index = minimal }" Index.minimal; + suite_mem; + ] module Context = Make_context (struct let root = test_dir @@ -230,7 +239,10 @@ module Pack = struct let test_reuse_index () = (* index and pack with different names. However, this behaviour is not exposed by irmin_pack.*) let index = Index.v ~log_size:4 ~fresh:true (Context.fresh_name "index") in - let* w1 = Pack.v ~fresh:true ~index (Context.fresh_name "pack") in + let indexing_strategy = Irmin_pack.Pack_store.Indexing_strategy.always in + let* w1 = + Pack.v ~fresh:true ~index ~indexing_strategy (Context.fresh_name "pack") + in let x1 = "foo" in let h1 = sha1 x1 in let k1 = From 76b1fe6c85ec34ef451c47b8554d66238e902737 Mon Sep 17 00:00:00 2001 From: Craig Ferguson Date: Wed, 8 Dec 2021 19:24:18 +0000 Subject: [PATCH 2/3] Add a CHANGES entry --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 70f76569f9..d6c804aded 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -164,6 +164,11 @@ reduce indexing overhead. This change is fully backwards-compatible with existing stores using `irmin-pack.2.x` versions, but not forwards compatible. (#1649 #1655, @CraigFe @Ngoguey42) + - Added support for user-specified indexing strategies. The default strategy + is to index all objects appended to the pack file (as before), but users may + now choose to index fewer objects in order to improve the write performance + of the store, at the cost of introducing potential duplicate values to the + pack file. (#1664, @CraigFe) - **irmin-unix** - Clean up command line interface. Allow config file to be specified when From 8eca001118156bd3560f57f3024f57ed6a037268 Mon Sep 17 00:00:00 2001 From: Craig Ferguson Date: Thu, 23 Dec 2021 14:24:07 +0000 Subject: [PATCH 3/3] irmin-pack: add an explicit default value for indexing strategy --- src/irmin-pack/conf.ml | 2 +- src/irmin-pack/irmin_pack_intf.ml | 5 ++++- src/irmin-pack/pack_store.ml | 2 ++ src/irmin-pack/pack_store_intf.ml | 5 +++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/irmin-pack/conf.ml b/src/irmin-pack/conf.ml index 8bfddf7ab3..2c5d449dc9 100644 --- a/src/irmin-pack/conf.ml +++ b/src/irmin-pack/conf.ml @@ -29,7 +29,7 @@ module Default = struct let readonly = false let merge_throttle = `Block_writes let freeze_throttle = `Block_writes - let indexing_strategy = Pack_store.Indexing_strategy.always + let indexing_strategy = Pack_store.Indexing_strategy.default end open Irmin.Backend.Conf diff --git a/src/irmin-pack/irmin_pack_intf.ml b/src/irmin-pack/irmin_pack_intf.ml index 78167a65cb..deb319b39c 100644 --- a/src/irmin-pack/irmin_pack_intf.ml +++ b/src/irmin-pack/irmin_pack_intf.ml @@ -48,7 +48,10 @@ module type Sigs = sig the strategy to use when the index cache is full and an async [Index.merge] in already in progress. [Block_writes] (the default) blocks any new writes until the merge is completed. [Overcommit_memory] - does not block but indefinitely expands the in-memory cache. *) + does not block but indefinitely expands the in-memory cache. + @param indexing_strategy + The {{!Pack_store.Indexing_strategy} indexing strategy} of the backend + store. Defaults to {!Pack_store.Indexing_strategy.default}. *) exception RO_not_allowed diff --git a/src/irmin-pack/pack_store.ml b/src/irmin-pack/pack_store.ml index 068efb4934..fb521e46ed 100644 --- a/src/irmin-pack/pack_store.ml +++ b/src/irmin-pack/pack_store.ml @@ -26,6 +26,8 @@ module Indexing_strategy = struct indexed (as they may be referenced via hash by other V0 objects), and this must be accounted for when reconstructing the index. *) true + + let default = always end module type S = S with type indexing_strategy := Indexing_strategy.t diff --git a/src/irmin-pack/pack_store_intf.ml b/src/irmin-pack/pack_store_intf.ml index 6a180beca5..172d55cdf6 100644 --- a/src/irmin-pack/pack_store_intf.ml +++ b/src/irmin-pack/pack_store_intf.ml @@ -76,6 +76,11 @@ module type Sigs = sig val minimal : t (** The strategy that indexes as few objects as possible while still maintaing store integrity. *) + + val default : t + (** [default] is the indexing strategy used by [irmin-pack] instances that + do not explicitly set an indexing strategy in {!Irmin_pack.config}. + Currently set to {!always}. *) end module type S = S with type indexing_strategy := Indexing_strategy.t