xref: /DragonReach/src/manager/unit_manager/mod.rs (revision 2069cc0dc0984a2981454b00316ba607f88ac512)
1 use std::{
2     collections::{hash_map::DefaultHasher, VecDeque},
3     hash::{Hash, Hasher},
4     process::Child,
5     sync::{Arc, Mutex, RwLock},
6 };
7 
8 use crate::unit::Unit;
9 use hashbrown::HashMap;
10 use lazy_static::lazy_static;
11 
12 lazy_static! {
13     /// 对于启动后即使退出亦认为其为运行状态的特殊注册类Service,对于这类进程做一个标记
14     static ref FLAG_RUNNING: RwLock<Vec<usize>> = RwLock::new(Vec::new());
15 
16     /// 任务等待队列,IDLE类型的service入队等待其它任务完成再执行
17     static ref IDLE_SERVIEC_DEQUE: Mutex<VecDeque<usize>> = Mutex::new(VecDeque::new());
18 
19     /// id到unit的映射表,全局的Unit管理表
20     pub(super) static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new());
21 
22     /// 辅助表,通过服务名映射其id
23     static ref NAME_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new());
24 
25     /// 全局运行中的Unit表
26     pub(super) static ref RUNNING_TABLE: RwLock<RunningTableManager> = RwLock::new(RunningTableManager { running_table: HashMap::new() });
27 
28     /// CMD进程表,用于处理Unit的CMD派生进程(ExecStartPre等命令派生进程)
29     pub(super) static ref CMD_PROCESS_TABLE: RwLock<HashMap<u32,Mutex<Child>>> = RwLock::new(HashMap::new());
30 }
31 
32 pub struct RunningTableManager {
33     running_table: HashMap<usize, Child>,
34 }
35 
36 #[allow(dead_code)]
37 impl RunningTableManager {
running_table(&self) -> &HashMap<usize, Child>38     pub fn running_table(&self) -> &HashMap<usize, Child> {
39         &self.running_table
40     }
41 
mut_running_table(&mut self) -> &mut HashMap<usize, Child>42     pub fn mut_running_table(&mut self) -> &mut HashMap<usize, Child> {
43         &mut self.running_table
44     }
45 }
46 
47 pub struct UnitManager;
48 
49 unsafe impl Sync for UnitManager {}
50 
51 #[allow(dead_code)]
52 impl UnitManager {
53     /// 插入一条path到unit_id的映射
insert_into_name_table(path: &str, unit: usize)54     pub fn insert_into_name_table(path: &str, unit: usize) {
55         let mut hasher = DefaultHasher::new();
56         path.hash(&mut hasher);
57         let hash = hasher.finish();
58         NAME_TO_UNIT_MAP.write().unwrap().insert(hash, unit);
59     }
60 
61     // 判断当前是否已经有了对应path的Unit
contains_name(path: &str) -> bool62     pub fn contains_name(path: &str) -> bool {
63         let mut hasher = DefaultHasher::new();
64         path.hash(&mut hasher);
65         let hash = hasher.finish();
66         NAME_TO_UNIT_MAP.read().unwrap().contains_key(&hash)
67     }
68 
69     // 通过path获取到Unit
get_unit_with_name(name: &str) -> Option<Arc<Mutex<dyn Unit>>>70     pub fn get_unit_with_name(name: &str) -> Option<Arc<Mutex<dyn Unit>>> {
71         let mut hasher = DefaultHasher::new();
72         name.hash(&mut hasher);
73         let hash = hasher.finish();
74         let map = NAME_TO_UNIT_MAP.read().unwrap();
75         let id = match map.get(&hash) {
76             Some(id) => id,
77             None => {
78                 return None;
79             }
80         };
81 
82         let map = ID_TO_UNIT_MAP.read().unwrap();
83         let ret = map.get(id).cloned();
84         ret
85     }
86 
87     // 通过unit_id获取Unit
get_unit_with_id(id: &usize) -> Option<Arc<Mutex<dyn Unit>>>88     pub fn get_unit_with_id(id: &usize) -> Option<Arc<Mutex<dyn Unit>>> {
89         let map = ID_TO_UNIT_MAP.read().unwrap();
90         let ret = map.get(&id).cloned();
91         ret
92     }
93 
94     // 通过id获取到path
95     // ↑感觉是笔误,应该是通过path获取到id
get_id_with_path(path: &str) -> Option<usize>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         NAME_TO_UNIT_MAP.read().unwrap().get(&hash).cloned()
101     }
102 
103     // 判断该Unit是否正在运行中
is_running_unit(id: &usize) -> bool104     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
push_running(unit_id: usize, p: Child)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
remove_running(id: usize)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映射表中插入数据
insert_unit_with_id(id: usize, unit: Arc<Mutex<dyn 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
contains_id(id: &usize) -> bool139     pub fn contains_id(id: &usize) -> bool {
140         ID_TO_UNIT_MAP.read().unwrap().contains_key(id)
141     }
142 
143     // 弹出一个处于IDLE状态的Service
pop_a_idle_service() -> Option<Arc<Mutex<dyn Unit>>>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,将在后续调度
push_a_idle_service(id: usize)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标记为运行状态,并且后续不会对其进行运行检查
push_flag_running(id: usize)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数
running_count() -> usize174     pub fn running_count() -> usize {
175         return RUNNING_TABLE.read().unwrap().running_table.len();
176     }
177 
178     // 向Cmd运行表中添加
push_cmd_proc(proc: Child)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     // 弹出指定id的cmd进程
pop_cmd_proc(id: u32) -> Option<Mutex<Child>>187     pub fn pop_cmd_proc(id: u32) -> Option<Mutex<Child>> {
188         CMD_PROCESS_TABLE.write().unwrap().remove(&id)
189     }
190 
191     // 初始化各Unit的依赖关系,此方法只需在解析完系统Unit文件后调用一次
init_units_dependencies()192     pub fn init_units_dependencies() {
193         let manager = ID_TO_UNIT_MAP.write().unwrap();
194 
195         // 处理before段,将before段的Unit添加此Unit为After
196         for (id, unit) in manager.iter() {
197             let mut unit = unit.lock().unwrap();
198             let before = unit.unit_base_mut().unit_part().before();
199             for rid in before {
200                 let req = UnitManager::get_unit_with_id(rid).unwrap();
201                 let mut req = req.lock().unwrap();
202                 req.unit_base_mut().mut_unit_part().push_after_unit(*id);
203             }
204         }
205 
206         for (id, unit) in manager.iter() {
207             let mut unit = unit.lock().unwrap();
208 
209             // 处理binds_to段
210             let binds_to = unit.unit_base_mut().unit_part().binds_to();
211             for rid in binds_to {
212                 let req = UnitManager::get_unit_with_id(rid).unwrap();
213                 let mut req = req.lock().unwrap();
214                 req.unit_base_mut().mut_unit_part().push_be_binded_by(*id);
215             }
216 
217             // 处理part_of段
218             let part_of = unit.unit_base_mut().unit_part().part_of();
219             for rid in part_of {
220                 let req = UnitManager::get_unit_with_id(rid).unwrap();
221                 let mut req = req.lock().unwrap();
222                 req.unit_base_mut().mut_unit_part().push_be_binded_by(*id);
223             }
224         }
225     }
226 
227     /// ## 如果Unit进程正在运行则杀死Unit进程
try_kill_running(id: usize) -> bool228     pub fn try_kill_running(id: usize) -> bool {
229         if Self::is_running_unit(&id) {
230             Self::kill_running(id);
231             return true;
232         }
233         return false;
234     }
235 
kill_running(id: usize)236     pub fn kill_running(id: usize) {
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