Skip to main content

reifydb_store_multi/tier/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4pub mod commit;
5pub mod persistent;
6pub mod read;
7
8use std::{collections::HashMap, ops::Bound};
9
10use reifydb_codec::key::encoded::EncodedKey;
11use reifydb_core::{common::CommitVersion, interface::store::EntryKind};
12use reifydb_value::{Result, util::cowvec::CowVec};
13
14use crate::MultiVersionScope;
15
16pub type DisplacedValues = Vec<(EncodedKey, u64)>;
17
18pub type TierBatch = HashMap<EntryKind, Vec<(EncodedKey, Option<CowVec<u8>>)>>;
19
20#[derive(Debug, Clone)]
21pub enum VersionedGetResult {
22	Value {
23		value: CowVec<u8>,
24		version: CommitVersion,
25	},
26
27	Tombstone,
28
29	NotFound,
30}
31
32impl VersionedGetResult {
33	pub fn value(self) -> Option<CowVec<u8>> {
34		match self {
35			VersionedGetResult::Value {
36				value,
37				..
38			} => Some(value),
39			VersionedGetResult::Tombstone | VersionedGetResult::NotFound => None,
40		}
41	}
42}
43
44#[derive(Debug, Clone)]
45pub struct RawEntry {
46	pub key: EncodedKey,
47	pub version: CommitVersion,
48	pub value: Option<CowVec<u8>>,
49}
50
51#[derive(Debug, Clone)]
52pub struct RangeBatch {
53	pub entries: Vec<RawEntry>,
54
55	pub has_more: bool,
56}
57
58impl RangeBatch {
59	pub fn empty() -> Self {
60		Self {
61			entries: Vec::new(),
62			has_more: false,
63		}
64	}
65
66	pub fn is_empty(&self) -> bool {
67		self.entries.is_empty()
68	}
69}
70
71#[derive(Debug, Clone)]
72pub struct RangeCursor {
73	pub last_key: Option<EncodedKey>,
74
75	pub exhausted: bool,
76}
77
78#[derive(Debug, Clone, Default)]
79pub struct HistoricalCursor {
80	pub last_key: Option<EncodedKey>,
81	pub last_version: Option<CommitVersion>,
82	pub exhausted: bool,
83}
84
85impl HistoricalCursor {
86	pub fn new() -> Self {
87		Self::default()
88	}
89
90	pub fn is_exhausted(&self) -> bool {
91		self.exhausted
92	}
93}
94
95impl RangeCursor {
96	pub fn new() -> Self {
97		Self {
98			last_key: None,
99			exhausted: false,
100		}
101	}
102
103	pub fn is_exhausted(&self) -> bool {
104		self.exhausted
105	}
106}
107
108impl Default for RangeCursor {
109	fn default() -> Self {
110		Self::new()
111	}
112}
113
114pub trait TierStorage: Send + Sync + Clone + 'static {
115	fn get(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<VersionedGetResult>;
116
117	fn get_many(
118		&self,
119		table: EntryKind,
120		keys: &[&[u8]],
121		version: CommitVersion,
122	) -> Result<Vec<VersionedGetResult>> {
123		let mut out = Vec::with_capacity(keys.len());
124		for &key in keys {
125			out.push(self.get(table, key, version)?);
126		}
127		Ok(out)
128	}
129
130	fn contains(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<bool> {
131		Ok(matches!(self.get(table, key, version)?, VersionedGetResult::Value { .. }))
132	}
133
134	fn set(&self, version: CommitVersion, batches: TierBatch) -> Result<DisplacedValues>;
135
136	fn range_next(
137		&self,
138		table: EntryKind,
139		cursor: &mut RangeCursor,
140		start: Bound<&[u8]>,
141		end: Bound<&[u8]>,
142		scope: MultiVersionScope,
143		batch_size: usize,
144	) -> Result<RangeBatch>;
145
146	fn range_rev_next(
147		&self,
148		table: EntryKind,
149		cursor: &mut RangeCursor,
150		start: Bound<&[u8]>,
151		end: Bound<&[u8]>,
152		scope: MultiVersionScope,
153		batch_size: usize,
154	) -> Result<RangeBatch>;
155
156	fn ensure_table(&self, table: EntryKind) -> Result<()>;
157
158	fn clear_table(&self, table: EntryKind) -> Result<()>;
159}
160
161pub trait TierBackend: TierStorage {}