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