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