From b28df317d1fcbf21f33bfb9b59e69b9b6dcc0da9 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Thu, 18 Apr 2024 13:32:51 +0100 Subject: [PATCH 1/4] Store: Move block_store_status type definition to avoid duplication --- src/lib_store/shared/naming.ml | 15 --------------- src/lib_store/shared/naming.mli | 2 -- src/lib_store/shared/store_types.ml | 23 +++++++++++++++++++++++ src/lib_store/shared/store_types.mli | 10 ++++++++++ src/lib_store/unix/block_store.ml | 11 +---------- src/lib_store/unix/block_store.mli | 9 ++------- 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/lib_store/shared/naming.ml b/src/lib_store/shared/naming.ml index 12bcb6202906..deb1cb76f52e 100644 --- a/src/lib_store/shared/naming.ml +++ b/src/lib_store/shared/naming.ml @@ -151,21 +151,6 @@ let caboose_file dir = block_descriptor_encoding Store_types.block_descriptor_equal -type block_store_status = Idle | Merging - -let block_store_status_encoding = - let open Data_encoding in - conv - (function Idle -> false | Merging -> true) - (function false -> Idle | true -> Merging) - bool - -let status_equal s1 s2 = - match (s1, s2) with - | Idle, Idle -> true - | Merging, Merging -> true - | Idle, Merging | Merging, Idle -> false - let block_store_status_file dir = make_encoded_file dir diff --git a/src/lib_store/shared/naming.mli b/src/lib_store/shared/naming.mli index 850036e9292d..bb0a18596f8c 100644 --- a/src/lib_store/shared/naming.mli +++ b/src/lib_store/shared/naming.mli @@ -133,8 +133,6 @@ val savepoint_file : val caboose_file : [`Chain_dir] directory -> ([`Caboose], block_descriptor) encoded_file -type block_store_status = Idle | Merging - val block_store_status_file : [`Chain_dir] directory -> ([`Status], block_store_status) encoded_file diff --git a/src/lib_store/shared/store_types.ml b/src/lib_store/shared/store_types.ml index 80a744ee744c..7b6b12ef23a2 100644 --- a/src/lib_store/shared/store_types.ml +++ b/src/lib_store/shared/store_types.ml @@ -23,6 +23,25 @@ (* *) (*****************************************************************************) +(* block_store_status *) + +type block_store_status = Idle | Merging + +let status_equal s1 s2 = + match (s1, s2) with + | Idle, Idle -> true + | Merging, Merging -> true + | Idle, Merging | Merging, Idle -> false + +let block_store_status_encoding = + let open Data_encoding in + conv + (function Idle -> false | Merging -> true) + (function false -> Idle | true -> Merging) + bool + +(* block_descriptor *) + type block_descriptor = Block_hash.t * int32 let block_descriptor_equal (bh1, lvl1) (bh2, lvl2) = @@ -35,6 +54,8 @@ let block_descriptor_encoding = let pp_block_descriptor fmt (hash, level) = Format.fprintf fmt "%a (level: %ld)" Block_hash.pp hash level +(* chain_config *) + type chain_config = { history_mode : History_mode.t; genesis : Genesis.t; @@ -58,6 +79,8 @@ let chain_config_encoding = (req "genesis" Genesis.encoding) (varopt "expiration" Time.Protocol.encoding)) +(* invalid_block *) + type invalid_block = {level : int32; errors : Error_monad.error list} let invalid_block_equal {level = l1; errors = e1} {level = l2; errors = e2} = diff --git a/src/lib_store/shared/store_types.mli b/src/lib_store/shared/store_types.mli index dc5b9aeabdb1..36f70f0e253d 100644 --- a/src/lib_store/shared/store_types.mli +++ b/src/lib_store/shared/store_types.mli @@ -25,6 +25,16 @@ (** {1 Global types used in the store library} *) +(** The type used to describe the status of the store i.e. whether we are + in the merging process or not *) +type block_store_status = Idle | Merging + +(** Equality function for {!block_store_status} *) +val status_equal : block_store_status -> block_store_status -> bool + +(** Encoding for {!block_store_status} *) +val block_store_status_encoding : block_store_status Data_encoding.t + (** The type used to describe a block pointer i.e. its hash and level. *) type block_descriptor = Block_hash.t * int32 diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index e4c07b573bc0..9144f2832400 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -31,8 +31,6 @@ let default_block_cache_limit = 1_000 type merge_status = Not_running | Running | Merge_failed of tztrace -type status = Naming.block_store_status = Idle | Merging - type block_store = { chain_dir : [`Chain_dir] Naming.directory; readonly : bool; @@ -42,7 +40,7 @@ type block_store = { mutable rw_floating_block_store : Floating_block_store.t; caboose : block_descriptor Stored_data.t; savepoint : block_descriptor Stored_data.t; - status_data : status Stored_data.t; + status_data : block_store_status Stored_data.t; block_cache : Block_repr.t Block_lru_cache.t; mutable gc_callback : (Block_hash.t -> unit tzresult Lwt.t) option; mutable split_callback : (unit -> unit tzresult Lwt.t) option; @@ -56,13 +54,6 @@ type t = block_store type key = Block of (Block_hash.t * int) -let status_encoding = - let open Data_encoding in - conv - (function Idle -> false | Merging -> true) - (function false -> Idle | true -> Merging) - Data_encoding.bool - let status_to_string = function Idle -> "idle" | Merging -> "merging" let cemented_block_store {cemented_store; _} = cemented_store diff --git a/src/lib_store/unix/block_store.mli b/src/lib_store/unix/block_store.mli index b12bb60381ce..31b72aef4b36 100644 --- a/src/lib_store/unix/block_store.mli +++ b/src/lib_store/unix/block_store.mli @@ -164,11 +164,6 @@ type key = Block of (Block_hash.t * int) (** The status of the merging thread *) type merge_status = Not_running | Running | Merge_failed of tztrace -(** The status of the store *) -type status = Idle | Merging - -val status_encoding : status Data_encoding.t - (** [cemented_block_store block_store] returns the instance of the cemented block store for [block_store]. *) val cemented_block_store : block_store -> Cemented_block_store.t @@ -193,9 +188,9 @@ val caboose : block_store -> block_descriptor Lwt.t val write_caboose : block_store -> block_descriptor -> unit tzresult Lwt.t -val status : block_store -> status Lwt.t +val status : block_store -> block_store_status Lwt.t -val write_status : block_store -> status -> unit tzresult Lwt.t +val write_status : block_store -> block_store_status -> unit tzresult Lwt.t val genesis_block : block_store -> Block_repr.t -- GitLab From 84304105b505732c5c0c65773605e10e87323c18 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 19 Apr 2024 12:14:21 +0100 Subject: [PATCH 2/4] Store: Refactor block_store_status --- src/lib_store/shared/naming.ml | 4 +-- src/lib_store/shared/naming.mli | 2 +- src/lib_store/shared/store_types.ml | 40 +++++++++++++++++++--------- src/lib_store/shared/store_types.mli | 35 +++++++++++++++++++----- src/lib_store/unix/block_store.ml | 37 ++++++++++++------------- src/lib_store/unix/block_store.mli | 4 +-- src/lib_store/unix/store.ml | 2 +- 7 files changed, 80 insertions(+), 44 deletions(-) diff --git a/src/lib_store/shared/naming.ml b/src/lib_store/shared/naming.ml index deb1cb76f52e..6b942ad3b995 100644 --- a/src/lib_store/shared/naming.ml +++ b/src/lib_store/shared/naming.ml @@ -155,8 +155,8 @@ let block_store_status_file dir = make_encoded_file dir ~filename:"status" - block_store_status_encoding - status_equal + Block_store_status.encoding + Block_store_status.equal let cemented_blocks_dir dir = mk_dir dir "cemented" diff --git a/src/lib_store/shared/naming.mli b/src/lib_store/shared/naming.mli index bb0a18596f8c..61c247254c71 100644 --- a/src/lib_store/shared/naming.mli +++ b/src/lib_store/shared/naming.mli @@ -134,7 +134,7 @@ val caboose_file : [`Chain_dir] directory -> ([`Caboose], block_descriptor) encoded_file val block_store_status_file : - [`Chain_dir] directory -> ([`Status], block_store_status) encoded_file + [`Chain_dir] directory -> ([`Status], Block_store_status.t) encoded_file val cemented_blocks_dir : [< `Chain_dir | `Snapshot_dir | `Snapshot_tmp_dir | `Tar_archive] directory -> diff --git a/src/lib_store/shared/store_types.ml b/src/lib_store/shared/store_types.ml index 7b6b12ef23a2..4a961a127fb3 100644 --- a/src/lib_store/shared/store_types.ml +++ b/src/lib_store/shared/store_types.ml @@ -25,20 +25,36 @@ (* block_store_status *) -type block_store_status = Idle | Merging +module Block_store_status = struct + type t = Idle | Merging -let status_equal s1 s2 = - match (s1, s2) with - | Idle, Idle -> true - | Merging, Merging -> true - | Idle, Merging | Merging, Idle -> false + let set_idle_status status_data = Stored_data.write status_data Idle -let block_store_status_encoding = - let open Data_encoding in - conv - (function Idle -> false | Merging -> true) - (function false -> Idle | true -> Merging) - bool + let set_merge_status status_data = Stored_data.write status_data Merging + + let is_idle = function Idle -> true | Merging -> false + + let is_merging = function Idle -> false | Merging -> true + + let create_idle_status = Idle + + let equal s1 s2 = + match (s1, s2) with + | Idle, Idle -> true + | Merging, Merging -> true + | Idle, Merging | Merging, Idle -> false + + let encoding = + let open Data_encoding in + conv + (function Idle -> false | Merging -> true) + (function false -> Idle | true -> Merging) + bool + + let pp ppf = function + | Idle -> Format.fprintf ppf "Idle" + | Merging -> Format.fprintf ppf "Merging" +end (* block_descriptor *) diff --git a/src/lib_store/shared/store_types.mli b/src/lib_store/shared/store_types.mli index 36f70f0e253d..94c18dc603a1 100644 --- a/src/lib_store/shared/store_types.mli +++ b/src/lib_store/shared/store_types.mli @@ -25,15 +25,36 @@ (** {1 Global types used in the store library} *) -(** The type used to describe the status of the store i.e. whether we are - in the merging process or not *) -type block_store_status = Idle | Merging +module Block_store_status : sig + (** The type used to describe the status of the store. *) + type t -(** Equality function for {!block_store_status} *) -val status_equal : block_store_status -> block_store_status -> bool + (* Setters *) -(** Encoding for {!block_store_status} *) -val block_store_status_encoding : block_store_status Data_encoding.t + val set_idle_status : t Stored_data.t -> unit tzresult Lwt.t + + val set_merge_status : t Stored_data.t -> unit tzresult Lwt.t + + (* Status querying *) + + val is_idle : t -> bool + + val is_merging : t -> bool + + (* Initialisers *) + + val create_idle_status : t + + (* Equality function *) + val equal : t -> t -> bool + + (* Encoding *) + val encoding : t Data_encoding.t + + (* Printing *) + + val pp : Format.formatter -> t -> unit +end (** The type used to describe a block pointer i.e. its hash and level. *) type block_descriptor = Block_hash.t * int32 diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index 9144f2832400..a74f5e460c06 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -40,7 +40,7 @@ type block_store = { mutable rw_floating_block_store : Floating_block_store.t; caboose : block_descriptor Stored_data.t; savepoint : block_descriptor Stored_data.t; - status_data : block_store_status Stored_data.t; + status_data : Block_store_status.t Stored_data.t; block_cache : Block_repr.t Block_lru_cache.t; mutable gc_callback : (Block_hash.t -> unit tzresult Lwt.t) option; mutable split_callback : (unit -> unit tzresult Lwt.t) option; @@ -54,8 +54,6 @@ type t = block_store type key = Block of (Block_hash.t * int) -let status_to_string = function Idle -> "idle" | Merging -> "merging" - let cemented_block_store {cemented_store; _} = cemented_store let floating_block_stores {ro_floating_block_stores; rw_floating_block_store; _} @@ -88,8 +86,6 @@ let write_caboose {caboose; _} v = let genesis_block {genesis_block; _} = genesis_block -let write_status {status_data; _} status = Stored_data.write status_data status - (** [global_predecessor_lookup chain_block_store hash pow_nth] retrieves the 2^[pow_nth] predecessor's hash from the block with corresponding [hash] by checking all stores iteratively. Returns [None] if the @@ -1387,11 +1383,12 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store let*! store_status = status block_store in let* () = fail_unless - (store_status = Idle) - (Cannot_merge_store {status = status_to_string store_status}) + (Block_store_status.is_idle store_status) + (Cannot_merge_store + {status = Format.asprintf "%a" Block_store_status.pp store_status}) in (* Mark the store's status as Merging *) - let* () = write_status block_store Merging in + let* () = Block_store_status.set_merge_status block_store.status_data in let new_head_lpbl = Block_repr.last_preserved_block_level new_head_metadata in @@ -1474,7 +1471,10 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store let* () = finalizer new_head_lpbl in (* The merge operation succeeded, the store is now idle. *) block_store.merging_thread <- None ; - let* () = write_status block_store Idle in + let* () = + Block_store_status.set_idle_status + block_store.status_data + in return_unit)) (fun () -> Lwt_mutex.unlock block_store.merge_mutex ; @@ -1550,7 +1550,7 @@ let merge_temporary_floating block_store = let*! rw = Floating_block_store.init chain_dir ~readonly:false RW in block_store.ro_floating_block_stores <- [ro] ; block_store.rw_floating_block_store <- rw ; - write_status block_store Idle + Block_store_status.set_idle_status block_store.status_data (* Removes the potentially leftover temporary files from the cementing of cycles. *) @@ -1582,12 +1582,11 @@ let may_recover_merge block_store = let* () = Lwt_idle_waiter.force_idle block_store.merge_scheduler (fun () -> Lwt_mutex.with_lock block_store.merge_mutex (fun () -> - let*! d = Stored_data.get block_store.status_data in - match d with - | Idle -> return_unit - | Merging -> - let*! () = Store_events.(emit recover_merge ()) in - merge_temporary_floating block_store)) + let*! status = Stored_data.get block_store.status_data in + if Block_store_status.is_idle status then return_unit + else + let*! () = Store_events.(emit recover_merge ()) in + merge_temporary_floating block_store)) in (* Try to clean temporary file anyway. *) let*! () = may_clean_cementing_artifacts block_store in @@ -1623,7 +1622,7 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = let* status_data = Stored_data.init (Naming.block_store_status_file chain_dir) - ~initial_data:Idle + ~initial_data:Block_store_status.create_idle_status in let block_cache = Block_lru_cache.create @@ -1654,7 +1653,9 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = if not readonly then may_recover_merge block_store else return_unit in let*! status = Stored_data.get status_data in - let* () = fail_unless (status = Idle) Cannot_load_degraded_store in + let* () = + fail_unless (Block_store_status.is_idle status) Cannot_load_degraded_store + in return block_store let create ?block_cache_limit chain_dir ~genesis_block = diff --git a/src/lib_store/unix/block_store.mli b/src/lib_store/unix/block_store.mli index 31b72aef4b36..600b262a9ad1 100644 --- a/src/lib_store/unix/block_store.mli +++ b/src/lib_store/unix/block_store.mli @@ -188,9 +188,7 @@ val caboose : block_store -> block_descriptor Lwt.t val write_caboose : block_store -> block_descriptor -> unit tzresult Lwt.t -val status : block_store -> block_store_status Lwt.t - -val write_status : block_store -> block_store_status -> unit tzresult Lwt.t +val status : block_store -> Block_store_status.t Lwt.t val genesis_block : block_store -> Block_repr.t diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index e74bee8e41f8..5f0f75ef0193 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -1674,7 +1674,7 @@ module Chain = struct (* We mark the merge as on-going to prevent the merge from being triggered and to update on-disk values. *) return_true - | Not_running when store_status <> Idle -> + | Not_running when not @@ Block_store_status.is_idle store_status -> (* Degenerate case, do the same as the Merge_failed case *) let*! () = Store_events.(emit notify_merge_error []) in return_true -- GitLab From 3973d0be447c5288a7f2be35e7f4b07b53cc0c65 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 19 Apr 2024 12:19:56 +0100 Subject: [PATCH 3/4] Store: Move the old block_store_status to legacy --- src/lib_store/shared/naming.ml | 6 ++-- src/lib_store/shared/naming.mli | 5 ++-- src/lib_store/shared/store_types.ml | 42 +++++++++++++++------------- src/lib_store/shared/store_types.mli | 34 +++++++++++----------- src/lib_store/unix/block_store.ml | 27 +++++++++++------- src/lib_store/unix/block_store.mli | 2 +- src/lib_store/unix/store.ml | 3 +- 7 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/lib_store/shared/naming.ml b/src/lib_store/shared/naming.ml index 6b942ad3b995..080a3cafe467 100644 --- a/src/lib_store/shared/naming.ml +++ b/src/lib_store/shared/naming.ml @@ -151,12 +151,12 @@ let caboose_file dir = block_descriptor_encoding Store_types.block_descriptor_equal -let block_store_status_file dir = +let legacy_block_store_status_file dir = make_encoded_file dir ~filename:"status" - Block_store_status.encoding - Block_store_status.equal + Block_store_status.Legacy.encoding + Block_store_status.Legacy.equal let cemented_blocks_dir dir = mk_dir dir "cemented" diff --git a/src/lib_store/shared/naming.mli b/src/lib_store/shared/naming.mli index 61c247254c71..4b36bcf376a3 100644 --- a/src/lib_store/shared/naming.mli +++ b/src/lib_store/shared/naming.mli @@ -133,8 +133,9 @@ val savepoint_file : val caboose_file : [`Chain_dir] directory -> ([`Caboose], block_descriptor) encoded_file -val block_store_status_file : - [`Chain_dir] directory -> ([`Status], Block_store_status.t) encoded_file +val legacy_block_store_status_file : + [`Chain_dir] directory -> + ([`Status], Block_store_status.Legacy.t) encoded_file val cemented_blocks_dir : [< `Chain_dir | `Snapshot_dir | `Snapshot_tmp_dir | `Tar_archive] directory -> diff --git a/src/lib_store/shared/store_types.ml b/src/lib_store/shared/store_types.ml index 4a961a127fb3..e5e167135eea 100644 --- a/src/lib_store/shared/store_types.ml +++ b/src/lib_store/shared/store_types.ml @@ -26,34 +26,36 @@ (* block_store_status *) module Block_store_status = struct - type t = Idle | Merging + module Legacy = struct + type t = Idle | Merging - let set_idle_status status_data = Stored_data.write status_data Idle + let set_idle_status status_data = Stored_data.write status_data Idle - let set_merge_status status_data = Stored_data.write status_data Merging + let set_merge_status status_data = Stored_data.write status_data Merging - let is_idle = function Idle -> true | Merging -> false + let is_idle = function Idle -> true | Merging -> false - let is_merging = function Idle -> false | Merging -> true + let is_merging = function Idle -> false | Merging -> true - let create_idle_status = Idle + let create_idle_status = Idle - let equal s1 s2 = - match (s1, s2) with - | Idle, Idle -> true - | Merging, Merging -> true - | Idle, Merging | Merging, Idle -> false + let equal s1 s2 = + match (s1, s2) with + | Idle, Idle -> true + | Merging, Merging -> true + | Idle, Merging | Merging, Idle -> false - let encoding = - let open Data_encoding in - conv - (function Idle -> false | Merging -> true) - (function false -> Idle | true -> Merging) - bool + let encoding = + let open Data_encoding in + conv + (function Idle -> false | Merging -> true) + (function false -> Idle | true -> Merging) + bool - let pp ppf = function - | Idle -> Format.fprintf ppf "Idle" - | Merging -> Format.fprintf ppf "Merging" + let pp ppf = function + | Idle -> Format.fprintf ppf "Idle" + | Merging -> Format.fprintf ppf "Merging" + end end (* block_descriptor *) diff --git a/src/lib_store/shared/store_types.mli b/src/lib_store/shared/store_types.mli index 94c18dc603a1..17289503755d 100644 --- a/src/lib_store/shared/store_types.mli +++ b/src/lib_store/shared/store_types.mli @@ -26,34 +26,36 @@ (** {1 Global types used in the store library} *) module Block_store_status : sig - (** The type used to describe the status of the store. *) - type t + module Legacy : sig + (** The type used to describe the status of the store. *) + type t - (* Setters *) + (* Setters *) - val set_idle_status : t Stored_data.t -> unit tzresult Lwt.t + val set_idle_status : t Stored_data.t -> unit tzresult Lwt.t - val set_merge_status : t Stored_data.t -> unit tzresult Lwt.t + val set_merge_status : t Stored_data.t -> unit tzresult Lwt.t - (* Status querying *) + (* Status querying *) - val is_idle : t -> bool + val is_idle : t -> bool - val is_merging : t -> bool + val is_merging : t -> bool - (* Initialisers *) + (* Initialisers *) - val create_idle_status : t + val create_idle_status : t - (* Equality function *) - val equal : t -> t -> bool + (* Equality function *) + val equal : t -> t -> bool - (* Encoding *) - val encoding : t Data_encoding.t + (* Encoding *) + val encoding : t Data_encoding.t - (* Printing *) + (* Printing *) - val pp : Format.formatter -> t -> unit + val pp : Format.formatter -> t -> unit + end end (** The type used to describe a block pointer i.e. its hash and level. *) diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index a74f5e460c06..df42bd7f07a0 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -40,7 +40,7 @@ type block_store = { mutable rw_floating_block_store : Floating_block_store.t; caboose : block_descriptor Stored_data.t; savepoint : block_descriptor Stored_data.t; - status_data : Block_store_status.t Stored_data.t; + status_data : Block_store_status.Legacy.t Stored_data.t; block_cache : Block_repr.t Block_lru_cache.t; mutable gc_callback : (Block_hash.t -> unit tzresult Lwt.t) option; mutable split_callback : (unit -> unit tzresult Lwt.t) option; @@ -1383,12 +1383,17 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store let*! store_status = status block_store in let* () = fail_unless - (Block_store_status.is_idle store_status) + (Block_store_status.Legacy.is_idle store_status) (Cannot_merge_store - {status = Format.asprintf "%a" Block_store_status.pp store_status}) + { + status = + Format.asprintf "%a" Block_store_status.Legacy.pp store_status; + }) in (* Mark the store's status as Merging *) - let* () = Block_store_status.set_merge_status block_store.status_data in + let* () = + Block_store_status.Legacy.set_merge_status block_store.status_data + in let new_head_lpbl = Block_repr.last_preserved_block_level new_head_metadata in @@ -1472,7 +1477,7 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store (* The merge operation succeeded, the store is now idle. *) block_store.merging_thread <- None ; let* () = - Block_store_status.set_idle_status + Block_store_status.Legacy.set_idle_status block_store.status_data in return_unit)) @@ -1550,7 +1555,7 @@ let merge_temporary_floating block_store = let*! rw = Floating_block_store.init chain_dir ~readonly:false RW in block_store.ro_floating_block_stores <- [ro] ; block_store.rw_floating_block_store <- rw ; - Block_store_status.set_idle_status block_store.status_data + Block_store_status.Legacy.set_idle_status block_store.status_data (* Removes the potentially leftover temporary files from the cementing of cycles. *) @@ -1583,7 +1588,7 @@ let may_recover_merge block_store = Lwt_idle_waiter.force_idle block_store.merge_scheduler (fun () -> Lwt_mutex.with_lock block_store.merge_mutex (fun () -> let*! status = Stored_data.get block_store.status_data in - if Block_store_status.is_idle status then return_unit + if Block_store_status.Legacy.is_idle status then return_unit else let*! () = Store_events.(emit recover_merge ()) in merge_temporary_floating block_store)) @@ -1621,8 +1626,8 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = (Int32.to_float caboose_level) ; let* status_data = Stored_data.init - (Naming.block_store_status_file chain_dir) - ~initial_data:Block_store_status.create_idle_status + (Naming.legacy_block_store_status_file chain_dir) + ~initial_data:Block_store_status.Legacy.create_idle_status in let block_cache = Block_lru_cache.create @@ -1654,7 +1659,9 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = in let*! status = Stored_data.get status_data in let* () = - fail_unless (Block_store_status.is_idle status) Cannot_load_degraded_store + fail_unless + (Block_store_status.Legacy.is_idle status) + Cannot_load_degraded_store in return block_store diff --git a/src/lib_store/unix/block_store.mli b/src/lib_store/unix/block_store.mli index 600b262a9ad1..47a25d920869 100644 --- a/src/lib_store/unix/block_store.mli +++ b/src/lib_store/unix/block_store.mli @@ -188,7 +188,7 @@ val caboose : block_store -> block_descriptor Lwt.t val write_caboose : block_store -> block_descriptor -> unit tzresult Lwt.t -val status : block_store -> Block_store_status.t Lwt.t +val status : block_store -> Block_store_status.Legacy.t Lwt.t val genesis_block : block_store -> Block_repr.t diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index 5f0f75ef0193..797adc85af50 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -1674,7 +1674,8 @@ module Chain = struct (* We mark the merge as on-going to prevent the merge from being triggered and to update on-disk values. *) return_true - | Not_running when not @@ Block_store_status.is_idle store_status -> + | Not_running + when not @@ Block_store_status.Legacy.is_idle store_status -> (* Degenerate case, do the same as the Merge_failed case *) let*! () = Store_events.(emit notify_merge_error []) in return_true -- GitLab From b0664c7c219cc24b5522f56879888607b17c24ae Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Wed, 24 Apr 2024 12:35:27 +0100 Subject: [PATCH 4/4] Store: Add new block_store_status with version upgrade Co-authored-by: Victor Allombert --- src/lib_node_config/data_version.ml | 29 ++++++++----- src/lib_store/mocked/store.ml | 3 ++ src/lib_store/shared/naming.ml | 7 +++ src/lib_store/shared/naming.mli | 3 ++ src/lib_store/shared/store_events.ml | 16 +++++++ src/lib_store/shared/store_types.ml | 65 ++++++++++++++++++++++++++++ src/lib_store/shared/store_types.mli | 45 ++++++++++++++----- src/lib_store/store.mli | 3 ++ src/lib_store/unix/block_store.ml | 45 +++++++++++-------- src/lib_store/unix/block_store.mli | 5 ++- src/lib_store/unix/store.ml | 15 ++++++- src/lib_store/unix/store.mli | 4 ++ 12 files changed, 198 insertions(+), 42 deletions(-) diff --git a/src/lib_node_config/data_version.ml b/src/lib_node_config/data_version.ml index 4b44db1a237f..5f05bc0c6295 100644 --- a/src/lib_node_config/data_version.ml +++ b/src/lib_node_config/data_version.ml @@ -101,7 +101,8 @@ end * - 1.0 : context upgrade (upgrade to irmin.3.3) -- v14.0 * - 2.0 : introduce context GC (upgrade to irmin.3.4) -- v15.0 * - 3.0 : change blocks' context hash semantics and introduce - context split (upgrade to irmin.3.5) -- v16.0 *) + context split (upgrade to irmin.3.5) -- v16.0 + * - 3.1 : change encoding for block store status -- v21.0 *) (* FIXME https://gitlab.com/tezos/tezos/-/issues/2861 We should enable the semantic versioning instead of applying @@ -118,7 +119,9 @@ let v_2_0 = Version.make ~major:2 ~minor:0 let v_3_0 = Version.make ~major:3 ~minor:0 -let current_version = v_3_0 +let v_3_1 = Version.make ~major:3 ~minor:1 + +let current_version = v_3_1 (* List of upgrade functions from each still supported previous version to the current [data_version] above. If this list grows too @@ -141,29 +144,32 @@ let upgradable_data_version = let*! () = Context.close ctxt in return_unit in - let v_3_0_upgrade ~data_dir genesis = + let v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3 = let store_dir = store_dir data_dir in - Store.v_3_0_upgrade ~store_dir genesis + Store.v_3_1_upgrade ~store_dir genesis ~upgrade_to_v3 in [ ( v_0_6, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:true ); ( v_0_7, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:true ); ( v_0_8, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:true ); ( v_1_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - v_3_0_upgrade ~data_dir genesis ); + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:true ); ( v_2_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - v_3_0_upgrade ~data_dir genesis ); + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:true ); + ( v_3_0, + fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> + v_3_1_upgrade ~data_dir genesis ~upgrade_to_v3:false ); ] type error += Invalid_data_dir_version of Version.t * Version.t @@ -456,8 +462,9 @@ let ensure_data_dir ?(mode = Is_compatible) genesis data_dir = (* Enable automatic upgrade to avoid users to manually upgrade. *) | Some (version, _) when Version.( - equal version v_2_0 || equal version v_1_0 || equal version v_0_6 - || equal version v_0_7 || equal version v_0_8) -> + equal version v_3_0 || equal version v_2_0 || equal version v_1_0 + || equal version v_0_6 || equal version v_0_7 || equal version v_0_8) + -> let* () = upgrade_data_dir ~data_dir genesis ~chain_name:() ~sandbox_parameters:() in diff --git a/src/lib_store/mocked/store.ml b/src/lib_store/mocked/store.ml index ffbe1c1dc9dd..97c38702a887 100644 --- a/src/lib_store/mocked/store.ml +++ b/src/lib_store/mocked/store.ml @@ -2077,3 +2077,6 @@ module Unsafe = struct end let v_3_0_upgrade ~store_dir:_ _genesis = Lwt_result_syntax.return_unit + +let v_3_1_upgrade ~store_dir:_ _genesis ~upgrade_to_v3:_ = + Lwt_result_syntax.return_unit diff --git a/src/lib_store/shared/naming.ml b/src/lib_store/shared/naming.ml index 080a3cafe467..f8716b9d5532 100644 --- a/src/lib_store/shared/naming.ml +++ b/src/lib_store/shared/naming.ml @@ -151,6 +151,13 @@ let caboose_file dir = block_descriptor_encoding Store_types.block_descriptor_equal +let block_store_status_file dir = + make_encoded_file + dir + ~filename:"status" + Block_store_status.encoding + Block_store_status.equal + let legacy_block_store_status_file dir = make_encoded_file dir diff --git a/src/lib_store/shared/naming.mli b/src/lib_store/shared/naming.mli index 4b36bcf376a3..7343d0a99625 100644 --- a/src/lib_store/shared/naming.mli +++ b/src/lib_store/shared/naming.mli @@ -133,6 +133,9 @@ val savepoint_file : val caboose_file : [`Chain_dir] directory -> ([`Caboose], block_descriptor) encoded_file +val block_store_status_file : + [`Chain_dir] directory -> ([`Status], Block_store_status.t) encoded_file + val legacy_block_store_status_file : [`Chain_dir] directory -> ([`Status], Block_store_status.Legacy.t) encoded_file diff --git a/src/lib_store/shared/store_events.ml b/src/lib_store/shared/store_events.ml index 54abbced2f7f..049b4f3e3e8b 100644 --- a/src/lib_store/shared/store_events.ml +++ b/src/lib_store/shared/store_events.ml @@ -201,6 +201,22 @@ let start_retreiving_cycles = ~msg:"retrieving cycles from floating store" () +let load_block_store_status = + declare_0 + ~section + ~level:Info + ~name:"load_block_store_status" + ~msg:"loading using legacy block_store_status encoding" + () + +let fixed_block_store_status = + declare_0 + ~section + ~level:Info + ~name:"fixed_block_store_status" + ~msg:"loading of block store status was successful" + () + let store_is_consistent = declare_0 ~section diff --git a/src/lib_store/shared/store_types.ml b/src/lib_store/shared/store_types.ml index e5e167135eea..ecf81132e337 100644 --- a/src/lib_store/shared/store_types.ml +++ b/src/lib_store/shared/store_types.ml @@ -26,6 +26,64 @@ (* block_store_status *) module Block_store_status = struct + type t = Idle of int | Merging of int + + let get_value status_data = + let open Lwt_syntax in + let* status = Stored_data.get status_data in + match status with + | Idle value -> return value + | Merging value -> return value + + let set_idle_status status_data = + let open Lwt_syntax in + let* status_value = get_value status_data in + Stored_data.write status_data (Idle (status_value + 1)) + + let set_merge_status status_data = + let open Lwt_syntax in + let* status_value = get_value status_data in + Stored_data.write status_data (Merging (status_value + 1)) + + let is_idle = function Idle _ -> true | Merging _ -> false + + let is_merging = function Idle _ -> false | Merging _ -> true + + let create_idle_status = Idle 0 + + let equal s1 s2 = + match (s1, s2) with + | Idle c1, Idle c2 when c1 = c2 -> true + | Merging c1, Merging c2 when c1 = c2 -> true + | Idle _, Idle _ + | Merging _, Merging _ + | Idle _, Merging _ + | Merging _, Idle _ -> + false + + let encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + (Tag 0) + ~title:"idle" + int31 + (function Idle c -> Some c | _ -> None) + (fun c -> Idle c); + case + (Tag 1) + ~title:"merging" + int31 + (function Merging c -> Some c | _ -> None) + (fun c -> Merging c); + ] + + let pp ppf = function + | Idle i -> Format.fprintf ppf "Idle %d" i + | Merging i -> Format.fprintf ppf "Merging %d" i + module Legacy = struct type t = Idle | Merging @@ -56,6 +114,13 @@ module Block_store_status = struct | Idle -> Format.fprintf ppf "Idle" | Merging -> Format.fprintf ppf "Merging" end + + let of_legacy legacy_status_data = + let open Lwt_result_syntax in + let*! legacy_status = Stored_data.get legacy_status_data in + match legacy_status with + | Legacy.Idle -> return (Idle 0) + | Merging -> return (Merging 0) end (* block_descriptor *) diff --git a/src/lib_store/shared/store_types.mli b/src/lib_store/shared/store_types.mli index 17289503755d..e2cce0135071 100644 --- a/src/lib_store/shared/store_types.mli +++ b/src/lib_store/shared/store_types.mli @@ -26,36 +26,59 @@ (** {1 Global types used in the store library} *) module Block_store_status : sig + (** The type used to describe the status of the store. *) + type t + + (* Getters *) + val get_value : t Stored_data.t -> int Lwt.t + + (* Setters *) + + val set_idle_status : t Stored_data.t -> unit tzresult Lwt.t + + val set_merge_status : t Stored_data.t -> unit tzresult Lwt.t + + (* Status querying *) + + val is_idle : t -> bool + + val is_merging : t -> bool + + (* Initialisers *) + + val create_idle_status : t + + (* Equality function *) + val equal : t -> t -> bool + + (* Encoding *) + val encoding : t Data_encoding.t + + (* Printing *) + + val pp : Format.formatter -> t -> unit + module Legacy : sig - (** The type used to describe the status of the store. *) type t - (* Setters *) - val set_idle_status : t Stored_data.t -> unit tzresult Lwt.t val set_merge_status : t Stored_data.t -> unit tzresult Lwt.t - (* Status querying *) - val is_idle : t -> bool val is_merging : t -> bool - (* Initialisers *) - val create_idle_status : t - (* Equality function *) val equal : t -> t -> bool - (* Encoding *) val encoding : t Data_encoding.t - (* Printing *) - val pp : Format.formatter -> t -> unit end + + val of_legacy : Legacy.t Stored_data.t -> t tzresult Lwt.t end (** The type used to describe a block pointer i.e. its hash and level. *) diff --git a/src/lib_store/store.mli b/src/lib_store/store.mli index 7221661a614a..894c4666fda6 100644 --- a/src/lib_store/store.mli +++ b/src/lib_store/store.mli @@ -1021,6 +1021,9 @@ end val v_3_0_upgrade : store_dir:string -> Genesis.t -> unit tzresult Lwt.t +val v_3_1_upgrade : + store_dir:string -> Genesis.t -> upgrade_to_v3:bool -> unit tzresult Lwt.t + (**/**) (** Unsafe set of functions intended for internal store manipulation diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index df42bd7f07a0..f68a9199af87 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -40,7 +40,7 @@ type block_store = { mutable rw_floating_block_store : Floating_block_store.t; caboose : block_descriptor Stored_data.t; savepoint : block_descriptor Stored_data.t; - status_data : Block_store_status.Legacy.t Stored_data.t; + status_data : Block_store_status.t Stored_data.t; block_cache : Block_repr.t Block_lru_cache.t; mutable gc_callback : (Block_hash.t -> unit tzresult Lwt.t) option; mutable split_callback : (unit -> unit tzresult Lwt.t) option; @@ -1383,17 +1383,12 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store let*! store_status = status block_store in let* () = fail_unless - (Block_store_status.Legacy.is_idle store_status) + (Block_store_status.is_idle store_status) (Cannot_merge_store - { - status = - Format.asprintf "%a" Block_store_status.Legacy.pp store_status; - }) + {status = Format.asprintf "%a" Block_store_status.pp store_status}) in (* Mark the store's status as Merging *) - let* () = - Block_store_status.Legacy.set_merge_status block_store.status_data - in + let* () = Block_store_status.set_merge_status block_store.status_data in let new_head_lpbl = Block_repr.last_preserved_block_level new_head_metadata in @@ -1477,7 +1472,7 @@ let merge_stores ?(cycle_size_limit = default_cycle_size_limit) block_store (* The merge operation succeeded, the store is now idle. *) block_store.merging_thread <- None ; let* () = - Block_store_status.Legacy.set_idle_status + Block_store_status.set_idle_status block_store.status_data in return_unit)) @@ -1555,7 +1550,7 @@ let merge_temporary_floating block_store = let*! rw = Floating_block_store.init chain_dir ~readonly:false RW in block_store.ro_floating_block_stores <- [ro] ; block_store.rw_floating_block_store <- rw ; - Block_store_status.Legacy.set_idle_status block_store.status_data + Block_store_status.set_idle_status block_store.status_data (* Removes the potentially leftover temporary files from the cementing of cycles. *) @@ -1588,7 +1583,7 @@ let may_recover_merge block_store = Lwt_idle_waiter.force_idle block_store.merge_scheduler (fun () -> Lwt_mutex.with_lock block_store.merge_mutex (fun () -> let*! status = Stored_data.get block_store.status_data in - if Block_store_status.Legacy.is_idle status then return_unit + if Block_store_status.is_idle status then return_unit else let*! () = Store_events.(emit recover_merge ()) in merge_temporary_floating block_store)) @@ -1626,8 +1621,8 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = (Int32.to_float caboose_level) ; let* status_data = Stored_data.init - (Naming.legacy_block_store_status_file chain_dir) - ~initial_data:Block_store_status.Legacy.create_idle_status + (Naming.block_store_status_file chain_dir) + ~initial_data:Block_store_status.create_idle_status in let block_cache = Block_lru_cache.create @@ -1659,9 +1654,7 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = in let*! status = Stored_data.get status_data in let* () = - fail_unless - (Block_store_status.Legacy.is_idle status) - Cannot_load_degraded_store + fail_unless (Block_store_status.is_idle status) Cannot_load_degraded_store in return block_store @@ -1839,3 +1832,21 @@ let v_3_0_upgrade chain_dir ~cleanups ~finalizers = Lwt.return_unit) in protect (fun () -> List.iter_es upgrade_floating_index all_kinds) + +let v_3_1_upgrade chain_dir = + let open Lwt_result_syntax in + (* Load using the legacy block_store_status encoding *) + let*! () = Store_events.(emit load_block_store_status ()) in + let* legacy_status_data = + Stored_data.init + (Naming.legacy_block_store_status_file chain_dir) + ~initial_data:Block_store_status.Legacy.create_idle_status + in + (* Convert to the new encoding *) + let* status = Block_store_status.of_legacy legacy_status_data in + (* Overwrite the status file *) + let* () = + Stored_data.write_file (Naming.block_store_status_file chain_dir) status + in + let*! () = Store_events.(emit fixed_block_store_status ()) in + return_unit diff --git a/src/lib_store/unix/block_store.mli b/src/lib_store/unix/block_store.mli index 47a25d920869..f1b0172d57c8 100644 --- a/src/lib_store/unix/block_store.mli +++ b/src/lib_store/unix/block_store.mli @@ -188,7 +188,7 @@ val caboose : block_store -> block_descriptor Lwt.t val write_caboose : block_store -> block_descriptor -> unit tzresult Lwt.t -val status : block_store -> Block_store_status.Legacy.t Lwt.t +val status : block_store -> Block_store_status.t Lwt.t val genesis_block : block_store -> Block_repr.t @@ -384,3 +384,6 @@ val v_3_0_upgrade : cleanups:(unit -> unit Lwt.t) list ref -> finalizers:(unit -> unit Lwt.t) list ref -> unit tzresult Lwt.t + +(** Upgrade the block_store_status *) +val v_3_1_upgrade : [`Chain_dir] Naming.directory -> unit tzresult Lwt.t diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index 797adc85af50..f3c3de7aa97d 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -1674,8 +1674,7 @@ module Chain = struct (* We mark the merge as on-going to prevent the merge from being triggered and to update on-disk values. *) return_true - | Not_running - when not @@ Block_store_status.Legacy.is_idle store_status -> + | Not_running when not @@ Block_store_status.is_idle store_status -> (* Degenerate case, do the same as the Merge_failed case *) let*! () = Store_events.(emit notify_merge_error []) in return_true @@ -3247,6 +3246,18 @@ let v_3_0_upgrade ~store_dir genesis = let*! () = List.iter_s (fun f -> f ()) !finalizers in return_unit) +let v_3_1_upgrade ~store_dir genesis ~upgrade_to_v3 = + let open Lwt_result_syntax in + let* () = + if upgrade_to_v3 then v_3_0_upgrade ~store_dir genesis else return_unit + in + (* Hypothesis: v_3_0_upgrade has been run before or is run here *) + let chain_id = Chain_id.of_block_hash genesis.Genesis.block in + let chain_dir = + Naming.chain_dir (Naming.store_dir ~dir_path:store_dir) chain_id + in + Block_store.v_3_1_upgrade chain_dir + (************ For testing and internal purposes only **************) module Unsafe = struct let repr_of_block b = b diff --git a/src/lib_store/unix/store.mli b/src/lib_store/unix/store.mli index 8be00d0f59ad..22bf36322b17 100644 --- a/src/lib_store/unix/store.mli +++ b/src/lib_store/unix/store.mli @@ -1019,6 +1019,10 @@ end {b Warning} Not backward-compatible. *) val v_3_0_upgrade : store_dir:string -> Genesis.t -> unit tzresult Lwt.t +(** Potentially upgrade to v_3 and then upgrade the block_store_status in v_3_1. *) +val v_3_1_upgrade : + store_dir:string -> Genesis.t -> upgrade_to_v3:bool -> unit tzresult Lwt.t + (**/**) (** Unsafe set of functions intended for internal store manipulation -- GitLab