ic_memory/ledger/
record.rs1#[cfg(any(test, feature = "test-support"))]
2use super::LedgerIntegrityError;
3use crate::{declaration::AllocationDeclaration, key::StableKey, slot::MemoryManagerSlot};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
18#[serde(deny_unknown_fields)]
19pub struct AllocationLedger {
20 pub(crate) current_generation: u64,
21 #[serde(deserialize_with = "crate::cbor::deserialize_records")]
22 pub(crate) records: Vec<AllocationRecord>,
23}
24
25#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
34#[serde(deny_unknown_fields)]
35pub struct AllocationRecord {
36 pub(crate) stable_key: StableKey,
37 pub(crate) slot: MemoryManagerSlot,
38 pub(crate) state: AllocationState,
39}
40
41#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
49#[serde(deny_unknown_fields)]
50pub enum AllocationState {
51 Reserved,
53 Active,
55 Retired,
57}
58
59#[derive(Clone, Debug, Eq, PartialEq)]
69pub struct RecoveredLedger {
70 ledger: AllocationLedger,
71}
72
73impl RecoveredLedger {
74 pub(crate) fn genesis_for_absent_snapshot(error: &super::LedgerCommitError) -> Option<Self> {
77 matches!(
78 error,
79 super::LedgerCommitError::Recovery(crate::CommitRecoveryError::NoValidGeneration)
80 )
81 .then(|| Self::from_trusted_ledger(AllocationLedger::empty_genesis()))
82 }
83
84 pub(crate) const fn from_trusted_ledger(ledger: AllocationLedger) -> Self {
85 Self { ledger }
86 }
87
88 #[must_use]
90 pub const fn ledger(&self) -> &AllocationLedger {
91 &self.ledger
92 }
93
94 #[must_use]
96 #[cfg(test)]
97 pub const fn current_generation(&self) -> u64 {
98 self.ledger.current_generation
99 }
100
101 pub(crate) fn into_ledger(self) -> AllocationLedger {
102 self.ledger
103 }
104}
105
106impl AllocationRecord {
107 pub(crate) fn from_declaration(
108 declaration: &AllocationDeclaration,
109 state: AllocationState,
110 ) -> Self {
111 Self {
112 stable_key: declaration.stable_key.clone(),
113 slot: declaration.slot.clone(),
114 state,
115 }
116 }
117
118 pub(crate) fn active(declaration: &AllocationDeclaration) -> Self {
119 Self::from_declaration(declaration, AllocationState::Active)
120 }
121
122 #[cfg(test)]
123 pub(crate) fn reserved(declaration: &AllocationDeclaration) -> Self {
124 Self::from_declaration(declaration, AllocationState::Reserved)
125 }
126
127 #[must_use]
129 pub const fn stable_key(&self) -> &StableKey {
130 &self.stable_key
131 }
132
133 #[must_use]
135 pub const fn slot(&self) -> &MemoryManagerSlot {
136 &self.slot
137 }
138
139 #[must_use]
141 pub const fn state(&self) -> AllocationState {
142 self.state
143 }
144}
145
146impl AllocationLedger {
147 pub(crate) const fn empty_genesis() -> Self {
148 Self {
149 current_generation: 0,
150 records: Vec::new(),
151 }
152 }
153
154 #[cfg(any(test, feature = "test-support"))]
157 pub fn new(
158 current_generation: u64,
159 records: Vec<AllocationRecord>,
160 ) -> Result<Self, LedgerIntegrityError> {
161 let ledger = Self {
162 current_generation,
163 records,
164 };
165 ledger.validate_integrity()?;
166 Ok(ledger)
167 }
168
169 #[must_use]
171 pub const fn current_generation(&self) -> u64 {
172 self.current_generation
173 }
174
175 #[must_use]
177 pub fn records(&self) -> &[AllocationRecord] {
178 &self.records
179 }
180
181 pub(crate) fn occupied_slots(&self) -> [bool; crate::constants::MAX_ALLOCATIONS] {
183 let mut occupied = [false; crate::constants::MAX_ALLOCATIONS];
184 for record in &self.records {
185 occupied[usize::from(record.slot.id())] = true;
186 }
187 occupied
188 }
189}