Skip to main content

reifydb_store_multi/buffer/
tier.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::{collections::HashMap, ops::Bound};
5
6use reifydb_core::{common::CommitVersion, encoded::key::EncodedKey, interface::store::EntryKind};
7use reifydb_type::{Result, util::cowvec::CowVec};
8
9use super::memory::storage::MemoryPrimitiveStorage;
10use crate::tier::{HistoricalCursor, RangeBatch, RangeCursor, TierBackend, TierBatch, TierStorage};
11
12#[derive(Clone)]
13#[repr(u8)]
14pub enum MultiBufferTier {
15	Memory(MemoryPrimitiveStorage) = 0,
16}
17
18impl MultiBufferTier {
19	pub fn memory() -> Self {
20		Self::Memory(MemoryPrimitiveStorage::new())
21	}
22}
23
24impl MultiBufferTier {
25	pub fn maintenance(&self) {
26		match self {
27			Self::Memory(_) => {}
28		}
29	}
30
31	pub fn count_current(&self, table: EntryKind) -> Result<u64> {
32		match self {
33			Self::Memory(s) => s.count_current(table),
34		}
35	}
36
37	pub fn count_historical(&self, table: EntryKind) -> Result<u64> {
38		match self {
39			Self::Memory(s) => s.count_historical(table),
40		}
41	}
42
43	pub fn list_all_entry_kinds(&self) -> Result<Vec<EntryKind>> {
44		match self {
45			Self::Memory(s) => s.list_all_entry_kinds(),
46		}
47	}
48}
49
50impl TierStorage for MultiBufferTier {
51	#[inline]
52	fn get(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<Option<CowVec<u8>>> {
53		match self {
54			Self::Memory(s) => s.get(table, key, version),
55		}
56	}
57
58	#[inline]
59	fn contains(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<bool> {
60		match self {
61			Self::Memory(s) => s.contains(table, key, version),
62		}
63	}
64
65	#[inline]
66	fn set(&self, version: CommitVersion, batches: TierBatch) -> Result<()> {
67		match self {
68			Self::Memory(s) => s.set(version, batches),
69		}
70	}
71
72	#[inline]
73	fn range_next(
74		&self,
75		table: EntryKind,
76		cursor: &mut RangeCursor,
77		start: Bound<&[u8]>,
78		end: Bound<&[u8]>,
79		version: CommitVersion,
80		batch_size: usize,
81	) -> Result<RangeBatch> {
82		match self {
83			Self::Memory(s) => s.range_next(table, cursor, start, end, version, batch_size),
84		}
85	}
86
87	#[inline]
88	fn range_rev_next(
89		&self,
90		table: EntryKind,
91		cursor: &mut RangeCursor,
92		start: Bound<&[u8]>,
93		end: Bound<&[u8]>,
94		version: CommitVersion,
95		batch_size: usize,
96	) -> Result<RangeBatch> {
97		match self {
98			Self::Memory(s) => s.range_rev_next(table, cursor, start, end, version, batch_size),
99		}
100	}
101
102	#[inline]
103	fn ensure_table(&self, table: EntryKind) -> Result<()> {
104		match self {
105			Self::Memory(s) => s.ensure_table(table),
106		}
107	}
108
109	#[inline]
110	fn clear_table(&self, table: EntryKind) -> Result<()> {
111		match self {
112			Self::Memory(s) => s.clear_table(table),
113		}
114	}
115
116	#[inline]
117	fn drop(&self, batches: HashMap<EntryKind, Vec<(EncodedKey, CommitVersion)>>) -> Result<()> {
118		match self {
119			Self::Memory(s) => s.drop(batches),
120		}
121	}
122
123	#[inline]
124	fn get_all_versions(&self, table: EntryKind, key: &[u8]) -> Result<Vec<(CommitVersion, Option<CowVec<u8>>)>> {
125		match self {
126			Self::Memory(s) => s.get_all_versions(table, key),
127		}
128	}
129
130	#[inline]
131	fn scan_historical_below(
132		&self,
133		table: EntryKind,
134		cutoff: CommitVersion,
135		cursor: &mut HistoricalCursor,
136		batch_size: usize,
137	) -> Result<Vec<(EncodedKey, CommitVersion)>> {
138		match self {
139			Self::Memory(s) => s.scan_historical_below(table, cutoff, cursor, batch_size),
140		}
141	}
142}
143
144impl TierBackend for MultiBufferTier {}
145
146#[cfg(test)]
147pub mod tests {
148	use super::*;
149
150	#[test]
151	fn test_memory_backend() {
152		let storage = MultiBufferTier::memory();
153
154		let key = EncodedKey::new(b"key".to_vec());
155		let version = CommitVersion(1);
156
157		storage.set(
158			version,
159			HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"value".to_vec())))])]),
160		)
161		.unwrap();
162		assert_eq!(storage.get(EntryKind::Multi, &key, version).unwrap().as_deref(), Some(b"value".as_slice()));
163	}
164
165	#[test]
166	fn test_range_next_memory() {
167		let storage = MultiBufferTier::memory();
168
169		let version = CommitVersion(1);
170		storage.set(
171			version,
172			HashMap::from([(
173				EntryKind::Multi,
174				vec![
175					(EncodedKey::new(b"a".to_vec()), Some(CowVec::new(b"1".to_vec()))),
176					(EncodedKey::new(b"b".to_vec()), Some(CowVec::new(b"2".to_vec()))),
177					(EncodedKey::new(b"c".to_vec()), Some(CowVec::new(b"3".to_vec()))),
178				],
179			)]),
180		)
181		.unwrap();
182
183		let mut cursor = RangeCursor::new();
184		let batch = storage
185			.range_next(EntryKind::Multi, &mut cursor, Bound::Unbounded, Bound::Unbounded, version, 100)
186			.unwrap();
187
188		assert_eq!(batch.entries.len(), 3);
189		assert!(!batch.has_more);
190		assert!(cursor.exhausted);
191	}
192}