Skip to main content

ic_memory/ledger/
error.rs

1use crate::{
2    key::{StableKey, StableKeyError},
3    ledger::LedgerPayloadEnvelopeError,
4    physical::CommitRecoveryError,
5    slot::MemoryManagerSlot,
6};
7
8///
9/// LedgerIntegrityError
10///
11/// Decoded ledger violates current ownership invariants.
12///
13
14#[non_exhaustive]
15#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
16pub enum LedgerIntegrityError {
17    /// Current structural recovery ceiling exceeded.
18    #[error("ledger exceeds {resource} limit {limit}")]
19    LimitExceeded {
20        resource: &'static str,
21        limit: usize,
22    },
23    /// Stable key appears in more than one retained allocation record.
24    #[error("stable key '{stable_key}' appears in more than one allocation record")]
25    DuplicateStableKey { stable_key: StableKey },
26    /// Memory ID appears in more than one retained allocation record.
27    #[error("allocation slot '{slot:?}' appears in more than one allocation record")]
28    DuplicateSlot { slot: MemoryManagerSlot },
29    /// Commit counter zero is reserved for empty genesis.
30    #[error("genesis ledger contains allocation records")]
31    NonemptyGenesis,
32}
33
34///
35/// LedgerCommitError
36///
37/// Failure to recover or commit a logical allocation ledger.
38#[non_exhaustive]
39#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
40pub enum LedgerCommitError {
41    /// Protected physical commit recovery failed.
42    #[error(transparent)]
43    Recovery(CommitRecoveryError),
44    /// Logical ledger payload envelope could not be decoded.
45    #[error(transparent)]
46    PayloadEnvelope(LedgerPayloadEnvelopeError),
47    /// Physical slot generation and decoded logical ledger generation disagree.
48    #[error(
49        "physical generation {physical_generation} does not match logical ledger generation {logical_generation}"
50    )]
51    PhysicalLogicalGenerationMismatch {
52        /// Generation encoded in the physical commit slot.
53        physical_generation: u64,
54        /// Generation decoded from the logical allocation ledger.
55        logical_generation: u64,
56    },
57    /// Built-in ledger decoding failed.
58    #[error("allocation ledger codec failed: {0}")]
59    Codec(String),
60    /// Decoded ledger violates current ownership invariants.
61    #[error(transparent)]
62    Integrity(LedgerIntegrityError),
63}
64
65///
66/// AllocationStageError
67///
68/// Failure to stage a validated allocation generation.
69///
70
71#[non_exhaustive]
72#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
73pub enum AllocationStageError {
74    /// The commit counter cannot advance without overflow.
75    #[error("ledger generation {generation} cannot be advanced without overflow")]
76    GenerationOverflow { generation: u64 },
77    #[error(transparent)]
78    Integrity(#[from] LedgerIntegrityError),
79    /// Validated declarations were produced against a different ledger generation.
80    #[error(
81        "validated allocations were produced at generation {validated_generation}, but ledger is at generation {ledger_generation}"
82    )]
83    StaleValidatedAllocations {
84        /// Generation carried by the validated allocation capability.
85        validated_generation: u64,
86        /// Current ledger generation.
87        ledger_generation: u64,
88    },
89    /// Stable key was historically bound to a different slot.
90    #[error("stable key '{stable_key}' was historically bound to a different allocation slot")]
91    StableKeySlotConflict {
92        /// Stable key being declared.
93        stable_key: StableKey,
94        /// Historical slot for the stable key.
95        historical_slot: MemoryManagerSlot,
96        /// Slot claimed by the declaration.
97        declared_slot: MemoryManagerSlot,
98    },
99    /// Slot was historically bound to a different stable key.
100    #[error("allocation slot '{slot:?}' was historically bound to stable key '{historical_key}'")]
101    SlotStableKeyConflict {
102        /// Slot being declared.
103        slot: MemoryManagerSlot,
104        /// Historical stable key for the slot.
105        historical_key: StableKey,
106        /// Stable key claimed by the declaration.
107        declared_key: StableKey,
108    },
109    /// Current declaration attempted to revive a retired allocation.
110    #[error("stable key '{stable_key}' was explicitly retired and cannot be redeclared")]
111    RetiredAllocation {
112        /// Retired stable key.
113        stable_key: StableKey,
114        /// Retired allocation slot.
115        slot: MemoryManagerSlot,
116    },
117}
118
119///
120/// AllocationReservationError
121///
122/// Failure to stage a reservation generation.
123#[non_exhaustive]
124#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
125pub enum AllocationReservationError {
126    #[error(transparent)]
127    Integrity(#[from] LedgerIntegrityError),
128    /// Ledger generation cannot be advanced without overflow.
129    #[error("ledger generation {generation} cannot be advanced without overflow")]
130    GenerationOverflow {
131        /// Current ledger generation.
132        generation: u64,
133    },
134    /// Reservation count exceeds the usable allocation-slot domain.
135    #[error("generation contains {count} reservations, exceeding the 255-allocation limit")]
136    TooManyReservations {
137        /// Number of reservations in the staged generation.
138        count: usize,
139    },
140    /// Stable key was historically bound to a different slot.
141    #[error("stable key '{stable_key}' was historically bound to a different allocation slot")]
142    StableKeySlotConflict {
143        /// Stable key being reserved.
144        stable_key: StableKey,
145        /// Historical slot for the stable key.
146        historical_slot: MemoryManagerSlot,
147        /// Slot claimed by the reservation.
148        reserved_slot: MemoryManagerSlot,
149    },
150    /// Slot was historically bound to a different stable key.
151    #[error("allocation slot '{slot:?}' was historically bound to stable key '{historical_key}'")]
152    SlotStableKeyConflict {
153        /// Slot being reserved.
154        slot: MemoryManagerSlot,
155        /// Historical stable key for the slot.
156        historical_key: StableKey,
157        /// Stable key claimed by the reservation.
158        reserved_key: StableKey,
159    },
160    /// Allocation already exists as an active record.
161    #[error("stable key '{stable_key}' is already active and cannot be reserved")]
162    ActiveAllocation {
163        /// Active stable key.
164        stable_key: StableKey,
165        /// Active allocation slot.
166        slot: MemoryManagerSlot,
167    },
168    /// Allocation was already retired and cannot be reserved.
169    #[error("stable key '{stable_key}' was explicitly retired and cannot be reserved")]
170    RetiredAllocation {
171        /// Retired stable key.
172        stable_key: StableKey,
173        /// Retired allocation slot.
174        slot: MemoryManagerSlot,
175    },
176}
177
178///
179/// AllocationRetirementError
180///
181/// Failure to stage an explicit retirement generation.
182#[non_exhaustive]
183#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
184pub enum AllocationRetirementError {
185    #[error(transparent)]
186    Integrity(#[from] LedgerIntegrityError),
187    /// Stable-key grammar failure.
188    #[error(transparent)]
189    Key(StableKeyError),
190    /// Ledger generation cannot be advanced without overflow.
191    #[error("ledger generation {generation} cannot be advanced without overflow")]
192    GenerationOverflow {
193        /// Current ledger generation.
194        generation: u64,
195    },
196    /// Stable key has no historical allocation record.
197    #[error("stable key '{0}' has no allocation record to retire")]
198    UnknownStableKey(StableKey),
199    /// Stable key was historically bound to a different slot.
200    #[error("stable key '{stable_key}' cannot be retired for a different allocation slot")]
201    SlotMismatch {
202        /// Stable key being retired.
203        stable_key: StableKey,
204        /// Historical slot for the stable key.
205        historical_slot: MemoryManagerSlot,
206        /// Slot named by the retirement request.
207        retired_slot: MemoryManagerSlot,
208    },
209    /// Allocation was already retired.
210    #[error("stable key '{stable_key}' was already retired")]
211    AlreadyRetired {
212        /// Retired stable key.
213        stable_key: StableKey,
214        /// Retired allocation slot.
215        slot: MemoryManagerSlot,
216    },
217}