icydb_core/db/data/
store.rs1use crate::{
7 db::{
8 data::{CanonicalRow, RawDataStoreKey, RawRow},
9 key_taxonomy::RawDataStoreKeyRange,
10 },
11 types::EntityTag,
12};
13use ic_memory::stable_structures::{
14 BTreeMap, DefaultMemoryImpl, btreemap::Iter, memory_manager::VirtualMemory,
15};
16#[cfg(feature = "diagnostics")]
17use std::cell::Cell;
18use std::ops::RangeBounds;
19
20#[cfg(feature = "diagnostics")]
21thread_local! {
22 static DATA_STORE_GET_CALL_COUNT: Cell<u64> = const { Cell::new(0) };
23}
24
25#[cfg(feature = "diagnostics")]
26fn record_data_store_get_call() {
27 DATA_STORE_GET_CALL_COUNT.with(|count| {
28 count.set(count.get().saturating_add(1));
29 });
30}
31
32pub struct DataStore {
42 map: BTreeMap<RawDataStoreKey, RawRow, VirtualMemory<DefaultMemoryImpl>>,
43}
44
45impl DataStore {
46 #[must_use]
48 pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
49 Self {
50 map: BTreeMap::init(memory),
51 }
52 }
53
54 pub(in crate::db) fn insert(
56 &mut self,
57 key: RawDataStoreKey,
58 row: CanonicalRow,
59 ) -> Option<RawRow> {
60 self.map.insert(key, row.into_raw_row())
61 }
62
63 #[cfg(test)]
65 pub(in crate::db) fn insert_raw_for_test(
66 &mut self,
67 key: RawDataStoreKey,
68 row: RawRow,
69 ) -> Option<RawRow> {
70 self.map.insert(key, row)
71 }
72
73 pub(in crate::db) fn remove(&mut self, key: &RawDataStoreKey) -> Option<RawRow> {
75 self.map.remove(key)
76 }
77
78 pub(in crate::db) fn get(&self, key: &RawDataStoreKey) -> Option<RawRow> {
80 #[cfg(feature = "diagnostics")]
81 record_data_store_get_call();
82
83 self.map.get(key)
84 }
85
86 #[must_use]
88 pub(in crate::db) fn contains(&self, key: &RawDataStoreKey) -> bool {
89 self.map.contains_key(key)
90 }
91
92 #[cfg(test)]
94 pub(in crate::db) fn clear(&mut self) {
95 self.map.clear_new();
96 }
97
98 #[must_use]
100 pub(in crate::db) fn len(&self) -> u64 {
101 self.map.len()
102 }
103
104 #[must_use]
106 #[cfg(test)]
107 pub(in crate::db) fn is_empty(&self) -> bool {
108 self.map.is_empty()
109 }
110
111 pub(in crate::db) fn entries(
113 &self,
114 ) -> Iter<'_, RawDataStoreKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
115 self.map.iter()
116 }
117
118 pub(in crate::db) fn range(
120 &self,
121 key_range: impl RangeBounds<RawDataStoreKey>,
122 ) -> Iter<'_, RawDataStoreKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
123 self.map.range(key_range)
124 }
125
126 pub(in crate::db) fn range_for_entity(
128 &self,
129 entity: EntityTag,
130 ) -> Iter<'_, RawDataStoreKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
131 let range = RawDataStoreKeyRange::entity_prefix(entity);
132 self.map.range(RawDataStoreKey::store_range_bounds(&range))
133 }
134
135 pub(in crate::db) fn memory_bytes(&self) -> u64 {
137 self.entries()
139 .map(|entry| entry.key().as_bytes().len() as u64 + entry.value().len() as u64)
140 .sum()
141 }
142
143 #[cfg(feature = "diagnostics")]
145 pub(in crate::db) fn current_get_call_count() -> u64 {
146 DATA_STORE_GET_CALL_COUNT.with(Cell::get)
147 }
148}