1 use std::hash::{Hash, Hasher}; 2 use std::{ 3 collections::hash_map::DefaultHasher, 4 collections::vec_deque::VecDeque, 5 print, println, 6 process::Child, 7 sync::{Arc, Mutex, RwLock}, 8 vec::Vec, 9 }; 10 11 use crate::unit::Unit; 12 use hashbrown::HashMap; 13 use lazy_static::lazy_static; 14 15 lazy_static! { 16 // 对于启动后即使退出亦认为其为运行状态的特殊注册类Service,对于这类进程做一个标记 17 static ref FLAG_RUNNING: RwLock<Vec<usize>> = RwLock::new(Vec::new()); 18 19 // 任务等待队列,IDLE类型的service入队等待其它任务完成再执行 20 static ref IDLE_SERVIEC_DEQUE: Mutex<VecDeque<usize>> = Mutex::new(VecDeque::new()); 21 22 // id到unit的映射表,全局的Unit管理表 23 static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new()); 24 25 // 辅助表,通过服务名映射其id 26 static ref PATH_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new()); 27 28 // 全局运行中的Unit表 29 pub(super) static ref RUNNING_TABLE: RwLock<RunningTableManager> = RwLock::new(RunningTableManager { running_table: HashMap::new() }); 30 31 // CMD进程表,用于处理Unit的CMD派生进程(ExecStartPre等命令派生进程) 32 pub(super) static ref CMD_PROCESS_TABLE: RwLock<HashMap<u32,Mutex<Child>>> = RwLock::new(HashMap::new()); 33 } 34 35 pub struct RunningTableManager { 36 running_table: HashMap<usize, Child>, 37 } 38 39 #[allow(dead_code)] 40 impl RunningTableManager { 41 pub fn running_table(&self) -> &HashMap<usize, Child> { 42 &self.running_table 43 } 44 45 pub fn mut_running_table(&mut self) -> &mut HashMap<usize, Child> { 46 &mut self.running_table 47 } 48 } 49 50 pub struct UnitManager; 51 52 unsafe impl Sync for UnitManager {} 53 54 #[allow(dead_code)] 55 impl UnitManager { 56 /// 插入一条path到unit_id的映射 57 pub fn insert_into_path_table(path: &str, unit: usize) { 58 let mut hasher = DefaultHasher::new(); 59 path.hash(&mut hasher); 60 let hash = hasher.finish(); 61 PATH_TO_UNIT_MAP.write().unwrap().insert(hash, unit); 62 } 63 64 // 判断当前是否已经有了对应path的Unit 65 pub fn contains_path(path: &str) -> bool { 66 let mut hasher = DefaultHasher::new(); 67 path.hash(&mut hasher); 68 let hash = hasher.finish(); 69 PATH_TO_UNIT_MAP.read().unwrap().contains_key(&hash) 70 } 71 72 // 通过path获取到Unit 73 pub fn get_unit_with_path(path: &str) -> Option<Arc<Mutex<dyn Unit>>> { 74 let mut hasher = DefaultHasher::new(); 75 path.hash(&mut hasher); 76 let hash = hasher.finish(); 77 let map = PATH_TO_UNIT_MAP.read().unwrap(); 78 let id = match map.get(&hash) { 79 Some(id) => id, 80 None => { 81 return None; 82 } 83 }; 84 85 let map = ID_TO_UNIT_MAP.read().unwrap(); 86 let ret = map.get(id).cloned(); 87 ret 88 } 89 90 // 通过unit_id获取Unit 91 pub fn get_unit_with_id(id: &usize) -> Option<Arc<Mutex<dyn Unit>>> { 92 let map = ID_TO_UNIT_MAP.read().unwrap(); 93 let ret = map.get(&id).cloned(); 94 ret 95 } 96 97 // 通过id获取到path 98 pub fn get_id_with_path(path: &str) -> Option<usize> { 99 let mut hasher = DefaultHasher::new(); 100 path.hash(&mut hasher); 101 let hash = hasher.finish(); 102 PATH_TO_UNIT_MAP.read().unwrap().get(&hash).cloned() 103 } 104 105 // 判断该Unit是否正在运行中 106 pub fn is_running_unit(id: &usize) -> bool { 107 RUNNING_TABLE.read().unwrap().running_table.contains_key(id) 108 || !FLAG_RUNNING 109 .read() 110 .unwrap() 111 .iter() 112 .filter(|x| **x == *id) 113 .collect::<Vec<_>>() 114 .is_empty() 115 } 116 117 // 向运行表中添加运行的Unit 118 pub fn push_running(unit_id: usize, p: Child) { 119 RUNNING_TABLE 120 .write() 121 .unwrap() 122 .running_table 123 .insert(unit_id, p); 124 } 125 126 // 删除运行表中的Unit 127 pub fn remove_running(id: usize) { 128 let mut table = RUNNING_TABLE.write().unwrap(); 129 table.running_table.remove(&id); 130 } 131 132 // 向id到Unit映射表中插入数据 133 pub fn insert_unit_with_id(id: usize, unit: Arc<Mutex<dyn Unit>>) { 134 let mut map = ID_TO_UNIT_MAP.write().unwrap(); 135 if !map.contains_key(&id) { 136 map.insert(id, unit); 137 } 138 } 139 140 // 判断当前DragonReach是否拥有目标id的Unit 141 pub fn contains_id(id: &usize) -> bool { 142 ID_TO_UNIT_MAP.read().unwrap().contains_key(id) 143 } 144 145 // 弹出一个处于IDLE状态的Service 146 pub fn pop_a_idle_service() -> Option<Arc<Mutex<dyn Unit>>> { 147 let id = IDLE_SERVIEC_DEQUE.lock().unwrap().pop_front(); 148 match id { 149 Some(id) => { 150 return Self::get_unit_with_id(&id); 151 } 152 None => { 153 return None; 154 } 155 } 156 } 157 158 // 添加IDLE状态的Service,将在后续调度 159 pub fn push_a_idle_service(id: usize) { 160 if !Self::contains_id(&id) { 161 return; 162 } 163 IDLE_SERVIEC_DEQUE.lock().unwrap().push_back(id); 164 } 165 166 // 将该Unit标记为运行状态,并且后续不会对其进行运行检查 167 pub fn push_flag_running(id: usize) { 168 let mut t = FLAG_RUNNING.write().unwrap(); 169 if t.contains(&id) { 170 return; 171 } 172 t.push(id); 173 } 174 175 // 当前运行的Unit数 176 pub fn running_count() -> usize { 177 return RUNNING_TABLE.read().unwrap().running_table.len(); 178 } 179 180 // 向Cmd运行表中添加 181 pub fn push_cmd_proc(proc: Child) { 182 CMD_PROCESS_TABLE 183 .write() 184 .unwrap() 185 .insert(proc.id(), Mutex::new(proc)); 186 } 187 188 // 删除对应cmd的进程 189 pub fn remove_cmd_proc(id: u32) { 190 CMD_PROCESS_TABLE.write().unwrap().remove(&id); 191 } 192 193 // 弹出指定id的cmd进程 194 pub fn pop_cmd_proc(id: u32) -> Option<Mutex<Child>> { 195 CMD_PROCESS_TABLE.write().unwrap().remove(&id) 196 } 197 198 // 初始化各Unit的依赖关系,此方法只需在解析完系统Unit文件后调用一次 199 pub fn init_units_dependencies() { 200 let manager = ID_TO_UNIT_MAP.write().unwrap(); 201 202 // 处理before段,将before段的Unit添加此Unit为After 203 for (id, unit) in manager.iter() { 204 let mut unit = unit.lock().unwrap(); 205 let before = unit.mut_unit_base().unit_part().before(); 206 for rid in before { 207 let req = UnitManager::get_unit_with_id(rid).unwrap(); 208 let mut req = req.lock().unwrap(); 209 req.mut_unit_base().mut_unit_part().push_after_unit(*id); 210 } 211 } 212 213 for (id, unit) in manager.iter() { 214 let mut unit = unit.lock().unwrap(); 215 216 // 处理binds_to段 217 let binds_to = unit.mut_unit_base().unit_part().binds_to(); 218 for rid in binds_to { 219 let req = UnitManager::get_unit_with_id(rid).unwrap(); 220 let mut req = req.lock().unwrap(); 221 req.mut_unit_base().mut_unit_part().push_be_binded_by(*id); 222 } 223 224 // 处理part_of段 225 let part_of = unit.mut_unit_base().unit_part().part_of(); 226 for rid in part_of { 227 let req = UnitManager::get_unit_with_id(rid).unwrap(); 228 let mut req = req.lock().unwrap(); 229 req.mut_unit_base().mut_unit_part().push_be_binded_by(*id); 230 } 231 } 232 } 233 234 /// ## 杀死Unit进程 235 pub fn kill_running(id: usize) { 236 if Self::is_running_unit(&id) { 237 let mut running_manager = RUNNING_TABLE.write().unwrap(); 238 let unit = running_manager.running_table.get_mut(&id).unwrap(); 239 let _ = unit.kill(); 240 println!("kill:{}", id); 241 running_manager.running_table.remove(&id); 242 } 243 } 244 } 245