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