1use dashmap::DashMap;
2use std::fs;
3use std::io;
4use std::sync::Arc;
5use tokio::fs::File;
6use tokio::io::AsyncBufReadExt;
7use rand::seq::SliceRandom; use std::time::SystemTime;
9
10pub struct AsyncLineCache {
11 pub cache: Arc<DashMap<String, String>>, pub file_times: Arc<DashMap<String, SystemTime>>, pub file_lines: Arc<DashMap<String, Vec<String>>>, }
15
16impl AsyncLineCache {
17 pub fn new() -> Self {
18 let cache = Arc::new(DashMap::new()); let file_times = Arc::new(DashMap::new()); let file_lines = Arc::new(DashMap::new()); AsyncLineCache { cache, file_times, file_lines }
22 }
23
24 pub async fn get_line(&self, filename: &str, lineno: usize) -> io::Result<Option<String>> {
25 println!("正在从文件 {} 中获取第 {} 行...", filename, lineno);
26 let file_metadata = fs::metadata(filename)?;
27 let last_modified = file_metadata.modified()?;
28 let cached_time = self.file_times.get(filename).map(|entry| *entry.value());
30 if cached_time.is_none() || cached_time.unwrap() < last_modified {
31 println!("文件已更新,正在重新加载缓存...");
32 self.check_cache(filename).await?;
33 }
34 println!("缓存检查完成...");
35 let key = format!("{}:{}", filename, lineno);
37 if let Some(line) = self.cache.get(&key) {
38 println!("从缓存中找到行内容: {:?}", line);
39 return Ok(Some(line.value().clone()));
40 }
41 if let Some(lines) = self.file_lines.get(filename) {
43 if lineno <= lines.len() {
44 let line = lines[lineno - 1].clone();
45 self.cache.insert(key, line.clone());
46 println!("从文件中读取行内容: {}", line);
47 return Ok(Some(line));
48 }
49 }
50 println!("文件 {} 中未找到第 {} 行", filename, lineno);
51 Ok(None)
52 }
53
54 pub async fn get_lines(&self, filename: &str) -> io::Result<Option<Vec<String>>> {
55 println!("正在从文件 {} 中获取所有行...", filename);
56 let file_metadata = fs::metadata(filename)?;
57 let last_modified = file_metadata.modified()?;
58 let cached_time = self.file_times.get(filename).map(|entry| *entry.value());
60 if cached_time.is_none() || cached_time.unwrap() < last_modified {
61 println!("文件已更新,正在重新加载缓存...");
62 self.check_cache(filename).await?;
63 }
64 println!("缓存检查完成...");
65 if let Some(lines) = self.file_lines.get(filename) {
67 println!("成功获取文件 {} 的所有行", filename);
68 return Ok(Some(lines.value().clone()));
69 }
70 println!("文件 {} 未找到或为空", filename);
71 Ok(None)
72 }
73
74 pub async fn random_line(&self, filename: &str) -> io::Result<Option<String>> {
75 let file_metadata = fs::metadata(filename)?;
76 let last_modified = file_metadata.modified()?;
77 let cached_time = self.file_times.get(filename).map(|entry| *entry.value());
79 if cached_time.is_none() || cached_time.unwrap() < last_modified {
80 self.check_cache(filename).await?;
81 }
82 if let Some(lines) = self.file_lines.get(filename) {
84 if !lines.is_empty() {
85 let random_line = lines.choose(&mut rand::thread_rng()).cloned();
86 return Ok(random_line);
87 }
88 }
89 Ok(None)
90 }
91
92 pub async fn clear_cache(&self) {
93 self.cache.clear();
95 self.file_times.clear();
97 self.file_lines.clear();
99 }
100
101 async fn check_cache(&self, filename: &str) -> io::Result<()> {
102 let file_metadata = fs::metadata(filename)?;
103 let last_modified = file_metadata.modified()?;
104 if let Some(cached_time) = self.file_times.get(filename).map(|entry| *entry.value()) {
105 if cached_time < last_modified {
106 println!("文件已更新,正在重新加载...");
107 self.reload_file(filename).await?;
108 }
109 } else {
110 println!("文件未缓存,正在加载...");
111 self.load_file(filename).await?;
112 }
113 Ok(())
114 }
115
116 async fn load_file(&self, filename: &str) -> io::Result<()> {
117 let file = File::open(filename).await?;
118 let reader = tokio::io::BufReader::new(file);
119 let mut lines = Vec::new();
120 let mut lines_stream = reader.lines();
121 while let Some(line) = lines_stream.next_line().await? {
123 lines.push(line);
124 }
125 self.file_lines.insert(filename.to_string(), lines);
126 let file_metadata = fs::metadata(filename)?;
127 let last_modified = file_metadata.modified()?;
128 self.file_times.insert(filename.to_string(), last_modified);
129 Ok(())
130 }
131
132 async fn reload_file(&self, filename: &str) -> io::Result<()> {
133 self.file_lines.remove(filename);
134 self.load_file(filename).await
135 }
136}