xref: /DragonReach/src/unit/mod.rs (revision b40b6b4d2f72c30a382f9f18740fa73d7fc90721)
1 use crate::error::parse_error::ParseError;
2 use crate::error::parse_error::ParseErrorType;
3 use crate::error::runtime_error::RuntimeError;
4 
5 use crate::executor::ExitStatus;
6 use crate::parse::parse_util::UnitParseUtil;
7 use crate::parse::Segment;
8 
9 #[cfg(target_os = "dragonos")]
10 use drstd as std;
11 
12 use std::any::Any;
13 use std::default::Default;
14 use std::fmt::Debug;
15 use std::marker::{Send, Sized, Sync};
16 
17 use std::result::Result;
18 use std::result::Result::Err;
19 use std::result::Result::Ok;
20 use std::string::String;
21 use std::sync::atomic::AtomicUsize;
22 use std::sync::atomic::Ordering;
23 
24 use std::vec::Vec;
25 
26 pub mod service;
27 pub mod target;
28 
29 use self::target::TargetUnit;
30 
31 pub fn generate_unit_id() -> usize {
32     static UNIT_ID: AtomicUsize = AtomicUsize::new(1);
33     return UNIT_ID.fetch_add(1, Ordering::SeqCst);
34 }
35 
36 //所有可解析的Unit都应该实现该trait
37 pub trait Unit: Sync + Send + Debug {
38     /// @brief 从文件获取到Unit,该函数是解析Unit文件的入口函数
39     ///
40     /// 从path解析Unit属性
41     ///
42     /// @param path 需解析的文件
43     ///
44     /// @return 解析成功则返回对应Unit的id,否则返回Err
45     fn from_path(path: &str) -> Result<usize, ParseError>
46     where
47         Self: Sized;
48 
49     fn as_any(&self) -> &dyn Any;
50 
51     fn as_mut_any(&mut self) -> &mut dyn Any;
52 
53     /// @brief 设置Unit属性
54     ///
55     /// 设置对应Unit属性
56     ///
57     /// @param segment  属性段类型
58     ///
59     /// @param attr     属性名
60     ///
61     /// @param val      属性值
62     ///
63     /// @return 设置成功则返回Ok(()),否则返回Err
64     fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError>;
65 
66     /// # 设置每个Unit都应该有的属性
67     ///
68     /// 设置BaseUnit
69     ///
70     /// ## param unit_base  设置值
71     fn set_unit_base(&mut self, unit_base: BaseUnit);
72 
73     /// # 获取UnitType
74     ///
75     /// ## return UnitType
76     fn unit_type(&self) -> UnitType;
77 
78     fn unit_base(&self) -> &BaseUnit;
79 
80     fn mut_unit_base(&mut self) -> &mut BaseUnit;
81 
82     fn unit_id(&self) -> usize;
83 
84     /// ## Unit的工作逻辑
85     ///
86     /// ### return OK(())/Err
87     fn run(&mut self) -> Result<(), RuntimeError>;
88 
89     /// ## 设置unit_id
90     ///
91     /// ### return OK(())/Err
92     fn set_unit_id(&mut self) -> usize {
93         let ret = generate_unit_id();
94         self.mut_unit_base().set_id(ret);
95         ret
96     }
97 
98     /// ## Unit退出后逻辑
99     ///
100     /// 一般只有可运行的Unit(如Service)需要重写此函数
101     fn after_exit(&mut self, _exit_status: ExitStatus) {}
102 
103     /// ## 初始化Unit内任务的一些参数,各个Unit所需处理的不相同,故放在总的Unit trait
104     fn init(&mut self) {}
105 
106     /// ## Unit的显式退出逻辑
107     fn exit(&mut self);
108 }
109 
110 //Unit状态
111 #[derive(Clone, Copy, Debug, PartialEq)]
112 pub enum UnitState {
113     Enabled,
114     Disabled,
115     Static,
116     Masked,
117 }
118 
119 //Unit类型
120 #[derive(Clone, Copy, PartialEq, Debug)]
121 pub enum UnitType {
122     Automount,
123     Device,
124     Mount,
125     Path,
126     Scope,
127     Service,
128     Slice,
129     Snapshot,
130     Socket,
131     Swap,
132     Target,
133     Timer,
134     Unknown,
135 }
136 
137 //记录unit文件基本信息,这个结构体里面的信息是所有Unit文件都可以有的属性
138 #[derive(Debug, Clone)]
139 pub struct BaseUnit {
140     unit_part: UnitPart,
141     install_part: InstallPart,
142     state: UnitState,
143     unit_type: UnitType,
144     unit_id: usize,
145 }
146 
147 impl Default for BaseUnit {
148     fn default() -> Self {
149         BaseUnit {
150             unit_part: UnitPart::default(),
151             install_part: InstallPart::default(),
152             state: UnitState::Disabled,
153             unit_type: UnitType::Unknown,
154             unit_id: 0,
155         }
156     }
157 }
158 
159 impl BaseUnit {
160     pub fn set_state(&mut self, state: UnitState) {
161         self.state = state;
162     }
163 
164     pub fn set_unit_type(&mut self, utype: UnitType) {
165         self.unit_type = utype;
166     }
167 
168     pub fn set_unit_part_attr(
169         &mut self,
170         attr_type: &BaseUnitAttr,
171         val: &str,
172     ) -> Result<(), ParseError> {
173         return self.unit_part.set_attr(attr_type, val);
174     }
175 
176     pub fn set_install_part_attr(
177         &mut self,
178         attr_type: &InstallUnitAttr,
179         val: &str,
180     ) -> Result<(), ParseError> {
181         return self.install_part.set_attr(attr_type, val);
182     }
183 
184     pub fn parse_and_set_attribute(&self) -> Result<(), ParseError> {
185         return Ok(());
186     }
187 
188     pub fn unit_part(&self) -> &UnitPart {
189         &self.unit_part
190     }
191 
192     pub fn mut_unit_part(&mut self) -> &mut UnitPart {
193         &mut self.unit_part
194     }
195 
196     pub fn install_part(&self) -> &InstallPart {
197         &self.install_part
198     }
199 
200     pub fn state(&self) -> &UnitState {
201         &self.state
202     }
203 
204     pub fn unit_type(&self) -> &UnitType {
205         &self.unit_type
206     }
207 
208     pub fn set_id(&mut self, id: usize) {
209         self.unit_id = id;
210     }
211 }
212 
213 #[derive(Default, Debug, Clone)]
214 pub struct Url {
215     pub url_string: String, // pub protocol: String,
216                             // pub host: String,
217                             // pub port: Option<u16>,
218                             // pub path: String,
219                             // pub query: Option<String>,
220                             // pub fragment: Option<String>,
221 }
222 
223 //对应Unit文件的Unit段
224 #[derive(Debug, Clone)]
225 pub struct UnitPart {
226     // Unit描述
227     description: String,
228     // Unit文档
229     documentation: Vec<Url>,
230     // 依赖项,同时与当前Unit启动,任意一个失败,终止该Unit的启动
231     requires: Vec<usize>,
232     // 依赖项,同时与当前Unit启动,不需要考虑其成功与否
233     wants: Vec<usize>,
234     // 该Unit在下列Units启动完成之后才能启动
235     after: Vec<usize>,
236     // after相反的语义
237     before: Vec<usize>,
238     // 与requires类似,但是这些模块任意一个意外结束或者重启时,该Unit也会终止或重启
239     binds_to: Vec<usize>,
240     // 与binds_to类似,但是不会随着当前Unit启动而启动
241     part_of: Vec<usize>,
242     // 启动失败时,需启动的项
243     on_failure: Vec<usize>,
244     // 与当前Unit冲突项
245     conflicts: Vec<usize>,
246     // 与当前Unit绑定的项,当前Unit失败或者重启时这些项也会跟着终止或重启
247     be_binded_by: Vec<usize>,
248 }
249 
250 impl Default for UnitPart {
251     fn default() -> Self {
252         UnitPart {
253             description: String::new(),
254             documentation: Vec::new(),
255             requires: Vec::new(),
256             wants: Vec::new(),
257             after: Vec::new(),
258             before: Vec::new(),
259             binds_to: Vec::new(),
260             part_of: Vec::new(),
261             on_failure: Vec::new(),
262             conflicts: Vec::new(),
263             be_binded_by: Vec::new(),
264         }
265     }
266 }
267 
268 impl UnitPart {
269     pub fn set_attr(&mut self, attr: &BaseUnitAttr, val: &str) -> Result<(), ParseError> {
270         match attr {
271             BaseUnitAttr::None => {
272                 return Err(ParseError::new(
273                     ParseErrorType::ESyntaxError,
274                     String::new(),
275                     0,
276                 ));
277             }
278             BaseUnitAttr::Description => self.description = String::from(val),
279             BaseUnitAttr::Documentation => {
280                 self.documentation.extend(UnitParseUtil::parse_url(val)?)
281             }
282             BaseUnitAttr::Requires => {
283                 let units = val.split_whitespace().collect::<Vec<&str>>();
284                 //TODO:目前先加入requires列表,可能会出现循环依赖问题,后续应解决循环依赖问题
285                 for unit_path in units {
286                     self.requires
287                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
288                 }
289             }
290             BaseUnitAttr::Wants => {
291                 let units = val.split_whitespace().collect::<Vec<&str>>();
292                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
293                 for unit_path in units {
294                     self.wants
295                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
296                 }
297             }
298             BaseUnitAttr::After => {
299                 let units = val.split_whitespace().collect::<Vec<&str>>();
300                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
301                 for unit_path in units {
302                     self.after
303                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
304                 }
305             }
306             BaseUnitAttr::Before => {
307                 let units = val.split_whitespace().collect::<Vec<&str>>();
308                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
309                 for unit_path in units {
310                     self.before
311                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
312                 }
313             }
314             BaseUnitAttr::BindsTo => {
315                 let units = val.split_whitespace().collect::<Vec<&str>>();
316                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
317                 for unit_path in units {
318                     self.binds_to
319                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
320                 }
321             }
322             BaseUnitAttr::PartOf => {
323                 let units = val.split_whitespace().collect::<Vec<&str>>();
324                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
325                 for unit_path in units {
326                     self.part_of
327                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
328                 }
329             }
330             BaseUnitAttr::OnFailure => {
331                 let units = val.split_whitespace().collect::<Vec<&str>>();
332                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
333                 for unit_path in units {
334                     self.on_failure
335                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
336                 }
337             }
338             BaseUnitAttr::Conflicts => {
339                 let units = val.split_whitespace().collect::<Vec<&str>>();
340                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
341                 for unit_path in units {
342                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
343                     self.conflicts.push(unit);
344                 }
345             }
346         }
347         return Ok(());
348     }
349 
350     pub fn description(&self) -> &str {
351         &self.description
352     }
353 
354     pub fn documentation(&self) -> &[Url] {
355         &self.documentation
356     }
357 
358     pub fn requires(&self) -> &[usize] {
359         &self.requires
360     }
361 
362     pub fn wants(&self) -> &[usize] {
363         &self.wants
364     }
365 
366     pub fn after(&self) -> &[usize] {
367         &self.after
368     }
369 
370     pub fn before(&self) -> &[usize] {
371         &self.before
372     }
373 
374     pub fn binds_to(&self) -> &[usize] {
375         &self.binds_to
376     }
377 
378     pub fn part_of(&self) -> &[usize] {
379         &self.part_of
380     }
381 
382     pub fn on_failure(&self) -> &[usize] {
383         &self.on_failure
384     }
385 
386     pub fn conflicts(&self) -> &[usize] {
387         &self.conflicts
388     }
389 
390     pub fn be_binded_by(&self) -> &[usize] {
391         &self.be_binded_by
392     }
393 
394     pub fn push_be_binded_by(&mut self, id: usize) {
395         if !self.be_binded_by.contains(&id) {
396             self.be_binded_by.push(id);
397         }
398     }
399 
400     pub fn push_after_unit(&mut self, id: usize) {
401         if !self.after.contains(&id) {
402             self.after.push(id);
403         }
404     }
405 }
406 
407 //对应Unit文件的Install段
408 #[derive(Debug, Clone)]
409 pub struct InstallPart {
410     wanted_by: Vec<usize>,
411     requires_by: Vec<usize>,
412     also: Vec<usize>,
413     alias: String,
414 }
415 
416 impl Default for InstallPart {
417     fn default() -> Self {
418         InstallPart {
419             wanted_by: Vec::new(),
420             requires_by: Vec::new(),
421             also: Vec::new(),
422             alias: String::new(),
423         }
424     }
425 }
426 
427 impl InstallPart {
428     pub fn set_attr(&mut self, attr: &InstallUnitAttr, val: &str) -> Result<(), ParseError> {
429         match attr {
430             InstallUnitAttr::RequiredBy => {
431                 let units = val.split_whitespace().collect::<Vec<&str>>();
432                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
433                 for unit_path in units {
434                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
435                     self.requires_by.push(unit);
436                 }
437             }
438             InstallUnitAttr::Also => {
439                 let units = val.split_whitespace().collect::<Vec<&str>>();
440                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
441                 for unit_path in units {
442                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
443                     self.also.push(unit);
444                 }
445             }
446             InstallUnitAttr::WantedBy => {
447                 let units = val.split_whitespace().collect::<Vec<&str>>();
448                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
449                 for unit_path in units {
450                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
451                     self.wanted_by.push(unit);
452                 }
453             }
454             InstallUnitAttr::Alias => {
455                 self.alias = String::from(val);
456             }
457             InstallUnitAttr::None => {
458                 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
459             }
460         }
461         return Ok(());
462     }
463 
464     pub fn wanted_by(&self) -> &[usize] {
465         &self.wanted_by
466     }
467 
468     pub fn requires_by(&self) -> &[usize] {
469         &self.requires_by
470     }
471 
472     pub fn also(&self) -> &[usize] {
473         &self.also
474     }
475 
476     pub fn alias(&self) -> &str {
477         &self.alias
478     }
479 }
480 //对应Unit文件的各种属性
481 pub enum BaseUnitAttr {
482     None,
483 
484     //Unit段
485     //描述该Unit文件的信息
486     Description,
487     //指定服务文档
488     Documentation,
489     //依赖的其它 Unit 列表
490     Requires,
491     //这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
492     Wants,
493     //后面列出的所有模块全部启动完成以后,才会启动当前的服务
494     After,
495     //在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
496     Before,
497     //这些Unit启动失败时该任务失败,都成功时该任务成功,在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
498     BindsTo,
499     //仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
500     PartOf,
501     //当这个模板启动失败时,就会自动启动列出的每个模块
502     OnFailure,
503     //与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然
504     Conflicts,
505 }
506 
507 pub enum InstallUnitAttr {
508     None,
509     //Install段
510     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中
511     WantedBy,
512     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中
513     RequiredBy,
514     //当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
515     Also,
516     //别名
517     Alias,
518 }
519