reifydb_store_multi/tier/commit/
buffer.rs1use std::{collections::HashMap, ops::Bound};
5
6use reifydb_codec::key::encoded::EncodedKey;
7use reifydb_core::{
8 common::CommitVersion,
9 interface::store::EntryKind,
10 metrics::{collect::MetricsCollector, sample::MetricsSample},
11};
12use reifydb_value::{Result, byte_size::ByteSize, util::cowvec::CowVec};
13
14use crate::{
15 MultiVersionScope,
16 tier::{
17 DisplacedValues, HistoricalCursor, RangeBatch, RangeCursor, TierBackend, TierBatch, TierStorage,
18 VersionedGetResult,
19 commit::memory::storage::{EvictedVersion, MemoryRowStorage},
20 },
21};
22
23#[derive(Clone)]
24#[repr(u8)]
25pub enum MultiCommitBufferTier {
26 Memory(MemoryRowStorage) = 0,
27}
28
29impl MultiCommitBufferTier {
30 pub fn memory() -> Self {
31 Self::Memory(MemoryRowStorage::new())
32 }
33}
34
35impl MultiCommitBufferTier {
36 pub fn maintenance(&self) {
37 match self {
38 Self::Memory(_) => {}
39 }
40 }
41
42 pub fn count_current(&self, table: EntryKind) -> Result<u64> {
43 match self {
44 Self::Memory(s) => s.count_current(table),
45 }
46 }
47
48 pub fn count_historical(&self, table: EntryKind) -> Result<u64> {
49 match self {
50 Self::Memory(s) => s.count_historical(table),
51 }
52 }
53
54 pub fn list_all_entry_kinds(&self) -> Result<Vec<EntryKind>> {
55 match self {
56 Self::Memory(s) => s.list_all_entry_kinds(),
57 }
58 }
59
60 pub fn list_entry_kinds_by_oldest_pending(&self) -> Result<Vec<EntryKind>> {
61 match self {
62 Self::Memory(s) => s.list_entry_kinds_by_oldest_pending(),
63 }
64 }
65
66 pub fn oldest_pending_for(&self, kind: EntryKind) -> Option<CommitVersion> {
67 match self {
68 Self::Memory(s) => s.oldest_pending_for(kind),
69 }
70 }
71
72 pub fn oldest_pending_version(&self) -> Option<CommitVersion> {
73 match self {
74 Self::Memory(s) => s.oldest_pending_version(),
75 }
76 }
77
78 pub fn current_resident_bytes(&self) -> ByteSize {
79 match self {
80 Self::Memory(s) => s.current_resident_bytes(),
81 }
82 }
83
84 pub fn historical_resident_bytes(&self) -> ByteSize {
85 match self {
86 Self::Memory(s) => s.historical_resident_bytes(),
87 }
88 }
89
90 #[inline]
91 pub fn compact(
92 &self,
93 batches: HashMap<EntryKind, Vec<(EncodedKey, CommitVersion)>>,
94 ) -> Result<Vec<EvictedVersion>> {
95 match self {
96 Self::Memory(s) => s.compact(batches),
97 }
98 }
99
100 #[inline]
101 pub fn get_all_versions(
102 &self,
103 table: EntryKind,
104 key: &[u8],
105 ) -> Result<Vec<(CommitVersion, Option<CowVec<u8>>)>> {
106 match self {
107 Self::Memory(s) => s.get_all_versions(table, key),
108 }
109 }
110
111 #[inline]
112 pub fn scan_historical_below(
113 &self,
114 table: EntryKind,
115 cutoff: CommitVersion,
116 cursor: &mut HistoricalCursor,
117 batch_size: usize,
118 ) -> Result<Vec<(EncodedKey, CommitVersion)>> {
119 match self {
120 Self::Memory(s) => s.scan_historical_below(table, cutoff, cursor, batch_size),
121 }
122 }
123}
124
125impl MetricsCollector for MultiCommitBufferTier {
126 fn collect(&self, out: &mut Vec<MetricsSample>) {
127 out.push(MetricsSample::heap("commit_buffer", "current_bytes", self.current_resident_bytes()));
128 out.push(MetricsSample::heap("commit_buffer", "historical_bytes", self.historical_resident_bytes()));
129 let kinds = self.list_all_entry_kinds().unwrap_or_default();
130 out.push(MetricsSample::count("commit_buffer", "table_count", kinds.len() as u64));
131 let current_entries: u64 = kinds.iter().map(|kind| self.count_current(*kind).unwrap_or(0)).sum();
132 out.push(MetricsSample::count("commit_buffer", "current_entries", current_entries));
133 }
134}
135
136impl TierStorage for MultiCommitBufferTier {
137 #[inline]
138 fn get(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<VersionedGetResult> {
139 match self {
140 Self::Memory(s) => s.get(table, key, version),
141 }
142 }
143
144 #[inline]
145 fn contains(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<bool> {
146 match self {
147 Self::Memory(s) => s.contains(table, key, version),
148 }
149 }
150
151 #[inline]
152 fn set(&self, version: CommitVersion, batches: TierBatch) -> Result<DisplacedValues> {
153 match self {
154 Self::Memory(s) => s.set(version, batches),
155 }
156 }
157
158 #[inline]
159 fn range_next(
160 &self,
161 table: EntryKind,
162 cursor: &mut RangeCursor,
163 start: Bound<&[u8]>,
164 end: Bound<&[u8]>,
165 scope: MultiVersionScope,
166 batch_size: usize,
167 ) -> Result<RangeBatch> {
168 match self {
169 Self::Memory(s) => s.range_next(table, cursor, start, end, scope, batch_size),
170 }
171 }
172
173 #[inline]
174 fn range_rev_next(
175 &self,
176 table: EntryKind,
177 cursor: &mut RangeCursor,
178 start: Bound<&[u8]>,
179 end: Bound<&[u8]>,
180 scope: MultiVersionScope,
181 batch_size: usize,
182 ) -> Result<RangeBatch> {
183 match self {
184 Self::Memory(s) => s.range_rev_next(table, cursor, start, end, scope, batch_size),
185 }
186 }
187
188 #[inline]
189 fn ensure_table(&self, table: EntryKind) -> Result<()> {
190 match self {
191 Self::Memory(s) => s.ensure_table(table),
192 }
193 }
194
195 #[inline]
196 fn clear_table(&self, table: EntryKind) -> Result<()> {
197 match self {
198 Self::Memory(s) => s.clear_table(table),
199 }
200 }
201}
202
203impl TierBackend for MultiCommitBufferTier {}
204
205#[cfg(test)]
206pub mod tests {
207 use super::*;
208
209 #[test]
210 fn test_memory_backend() {
211 let storage = MultiCommitBufferTier::memory();
212
213 let key = EncodedKey::new(b"key");
214 let version = CommitVersion(1);
215
216 storage.set(
217 version,
218 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"value".to_vec())))])]),
219 )
220 .unwrap();
221 assert_eq!(
222 storage.get(EntryKind::Multi, &key, version).unwrap().value().as_deref(),
223 Some(b"value".as_slice())
224 );
225 }
226
227 #[test]
228 fn test_range_next_memory() {
229 let storage = MultiCommitBufferTier::memory();
230
231 let version = CommitVersion(1);
232 storage.set(
233 version,
234 HashMap::from([(
235 EntryKind::Multi,
236 vec![
237 (EncodedKey::new(b"a"), Some(CowVec::new(b"1".to_vec()))),
238 (EncodedKey::new(b"b"), Some(CowVec::new(b"2".to_vec()))),
239 (EncodedKey::new(b"c"), Some(CowVec::new(b"3".to_vec()))),
240 ],
241 )]),
242 )
243 .unwrap();
244
245 let mut cursor = RangeCursor::new();
246 let batch = storage
247 .range_next(
248 EntryKind::Multi,
249 &mut cursor,
250 Bound::Unbounded,
251 Bound::Unbounded,
252 MultiVersionScope::AsOf {
253 read: version,
254 },
255 100,
256 )
257 .unwrap();
258
259 assert_eq!(batch.entries.len(), 3);
260 assert!(!batch.has_more);
261 assert!(cursor.exhausted);
262 }
263}