xref: /DragonReach/src/executor/mod.rs (revision b40b6b4d2f72c30a382f9f18740fa73d7fc90721)
1 #[cfg(target_os = "dragonos")]
2 use drstd as std;
3 
4 pub mod dep_graph;
5 pub mod service_executor;
6 
7 use crate::{
8     error::runtime_error::{RuntimeError, RuntimeErrorType},
9     manager::UnitManager,
10     unit::Unit,
11 };
12 
13 #[derive(Debug, Clone, Copy)]
14 pub enum ExitStatus {
15     Success,  // 成功退出
16     Failure,  // 启动失败
17     Abnormal, // 异常退出
18     Abort,    // 显式退出
19     Watchdog, // 超时检测
20 }
21 
22 impl ExitStatus {
23     /// ## 从错误码获得退出状态
24     ///
25     /// 注意,该方法只会返回Success(exit_code == 0)和Abnormal(exit_code != 0)两种状态
26     /// 其他DragonReach定义的退出状态需要手动指定
27     ///
28     /// ### return Success(exit_code == 0)、Abnormal(exit_code != 0)
29     pub fn from_exit_code(exit_code: i32) -> Self {
30         match exit_code {
31             0 => return Self::Success,
32             _ => return Self::Abnormal,
33         }
34     }
35 }
36 
37 //Unit的全局执行器
38 pub struct Executor;
39 
40 impl Executor {
41     /// ## 全局执行器入口,将会进行启动检测以及循环依赖检测
42     pub fn exec(unit_id: usize) -> Result<(), RuntimeError> {
43         // TODO: 添加超时检测,这个工作应该在线程执行
44 
45         match Self::exec_(unit_id) {
46             Ok(_) => Ok(()),
47             Err(e) => {
48                 let mutex = UnitManager::get_unit_with_id(&unit_id).unwrap();
49                 let mut unit = mutex.lock().unwrap();
50 
51                 // 启动失败时启动onfailure项目
52                 for id in unit.unit_base().unit_part().on_failure() {
53                     // TODO: 待日志库开发后,这里的错误处理应该是打印日志
54                     let _ = Executor::exec(*id);
55                 }
56 
57                 unit.after_exit(ExitStatus::Failure);
58                 return Err(e);
59             }
60         }
61     }
62     pub fn exec_(unit_id: usize) -> Result<(), RuntimeError> {
63         // TODO: 目前的启动逻辑还是串行启动,后续需更改为并行启动某些项
64 
65         let unit = match UnitManager::get_unit_with_id(&unit_id) {
66             Some(s) => s,
67             None => {
68                 return Err(RuntimeError::new(RuntimeErrorType::FileNotFound));
69             }
70         };
71 
72         let mut unit = unit.lock().unwrap();
73 
74         //TODO: 优化此处,解析时也用到了拓扑排序,尝试使用那次拓扑排序的结果
75         // 此处不需要再次拓扑排序,在parse时已经确定不会出现循环依赖,现在仅需按照启动流程启动即可
76         // let mut graph = DepGraph::construct_graph(&unit);
77         // let sort_ret = graph.topological_sort()?;
78 
79         // 优先启动After
80         for u in unit.unit_base().unit_part().after() {
81             if UnitManager::is_running_unit(&u) {
82                 continue;
83             }
84 
85             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
86             let mut after = mutex.lock().unwrap();
87             after.run()?;
88         }
89 
90         // 启动Requires
91         for u in unit.unit_base().unit_part().requires() {
92             if UnitManager::is_running_unit(&u) {
93                 continue;
94             }
95             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
96             let mut after = mutex.lock().unwrap();
97             after.run()?;
98         }
99 
100         // 启动binds
101         for u in unit.unit_base().unit_part().binds_to() {
102             if UnitManager::is_running_unit(&u) {
103                 continue;
104             }
105             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
106             let mut after = mutex.lock().unwrap();
107             after.run()?;
108         }
109 
110         // 启动Wants
111         for u in unit.unit_base().unit_part().wants() {
112             if UnitManager::is_running_unit(&u) {
113                 continue;
114             }
115             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
116             let mut after = mutex.lock().unwrap();
117             let _ = after.run();
118         }
119 
120         // 启动自身
121         unit.run()?;
122         return Ok(());
123     }
124 }
125