1 use std::{collections::BTreeMap, fmt::Debug, fs::File, io::Write, path::PathBuf}; 2 3 use log::error; 4 5 use crate::constant::CMD_ARGS; 6 7 /// 日志集合 8 /// 9 /// 所有的日志都会被存到这个集合中, 以便于进行各种操作 10 /// 11 /// 日志集合的后端可以在日志插入前后做一些操作(需要实现[`LogSetBackend`]) 12 #[derive(Debug)] 13 #[allow(dead_code)] 14 pub struct LogSet<K, V> { 15 inner: BTreeMap<K, V>, 16 backend: Box<dyn LogSetBackend<K, V>>, 17 name: String, 18 file_path: PathBuf, 19 log_file: Option<File>, 20 } 21 22 #[allow(dead_code)] 23 impl<K: Ord, V: Clone + PartialEq + Debug> LogSet<K, V> { 24 pub fn new(name: String, backend: Option<Box<dyn LogSetBackend<K, V>>>) -> Self { 25 let mut file_path = CMD_ARGS.read().unwrap().as_ref().unwrap().log_dir.clone(); 26 file_path.push(format!("{}-{}.log", name, std::process::id())); 27 28 let log_file = File::create(&file_path).expect("Failed to create log file."); 29 30 Self { 31 inner: BTreeMap::new(), 32 backend: backend.unwrap_or_else(|| Box::new(DefaultBackend::new())), 33 name, 34 file_path, 35 log_file: Some(log_file), 36 } 37 } 38 39 pub fn insert(&mut self, key: K, value: V) { 40 let cloned_value = value.clone(); 41 self.backend.before_insert(&self.name, &value); 42 43 let prev = self.inner.insert(key, value); 44 if let Some(prev) = prev { 45 if prev.ne(&cloned_value) { 46 error!( 47 "LogSet::insert(): prev != cloned_value: prev: {:?}, cloned_value: {:?}", 48 prev, cloned_value 49 ); 50 } 51 } else { 52 self.log_file 53 .as_mut() 54 .map(|f| writeln!(f, "{:?}", cloned_value).ok()); 55 } 56 57 self.backend.after_insert(&self.name, &cloned_value); 58 } 59 60 pub fn file_path(&self) -> &PathBuf { 61 &self.file_path 62 } 63 64 pub fn len(&self) -> usize { 65 self.inner.len() 66 } 67 68 pub fn get(&self, key: &K) -> Option<&V> { 69 self.inner.get(key) 70 } 71 72 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { 73 self.inner.get_mut(key) 74 } 75 76 pub fn remove(&mut self, key: &K) -> Option<V> { 77 self.inner.remove(key) 78 } 79 80 pub fn clear(&mut self) { 81 self.inner.clear(); 82 } 83 84 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> { 85 self.inner.iter() 86 } 87 88 pub fn contains_key(&self, key: &K) -> bool { 89 self.inner.contains_key(key) 90 } 91 } 92 93 /// 日志集合的后端, 用于在日志插入前后做一些操作 94 pub trait LogSetBackend<K, V>: Debug { 95 fn before_insert(&mut self, _log_set_name: &str, _log: &V) {} 96 97 fn after_insert(&mut self, _log_set_name: &str, _log: &V) {} 98 } 99 100 #[derive(Debug)] 101 struct DefaultBackend(()); 102 103 impl DefaultBackend { 104 pub const fn new() -> Self { 105 Self(()) 106 } 107 } 108 109 impl<K, V> LogSetBackend<K, V> for DefaultBackend { 110 fn before_insert(&mut self, _log_set_name: &str, _log: &V) {} 111 112 fn after_insert(&mut self, _log_set_name: &str, _log: &V) {} 113 } 114