use std::{collections::HashMap, fs::{self, File}, io::Read, path::PathBuf, str::FromStr, sync::{Arc, RwLock}}; use log::info; use serde::{Deserialize, Serialize}; use crate::utils::{file_size_in_kb, get_last_modified_time, k_deserialize}; use super::hdlparam::FastHdlparam; pub enum CacheResult { Ok(T), NotNeedCache, CacheNotFound, NotHit, FailDeserialize, Error(String) } #[derive(Debug, Serialize, Deserialize)] pub struct CacheItem { /// 文件名字 pub file_name: String, /// 文件大小,单位 KB pub size: u64, /// 版本,根据特定算法得出 pub version: String, /// 缓存文件的名字 pub cache_name: String } /// 用于进行高效 IR 缓存的模块 pub struct CacheManager { /// 缓存文件夹根目录 pub root_dir: PathBuf, /// meta 文件内容 pub meta_name: String, /// meta 内容 pub meta: Arc>> } impl CacheManager { pub fn new(root_dir: &str) -> Self { // 读入 meta 文件 let root_dir = PathBuf::from_str(root_dir).unwrap(); let meta_name = "index.cache"; let meta_path = root_dir.join(meta_name); let meta = get_or_init_meta(&meta_path); // 如果不存在 root dir,则创建 if !root_dir.exists() { match fs::create_dir_all(&root_dir) { Ok(_) => {}, Err(err) => info!("error happen when create {root_dir:?}: {err:?}") } } CacheManager { root_dir, meta_name: meta_name.to_string(), meta: Arc::new(RwLock::new(meta)) } } pub fn is_big_file(&self, path: &PathBuf) -> bool { if let Ok(size) = file_size_in_kb(path.to_str().unwrap()) { return size >= 1024; } false } fn get_version(&self, path: &PathBuf) -> String { let path_str = path.to_str().unwrap(); if let Ok(modify_ts) = get_last_modified_time(path_str) { return modify_ts.to_string(); } "".to_string() } /// ## 说明 /// 尝试获取当前的路径文件的 fast 的缓存 /// /// ## None /// /// * 如果本来就没有缓存 /// * 缓冲的 version 对不上 pub fn try_get_fast_cache(&self, path: &PathBuf) -> CacheResult { if !self.is_big_file(path) { return CacheResult::NotNeedCache } let path_string = path.to_str().unwrap(); let meta_handle = self.meta.read().unwrap(); if let Some(cache_item) = meta_handle.get(path_string) { let current_version = self.get_version(path); let cache_path = self.root_dir.join(&cache_item.cache_name); if current_version == cache_item.version && cache_path.exists() { // hit cache if let Ok(fast) = k_deserialize::(&cache_path) { return CacheResult::Ok(fast); } } } CacheResult::CacheNotFound } pub fn update_cache() { } } fn get_or_init_meta(meta_path: &PathBuf) -> HashMap { if meta_path.exists() { // 读取文件 if let Ok(meta_map) = k_deserialize::>(meta_path) { return meta_map; } } // 重新创建新的 HashMap::::new() }