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 candid::CandidType;
15use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
16use serde::Deserialize;
17
18#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
26pub enum IndexState {
27 Building,
28 #[default]
29 Ready,
30 Dropping,
31}
32
33impl IndexState {
34 #[must_use]
36 pub const fn as_str(self) -> &'static str {
37 match self {
38 Self::Building => "building",
39 Self::Ready => "ready",
40 Self::Dropping => "dropping",
41 }
42 }
43}
44
45pub struct IndexStore {
54 pub(super) map: BTreeMap<RawIndexKey, RawIndexEntry, VirtualMemory<DefaultMemoryImpl>>,
55 generation: u64,
56 state: IndexState,
57}
58
59impl IndexStore {
60 #[must_use]
61 pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
62 Self {
63 map: BTreeMap::init(memory),
64 generation: 0,
65 state: IndexState::Ready,
68 }
69 }
70
71 #[expect(clippy::redundant_closure_for_method_calls)]
73 pub(crate) fn entries(&self) -> Vec<(RawIndexKey, RawIndexEntry)> {
74 self.map.iter().map(|entry| entry.into_pair()).collect()
75 }
76
77 pub(in crate::db) fn get(&self, key: &RawIndexKey) -> Option<RawIndexEntry> {
78 self.map.get(key)
79 }
80
81 pub fn len(&self) -> u64 {
82 self.map.len()
83 }
84
85 pub fn is_empty(&self) -> bool {
86 self.map.is_empty()
87 }
88
89 #[must_use]
90 pub(in crate::db) const fn generation(&self) -> u64 {
91 self.generation
92 }
93
94 #[must_use]
96 pub(in crate::db) const fn state(&self) -> IndexState {
97 self.state
98 }
99
100 pub(in crate::db) const fn mark_building(&mut self) {
103 self.state = IndexState::Building;
104 }
105
106 pub(in crate::db) const fn mark_ready(&mut self) {
108 self.state = IndexState::Ready;
109 }
110
111 pub(in crate::db) const fn mark_dropping(&mut self) {
113 self.state = IndexState::Dropping;
114 }
115
116 pub(crate) fn insert(
117 &mut self,
118 key: RawIndexKey,
119 entry: RawIndexEntry,
120 ) -> Option<RawIndexEntry> {
121 let previous = self.map.insert(key, entry);
122 self.bump_generation();
123 previous
124 }
125
126 pub(crate) fn remove(&mut self, key: &RawIndexKey) -> Option<RawIndexEntry> {
127 let previous = self.map.remove(key);
128 self.bump_generation();
129 previous
130 }
131
132 pub fn clear(&mut self) {
133 self.map.clear();
134 self.bump_generation();
135 }
136
137 pub(in crate::db) fn mark_memberships_missing_for_storage_key(
140 &mut self,
141 storage_key: StorageKey,
142 ) -> Result<usize, InternalError> {
143 let mut entries = Vec::new();
144
145 for entry in self.map.iter() {
146 entries.push(entry.into_pair());
147 }
148
149 let mut marked = 0usize;
150
151 for (raw_key, mut raw_entry) in entries {
152 if raw_entry
153 .mark_key_missing(storage_key)
154 .map_err(InternalError::index_entry_decode_failed)?
155 {
156 self.map.insert(raw_key, raw_entry);
157 marked = marked.saturating_add(1);
158 }
159 }
160
161 if marked > 0 {
162 self.bump_generation();
163 }
164
165 Ok(marked)
166 }
167
168 pub fn memory_bytes(&self) -> u64 {
170 self.map
171 .iter()
172 .map(|entry| entry.key().as_bytes().len() as u64 + entry.value().len() as u64)
173 .sum()
174 }
175
176 const fn bump_generation(&mut self) {
177 self.generation = self.generation.saturating_add(1);
178 }
179}