use crate::config::{DiskAccessMode, PrefetchMode};
pub(super) fn mmap_enabled_via_env() -> bool {
std::env::var("CQLITE_USE_MMAP")
.ok()
.as_deref()
.map(parse_truthy_env)
.unwrap_or(false)
}
pub(super) fn parse_truthy_env(value: &str) -> bool {
matches!(
value.trim().to_ascii_lowercase().as_str(),
"1" | "true" | "yes" | "on"
)
}
pub(super) fn parse_disk_access_mode(value: &str) -> Option<DiskAccessMode> {
match value.trim().to_ascii_lowercase().as_str() {
"auto" => Some(DiskAccessMode::Auto),
"buffered" | "buffer" => Some(DiskAccessMode::Buffered),
"mmap" | "mapped" => Some(DiskAccessMode::Mmap),
"direct" | "directio" | "direct_io" | "o_direct" => Some(DiskAccessMode::Direct),
_ => None,
}
}
pub(super) fn parse_prefetch_mode(value: &str) -> Option<PrefetchMode> {
match value.trim().to_ascii_lowercase().as_str() {
"off" | "none" | "no" => Some(PrefetchMode::Off),
"sequential" | "seq" => Some(PrefetchMode::Sequential),
"willneed" | "will_need" | "will-need" => Some(PrefetchMode::WillNeed),
"auto" => Some(PrefetchMode::Auto),
_ => None,
}
}
pub(super) fn disk_access_mode_via_env() -> Option<DiskAccessMode> {
std::env::var("CQLITE_DISK_ACCESS_MODE")
.ok()
.as_deref()
.and_then(parse_disk_access_mode)
}
pub(super) fn prefetch_mode_via_env() -> Option<PrefetchMode> {
std::env::var("CQLITE_PREFETCH")
.ok()
.as_deref()
.and_then(parse_prefetch_mode)
}
pub(super) fn system_memory_bytes() -> Option<u64> {
#[cfg(unix)]
{
let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
if pages > 0 && page_size > 0 {
return Some((pages as u64).saturating_mul(page_size as u64));
}
None
}
#[cfg(not(unix))]
{
None
}
}
pub(super) fn resolve_disk_access_mode(
configured: DiskAccessMode,
file_size: u64,
mmap_min_size_bytes: u64,
memory_fraction: f64,
system_memory: Option<u64>,
direct_io_available: bool,
) -> DiskAccessMode {
if file_size == 0 {
return DiskAccessMode::Buffered;
}
match configured {
DiskAccessMode::Buffered => DiskAccessMode::Buffered,
DiskAccessMode::Mmap => DiskAccessMode::Mmap,
DiskAccessMode::Direct => DiskAccessMode::Direct,
DiskAccessMode::Auto => {
if file_size < mmap_min_size_bytes {
return DiskAccessMode::Buffered;
}
let fraction = if memory_fraction.is_finite() && memory_fraction > 0.0 {
memory_fraction.min(1.0)
} else {
0.5
};
if direct_io_available {
if let Some(mem) = system_memory {
let threshold = (mem as f64 * fraction) as u64;
if file_size > threshold {
return DiskAccessMode::Direct;
}
}
}
DiskAccessMode::Mmap
}
}
}
pub(super) const fn direct_io_available() -> bool {
cfg!(all(
unix,
any(
target_os = "linux",
target_os = "android",
target_os = "macos"
)
))
}
#[cfg(unix)]
pub(super) fn mmap_open_advice_for(prefetch: PrefetchMode) -> Option<memmap2::Advice> {
match prefetch {
PrefetchMode::Off | PrefetchMode::Auto => None,
PrefetchMode::Sequential => Some(memmap2::Advice::Sequential),
PrefetchMode::WillNeed => None,
}
}