1 #[cfg(target_os = "dragonos")] 2 use drstd as std; 3 use std::hash::{Hash, Hasher}; 4 use std::{ 5 collections::hash_map::DefaultHasher, 6 collections::vec_deque::VecDeque, 7 process::Child, 8 sync::{Arc, Mutex, RwLock}, 9 vec::Vec, 10 }; 11 12 use crate::unit::service::ServiceUnit; 13 use crate::unit::{service, Unit}; 14 use hashbrown::HashMap; 15 use lazy_static::lazy_static; 16 17 lazy_static! { 18 // 对于启动后即使退出亦认为其为运行状态的特殊注册类Service,对于这类进程做一个标记 19 static ref FLAG_RUNNING: RwLock<Vec<usize>> = RwLock::new(Vec::new()); 20 21 // 任务等待队列,IDLE类型的service入队等待其它任务完成再执行 22 static ref IDLE_SERVIEC_DEQUE: Mutex<VecDeque<usize>> = Mutex::new(VecDeque::new()); 23 24 // id到unit的映射表,全局的Unit管理表 25 static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new()); 26 27 // 辅助表,通过服务名映射其id 28 static ref PATH_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new()); 29 30 // 全局运行中的Unit表 31 pub(super) static ref RUNNING_TABLE: RwLock<RunningTableManager> = RwLock::new(RunningTableManager { running_table: Vec::new() }); 32 33 // CMD进程表,用于处理Unit的CMD派生进程(ExecStartPre等命令派生进程) 34 pub(super) static ref CMD_PROCESS_TABLE: RwLock<HashMap<u32,Mutex<Child>>> = RwLock::new(HashMap::new()); 35 } 36 37 pub struct RunningTableManager { 38 running_table: Vec<RunningUnit>, 39 } 40 41 impl<'a> IntoIterator for &'a mut RunningTableManager { 42 type Item = &'a mut RunningUnit; 43 type IntoIter = std::slice::IterMut<'a, RunningUnit>; 44 45 fn into_iter(self) -> Self::IntoIter { 46 self.running_table.iter_mut() 47 } 48 } 49 50 pub struct RunningUnit { 51 process: Child, 52 unit_id: usize, 53 } 54 impl RunningUnit { 55 pub fn new(p: Child, unit: usize) -> Self { 56 RunningUnit { 57 process: p, 58 unit_id: unit, 59 } 60 } 61 62 pub fn child(&mut self) -> &mut Child { 63 &mut self.process 64 } 65 66 pub fn id(&self) -> &usize { 67 &self.unit_id 68 } 69 } 70 71 pub struct UnitManager; 72 73 unsafe impl Sync for UnitManager {} 74 75 impl UnitManager { 76 pub fn insert_into_path_table(path: &str, unit: usize) { 77 let mut hasher = DefaultHasher::new(); 78 path.hash(&mut hasher); 79 let hash = hasher.finish(); 80 PATH_TO_UNIT_MAP.write().unwrap().insert(hash, unit); 81 } 82 83 pub fn contains_path(path: &str) -> bool { 84 let mut hasher = DefaultHasher::new(); 85 path.hash(&mut hasher); 86 let hash = hasher.finish(); 87 PATH_TO_UNIT_MAP.read().unwrap().contains_key(&hash) 88 } 89 90 pub fn get_unit_with_path(path: &str) -> Option<Arc<Mutex<dyn Unit>>> { 91 let mut hasher = DefaultHasher::new(); 92 path.hash(&mut hasher); 93 let hash = hasher.finish(); 94 let map = PATH_TO_UNIT_MAP.read().unwrap(); 95 let id = match map.get(&hash) { 96 Some(id) => id, 97 None => { 98 return None; 99 } 100 }; 101 102 let map = ID_TO_UNIT_MAP.read().unwrap(); 103 let ret = map.get(id).cloned(); 104 ret 105 } 106 107 pub fn get_unit_with_id(id: &usize) -> Option<Arc<Mutex<dyn Unit>>> { 108 let map = ID_TO_UNIT_MAP.read().unwrap(); 109 let ret = map.get(&id).cloned(); 110 ret 111 } 112 113 pub fn get_id_with_path(path: &str) -> Option<usize> { 114 let mut hasher = DefaultHasher::new(); 115 path.hash(&mut hasher); 116 let hash = hasher.finish(); 117 PATH_TO_UNIT_MAP.read().unwrap().get(&hash).cloned() 118 } 119 120 pub fn is_running_unit(id: &usize) -> bool { 121 !RUNNING_TABLE 122 .read() 123 .unwrap() 124 .running_table 125 .iter() 126 .filter(|x| x.unit_id == *id) 127 .collect::<Vec<_>>() 128 .is_empty() 129 } 130 131 pub fn push_running(unit: RunningUnit) { 132 RUNNING_TABLE.write().unwrap().running_table.push(unit); 133 } 134 135 pub fn remove_running(id: usize) { 136 let mut table = RUNNING_TABLE.write().unwrap(); 137 match table.running_table.iter().position(|x| x.unit_id == id) { 138 Some(idx) => { 139 table.running_table.remove(idx); 140 } 141 _ => (), 142 } 143 } 144 145 pub fn insert_unit_with_id(id: usize, unit: Arc<Mutex<dyn Unit>>) { 146 let mut map = ID_TO_UNIT_MAP.write().unwrap(); 147 if !map.contains_key(&id) { 148 map.insert(id, unit); 149 } 150 } 151 152 pub fn contains_id(id: &usize) -> bool { 153 ID_TO_UNIT_MAP.read().unwrap().contains_key(id) 154 } 155 156 pub fn pop_a_idle_service() -> Option<Arc<Mutex<dyn Unit>>> { 157 let id = IDLE_SERVIEC_DEQUE.lock().unwrap().pop_front(); 158 match id { 159 Some(id) => { 160 return Self::get_unit_with_id(&id); 161 } 162 None => { 163 return None; 164 } 165 } 166 } 167 168 pub fn push_a_idle_service(id: usize) { 169 if !Self::contains_id(&id) { 170 return; 171 } 172 IDLE_SERVIEC_DEQUE.lock().unwrap().push_back(id); 173 } 174 175 pub fn push_flag_running(id: usize) { 176 let mut t = FLAG_RUNNING.write().unwrap(); 177 if t.contains(&id) { 178 return; 179 } 180 t.push(id); 181 } 182 183 pub fn running_count() -> usize { 184 return RUNNING_TABLE.read().unwrap().running_table.len(); 185 } 186 187 pub fn push_cmd_proc(proc: Child) { 188 CMD_PROCESS_TABLE 189 .write() 190 .unwrap() 191 .insert(proc.id(), Mutex::new(proc)); 192 } 193 194 pub fn remove_cmd_proc(id: u32) { 195 CMD_PROCESS_TABLE.write().unwrap().remove(&id); 196 } 197 } 198