Skip to main content

icydb_core/db/data/
store.rs

1//! Module: data::store
2//! Responsibility: stable BTreeMap-backed row persistence.
3//! Does not own: key/row validation policy beyond type boundaries.
4//! Boundary: commit/executor call into this layer after prevalidation.
5
6use crate::db::data::{CanonicalRow, DataKey, RawDataKey, RawRow};
7use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
8
9///
10/// DataStore
11///
12/// Thin persistence wrapper over one stable BTreeMap.
13///
14/// Invariant: callers provide already-validated `RawDataKey` and canonical row bytes.
15/// This type intentionally does not enforce commit-phase ordering.
16///
17
18pub struct DataStore {
19    map: BTreeMap<RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>>,
20    secondary_covering_authoritative: bool,
21    secondary_existence_witness_authoritative: bool,
22}
23
24impl DataStore {
25    /// Initialize a data store with the provided backing memory.
26    #[must_use]
27    pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
28        Self {
29            map: BTreeMap::init(memory),
30            secondary_covering_authoritative: false,
31            secondary_existence_witness_authoritative: false,
32        }
33    }
34
35    /// Insert or replace one row by raw key.
36    pub(in crate::db) fn insert(&mut self, key: RawDataKey, row: CanonicalRow) -> Option<RawRow> {
37        let previous = self.map.insert(key, row.into_raw_row());
38        self.invalidate_secondary_covering_authority();
39        self.invalidate_secondary_existence_witness_authority();
40
41        previous
42    }
43
44    /// Insert one raw row directly for corruption-focused test setup only.
45    #[cfg(test)]
46    pub(crate) fn insert_raw_for_test(&mut self, key: RawDataKey, row: RawRow) -> Option<RawRow> {
47        let previous = self.map.insert(key, row);
48        self.invalidate_secondary_covering_authority();
49        self.invalidate_secondary_existence_witness_authority();
50
51        previous
52    }
53
54    /// Remove one row by raw key.
55    pub fn remove(&mut self, key: &RawDataKey) -> Option<RawRow> {
56        let previous = self.map.remove(key);
57        self.invalidate_secondary_covering_authority();
58        self.invalidate_secondary_existence_witness_authority();
59
60        previous
61    }
62
63    /// Load one row by raw key.
64    pub fn get(&self, key: &RawDataKey) -> Option<RawRow> {
65        self.map.get(key)
66    }
67
68    /// Return whether one raw key exists without cloning the row payload.
69    #[must_use]
70    pub fn contains(&self, key: &RawDataKey) -> bool {
71        self.map.contains_key(key)
72    }
73
74    /// Clear all stored rows from the data store.
75    pub fn clear(&mut self) {
76        self.map.clear();
77        self.invalidate_secondary_covering_authority();
78        self.invalidate_secondary_existence_witness_authority();
79    }
80
81    /// Return whether this row store currently participates in a synchronized
82    /// secondary-covering authority witness.
83    #[must_use]
84    pub(in crate::db) const fn secondary_covering_authoritative(&self) -> bool {
85        self.secondary_covering_authoritative
86    }
87
88    /// Mark this row store as synchronized with its paired secondary index
89    /// store after successful commit or recovery.
90    pub(in crate::db) const fn mark_secondary_covering_authoritative(&mut self) {
91        self.secondary_covering_authoritative = true;
92    }
93
94    /// Return whether this row store currently participates in an explicit
95    /// secondary existence-witness contract.
96    #[must_use]
97    pub(in crate::db) const fn secondary_existence_witness_authoritative(&self) -> bool {
98        self.secondary_existence_witness_authoritative
99    }
100
101    /// Mark this row store as synchronized with the paired secondary
102    /// existence-witness contract after successful commit, recovery, or a
103    /// storage-owned stale-fixture mutation that updates the witness itself.
104    pub(in crate::db) const fn mark_secondary_existence_witness_authoritative(&mut self) {
105        self.secondary_existence_witness_authoritative = true;
106    }
107
108    /// Sum of bytes used by all stored rows.
109    pub fn memory_bytes(&self) -> u64 {
110        // Report map footprint as key bytes + row bytes per entry.
111        self.iter()
112            .map(|entry| DataKey::STORED_SIZE_BYTES + entry.value().len() as u64)
113            .sum()
114    }
115
116    // Any direct row-store mutation invalidates the secondary covering
117    // authority witness until commit/recovery re-synchronizes the pair.
118    const fn invalidate_secondary_covering_authority(&mut self) {
119        self.secondary_covering_authoritative = false;
120    }
121
122    // Any direct row-store mutation also invalidates the explicit secondary
123    // existence witness until storage or recovery rebuilds it.
124    const fn invalidate_secondary_existence_witness_authority(&mut self) {
125        self.secondary_existence_witness_authoritative = false;
126    }
127}
128
129impl std::ops::Deref for DataStore {
130    type Target = BTreeMap<RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>>;
131
132    fn deref(&self) -> &Self::Target {
133        &self.map
134    }
135}