digital-lsp-server/src/core/cache_storage.rs
2024-10-02 22:40:54 +08:00

127 lines
3.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<T> {
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<RwLock<HashMap<String, CacheItem>>>
}
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<FastHdlparam> {
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::<FastHdlparam>(&cache_path) {
return CacheResult::Ok(fast);
}
}
}
CacheResult::CacheNotFound
}
pub fn update_cache() {
}
}
fn get_or_init_meta(meta_path: &PathBuf) -> HashMap<String, CacheItem> {
if meta_path.exists() {
// 读取文件
if let Ok(meta_map) = k_deserialize::<HashMap<String, CacheItem>>(meta_path) {
return meta_map;
}
}
// 重新创建新的
HashMap::<String, CacheItem>::new()
}