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 34 pub struct RunningTableManager { 35 running_table: Vec<RunningUnit>, 36 } 37 38 impl<'a> IntoIterator for &'a mut RunningTableManager { 39 type Item = &'a mut RunningUnit; 40 type IntoIter = std::slice::IterMut<'a, RunningUnit>; 41 42 fn into_iter(self) -> Self::IntoIter { 43 self.running_table.iter_mut() 44 } 45 } 46 47 pub struct RunningUnit { 48 process: Child, 49 unit_id: usize, 50 } 51 impl RunningUnit { 52 pub fn new(p: Child, unit: usize) -> Self { 53 RunningUnit { 54 process: p, 55 unit_id: unit, 56 } 57 } 58 59 pub fn child(&mut self) -> &mut Child { 60 &mut self.process 61 } 62 63 pub fn id(&self) -> &usize { 64 &self.unit_id 65 } 66 } 67 68 pub struct UnitManager; 69 70 unsafe impl Sync for UnitManager {} 71 72 impl UnitManager { 73 pub fn insert_into_path_table(path: &str, unit: usize) { 74 let mut hasher = DefaultHasher::new(); 75 path.hash(&mut hasher); 76 let hash = hasher.finish(); 77 PATH_TO_UNIT_MAP.write().unwrap().insert(hash, unit); 78 } 79 80 pub fn contains_path(path: &str) -> bool { 81 let mut hasher = DefaultHasher::new(); 82 path.hash(&mut hasher); 83 let hash = hasher.finish(); 84 PATH_TO_UNIT_MAP.read().unwrap().contains_key(&hash) 85 } 86 87 pub fn get_unit_with_path(path: &str) -> Option<Arc<Mutex<dyn Unit>>> { 88 let mut hasher = DefaultHasher::new(); 89 path.hash(&mut hasher); 90 let hash = hasher.finish(); 91 let map = PATH_TO_UNIT_MAP.read().unwrap(); 92 let id = match map.get(&hash) { 93 Some(id) => id, 94 None => { 95 return None; 96 } 97 }; 98 99 let map = ID_TO_UNIT_MAP.read().unwrap(); 100 let ret = map.get(id).cloned(); 101 ret 102 } 103 104 pub fn get_unit_with_id(id: &usize) -> Option<Arc<Mutex<dyn Unit>>> { 105 let map = ID_TO_UNIT_MAP.read().unwrap(); 106 let ret = map.get(&id).cloned(); 107 ret 108 } 109 110 pub fn get_id_with_path(path: &str) -> Option<usize> { 111 let mut hasher = DefaultHasher::new(); 112 path.hash(&mut hasher); 113 let hash = hasher.finish(); 114 PATH_TO_UNIT_MAP.read().unwrap().get(&hash).cloned() 115 } 116 117 pub fn is_running_unit(id: &usize) -> bool { 118 !RUNNING_TABLE 119 .read() 120 .unwrap() 121 .running_table 122 .iter() 123 .filter(|x| x.unit_id == *id) 124 .collect::<Vec<_>>() 125 .is_empty() 126 } 127 128 pub fn push_running(unit: RunningUnit) { 129 RUNNING_TABLE.write().unwrap().running_table.push(unit); 130 } 131 132 pub fn remove_running(id: usize) { 133 let mut table = RUNNING_TABLE.write().unwrap(); 134 match table.running_table.iter().position(|x| x.unit_id == id) { 135 Some(idx) => { 136 table.running_table.remove(idx); 137 } 138 _ => (), 139 } 140 } 141 142 pub fn insert_unit_with_id(id: usize, unit: Arc<Mutex<dyn Unit>>) { 143 let mut map = ID_TO_UNIT_MAP.write().unwrap(); 144 if !map.contains_key(&id) { 145 map.insert(id, unit); 146 } 147 } 148 149 pub fn contains_id(id: &usize) -> bool{ 150 ID_TO_UNIT_MAP.read().unwrap().contains_key(id) 151 } 152 153 pub fn pop_a_idle_service() -> Option<Arc<Mutex<dyn Unit>>>{ 154 let id = IDLE_SERVIEC_DEQUE.lock().unwrap().pop_front(); 155 match id { 156 Some(id) => { 157 return Self::get_unit_with_id(&id); 158 } 159 None =>{ 160 return None; 161 } 162 } 163 } 164 165 pub fn push_a_idle_service(id: usize){ 166 if !Self::contains_id(&id) { 167 return; 168 } 169 IDLE_SERVIEC_DEQUE.lock().unwrap().push_back(id); 170 } 171 172 pub fn push_flag_running(id: usize){ 173 let mut t = FLAG_RUNNING.write().unwrap(); 174 if t.contains(&id){ 175 return; 176 } 177 t.push(id); 178 } 179 180 pub fn running_count() -> usize{ 181 return RUNNING_TABLE.read().unwrap().running_table.len(); 182 } 183 } 184