indexedlog/
config.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8//! Default configs for indexed log.
9
10use std::sync::atomic;
11use std::sync::atomic::AtomicI64;
12use std::sync::atomic::AtomicU32;
13
14/// If set to true, prefer symlinks to normal files for atomic_write. This avoids
15/// states where the metadata file is empty in theory.
16///
17/// Be careful with cases like mixing using ntfs-3g and Windows NTFS on files - they
18/// might use different forms of symlink and are incompatible with this feature.
19pub static SYMLINK_ATOMIC_WRITE: atomic::AtomicBool = atomic::AtomicBool::new(cfg!(test));
20
21/// If set to true, enable fsync for writing.
22static ENFORCE_FSYNC: atomic::AtomicBool = atomic::AtomicBool::new(false);
23
24/// Default chmod mode for directories.
25/// u: rwx g:rws o:r-x
26pub static CHMOD_DIR: AtomicI64 = AtomicI64::new(0o2775);
27
28// XXX: This works around https://github.com/Stebalien/tempfile/pull/61.
29/// Default chmod mode for atomic_write files.
30pub static CHMOD_FILE: AtomicI64 = AtomicI64::new(0o664);
31
32/// Default maximum chain length for index. See `index::OpenOptions::checksum_max_chain_len`.
33pub static INDEX_CHECKSUM_MAX_CHAIN_LEN: AtomicU32 = AtomicU32::new(10);
34
35/// Set whether to fsync globally. fsync will be performed if either the local
36/// or global fsync flag is set.
37pub fn set_global_fsync(flag: bool) {
38    ENFORCE_FSYNC.store(flag, atomic::Ordering::Release);
39}
40
41/// Get the fsync flag set by `set_global_fsync`.
42pub fn get_global_fsync() -> bool {
43    ENFORCE_FSYNC.load(atomic::Ordering::Acquire)
44}
45
46/// Set the "page_out" threshold in bytes.
47///
48/// When `Log` entry reads exceed the limit, try to inform the kernel to
49/// release the memory and reload the mmap buffers from disk later.
50///
51/// On Windows, use `EmptyWorkingSet` which affects the entire process.
52/// On *nix, use `madvise(..., MADV_DONTNEED)` for all mmap buffers
53/// created by this crate when `threshold > 0`.
54///
55/// Note the byte count is an approximate:
56/// - The kernel might read ahead.
57/// - We don't de-duplicate reads of a same region.
58/// - We don't count (frequent, small) index read for performance reasons.
59/// The `madvise(..., MADV_DONTNEED)` might not take immediate effect.
60/// See its manual page for details.
61///
62/// If `threshold <= 0`, auto page out is disabled.
63pub fn set_page_out_threshold(threshold: i64) {
64    let old_threshold = crate::page_out::THRESHOLD.swap(threshold, atomic::Ordering::AcqRel);
65    let delta = threshold - old_threshold;
66    crate::page_out::adjust_available(delta);
67}
68
69/// Configure various settings based on a `Config`.
70#[cfg(feature = "configurable")]
71pub fn configure(config: &dyn configmodel::Config) -> configmodel::Result<()> {
72    use configmodel::convert::ByteCount;
73    use configmodel::ConfigExt;
74
75    if cfg!(unix) {
76        let chmod_file = config.get_or("permissions", "chmod-file", || -1)?;
77        if chmod_file >= 0 {
78            CHMOD_FILE.store(chmod_file, atomic::Ordering::Release);
79        }
80
81        let chmod_dir = config.get_or("permissions", "chmod-dir", || -1)?;
82        if chmod_dir >= 0 {
83            CHMOD_DIR.store(chmod_dir, atomic::Ordering::Release);
84        }
85
86        let use_symlink_atomic_write: bool =
87            config.get_or_default("format", "use-symlink-atomic-write")?;
88        SYMLINK_ATOMIC_WRITE.store(use_symlink_atomic_write, atomic::Ordering::Release);
89
90        #[cfg(all(unix, feature = "sigbus-handler"))]
91        {
92            let use_sigbus_handler: bool =
93                config.get_or_default("unsafe", "indexedlog-zerofill-mmap-sigbus")?;
94            if use_sigbus_handler {
95                crate::sigbus::register_sigbus_handler();
96            }
97        }
98    }
99
100    if let Some(max_chain_len) =
101        config.get_opt::<u32>("storage", "indexedlog-max-index-checksum-chain-len")?
102    {
103        INDEX_CHECKSUM_MAX_CHAIN_LEN.store(max_chain_len, atomic::Ordering::Release);
104    }
105
106    if let Some(threshold) =
107        config.get_opt::<ByteCount>("storage", "indexedlog-page-out-threshold")?
108    {
109        set_page_out_threshold(threshold.value() as _);
110    }
111
112    let fsync: bool = config.get_or_default("storage", "indexedlog-fsync")?;
113    set_global_fsync(fsync);
114
115    Ok(())
116}