Skip to content

Commit

Permalink
Add Tree.is_val and Tree.Contents.is_val functions
Browse files Browse the repository at this point in the history
These functions check whether the node/contents are available in
memory or not (ie. if calling a function on those could incur IO
costs).
  • Loading branch information
samoht committed Jun 7, 2022
1 parent 0e6b3de commit 366fc45
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/irmin-test/store.ml
Expand Up @@ -1301,6 +1301,13 @@ module Make (S : Generic_key) = struct

(* Testing other tree operations. *)
let v0 = S.Tree.empty () in
let b0 = S.Tree.is_val v0 [] in
Alcotest.(check bool) "empty is_val /" true b0;
let b0 = S.Tree.is_val v0 [ "foo" ] in
Alcotest.(check bool) "empty is_val /foo" true b0;
let b0 = S.Tree.is_val v0 [ "foo"; "bar" ] in
Alcotest.(check bool) "empty is_val /foo/bar" true b0;

let* c = S.Tree.to_concrete v0 in
(match c with
| `Tree [] -> ()
Expand Down
29 changes: 29 additions & 0 deletions src/irmin/tree.ml
Expand Up @@ -320,6 +320,8 @@ module Make (P : Backend.S) = struct
if cache then c.info.ptr <- Hash h;
h)

let is_val t = match cached_value t with None -> false | Some _ -> true

let key t =
match t.v with Key (_, k) -> Some k | Value _ | Pruned _ -> None

Expand Down Expand Up @@ -1227,6 +1229,20 @@ module Make (P : Backend.S) = struct

let findv = findv_aux ~value_of_key ~return:Lwt.return ~bind:Lwt.bind

exception Lazy

let findv' ctx t k =
findv_aux ~cache:false
~value_of_key:(fun ~cache:_ _ _ _ -> raise Lazy)
~return:Fun.id
~bind:(fun x f -> f x)
ctx t k

let is_val t =
match (cached_map t, cached_value t) with
| None, None -> false
| _ -> true

let seq_of_map ?(offset = 0) ?length m : (step * elt) Seq.t =
let take seq =
match length with None -> seq | Some n -> Seq.take n seq
Expand Down Expand Up @@ -1691,6 +1707,19 @@ module Make (P : Backend.S) = struct
| `Node n -> (aux [@tailcall]) n path
| `Contents _ -> Lwt.return_none

let is_val t path =
let rec aux node path =
match Path.decons path with
| None -> Node.is_val node
| Some (h, p) -> (
match Node.findv' "is_val" node h with
| None -> true
| exception Node.Lazy -> false
| Some (`Contents (c, _)) -> Contents.is_val c
| Some (`Node n) -> aux n p)
in
match t with `Node n -> aux n path | `Contents (c, _) -> Contents.is_val c

let find_tree (t : t) path =
let cache = true in
[%log.debug "Tree.find_tree %a" pp_path path];
Expand Down
10 changes: 10 additions & 0 deletions src/irmin/tree_intf.ml
Expand Up @@ -82,6 +82,12 @@ module type S = sig
(** [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. *)

val is_val : t -> path -> bool
(** [is_val t k] is [true] iff the path [k] has already been forced in [t]. In
that case, that means that all the nodes traversed by [k] are loaded in
memory. If the leaf node is a contents [c], then [Contents.is_val c]
should also be [true]. *)

(** {1 Diffs} *)

val diff : t -> t -> (path * (contents * metadata) Diff.t) list Lwt.t
Expand Down Expand Up @@ -128,6 +134,10 @@ module type S = sig
(** Equivalent to {!val-force}, but raises an exception if the lazy content
value is not present in the underlying repository. *)

val is_val : t -> bool
(** [is_val x] is [true] iff [x] has already been forced (and so is loaded
in memory). *)

val clear : t -> unit
(** [clear t] clears [t]'s cache. *)

Expand Down

0 comments on commit 366fc45

Please sign in to comment.