1#![cfg_attr(not(debug_assertions), deny(clippy::disallowed_methods))]
9#![cfg_attr(debug_assertions, warn(clippy::disallowed_methods))]
10#![cfg_attr(not(debug_assertions), deny(warnings))]
11#![allow(clippy::tabs_in_doc_comments)]
12
13use reifydb_core::{
14 event::EventBus,
15 interface::version::{ComponentType, HasVersion, SystemVersion},
16};
17use reifydb_value::Result;
18
19pub mod flush;
20pub mod tier;
21
22pub mod config;
23pub mod store;
24
25use std::{collections::HashMap, sync::Arc};
26
27use config::{CommitBufferConfig, MultiStoreConfig};
28use reifydb_codec::key::encoded::{EncodedKey, EncodedKeyRange};
29use reifydb_core::{
30 common::CommitVersion,
31 delta::Delta,
32 interface::store::{
33 MultiVersionCommit, MultiVersionContains, MultiVersionGet, MultiVersionGetPrevious, MultiVersionRow,
34 MultiVersionStore,
35 },
36 metrics::collect::MetricsCollector,
37};
38use reifydb_runtime::shutdown::Shutdown;
39#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
40use reifydb_sqlite::SqliteTempPathGuard;
41use reifydb_value::util::cowvec::CowVec;
42use store::StandardMultiStore;
43use tier::read::ReadBufferShardMetrics;
44
45pub mod memory {}
46pub mod sqlite {}
47
48pub struct MultiStoreVersion;
49
50impl HasVersion for MultiStoreVersion {
51 fn version(&self) -> SystemVersion {
52 SystemVersion {
53 name: env!("CARGO_PKG_NAME")
54 .strip_prefix("reifydb-")
55 .unwrap_or(env!("CARGO_PKG_NAME"))
56 .to_string(),
57 version: env!("CARGO_PKG_VERSION").to_string(),
58 description: "Multi-version storage for OLTP operations with MVCC support".to_string(),
59 r#type: ComponentType::Module,
60 }
61 }
62}
63
64#[repr(u8)]
65#[derive(Clone)]
66pub enum MultiStore {
67 Standard(StandardMultiStore) = 0,
68}
69
70impl MultiStore {
71 pub fn standard(config: MultiStoreConfig) -> Self {
72 Self::Standard(StandardMultiStore::new(config).unwrap())
73 }
74}
75
76impl MultiStore {
77 pub fn testing_memory() -> Self {
78 MultiStore::Standard(StandardMultiStore::testing_memory())
79 }
80
81 pub fn testing_memory_with_eventbus(event_bus: EventBus) -> Self {
82 MultiStore::Standard(StandardMultiStore::testing_memory_with_eventbus(event_bus))
83 }
84
85 #[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
86 pub fn testing_memory_with_persistent_sqlite() -> (Self, SqliteTempPathGuard) {
87 let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite();
88 (MultiStore::Standard(store), guard)
89 }
90
91 #[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
92 pub fn testing_memory_with_persistent_sqlite_with_eventbus(event_bus: EventBus) -> (Self, SqliteTempPathGuard) {
93 let (store, guard) = StandardMultiStore::testing_memory_with_persistent_sqlite_with_eventbus(event_bus);
94 (MultiStore::Standard(store), guard)
95 }
96
97 pub fn flush_pending_blocking(&self) {
98 match self {
99 MultiStore::Standard(store) => store.flush_pending_blocking(),
100 }
101 }
102
103 pub fn flush_all_blocking(&self) {
104 match self {
105 MultiStore::Standard(store) => store.flush_all_blocking(),
106 }
107 }
108
109 pub fn commit(&self) -> &tier::commit::buffer::MultiCommitBufferTier {
110 match self {
111 MultiStore::Standard(store) => store.commit(),
112 }
113 }
114
115 pub fn metrics_collectors(&self) -> Vec<Arc<dyn MetricsCollector>> {
116 match self {
117 MultiStore::Standard(store) => store.metrics_collectors(),
118 }
119 }
120
121 pub fn read_buffer_shard_metrics(&self) -> Vec<ReadBufferShardMetrics> {
122 match self {
123 MultiStore::Standard(store) => store.read_buffer_shard_metrics(),
124 }
125 }
126
127 pub fn persistent(&self) -> Option<&tier::persistent::MultiPersistentTier> {
128 match self {
129 MultiStore::Standard(store) => store.persistent(),
130 }
131 }
132
133 pub fn clear_eviction_watermark(&self) {
134 match self {
135 MultiStore::Standard(store) => store.clear_eviction_watermark(),
136 }
137 }
138}
139
140impl Shutdown for MultiStore {
141 fn shutdown(&self) {
142 match self {
143 MultiStore::Standard(store) => store.shutdown(),
144 }
145 }
146}
147
148impl MultiVersionGet for MultiStore {
149 #[inline]
150 fn get(&self, key: &EncodedKey, version: CommitVersion) -> Result<Option<MultiVersionRow>> {
151 match self {
152 MultiStore::Standard(store) => MultiVersionGet::get(store, key, version),
153 }
154 }
155}
156
157impl MultiVersionContains for MultiStore {
158 #[inline]
159 fn contains(&self, key: &EncodedKey, version: CommitVersion) -> Result<bool> {
160 match self {
161 MultiStore::Standard(store) => MultiVersionContains::contains(store, key, version),
162 }
163 }
164}
165
166impl MultiVersionCommit for MultiStore {
167 #[inline]
168 fn commit(&self, deltas: CowVec<Delta>, version: CommitVersion) -> Result<()> {
169 match self {
170 MultiStore::Standard(store) => MultiVersionCommit::commit(store, deltas, version),
171 }
172 }
173}
174
175impl MultiVersionGetPrevious for MultiStore {
176 #[inline]
177 fn get_previous_version(
178 &self,
179 key: &EncodedKey,
180 before_version: CommitVersion,
181 ) -> Result<Option<MultiVersionRow>> {
182 match self {
183 MultiStore::Standard(store) => store.get_previous_version(key, before_version),
184 }
185 }
186}
187
188pub type MultiVersionRangeIterator<'a> = Box<dyn Iterator<Item = Result<MultiVersionRow>> + Send + 'a>;
189
190#[derive(Debug, Copy, Clone, PartialEq, Eq)]
192pub enum MultiVersionScope {
193 AsOf {
195 read: CommitVersion,
196 },
197 Between {
200 after: CommitVersion,
201 read: CommitVersion,
202 },
203}
204
205impl MultiVersionScope {
206 #[inline]
207 pub fn read(&self) -> CommitVersion {
208 match self {
209 Self::AsOf {
210 read,
211 }
212 | Self::Between {
213 read,
214 ..
215 } => *read,
216 }
217 }
218
219 #[inline]
220 pub fn contains(&self, v: CommitVersion) -> bool {
221 match self {
222 Self::AsOf {
223 read,
224 } => v <= *read,
225 Self::Between {
226 after,
227 read,
228 } => v > *after && v <= *read,
229 }
230 }
231}
232
233impl MultiStore {
234 pub fn range(
235 &self,
236 range: EncodedKeyRange,
237 scope: MultiVersionScope,
238 batch_size: usize,
239 ) -> MultiVersionRangeIterator<'_> {
240 match self {
241 MultiStore::Standard(store) => Box::new(store.range(range, scope, batch_size)),
242 }
243 }
244
245 pub fn range_persistence(
246 &self,
247 range: EncodedKeyRange,
248 scope: MultiVersionScope,
249 batch_size: usize,
250 ) -> MultiVersionRangeIterator<'_> {
251 match self {
252 MultiStore::Standard(store) => Box::new(store.range_persistence(range, scope, batch_size)),
253 }
254 }
255
256 pub fn range_rev(
257 &self,
258 range: EncodedKeyRange,
259 scope: MultiVersionScope,
260 batch_size: usize,
261 ) -> MultiVersionRangeIterator<'_> {
262 match self {
263 MultiStore::Standard(store) => Box::new(store.range_rev(range, scope, batch_size)),
264 }
265 }
266
267 pub fn range_rev_persistence(
268 &self,
269 range: EncodedKeyRange,
270 scope: MultiVersionScope,
271 batch_size: usize,
272 ) -> MultiVersionRangeIterator<'_> {
273 match self {
274 MultiStore::Standard(store) => Box::new(store.range_rev_persistence(range, scope, batch_size)),
275 }
276 }
277
278 pub fn get_many(
279 &self,
280 keys: &[EncodedKey],
281 version: CommitVersion,
282 ) -> Result<HashMap<EncodedKey, MultiVersionRow>> {
283 match self {
284 MultiStore::Standard(store) => store.get_many(keys, version),
285 }
286 }
287}
288
289impl MultiVersionStore for MultiStore {}