xref: /DragonReach/src/unit/mod.rs (revision 236b9b4f4d4f527c482cad40d09674195023e5fb)
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 #[derive(Clone, Copy, Debug, PartialEq)]
109 pub enum UnitState {
110     Enabled,
111     Disabled,
112     Static,
113     Masked,
114 }
115 
116 //Unit类型
117 #[derive(Clone, Copy, PartialEq, Debug)]
118 pub enum UnitType {
119     Automount,
120     Device,
121     Mount,
122     Path,
123     Scope,
124     Service,
125     Slice,
126     Snapshot,
127     Socket,
128     Swap,
129     Target,
130     Timer,
131     Unknown,
132 }
133 
134 //记录unit文件基本信息,这个结构体里面的信息是所有Unit文件都可以有的属性
135 #[derive(Debug, Clone)]
136 pub struct BaseUnit {
137     unit_part: UnitPart,
138     install_part: InstallPart,
139     state: UnitState,
140     unit_type: UnitType,
141     unit_id: usize,
142 }
143 
144 impl Default for BaseUnit {
145     fn default() -> Self {
146         BaseUnit {
147             unit_part: UnitPart::default(),
148             install_part: InstallPart::default(),
149             state: UnitState::Disabled,
150             unit_type: UnitType::Unknown,
151             unit_id: 0,
152         }
153     }
154 }
155 
156 impl BaseUnit {
157     pub fn set_state(&mut self, state: UnitState) {
158         self.state = state;
159     }
160 
161     pub fn set_unit_type(&mut self, utype: UnitType) {
162         self.unit_type = utype;
163     }
164 
165     pub fn set_unit_part_attr(
166         &mut self,
167         attr_type: &BaseUnitAttr,
168         val: &str,
169     ) -> Result<(), ParseError> {
170         return self.unit_part.set_attr(attr_type, val);
171     }
172 
173     pub fn set_install_part_attr(
174         &mut self,
175         attr_type: &InstallUnitAttr,
176         val: &str,
177     ) -> Result<(), ParseError> {
178         return self.install_part.set_attr(attr_type, val);
179     }
180 
181     pub fn parse_and_set_attribute(&self) -> Result<(), ParseError> {
182         return Ok(());
183     }
184 
185     pub fn unit_part(&self) -> &UnitPart {
186         &self.unit_part
187     }
188 
189     pub fn mut_unit_part(&mut self) -> &mut UnitPart {
190         &mut self.unit_part
191     }
192 
193     pub fn install_part(&self) -> &InstallPart {
194         &self.install_part
195     }
196 
197     pub fn state(&self) -> &UnitState {
198         &self.state
199     }
200 
201     pub fn unit_type(&self) -> &UnitType {
202         &self.unit_type
203     }
204 
205     pub fn set_id(&mut self, id: usize) {
206         self.unit_id = id;
207     }
208 }
209 
210 #[derive(Default, Debug, Clone)]
211 pub struct Url {
212     pub url_string: String, // pub protocol: String,
213                             // pub host: String,
214                             // pub port: Option<u16>,
215                             // pub path: String,
216                             // pub query: Option<String>,
217                             // pub fragment: Option<String>,
218 }
219 
220 //对应Unit文件的Unit段
221 #[derive(Debug, Clone)]
222 pub struct UnitPart {
223     // Unit描述
224     description: String,
225     // Unit文档
226     documentation: Vec<Url>,
227     // 依赖项,同时与当前Unit启动,任意一个失败,终止该Unit的启动
228     requires: Vec<usize>,
229     // 依赖项,同时与当前Unit启动,不需要考虑其成功与否
230     wants: Vec<usize>,
231     // 该Unit在下列Units启动完成之后才能启动
232     after: Vec<usize>,
233     // after相反的语义
234     before: Vec<usize>,
235     // 与requires类似,但是这些模块任意一个意外结束或者重启时,该Unit也会终止或重启
236     binds_to: Vec<usize>,
237     // 与binds_to类似,但是不会随着当前Unit启动而启动
238     part_of: Vec<usize>,
239     // 启动失败时,需启动的项
240     on_failure: Vec<usize>,
241     // 与当前Unit冲突项
242     conflicts: Vec<usize>,
243     // 与当前Unit绑定的项,当前Unit失败或者重启时这些项也会跟着终止或重启
244     be_binded_by: Vec<usize>,
245 }
246 
247 impl Default for UnitPart {
248     fn default() -> Self {
249         UnitPart {
250             description: String::new(),
251             documentation: Vec::new(),
252             requires: Vec::new(),
253             wants: Vec::new(),
254             after: Vec::new(),
255             before: Vec::new(),
256             binds_to: Vec::new(),
257             part_of: Vec::new(),
258             on_failure: Vec::new(),
259             conflicts: Vec::new(),
260             be_binded_by: Vec::new(),
261         }
262     }
263 }
264 
265 impl UnitPart {
266     pub fn set_attr(&mut self, attr: &BaseUnitAttr, val: &str) -> Result<(), ParseError> {
267         match attr {
268             BaseUnitAttr::None => {
269                 return Err(ParseError::new(
270                     ParseErrorType::ESyntaxError,
271                     String::new(),
272                     0,
273                 ));
274             }
275             BaseUnitAttr::Description => self.description = String::from(val),
276             BaseUnitAttr::Documentation => {
277                 self.documentation.extend(UnitParseUtil::parse_url(val)?)
278             }
279             BaseUnitAttr::Requires => {
280                 let units = val.split_whitespace().collect::<Vec<&str>>();
281                 //TODO:目前先加入requires列表,可能会出现循环依赖问题,后续应解决循环依赖问题
282                 for unit_path in units {
283                     self.requires
284                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
285                 }
286             }
287             BaseUnitAttr::Wants => {
288                 let units = val.split_whitespace().collect::<Vec<&str>>();
289                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
290                 for unit_path in units {
291                     self.wants
292                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
293                 }
294             }
295             BaseUnitAttr::After => {
296                 let units = val.split_whitespace().collect::<Vec<&str>>();
297                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
298                 for unit_path in units {
299                     self.after
300                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
301                 }
302             }
303             BaseUnitAttr::Before => {
304                 let units = val.split_whitespace().collect::<Vec<&str>>();
305                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
306                 for unit_path in units {
307                     self.before
308                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
309                 }
310             }
311             BaseUnitAttr::BindsTo => {
312                 let units = val.split_whitespace().collect::<Vec<&str>>();
313                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
314                 for unit_path in units {
315                     self.binds_to
316                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
317                 }
318             }
319             BaseUnitAttr::PartOf => {
320                 let units = val.split_whitespace().collect::<Vec<&str>>();
321                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
322                 for unit_path in units {
323                     self.part_of
324                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
325                 }
326             }
327             BaseUnitAttr::OnFailure => {
328                 let units = val.split_whitespace().collect::<Vec<&str>>();
329                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
330                 for unit_path in units {
331                     self.on_failure
332                         .push(UnitParseUtil::parse_unit_no_type(unit_path)?);
333                 }
334             }
335             BaseUnitAttr::Conflicts => {
336                 let units = val.split_whitespace().collect::<Vec<&str>>();
337                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
338                 for unit_path in units {
339                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
340                     self.conflicts.push(unit);
341                 }
342             }
343         }
344         return Ok(());
345     }
346 
347     pub fn description(&self) -> &str {
348         &self.description
349     }
350 
351     pub fn documentation(&self) -> &[Url] {
352         &self.documentation
353     }
354 
355     pub fn requires(&self) -> &[usize] {
356         &self.requires
357     }
358 
359     pub fn wants(&self) -> &[usize] {
360         &self.wants
361     }
362 
363     pub fn after(&self) -> &[usize] {
364         &self.after
365     }
366 
367     pub fn before(&self) -> &[usize] {
368         &self.before
369     }
370 
371     pub fn binds_to(&self) -> &[usize] {
372         &self.binds_to
373     }
374 
375     pub fn part_of(&self) -> &[usize] {
376         &self.part_of
377     }
378 
379     pub fn on_failure(&self) -> &[usize] {
380         &self.on_failure
381     }
382 
383     pub fn conflicts(&self) -> &[usize] {
384         &self.conflicts
385     }
386 
387     pub fn be_binded_by(&self) -> &[usize] {
388         &self.be_binded_by
389     }
390 
391     pub fn push_be_binded_by(&mut self, id: usize) {
392         if !self.be_binded_by.contains(&id) {
393             self.be_binded_by.push(id);
394         }
395     }
396 
397     pub fn push_after_unit(&mut self, id: usize) {
398         if !self.after.contains(&id) {
399             self.after.push(id);
400         }
401     }
402 }
403 
404 //对应Unit文件的Install段
405 #[derive(Debug, Clone)]
406 pub struct InstallPart {
407     wanted_by: Vec<usize>,
408     requires_by: Vec<usize>,
409     also: Vec<usize>,
410     alias: String,
411 }
412 
413 impl Default for InstallPart {
414     fn default() -> Self {
415         InstallPart {
416             wanted_by: Vec::new(),
417             requires_by: Vec::new(),
418             also: Vec::new(),
419             alias: String::new(),
420         }
421     }
422 }
423 
424 impl InstallPart {
425     pub fn set_attr(&mut self, attr: &InstallUnitAttr, val: &str) -> Result<(), ParseError> {
426         match attr {
427             InstallUnitAttr::RequiredBy => {
428                 let units = val.split_whitespace().collect::<Vec<&str>>();
429                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
430                 for unit_path in units {
431                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
432                     self.requires_by.push(unit);
433                 }
434             }
435             InstallUnitAttr::Also => {
436                 let units = val.split_whitespace().collect::<Vec<&str>>();
437                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
438                 for unit_path in units {
439                     let unit = UnitParseUtil::parse_unit_no_type(unit_path)?;
440                     self.also.push(unit);
441                 }
442             }
443             InstallUnitAttr::WantedBy => {
444                 let units = val.split_whitespace().collect::<Vec<&str>>();
445                 //TODO:目前先加入列表,可能会出现循环依赖问题,后续应解决循环依赖问题
446                 for unit_path in units {
447                     let unit = UnitParseUtil::parse_unit::<TargetUnit>(unit_path)?;
448                     self.wanted_by.push(unit);
449                 }
450             }
451             InstallUnitAttr::Alias => {
452                 self.alias = String::from(val);
453             }
454             InstallUnitAttr::None => {
455                 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
456             }
457         }
458         return Ok(());
459     }
460 
461     pub fn wanted_by(&self) -> &[usize] {
462         &self.wanted_by
463     }
464 
465     pub fn requires_by(&self) -> &[usize] {
466         &self.requires_by
467     }
468 
469     pub fn also(&self) -> &[usize] {
470         &self.also
471     }
472 
473     pub fn alias(&self) -> &str {
474         &self.alias
475     }
476 }
477 //对应Unit文件的各种属性
478 pub enum BaseUnitAttr {
479     None,
480 
481     //Unit段
482     //描述该Unit文件的信息
483     Description,
484     //指定服务文档
485     Documentation,
486     //依赖的其它 Unit 列表
487     Requires,
488     //这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
489     Wants,
490     //后面列出的所有模块全部启动完成以后,才会启动当前的服务
491     After,
492     //在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
493     Before,
494     //这些Unit启动失败时该任务失败,都成功时该任务成功,在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
495     BindsTo,
496     //仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
497     PartOf,
498     //当这个模板启动失败时,就会自动启动列出的每个模块
499     OnFailure,
500     //与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然
501     Conflicts,
502 }
503 
504 pub enum InstallUnitAttr {
505     None,
506     //Install段
507     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中
508     WantedBy,
509     //依赖当前服务的模块。当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中
510     RequiredBy,
511     //当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
512     Also,
513     //别名
514     Alias,
515 }
516