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