Skip to main content

reifydb_store_multi/tier/read/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4//! Read buffer tier of the multi-version store. Serves cold keys that the commit buffer has already evicted below
5//! the eviction watermark, so a repeated point read does not have to fall through to the persistent tier every
6//! time. Each entry caches the latest committed `(version, value)` plus, while that version is still unflushed,
7//! the immediately superseded one; a hit is served from the newest slot at or below the requested snapshot
8//! version, otherwise the caller reads through to the persistent tier which honors the full version bound. The
9//! previous slot is only ever filled by an in-place supersede (never by a warm merge), so it is guaranteed to be
10//! version-adjacent to the current slot. Range scans consult this tier only for buckets marked `range_complete`: a
11//! whole page loaded in one consistent read of the persistent tier, which therefore mirrors every persisted row for
12//! its contiguous key interval and can serve the persistent contribution of a range scan. Any incomplete bucket
13//! reads through to the persistent tier, and the always-scanned commit buffer still wins on version, so the cache
14//! can never mask a newer value nor resurrect a deleted one.
15
16mod point;
17mod pool;
18mod range;
19#[cfg(test)]
20mod tests;
21
22use std::{
23	collections::{BTreeMap, HashMap},
24	sync::{Arc, atomic::AtomicU8},
25};
26
27use reifydb_codec::key::encoded::EncodedKey;
28use reifydb_core::common::CommitVersion;
29use reifydb_runtime::sync::mutex::Mutex;
30use reifydb_store::row::page::{DEFAULT_BUCKET_SHIFT, PageId};
31use reifydb_value::util::cowvec::CowVec;
32
33use crate::tier::RangeBatch;
34
35#[derive(Clone, Copy, Debug)]
36pub struct ReadBufferConfig {
37	pub resident_pages: usize,
38	pub bucket_shift: u8,
39	pub shards: usize,
40}
41
42impl Default for ReadBufferConfig {
43	fn default() -> Self {
44		Self {
45			resident_pages: 1024,
46			bucket_shift: DEFAULT_BUCKET_SHIFT,
47			shards: 16,
48		}
49	}
50}
51
52#[derive(Clone)]
53struct PageEntry {
54	version: CommitVersion,
55	value: Option<CowVec<u8>>,
56	previous: Option<(CommitVersion, Option<CowVec<u8>>)>,
57}
58
59struct ResidentPage {
60	entries: BTreeMap<EncodedKey, PageEntry>,
61	hot: bool,
62	tick: u64,
63	range_complete: bool,
64	warm_blocked: bool,
65}
66
67pub enum ServedChunk {
68	Served(RangeBatch),
69	Gap,
70}
71
72struct Shard {
73	pages: HashMap<PageId, ResidentPage>,
74	warming: HashMap<PageId, bool>,
75	next_tick: u64,
76	page_cap: usize,
77}
78
79struct PoolInner {
80	shards: Box<[Mutex<Shard>]>,
81	bucket_shift: AtomicU8,
82}
83
84#[derive(Clone)]
85pub struct MultiReadBufferTier {
86	inner: Arc<PoolInner>,
87}