icydb_core/db/index/
store.rs1use crate::{
7 db::{
8 data::StorageKey,
9 index::{entry::RawIndexEntry, key::RawIndexKey},
10 },
11 error::InternalError,
12};
13
14use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
15
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
24pub enum IndexState {
25 Building,
26 Valid,
27 Dropping,
28}
29
30pub struct IndexStore {
39 pub(super) map: BTreeMap<RawIndexKey, RawIndexEntry, VirtualMemory<DefaultMemoryImpl>>,
40 generation: u64,
41 state: IndexState,
42 secondary_covering_authoritative: bool,
43 secondary_existence_witness_authoritative: bool,
44}
45
46impl IndexStore {
47 #[must_use]
48 pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
49 Self {
50 map: BTreeMap::init(memory),
51 generation: 0,
52 state: IndexState::Valid,
56 secondary_covering_authoritative: false,
57 secondary_existence_witness_authoritative: false,
58 }
59 }
60
61 #[allow(clippy::redundant_closure_for_method_calls)]
63 pub(crate) fn entries(&self) -> Vec<(RawIndexKey, RawIndexEntry)> {
64 self.map.iter().map(|entry| entry.into_pair()).collect()
65 }
66
67 pub(in crate::db) fn get(&self, key: &RawIndexKey) -> Option<RawIndexEntry> {
68 self.map.get(key)
69 }
70
71 pub fn len(&self) -> u64 {
72 self.map.len()
73 }
74
75 pub fn is_empty(&self) -> bool {
76 self.map.is_empty()
77 }
78
79 #[must_use]
80 pub(in crate::db) const fn generation(&self) -> u64 {
81 self.generation
82 }
83
84 #[must_use]
86 pub(in crate::db) const fn state(&self) -> IndexState {
87 self.state
88 }
89
90 #[must_use]
92 pub(in crate::db) const fn is_valid(&self) -> bool {
93 matches!(self.state, IndexState::Valid)
94 }
95
96 pub(in crate::db) const fn mark_building(&mut self) {
99 self.state = IndexState::Building;
100 self.invalidate_secondary_covering_authority();
101 self.invalidate_secondary_existence_witness_authority();
102 }
103
104 pub(in crate::db) const fn mark_valid(&mut self) {
107 self.state = IndexState::Valid;
108 }
109
110 pub(in crate::db) const fn mark_dropping(&mut self) {
113 self.state = IndexState::Dropping;
114 self.invalidate_secondary_covering_authority();
115 self.invalidate_secondary_existence_witness_authority();
116 }
117
118 pub(crate) fn insert(
119 &mut self,
120 key: RawIndexKey,
121 entry: RawIndexEntry,
122 ) -> Option<RawIndexEntry> {
123 let previous = self.map.insert(key, entry);
124 self.bump_generation();
125 self.invalidate_secondary_covering_authority();
126 self.invalidate_secondary_existence_witness_authority();
127 previous
128 }
129
130 pub(crate) fn remove(&mut self, key: &RawIndexKey) -> Option<RawIndexEntry> {
131 let previous = self.map.remove(key);
132 self.bump_generation();
133 self.invalidate_secondary_covering_authority();
134 self.invalidate_secondary_existence_witness_authority();
135 previous
136 }
137
138 pub fn clear(&mut self) {
139 self.map.clear();
140 self.bump_generation();
141 self.invalidate_secondary_covering_authority();
142 self.invalidate_secondary_existence_witness_authority();
143 }
144
145 #[must_use]
148 pub(in crate::db) const fn secondary_covering_authoritative(&self) -> bool {
149 self.secondary_covering_authoritative
150 }
151
152 pub(in crate::db) fn mark_secondary_covering_authoritative(&mut self) {
155 debug_assert!(
156 self.is_valid(),
157 "secondary covering authority must not be restored while the index is Building or Dropping",
158 );
159 self.secondary_covering_authoritative = true;
160 }
161
162 #[must_use]
165 pub(in crate::db) const fn secondary_existence_witness_authoritative(&self) -> bool {
166 self.secondary_existence_witness_authoritative
167 }
168
169 pub(in crate::db) fn mark_secondary_existence_witness_authoritative(&mut self) {
172 debug_assert!(
173 self.is_valid(),
174 "storage existence witness authority must not be restored while the index is Building or Dropping",
175 );
176 self.secondary_existence_witness_authoritative = true;
177 }
178
179 pub(in crate::db) fn mark_memberships_missing_for_storage_key(
182 &mut self,
183 storage_key: StorageKey,
184 ) -> Result<usize, InternalError> {
185 let mut entries = Vec::new();
186
187 for entry in self.map.iter() {
188 entries.push(entry.into_pair());
189 }
190
191 let mut marked = 0usize;
192
193 for (raw_key, mut raw_entry) in entries {
194 if raw_entry
195 .mark_key_missing(storage_key)
196 .map_err(InternalError::index_entry_decode_failed)?
197 {
198 self.map.insert(raw_key, raw_entry);
199 marked = marked.saturating_add(1);
200 }
201 }
202
203 if marked > 0 {
204 self.bump_generation();
205 self.invalidate_secondary_covering_authority();
206 self.invalidate_secondary_existence_witness_authority();
207 }
208
209 Ok(marked)
210 }
211
212 pub fn memory_bytes(&self) -> u64 {
214 self.map
215 .iter()
216 .map(|entry| entry.key().as_bytes().len() as u64 + entry.value().len() as u64)
217 .sum()
218 }
219
220 const fn bump_generation(&mut self) {
221 self.generation = self.generation.saturating_add(1);
222 }
223
224 const fn invalidate_secondary_covering_authority(&mut self) {
225 self.secondary_covering_authoritative = false;
226 }
227
228 const fn invalidate_secondary_existence_witness_authority(&mut self) {
229 self.secondary_existence_witness_authoritative = false;
230 }
231}