From b110b5b2f5ba77735de7c56514154a5b388aea01 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 12 Apr 2023 12:29:39 +0200 Subject: [PATCH 1/3] SCORU/Node: use a lock file to prevent access to rollup node data --- src/proto_alpha/lib_sc_rollup_node/event.ml | 10 +++++ src/proto_alpha/lib_sc_rollup_node/event.mli | 4 ++ .../lib_sc_rollup_node/node_context.ml | 41 ++++++++++++++++++- .../lib_sc_rollup_node/node_context.mli | 2 + .../sc_rollup_node_errors.ml | 19 ++++++++- 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/event.ml b/src/proto_alpha/lib_sc_rollup_node/event.ml index ea2fa9aaa35e..79b27226eef8 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.ml +++ b/src/proto_alpha/lib_sc_rollup_node/event.ml @@ -124,6 +124,14 @@ module Simple = struct "Warning: DAL is enabled in the protocol but no DAL node was provided \ for the rollup node." () + + let acquiring_lock = + declare_0 + ~section + ~name:"acquiring_lock" + ~level:Notice + ~msg:"Acquiring lock on data directory." + () end let starting_node = Simple.(emit starting_node) @@ -157,3 +165,5 @@ let kernel_debug_dont_wait msg = Simple.(emit__dont_wait__use_with_care kernel_debug) msg let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () + +let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_alpha/lib_sc_rollup_node/event.mli b/src/proto_alpha/lib_sc_rollup_node/event.mli index cad046f4fe71..188c37b99008 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.mli +++ b/src/proto_alpha/lib_sc_rollup_node/event.mli @@ -75,3 +75,7 @@ val kernel_debug_dont_wait : string -> unit (** [warn_dal_enabled_no_node ()] emits a warning for when DAL is enabled in the protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t + +(** [acquiring_lock ()] emits an event to indicate that the node is attempting + to acquire a lock on the data directory. *) +val acquiring_lock : unit -> unit Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.ml b/src/proto_alpha/lib_sc_rollup_node/node_context.ml index da0689f47a99..9579bedbf958 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -47,6 +47,7 @@ type 'a t = { fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; loser_mode : Loser_mode.t; + lockfile : Lwt_unix.file_descr; store : 'a store; context : 'a Context.index; lcc : ('a, lcc) Reference.t; @@ -129,6 +130,38 @@ let check_and_set_rollup_address context rollup_address = fail_unless Sc_rollup.Address.(rollup_address = saved_address) @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} +let lock ~data_dir = + let lockfile_path = Filename.concat data_dir "lock" in + let lock_aux ~data_dir = + let open Lwt_result_syntax in + let*! () = Event.acquiring_lock () in + let*! () = Lwt_utils_unix.create_dir data_dir in + let* lockfile = + protect @@ fun () -> + Lwt_unix.openfile + lockfile_path + [Unix.O_CREAT; O_RDWR; O_CLOEXEC; O_SYNC] + 0o644 + |> Lwt_result.ok + in + let* () = + protect ~on_error:(fun err -> + let*! () = Lwt_unix.close lockfile in + fail err) + @@ fun () -> + let*! () = Lwt_unix.lockf lockfile Unix.F_LOCK 0 in + return_unit + in + return lockfile + in + trace (Sc_rollup_node_errors.Could_not_acquire_lock lockfile_path) + @@ lock_aux ~data_dir + +let unlock {lockfile; _} = + Lwt.finalize + (fun () -> Lwt_unix.lockf lockfile Unix.F_ULOCK 0) + (fun () -> Lwt_unix.close lockfile) + let init (cctxt : Protocol_client_context.full) ~data_dir mode Configuration.( { @@ -143,6 +176,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode _; } as configuration) = let open Lwt_result_syntax in + let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint in @@ -208,11 +242,12 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode fee_parameters; protocol_constants; loser_mode; + lockfile; store; context; } -let close {cctxt; store; context; l1_ctxt; _} = +let close ({cctxt; store; context; l1_ctxt; _} as node_ctxt) = let open Lwt_result_syntax in let message = cctxt#message in let*! () = message "Shutting down L1@." in @@ -221,6 +256,8 @@ let close {cctxt; store; context; l1_ctxt; _} = let*! () = Context.close context in let*! () = message "Closing store@." in let* () = Store.close store in + let*! () = message "Releasing lock@." in + let*! () = unlock node_ctxt in return_unit let checkout_context node_ctxt block_hash = @@ -757,6 +794,7 @@ module Internal_for_tests = struct |> Data_encoding.Binary.to_bytes_exn Constants_repr.encoding |> Data_encoding.Binary.of_bytes_exn Constants.encoding in + let* lockfile = lock ~data_dir in let* store = Store.load Read_write @@ -794,6 +832,7 @@ module Internal_for_tests = struct fee_parameters = Configuration.default_fee_parameters; protocol_constants; loser_mode = Loser_mode.no_failures; + lockfile; store; context; } diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.mli b/src/proto_alpha/lib_sc_rollup_node/node_context.mli index 5e1123e56da6..7fc8e343c708 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -65,6 +65,8 @@ type 'a t = { loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) + lockfile : Lwt_unix.file_descr; + (** A lock file acquired when the node starts. *) store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) diff --git a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml index c0b3197a1bbe..b00d2cb1e556 100644 --- a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -57,6 +57,7 @@ type error += | No_publisher | Refutation_player_failed_to_start | No_refutation_coordinator + | Could_not_acquire_lock of string type error += Lost_game of Protocol.Alpha_context.Sc_rollup.Game.game_result @@ -345,4 +346,20 @@ let () = `Permanent Data_encoding.unit (function Refutation_player_failed_to_start -> Some () | _ -> None) - (fun () -> Refutation_player_failed_to_start) + (fun () -> Refutation_player_failed_to_start) ; + + register_error_kind + `Permanent + ~id:"could_not_acquire_lock" + ~title:"Could not acquire lock on data dir" + ~description:"Could not acquire lock on data dir." + ~pp:(fun ppf f -> + Format.fprintf + ppf + "Could not acquire lock on data directory, another rollup node may \ + already be running with this data. If this is not the case, consider \ + removing manually the file %S" + f) + Data_encoding.(obj1 (req "lock_file" string)) + (function Could_not_acquire_lock f -> Some f | _ -> None) + (fun f -> Could_not_acquire_lock f) -- GitLab From 29cd7b66657843ad4b67e8e0e8139e0b243730c4 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 12 Apr 2023 12:29:39 +0200 Subject: [PATCH 2/3] SCORU/Node: Backport !8447 to Mumbai rollup node - SCORU/Node: use a lock file to prevent access to rollup node data --- .../lib_sc_rollup_node/event.ml | 10 +++++ .../lib_sc_rollup_node/event.mli | 4 ++ .../lib_sc_rollup_node/node_context.ml | 41 ++++++++++++++++++- .../lib_sc_rollup_node/node_context.mli | 2 + .../sc_rollup_node_errors.ml | 19 ++++++++- 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml index ea2fa9aaa35e..79b27226eef8 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml @@ -124,6 +124,14 @@ module Simple = struct "Warning: DAL is enabled in the protocol but no DAL node was provided \ for the rollup node." () + + let acquiring_lock = + declare_0 + ~section + ~name:"acquiring_lock" + ~level:Notice + ~msg:"Acquiring lock on data directory." + () end let starting_node = Simple.(emit starting_node) @@ -157,3 +165,5 @@ let kernel_debug_dont_wait msg = Simple.(emit__dont_wait__use_with_care kernel_debug) msg let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () + +let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli index cad046f4fe71..188c37b99008 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli @@ -75,3 +75,7 @@ val kernel_debug_dont_wait : string -> unit (** [warn_dal_enabled_no_node ()] emits a warning for when DAL is enabled in the protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t + +(** [acquiring_lock ()] emits an event to indicate that the node is attempting + to acquire a lock on the data directory. *) +val acquiring_lock : unit -> unit Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml index 8e679744649d..7232ef3eb7fe 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml @@ -46,6 +46,7 @@ type 'a t = { fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; loser_mode : Loser_mode.t; + lockfile : Lwt_unix.file_descr; store : 'a store; context : 'a Context.index; lcc : ('a, lcc) Reference.t; @@ -128,6 +129,38 @@ let check_and_set_rollup_address context rollup_address = fail_unless Sc_rollup.Address.(rollup_address = saved_address) @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} +let lock ~data_dir = + let lockfile_path = Filename.concat data_dir "lock" in + let lock_aux ~data_dir = + let open Lwt_result_syntax in + let*! () = Event.acquiring_lock () in + let*! () = Lwt_utils_unix.create_dir data_dir in + let* lockfile = + protect @@ fun () -> + Lwt_unix.openfile + lockfile_path + [Unix.O_CREAT; O_RDWR; O_CLOEXEC; O_SYNC] + 0o644 + |> Lwt_result.ok + in + let* () = + protect ~on_error:(fun err -> + let*! () = Lwt_unix.close lockfile in + fail err) + @@ fun () -> + let*! () = Lwt_unix.lockf lockfile Unix.F_LOCK 0 in + return_unit + in + return lockfile + in + trace (Sc_rollup_node_errors.Could_not_acquire_lock lockfile_path) + @@ lock_aux ~data_dir + +let unlock {lockfile; _} = + Lwt.finalize + (fun () -> Lwt_unix.lockf lockfile Unix.F_ULOCK 0) + (fun () -> Lwt_unix.close lockfile) + let init (cctxt : Protocol_client_context.full) ~data_dir mode Configuration.( { @@ -142,6 +175,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode _; } as configuration) = let open Lwt_result_syntax in + let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint in @@ -194,11 +228,12 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode fee_parameters; protocol_constants; loser_mode; + lockfile; store; context; } -let close {cctxt; store; context; l1_ctxt; _} = +let close ({cctxt; store; context; l1_ctxt; _} as node_ctxt) = let open Lwt_result_syntax in let message = cctxt#message in let*! () = message "Shutting down L1@." in @@ -207,6 +242,8 @@ let close {cctxt; store; context; l1_ctxt; _} = let*! () = Context.close context in let*! () = message "Closing store@." in let* () = Store.close store in + let*! () = message "Releasing lock@." in + let*! () = unlock node_ctxt in return_unit let checkout_context node_ctxt block_hash = @@ -758,6 +795,7 @@ module Internal_for_tests = struct |> Data_encoding.Binary.to_bytes_exn Constants_repr.encoding |> Data_encoding.Binary.of_bytes_exn Constants.encoding in + let* lockfile = lock ~data_dir in let* store = Store.load Read_write @@ -794,6 +832,7 @@ module Internal_for_tests = struct fee_parameters = Configuration.default_fee_parameters; protocol_constants; loser_mode = Loser_mode.no_failures; + lockfile; store; context; } diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli index 03fb62b860c4..65c7fb4bba07 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli @@ -63,6 +63,8 @@ type 'a t = { loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) + lockfile : Lwt_unix.file_descr; + (** A lock file acquired when the node starts. *) store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml index c0b3197a1bbe..b00d2cb1e556 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -57,6 +57,7 @@ type error += | No_publisher | Refutation_player_failed_to_start | No_refutation_coordinator + | Could_not_acquire_lock of string type error += Lost_game of Protocol.Alpha_context.Sc_rollup.Game.game_result @@ -345,4 +346,20 @@ let () = `Permanent Data_encoding.unit (function Refutation_player_failed_to_start -> Some () | _ -> None) - (fun () -> Refutation_player_failed_to_start) + (fun () -> Refutation_player_failed_to_start) ; + + register_error_kind + `Permanent + ~id:"could_not_acquire_lock" + ~title:"Could not acquire lock on data dir" + ~description:"Could not acquire lock on data dir." + ~pp:(fun ppf f -> + Format.fprintf + ppf + "Could not acquire lock on data directory, another rollup node may \ + already be running with this data. If this is not the case, consider \ + removing manually the file %S" + f) + Data_encoding.(obj1 (req "lock_file" string)) + (function Could_not_acquire_lock f -> Some f | _ -> None) + (fun f -> Could_not_acquire_lock f) -- GitLab From 9cb23653455cd6af7b49542f5965f62f38da0d4a Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 12 Apr 2023 12:29:39 +0200 Subject: [PATCH 3/3] SCORU/Node: Backport !8447 to Nairobi rollup node - SCORU/Node: use a lock file to prevent access to rollup node data --- .../lib_sc_rollup_node/event.ml | 10 +++++ .../lib_sc_rollup_node/event.mli | 4 ++ .../lib_sc_rollup_node/node_context.ml | 41 ++++++++++++++++++- .../lib_sc_rollup_node/node_context.mli | 2 + .../sc_rollup_node_errors.ml | 19 ++++++++- 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml index ea2fa9aaa35e..79b27226eef8 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml @@ -124,6 +124,14 @@ module Simple = struct "Warning: DAL is enabled in the protocol but no DAL node was provided \ for the rollup node." () + + let acquiring_lock = + declare_0 + ~section + ~name:"acquiring_lock" + ~level:Notice + ~msg:"Acquiring lock on data directory." + () end let starting_node = Simple.(emit starting_node) @@ -157,3 +165,5 @@ let kernel_debug_dont_wait msg = Simple.(emit__dont_wait__use_with_care kernel_debug) msg let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () + +let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli index cad046f4fe71..188c37b99008 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli @@ -75,3 +75,7 @@ val kernel_debug_dont_wait : string -> unit (** [warn_dal_enabled_no_node ()] emits a warning for when DAL is enabled in the protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t + +(** [acquiring_lock ()] emits an event to indicate that the node is attempting + to acquire a lock on the data directory. *) +val acquiring_lock : unit -> unit Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml index e80c753579cc..62282c4ee321 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml @@ -46,6 +46,7 @@ type 'a t = { fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; loser_mode : Loser_mode.t; + lockfile : Lwt_unix.file_descr; store : 'a store; context : 'a Context.index; lcc : ('a, lcc) Reference.t; @@ -128,6 +129,38 @@ let check_and_set_rollup_address context rollup_address = fail_unless Sc_rollup.Address.(rollup_address = saved_address) @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} +let lock ~data_dir = + let lockfile_path = Filename.concat data_dir "lock" in + let lock_aux ~data_dir = + let open Lwt_result_syntax in + let*! () = Event.acquiring_lock () in + let*! () = Lwt_utils_unix.create_dir data_dir in + let* lockfile = + protect @@ fun () -> + Lwt_unix.openfile + lockfile_path + [Unix.O_CREAT; O_RDWR; O_CLOEXEC; O_SYNC] + 0o644 + |> Lwt_result.ok + in + let* () = + protect ~on_error:(fun err -> + let*! () = Lwt_unix.close lockfile in + fail err) + @@ fun () -> + let*! () = Lwt_unix.lockf lockfile Unix.F_LOCK 0 in + return_unit + in + return lockfile + in + trace (Sc_rollup_node_errors.Could_not_acquire_lock lockfile_path) + @@ lock_aux ~data_dir + +let unlock {lockfile; _} = + Lwt.finalize + (fun () -> Lwt_unix.lockf lockfile Unix.F_ULOCK 0) + (fun () -> Lwt_unix.close lockfile) + let init (cctxt : Protocol_client_context.full) ~data_dir mode Configuration.( { @@ -142,6 +175,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode _; } as configuration) = let open Lwt_result_syntax in + let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint in @@ -194,11 +228,12 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode fee_parameters; protocol_constants; loser_mode; + lockfile; store; context; } -let close {cctxt; store; context; l1_ctxt; _} = +let close ({cctxt; store; context; l1_ctxt; _} as node_ctxt) = let open Lwt_result_syntax in let message = cctxt#message in let*! () = message "Shutting down L1@." in @@ -207,6 +242,8 @@ let close {cctxt; store; context; l1_ctxt; _} = let*! () = Context.close context in let*! () = message "Closing store@." in let* () = Store.close store in + let*! () = message "Releasing lock@." in + let*! () = unlock node_ctxt in return_unit let checkout_context node_ctxt block_hash = @@ -743,6 +780,7 @@ module Internal_for_tests = struct |> Data_encoding.Binary.to_bytes_exn Constants_repr.encoding |> Data_encoding.Binary.of_bytes_exn Constants.encoding in + let* lockfile = lock ~data_dir in let* store = Store.load Read_write @@ -779,6 +817,7 @@ module Internal_for_tests = struct fee_parameters = Configuration.default_fee_parameters; protocol_constants; loser_mode = Loser_mode.no_failures; + lockfile; store; context; } diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli index 7583b4377195..55897abfc7c6 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli @@ -63,6 +63,8 @@ type 'a t = { loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) + lockfile : Lwt_unix.file_descr; + (** A lock file acquired when the node starts. *) store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml index c0b3197a1bbe..b00d2cb1e556 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -57,6 +57,7 @@ type error += | No_publisher | Refutation_player_failed_to_start | No_refutation_coordinator + | Could_not_acquire_lock of string type error += Lost_game of Protocol.Alpha_context.Sc_rollup.Game.game_result @@ -345,4 +346,20 @@ let () = `Permanent Data_encoding.unit (function Refutation_player_failed_to_start -> Some () | _ -> None) - (fun () -> Refutation_player_failed_to_start) + (fun () -> Refutation_player_failed_to_start) ; + + register_error_kind + `Permanent + ~id:"could_not_acquire_lock" + ~title:"Could not acquire lock on data dir" + ~description:"Could not acquire lock on data dir." + ~pp:(fun ppf f -> + Format.fprintf + ppf + "Could not acquire lock on data directory, another rollup node may \ + already be running with this data. If this is not the case, consider \ + removing manually the file %S" + f) + Data_encoding.(obj1 (req "lock_file" string)) + (function Could_not_acquire_lock f -> Some f | _ -> None) + (fun f -> Could_not_acquire_lock f) -- GitLab