blob: a27539fc6dcb7f9a75ab8b57f8b3c6abded79827 (
plain) (
tree)
|
|
type address = Concepts.Hash.hash
type branch_index_root = address
let fixed_label = "rnt.initialization"
let fixed_label_address = Concepts.Hash.hash_of_bytes (Bytes.of_string fixed_label)
module Error = struct
open Concepts.Condition
let malformed_address length =
condition "initialization-malformed-address"
"The initialization fixed key does not contain a valid address"
("length" |=| Concepts.Value.Integer length)
let missing_branch_index address =
condition "initialization-branch-index-missing"
"The initialization fixed key points at a missing branch index"
("address" |=| Concepts.Value.String (Concepts.Hash.to_raw_string address))
end
let address_to_blob address =
Concepts.Object.Field.address address |> Concepts.Codec.Bencode.to_blob
let address_of_blob blob =
let open Utilities.Result in
let* data = Concepts.Codec.Bencode.of_blob blob in
let* raw = Concepts.Codec.Bencode.as_string data in
if String.length raw = Concepts.Hash.size then Ok (Concepts.Hash.of_raw_string raw)
else Error (Error.malformed_address (String.length raw))
module Make (Store : Abstract.Storage.STORAGE) = struct
module Branch_index = BranchIndex.Make (Store)
module S = Storage.Make (Store)
let read_in_transaction tx =
let open Utilities.Result in
let* fixed = Store.get tx fixed_label_address in
match fixed with
| None -> Ok None
| Some fixed ->
let* root = address_of_blob fixed in
let* branch_index = Branch_index.find tx root in
begin match branch_index with
| Some _ -> Ok (Some root)
| None -> Error (Error.missing_branch_index root)
end
let store_fixed_root tx root = Store.put tx fixed_label_address (address_to_blob root)
let create_initial_branch_state tx =
let open Utilities.Result in
(* The first branch state has no synthetic "genesis" commit. Both [current]
and [history] point at persisted empty trees; the runtime mounts /system
around those roots after initialization. *)
let* empty_root = Branch_index.empty_under tx in
Concepts.BranchState.make ~current:empty_root ~history:empty_root ~tip:None
|> Concepts.BranchState.to_blob
|> S.store_blob tx
let ensure_default_branch tx root branch_index =
let open Utilities.Result in
let* current = Branch_index.find_branch tx BranchIndex.default_branch_name branch_index in
match current with
| Some _ -> Ok root
| None ->
(* Older initialization slices could leave a valid but empty branch
index. Repair it by publishing a new root containing master. *)
let* branch_state = create_initial_branch_state tx in
let* branch_index =
Branch_index.put_branch tx BranchIndex.default_branch_name branch_state branch_index
in
Ok (Branch_index.hash_of branch_index)
let create_in_transaction tx =
let open Utilities.Result in
let* branch_state = create_initial_branch_state tx in
let* branch_index =
Branch_index.put_branch tx BranchIndex.default_branch_name branch_state Branch_index.empty
in
let root = Branch_index.hash_of branch_index in
let* () = store_fixed_root tx root in
Ok root
let initialize connection =
S.with_transaction connection (fun tx ->
let open Utilities.Result in
let* current = read_in_transaction tx in
match current with
| None -> create_in_transaction tx
| Some root ->
let* branch_index = Branch_index.find tx root in
begin match branch_index with
| None -> Error (Error.missing_branch_index root)
| Some branch_index ->
let* root' = ensure_default_branch tx root branch_index in
let* () =
if Concepts.Hash.hash_equals root root' then Ok () else store_fixed_root tx root'
in
Ok root'
end )
end
|