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