···33type node_raw =
44 { (* link to lower level left subtree with all keys sorting before this node *)
55 l: Cid.t option
66- ; (* ordered list of entries below this node *)
66+ ; (* ordered list of entries in this node *)
77 e: entry_raw list }
8899and entry_raw =
···3838and entry_hydrated =
3939 {layer: int; key: string; value: Cid.t; right: node_hydrated option}
40404141+(* figures out where to put an entry in or below a hydrated node, returns new node *)
4242+let rec insert_entry node entry : node_hydrated Lwt.t =
4343+ let entry_layer = Util.leading_zeros_on_hash entry.key in
4444+ (* as long as node layer <= entry layer, create a new node above node
4545+ until we have a node at the correct height for the entry to be inserted *)
4646+ let rec build_insert_node node layer =
4747+ if layer >= entry_layer then node
4848+ else
4949+ build_insert_node
5050+ {layer= layer + 1; left= Some node; entries= []}
5151+ (layer + 1)
5252+ in
5353+ let insert_node = build_insert_node node node.layer in
5454+ (* if entry is below node, recursively insert into node's left subtree *)
5555+ if entry_layer < insert_node.layer then
5656+ match (insert_node.entries, insert_node.left) with
5757+ | [], None ->
5858+ failwith "found totally empty mst node"
5959+ | [], Some left ->
6060+ node.left <- Some (Lwt_main.run (insert_entry left entry)) ;
6161+ Lwt.return insert_node
6262+ | _ ->
6363+ Lwt.return insert_node
6464+ else (
6565+ (* if entry is at this node's layer, append it to node's entries,
6666+ checking that its key occurs after the last existing entry *)
6767+ assert (node.layer = entry_layer) ;
6868+ ( match Util.last node.entries with
6969+ | Some last ->
7070+ (* we can assert this because hydrate_from_map calls this function
7171+ while iterating over keys in sorted order *)
7272+ assert (entry.key > last.key)
7373+ | None ->
7474+ () ) ;
7575+ node.entries <- node.entries @ [entry] ;
7676+ Lwt.return node )
7777+7878+(* helper to find the entry with a given key in a hydrated node *)
7979+let find_entry_nonrec node key =
8080+ let rec aux entries =
8181+ match entries with
8282+ | [] ->
8383+ None
8484+ | e :: es ->
8585+ if e.key = key then Some e else if e.key > key then None else aux es
8686+ in
8787+ aux node.entries
8888+8989+(* hydrates a list of entries with their keys; layer and right value are placeholders *)
9090+let hydrate_entries_keys_only node =
9191+ node.e
9292+ |> List.fold_left
9393+ (fun (prev_path, entries) entry ->
9494+ let prefix = String.sub prev_path 0 entry.p in
9595+ let path = String.concat "" [prefix; Bytes.to_string entry.k] in
9696+ Util.ensure_valid_key path ;
9797+ (path, entries @ [{layer= 0; key= path; value= entry.v; right= None}]) )
9898+ ("", [])
9999+ |> snd
100100+41101module Make (Store : Storage.Writable_blockstore) = struct
42102 type bs = Store.t
43103···4510546106 let create blockstore root = {blockstore; root}
47107108108+ (* decodes a node retrieved from the blockstore *)
48109 let decode_block b : node_raw =
49110 match Dag_cbor.decode b with
50111 | `Map node ->
···96157 | _ ->
97158 raise (Invalid_argument "invalid block")
98159160160+ (* retrieves & decodes a node by cid *)
99161 let retrieve_node t cid : node_raw option Lwt.t =
100162 match%lwt Store.get_bytes t.blockstore cid with
101163 | Some bytes ->
···103165 | None ->
104166 Lwt.return_none
105167168168+ (* returns the layer of a node *)
106169 let rec get_node_height t node : int Lwt.t =
107170 match (node.l, node.e) with
108171 | None, [] ->
···121184 | _ ->
122185 failwith "first node entry has nonzero p value" )
123186187187+ (* calls fn with each entry's key and cid *)
124188 let traverse t fn : unit Lwt.t =
125189 let rec traverse node =
126190 let%lwt () =
···149213 | None ->
150214 failwith "root cid not found in repo store"
151215216216+ (* returns a map of key -> cid *)
152217 let build_map t : Cid.t StringMap.t Lwt.t =
153218 let map = StringMap.empty in
154219 let%lwt () =
···156221 in
157222 Lwt.return map
158223159159- let rec insert_entry node entry : node_hydrated Lwt.t =
160160- let entry_layer = Util.leading_zeros_on_hash entry.key in
161161- (* as long as node layer <= entry layer, create a new node above node
162162- until we have a node at the correct height for the entry to be inserted *)
163163- let rec build_insert_node node layer =
164164- if layer >= entry_layer then node
165165- else
166166- build_insert_node
167167- {layer= layer + 1; left= Some node; entries= []}
168168- (layer + 1)
169169- in
170170- let insert_node = build_insert_node node node.layer in
171171- (* if entry is below node, recursively insert into node's left subtree *)
172172- if entry_layer < insert_node.layer then
173173- match (insert_node.entries, insert_node.left) with
174174- | [], None ->
175175- failwith "found totally empty mst node"
176176- | [], Some left ->
177177- node.left <- Some (Lwt_main.run (insert_entry left entry)) ;
178178- Lwt.return insert_node
179179- | _ ->
180180- Lwt.return insert_node
181181- else (
182182- (* if entry is at this node's layer, append it to node's entries,
183183- checking that its key occurs after the last existing entry *)
184184- assert (node.layer = entry_layer) ;
185185- if List.length node.entries > 0 then
186186- assert (entry.key > (List.rev node.entries |> List.hd).key) ;
187187- node.entries <- node.entries @ [entry] ;
188188- Lwt.return node )
189189-190190- let hydrate_from_map t map =
224224+ (* produces a hydrated mst from a map of key -> cid *)
225225+ let hydrate_from_map t map : Cid.t Lwt.t =
191226 let keys =
192227 map |> StringMap.bindings |> List.map fst |> List.sort String.compare
193228 in
···241276 Lwt.return cid
242277 in
243278 finalize root
279279+280280+ (* returns cids and blocks that form the path from a given node to a given entry *)
281281+ let rec path_to_entry t node key : (Cid.t * bytes) list Lwt.t =
282282+ let%lwt root_bytes = Store.get_bytes t node in
283283+ let%lwt root =
284284+ match root_bytes with
285285+ | None ->
286286+ Lwt.return_none
287287+ | Some bytes ->
288288+ Lwt.return_some (decode_block bytes)
289289+ in
290290+ let path_tail = [(node, Option.get root_bytes)] in
291291+ (* if there is a left child, try to find a path through the left subtree *)
292292+ let%lwt path_through_left =
293293+ match root with
294294+ | None ->
295295+ Lwt.return_some []
296296+ | Some root -> (
297297+ match root.l with
298298+ | None ->
299299+ Lwt.return_none
300300+ | Some left -> (
301301+ match%lwt path_to_entry t left key with
302302+ | [] ->
303303+ Lwt.return_none
304304+ | path ->
305305+ (* Option.get is safe because root is Some only when root_bytes is Some *)
306306+ Lwt.return_some (path @ path_tail) ) )
307307+ in
308308+ match path_through_left with
309309+ | Some path ->
310310+ Lwt.return path
311311+ | None -> (
312312+ (* if a left subtree path couldn't be found, find the entry whose right subtree this key would belong to *)
313313+ let root' = Option.get root in
314314+ let entries_keys = hydrate_entries_keys_only root' in
315315+ let entries_len = List.length root'.e in
316316+ let entry_index =
317317+ match List.find_index (fun e -> e.key >= key) entries_keys with
318318+ | Some index ->
319319+ index
320320+ | None ->
321321+ entries_len
322322+ in
323323+ (* entry_index here is actually the entry to the right of the subtree the key would belong to *)
324324+ match entry_index with
325325+ | _
326326+ (* because entries[entry_index] might turn out to be the entry we're looking for *)
327327+ when entry_index < entries_len
328328+ && (List.nth entries_keys entry_index).key = key ->
329329+ Lwt.return path_tail
330330+ | _ -> (
331331+ (* otherwise, we continue down the right subtree of the entry before entry_index *)
332332+ match Util.last root'.e with
333333+ | Some last when last.t != None ->
334334+ let%lwt path_through_right =
335335+ path_to_entry t (Option.get last.t) key
336336+ in
337337+ Lwt.return (path_through_right @ path_tail)
338338+ | _ ->
339339+ Lwt.return path_tail ) )
340340+341341+ (* returns all mst entries in order for a car stream *)
342342+ let to_car_stream t : (Cid.t * bytes) Seq.t =
343343+ let module M = struct
344344+ type stage =
345345+ | Nodes of
346346+ (* currently walking nodes *)
347347+348348+ { next: Cid.t list (* next cids to fetch *)
349349+ ; fetched: (Cid.t * bytes) list (* fetched cids and their bytes *)
350350+ ; leaves: Cid.Set.t (* seen leaf cids *) }
351351+ | Leaves of
352352+ (* done walking nodes, streaming accumulated leaves *)
353353+ (Cid.t * bytes) list
354354+ | Done
355355+ end in
356356+ let open M in
357357+ let init_state =
358358+ Nodes {next= [t.root]; fetched= []; leaves= Cid.Set.empty}
359359+ in
360360+ let rec step = function
361361+ | Done ->
362362+ None
363363+ (* node has been fetched, can now be yielded *)
364364+ | Nodes ({fetched= (cid, bytes) :: rest; _} as s) ->
365365+ Some ((cid, bytes), Nodes {s with fetched= rest})
366366+ (* need to fetch next nodes *)
367367+ | Nodes {next; fetched= []; leaves} ->
368368+ if List.is_empty next then (
369369+ (* finished traversing nodes, time to switch to leaves *)
370370+ let leaves_list = Cid.Set.to_list leaves in
371371+ let leaves_bm =
372372+ Lwt_main.run (Store.get_blocks t.blockstore leaves_list)
373373+ in
374374+ if leaves_bm.missing <> [] then failwith "missing mst leaf blocks" ;
375375+ let leaves_nodes = Storage.Block_map.entries leaves_bm.blocks in
376376+ match leaves_nodes with
377377+ | [] ->
378378+ (* with Done, we don't care about the first pair element *)
379379+ Some (Obj.magic (), Done)
380380+ | _ ->
381381+ (* it's leafin time *)
382382+ step (Leaves leaves_nodes) )
383383+ else
384384+ (* go ahead and fetch the next nodes *)
385385+ let bm = Lwt_main.run (Store.get_blocks t.blockstore next) in
386386+ if bm.missing <> [] then failwith "missing mst nodes" ;
387387+ let fetched, next', leaves' =
388388+ List.fold_left
389389+ (fun (acc, nxt, lvs) cid ->
390390+ let bytes =
391391+ (* we should be safe to do this since we just got the cids from the blockmap *)
392392+ Storage.Block_map.get cid bm.blocks |> Option.get
393393+ in
394394+ let node = decode_block bytes in
395395+ let nxt' =
396396+ List.fold_left
397397+ (* node.entries.map(e => e.right) *)
398398+ (fun n e -> match e.t with Some c -> c :: n | None -> n )
399399+ (* start with [node.left, ...nxt] if node has a left subtree *)
400400+ ( match node.l with
401401+ | Some l ->
402402+ l :: nxt
403403+ | None ->
404404+ nxt )
405405+ node.e
406406+ in
407407+ let lvs' =
408408+ (* add each entry in this node to the list of seen leaves *)
409409+ List.fold_left (fun s e -> Cid.Set.add e.v s) lvs node.e
410410+ in
411411+ (* prepending is O(1) per prepend + one O(n) to reverse, vs. O(n) per append = O(n^2) total *)
412412+ ((cid, bytes) :: acc, nxt', lvs') )
413413+ ([], [], leaves) next
414414+ in
415415+ step
416416+ (Nodes
417417+ { next= List.rev next'
418418+ ; fetched= List.rev fetched
419419+ ; leaves= leaves' } )
420420+ (* if we're onto yielding leaves, do that *)
421421+ | Leaves ((cid, bytes) :: rest) ->
422422+ let next = if rest = [] then Done else Leaves rest in
423423+ Some ((cid, bytes), next)
424424+ (* once we're out of leaves, we're done *)
425425+ | Leaves [] ->
426426+ Some (Obj.magic (), Done)
427427+ in
428428+ Seq.unfold step init_state
244429end
+7
mist/lib/storage/memory_store.ml
···6677 let create ?(blocks = Block_map.empty) () = {blocks; root= None; rev= None}
8899+ let get_root s =
1010+ match s.root with
1111+ | Some root ->
1212+ Lwt.return_some root
1313+ | None ->
1414+ Lwt.return_none
1515+916 let get_bytes s cid = Lwt.return (Block_map.get cid s.blocks)
10171118 let has s cid = Lwt.return (Block_map.has cid s.blocks)
+9-4
mist/lib/storage/overlay_store.ml
···991010 let create top bottom = {top; bottom}
11111212+ let get_root {top; bottom} =
1313+ match%lwt Top.get_root top with
1414+ | Some _ as res ->
1515+ Lwt.return res
1616+ | None ->
1717+ Bottom.get_root bottom
1818+1219 let get_bytes {top; bottom} cid =
1313- let* from_top = Top.get_bytes top cid in
1414- match from_top with
2020+ match%lwt Top.get_bytes top cid with
1521 | Some _ as res ->
1622 Lwt.return res
1723 | None ->
1824 Bottom.get_bytes bottom cid
19252026 let has {top; bottom} cid =
2121- let* from_top = Top.has top cid in
2222- match from_top with
2727+ match%lwt Top.has top cid with
2328 | true ->
2429 Lwt.return_true
2530 | false ->
+2
mist/lib/storage/repo_store.ml
···99module type Readable = sig
1010 type t
11111212+ val get_root : t -> Cid.t option Lwt.t
1313+1214 val get_bytes : t -> Cid.t -> bytes option Lwt.t
13151416 val has : t -> Cid.t -> bool Lwt.t
+3
mist/lib/util.ml
···45454646let ensure_valid_key (key : string) : unit =
4747 if not (is_valid_mst_key key) then raise (Invalid_argument "invalid mst key")
4848+4949+let rec last (lst : 'a list) : 'a option =
5050+ match lst with [] -> None | [x] -> Some x | _ :: xs -> last xs