|
use memmap2::{MmapMut, MmapOptions}; |
|
use rkyv::{archived_root, Deserialize as _}; |
|
use std::fs::OpenOptions; |
|
|
|
use crate::app::lazy::{LOGS_FILE_PATH, PAGES_FILE_PATH}; |
|
|
|
use super::{AppConfig, AppState, Pages, RequestLog, APP_CONFIG}; |
|
|
|
impl AppState { |
|
|
|
pub(crate) async fn save_logs(&self) -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
let bytes = rkyv::to_bytes::<_, 256>(&self.request_logs)?; |
|
|
|
|
|
let file = OpenOptions::new() |
|
.read(true) |
|
.write(true) |
|
.create(true) |
|
.open(LOGS_FILE_PATH.as_str())?; |
|
|
|
|
|
if bytes.len() > usize::MAX / 2 { |
|
return Err("日志数据过大".into()); |
|
} |
|
|
|
|
|
file.set_len(bytes.len() as u64)?; |
|
|
|
|
|
let mut mmap = unsafe { MmapMut::map_mut(&file)? }; |
|
|
|
|
|
mmap.copy_from_slice(&bytes); |
|
|
|
|
|
mmap.flush()?; |
|
|
|
Ok(()) |
|
} |
|
|
|
|
|
pub(super) async fn load_saved_logs() -> Result<Vec<RequestLog>, Box<dyn std::error::Error>> { |
|
let file = match OpenOptions::new().read(true).open(LOGS_FILE_PATH.as_str()) { |
|
Ok(file) => file, |
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => { |
|
return Ok(Vec::new()); |
|
} |
|
Err(e) => return Err(Box::new(e)), |
|
}; |
|
|
|
|
|
if file.metadata()?.len() > usize::MAX as u64 { |
|
return Err("日志文件过大".into()); |
|
} |
|
|
|
|
|
let mmap = unsafe { MmapOptions::new().map(&file)? }; |
|
|
|
|
|
let archived = unsafe { archived_root::<Vec<RequestLog>>(&mmap) }; |
|
Ok(archived.deserialize(&mut rkyv::Infallible)?) |
|
} |
|
} |
|
|
|
impl AppConfig { |
|
pub fn save_config() -> Result<(), Box<dyn std::error::Error>> { |
|
let pages = APP_CONFIG.read().pages.clone(); |
|
let bytes = rkyv::to_bytes::<_, 256>(&pages)?; |
|
|
|
let file = OpenOptions::new() |
|
.read(true) |
|
.write(true) |
|
.create(true) |
|
.open(PAGES_FILE_PATH.as_str())?; |
|
|
|
|
|
if bytes.len() > usize::MAX / 2 { |
|
return Err("配置数据过大".into()); |
|
} |
|
|
|
file.set_len(bytes.len() as u64)?; |
|
|
|
let mut mmap = unsafe { MmapMut::map_mut(&file)? }; |
|
mmap.copy_from_slice(&bytes); |
|
mmap.flush()?; |
|
|
|
Ok(()) |
|
} |
|
|
|
pub fn load_saved_config() -> Result<(), Box<dyn std::error::Error>> { |
|
let file = match OpenOptions::new().read(true).open(PAGES_FILE_PATH.as_str()) { |
|
Ok(file) => file, |
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => { |
|
return Ok(()); |
|
} |
|
Err(e) => return Err(Box::new(e)), |
|
}; |
|
|
|
|
|
if file.metadata()?.len() > usize::MAX as u64 { |
|
return Err("配置文件过大".into()); |
|
} |
|
|
|
let mmap = unsafe { MmapOptions::new().map(&file)? }; |
|
|
|
let archived = unsafe { archived_root::<Pages>(&mmap) }; |
|
let pages = archived.deserialize(&mut rkyv::Infallible)?; |
|
let mut config = APP_CONFIG.write(); |
|
config.pages = pages; |
|
|
|
Ok(()) |
|
} |
|
} |
|
|