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