SpaceOS block storage layout
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Thomas Gazagnaire. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** SpaceOS block storage layout.
7
8 Wraps a {!Block.t} with the SpaceOS storage layout:
9
10 {v
11 Block 0 Superblock (48 bytes)
12 Blocks 1-16 Parameter store (252-byte entries)
13 Blocks 17-32 Event log ring buffer (76-byte records)
14 Blocks 33+ Data product area
15 v} *)
16
17(** {1 Storage Handle} *)
18
19type t
20(** A SpaceOS block storage handle. *)
21
22val block : t -> Block.t
23(** [block t] returns the underlying block device. *)
24
25(** {1 Lifecycle} *)
26
27val v :
28 Block.t -> tenant_id:int -> uuid:string -> epoch:int64 -> (t, string) result
29(** [v blk ~tenant_id ~uuid ~epoch] initializes a block device with the SpaceOS
30 storage layout. Writes the superblock and zeros the parameter and event log
31 areas. *)
32
33val open_ : Block.t -> (t, string) result
34(** [open_ blk] reads and validates the superblock from an existing device. *)
35
36(** {1 Superblock} *)
37
38val superblock : t -> Space_wire.Superblock.t
39(** [superblock t] returns the validated superblock. *)
40
41(** {1 Parameter Store} *)
42
43val max_params : t -> int
44(** [max_params t] returns the maximum number of parameter slots. *)
45
46val read_param : t -> slot:int -> (Space_wire.Param_entry.t, string) result
47(** [read_param t ~slot] reads a parameter entry from the given slot (0-based
48 index within the parameter area). *)
49
50val write_param :
51 t -> slot:int -> Space_wire.Param_entry.t -> (unit, string) result
52(** [write_param t ~slot entry] writes a parameter entry to the given slot. *)
53
54val param : t -> id:int -> (Space_wire.Param_entry.t option, string) result
55(** [param t ~id] scans all parameter slots and returns the entry with matching
56 [id] and the highest generation, or [None] if not found. *)
57
58val put_param : t -> id:int -> string -> (unit, string) result
59(** [put_param t ~id value] writes a new parameter entry with the given [id] and
60 [value]. The generation is set to one more than the highest existing
61 generation for that [id]. Writes to the first free slot. *)
62
63val latest_params : t -> (Space_wire.Param_entry.t list, string) result
64(** [latest_params t] returns one entry per param_id, each with the highest
65 generation found in the parameter store. *)
66
67(** {1 Event Log} *)
68
69val read_event_pointer : t -> (int, string) result
70(** [read_event_pointer t] reads the current write pointer (record index). *)
71
72val read_event : t -> index:int -> (Space_wire.Event_log.t, string) result
73(** [read_event t ~index] reads an event log record at the given index. *)
74
75val write_event : t -> Space_wire.Event_log.t -> (unit, string) result
76(** [write_event t entry] appends an event to the ring buffer, advancing the
77 write pointer. *)
78
79val event_count : t -> (int, string) result
80(** [event_count t] returns the number of events written (the write pointer). *)
81
82val recent_events :
83 t -> count:int -> (Space_wire.Event_log.t list, string) result
84(** [recent_events t ~count] returns the [count] most recent events in
85 chronological order. Returns fewer if fewer have been written. *)
86
87(** {1 Data Product Area} *)
88
89val dp_start : t -> int
90(** [dp_start t] returns the first block of the DP area. *)
91
92val dp_size : t -> int
93(** [dp_size t] returns the number of blocks in the DP area. *)
94
95val read_dp : t -> offset:int -> (Space_wire.Dp_payload.t, string) result
96(** [read_dp t ~offset] reads a DP payload from the given block offset within
97 the DP area. *)
98
99val write_dp :
100 t -> offset:int -> Space_wire.Dp_payload.t -> (unit, string) result
101(** [write_dp t ~offset payload] writes a DP payload at the given block offset
102 within the DP area. *)
103
104val dp_catalog : t -> (Space_wire.Dp_payload.t list, string) result
105(** [dp_catalog t] reads the DP catalog from block 0 of the DP area. Returns the
106 list of registered data products. *)
107
108val dp : t -> name:string -> (Space_wire.Dp_payload.t option, string) result
109(** [dp t ~name] scans the catalog for a DP with the given name. *)
110
111val write_dp_data :
112 t ->
113 dp_class:int ->
114 priority:int ->
115 name:string ->
116 string ->
117 (Space_wire.Dp_payload.t, string) result
118(** [write_dp_data t ~dp_class ~priority ~name data] computes a CRC over [data],
119 allocates blocks in the DP area, writes [data], and appends a catalog entry.
120 Returns the new catalog entry. *)
121
122val read_dp_data : t -> Space_wire.Dp_payload.t -> (string, string) result
123(** [read_dp_data t dp] reads the raw block data for a DP entry. The returned
124 string may be padded to sector boundaries. *)
125
126(** {1 Pretty Printing} *)
127
128val pp : t Fmt.t
129(** [pp ppf t] prints a summary of the storage layout. *)