Skip to main content

turbo_persistence/
lib.rs

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