#[cfg(any(
all(test, feature = "check_contracts_in_tests"),
feature = "check_contracts"
))]
use contracts::*;
#[cfg(not(any(
all(test, feature = "check_contracts_in_tests"),
feature = "check_contracts"
)))]
use disabled_contracts::*;
use std::ffi::c_void;
use std::fs::File;
use std::path::PathBuf;
use std::ptr::NonNull;
use std::sync::Mutex;
use crate::Mapper;
#[derive(Debug)]
pub struct FileBackedMapper {}
lazy_static::lazy_static! {
static ref FILE_BACKED_PATH: Mutex<Option<PathBuf>> = Default::default();
}
pub fn set_file_backed_slab_directory(path: Option<PathBuf>) {
let mut global_path = FILE_BACKED_PATH.lock().unwrap();
*global_path = path;
}
fn get_temp_file() -> Result<Option<File>, i32> {
let path = FILE_BACKED_PATH.lock().unwrap();
match &*path {
Some(dir) if dir.to_str() == Some(":memory:") => Ok(None),
Some(dir) => tempfile::tempfile_in(dir).map(Some),
None => tempfile::tempfile().map(Some),
}
.map_err(|e| e.raw_os_error().unwrap_or(0))
}
#[contract_trait]
impl Mapper for FileBackedMapper {
fn page_size(&self) -> usize {
crate::map::page_size()
}
fn reserve(
&self,
desired_size: usize,
_data_size: usize,
_prefix: usize,
_suffix: usize,
) -> Result<(NonNull<c_void>, usize), i32> {
let region: NonNull<c_void> = crate::map::reserve_region(desired_size)?;
Ok((region, desired_size))
}
fn release(&self, base: NonNull<c_void>, size: usize) -> Result<(), i32> {
crate::map::release_region(base, size)
}
fn allocate_meta(&self, base: NonNull<c_void>, size: usize) -> Result<(), i32> {
crate::map::allocate_region(base, size)
}
fn allocate_data(&self, base: NonNull<c_void>, size: usize) -> Result<(), i32> {
let tempfile = get_temp_file()?;
match tempfile {
Some(file) => crate::map::allocate_file_region(file, base, size),
None => crate::map::allocate_region(base, size),
}
}
}