xref: /DragonReach/src/manager/unit_manager/mod.rs (revision 56797478d93fa8dbba9da9f520575e529b5f3326)
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