Skip to main content

turbo_persistence/
lib.rs

1#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
2#![feature(once_cell_try)]
3#![feature(sync_unsafe_cell)]
4// Miri compiles a reduced test subset, leaving helpers from disabled tests intentionally unused.
5#![cfg_attr(miri, allow(dead_code, unused_imports))]
6
7mod arc_bytes;
8pub(crate) mod be;
9mod collector;
10mod collector_entry;
11mod compaction;
12mod compression;
13mod constants;
14mod db;
15mod key;
16mod lookup_entry;
17mod merge_iter;
18pub mod meta_file;
19mod meta_file_builder;
20#[cfg(feature = "mmap")]
21pub mod mmap_helper;
22mod parallel_scheduler;
23mod rc_bytes;
24mod shared_bytes;
25pub mod sst_filter;
26pub mod static_sorted_file;
27mod static_sorted_file_builder;
28mod value_block_count_tracker;
29mod value_buf;
30mod write_batch;
31
32#[cfg(test)]
33mod tests;
34
35pub use arc_bytes::ArcBytes;
36pub use compression::{Compression, checksum_block};
37pub use db::{
38    CommitStats, CompactConfig, CurrentDbVersion, MetaFileEntryInfo, MetaFileInfo,
39    TurboPersistence, read_current_version,
40};
41
42/// Controls how SST and meta files are read from disk.
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub enum AccessMode {
45    /// Memory-map the file and access blocks via the mapped region.
46    #[cfg(feature = "mmap")]
47    Mmap,
48    /// Read blocks directly from the file via pread (no mmap).
49    File,
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub enum FamilyKind {
54    /// Each key maps to a single value (default LSM behavior).
55    /// When multiple entries have the same key, only the newest is retained during compaction or
56    /// returned by queries
57    /// Access must use `get` not `get_multiple`
58    SingleValue,
59    /// Each key can map to multiple values.
60    /// Duplicate values are not dropped.
61    /// The order of values returned by `get_multiple` is undefined.
62    /// Access must use `get_multiple` not `get`
63    MultiValue,
64}
65
66/// Configuration for a single family to describe how the data is stored.
67#[derive(Clone, Copy, Debug)]
68pub struct FamilyConfig {
69    pub name: &'static str,
70    pub kind: FamilyKind,
71    pub compression: Compression,
72}
73
74/// Database-wide configuration with per-family storage settings.
75///
76/// Each family (keyspace) can select storage behavior suited to its access patterns and data
77/// characteristics.
78#[derive(Clone, Debug)]
79pub struct DbConfig<const FAMILIES: usize> {
80    pub family_configs: [FamilyConfig; FAMILIES],
81    /// How SST and meta files are read from disk.
82    pub access_mode: AccessMode,
83}
84
85/// Returns the default access mode for this execution environment.
86///
87/// Builds without mmap support always use file I/O. Builds with mmap support honor
88/// `TURBO_PERSISTENCE_MMAP=0`; mmap remains the default otherwise.
89fn default_access_mode() -> AccessMode {
90    #[cfg(not(feature = "mmap"))]
91    return AccessMode::File;
92
93    #[cfg(feature = "mmap")]
94    access_mode_env_var()
95}
96
97/// Returns mmap mode when the feature is enabled, and file mode otherwise.
98///
99/// Call sites that specifically want mmap use this helper because `AccessMode::Mmap` does not
100/// exist without the feature; they fall back to file I/O and still exercise surrounding logic.
101#[cfg(any(test, feature = "verify_sst_content"))]
102pub(crate) fn mmap_access_mode() -> AccessMode {
103    #[cfg(not(feature = "mmap"))]
104    return AccessMode::File;
105
106    #[cfg(feature = "mmap")]
107    AccessMode::Mmap
108}
109
110#[cfg(feature = "mmap")]
111fn access_mode_env_var() -> AccessMode {
112    static ACCESS_MODE_ENV: std::sync::LazyLock<AccessMode> = std::sync::LazyLock::new(|| {
113        if std::env::var("TURBO_PERSISTENCE_MMAP")
114            .ok()
115            .is_some_and(|v| v == "0")
116        {
117            AccessMode::File
118        } else {
119            AccessMode::Mmap
120        }
121    });
122    *ACCESS_MODE_ENV
123}
124
125impl<const FAMILIES: usize> DbConfig<FAMILIES> {
126    /// Returns a config with all defaults, using the execution environment's default access mode.
127    pub fn new() -> Self {
128        Self {
129            family_configs: [FamilyConfig {
130                name: "unknown",
131                kind: FamilyKind::SingleValue,
132                compression: Compression::Lz4,
133            }; FAMILIES],
134            access_mode: default_access_mode(),
135        }
136    }
137}
138/// The largest value that [`WriteBatch::delete_value`] can delete, since the tombstone stores
139/// a copy of the value inline.
140pub use constants::MAX_INLINE_VALUE_SIZE;
141
142impl<const FAMILIES: usize> Default for DbConfig<FAMILIES> {
143    fn default() -> Self {
144        Self::new()
145    }
146}
147pub use key::{KeyBase, QueryKey, StoreKey, hash_key};
148pub use meta_file::MetaEntryFlags;
149pub use parallel_scheduler::{ParallelScheduler, SerialScheduler};
150pub use static_sorted_file::{
151    BlockCache, BlockCacheLifecycle, BlockWeighter, KeyBlockLayout, SstLookupResult,
152    StaticSortedFile, StaticSortedFileMetaData,
153};
154pub use static_sorted_file_builder::{
155    BLOCK_HEADER_SIZE, Entry, EntryValue, StreamingSstWriter, write_static_stored_file,
156};
157pub use value_buf::ValueBuffer;
158pub use write_batch::WriteBatch;