Browse Source

feat(unit/timer_unit) :First step implementation of timer unit #41 (#44)

实现timer类型的unit

Co-authored-by: BrahmaMantra <2033552517.qq.com>
BrahmaMantra 11 months ago
parent
commit
2069cc0dc0

+ 16 - 0
.vscode/launch.json

@@ -0,0 +1,16 @@
+{
+    // 使用 IntelliSense 了解相关属性。 
+    // 悬停以查看现有属性的描述。
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "lldb",
+            "request": "launch",
+            "name": "Debug",
+            "program": "${workspaceFolder}/<executable file>",
+            "args": [],
+            "cwd": "${workspaceFolder}"
+        }
+    ]
+}

+ 1 - 0
Cargo.toml

@@ -18,6 +18,7 @@ hashbrown = "0.11"
 cfg-if = { version = "1.0" }
 lazy_static = { version = "1.4.0" }
 libc = "0.2"
+humantime = "2.1"
 
 [profile.release]
 panic = 'abort'

+ 7 - 0
parse_test/test_timer_unit.service

@@ -0,0 +1,7 @@
+[Unit]
+Description=a test for timer_unit
+
+[Service]
+Type=simple
+ExecStart=-/bin/about.elf
+ExecStartPre=-/bin/clear

+ 7 - 0
parse_test/test_timer_unit.timer

@@ -0,0 +1,7 @@
+[Unit]
+Description=a timer for the same_name.service
+
+[Timer]
+OnActiveSec=3s
+OnUnitActiveSec=5s
+Unit=test_timer_unit.service

+ 3 - 3
src/main.rs

@@ -9,15 +9,15 @@ mod time;
 mod unit;
 
 use error::ErrorFormat;
-use executor::Executor;
 use manager::{timer_manager::TimerManager, Manager};
 use parse::UnitParser;
 use systemctl::listener::Systemctl;
 
+use crate::executor::Executor;
+
 pub struct FileDescriptor(usize);
 
 const DRAGON_REACH_UNIT_DIR: &'static str = "/etc/reach/system/";
-
 fn main() {
     // 初始化
     Systemctl::init();
@@ -46,12 +46,12 @@ fn main() {
                 0
             }
         };
-
         if id != 0 {
             if let Err(e) = Executor::exec(id) {
                 eprintln!("Err:{}", e.error_format());
             }
         }
+        println!("Parse {} success!", path);
     }
 
     // 启动完服务后进入主循环

+ 8 - 1
src/manager/mod.rs

@@ -21,7 +21,6 @@ impl Manager {
             match proc.try_wait() {
                 //进程正常退出
                 Ok(Some(status)) => {
-                    //TODO:交付给相应类型的Unit类型去执行退出后的逻辑
                     exited_unit.push((
                         *unit.0,
                         ExitStatus::from_exit_code(status.code().unwrap_or(0)),
@@ -49,6 +48,14 @@ impl Manager {
             // 取消该任务的定时器任务
             TimerManager::cancel_timer(tmp.0);
 
+            let _ = UnitManager::get_unit_with_id(&tmp.0)
+                .unwrap()
+                .lock()
+                .unwrap()
+                .exit(); //交付给相应类型的Unit类型去执行退出后的逻辑
+
+            TimerManager::update_next_trigger(tmp.0, false); //更新所有归属于此unit的计时器
+
             // 交付处理子进程退出逻辑
             let unit = UnitManager::get_unit_with_id(&tmp.0).unwrap();
             unit.lock().unwrap().after_exit(tmp.1);

+ 131 - 6
src/manager/timer_manager/mod.rs

@@ -1,17 +1,27 @@
-use std::{sync::RwLock, time::Duration};
+use std::{
+    sync::{Arc, Mutex, RwLock},
+    time::Duration,
+};
 
-use crate::{error::runtime_error::RuntimeError, time::timer::Timer};
+use crate::{
+    error::runtime_error::RuntimeError, time::timer::Timer, unit::timer::TimerUnit, unit::Unit,
+};
+use hashbrown::HashMap;
 use lazy_static::lazy_static;
-
 lazy_static! {
     // 管理全局计时器任务
-    static ref TIMER_TASK_MANAGER: RwLock<TimerManager> = RwLock::new(TimerManager {
-        inner_timers: Vec::new()
+    static ref TIMER_TASK_MANAGER:RwLock<TimerManager> = RwLock::new(TimerManager {
+        inner_timers: Vec::new(),
+        timer_unit_map: RwLock::new(HashMap::new()),
+
+        id_table:RwLock::new(Vec::new())
     });
 }
 
 pub struct TimerManager {
     inner_timers: Vec<Timer>,
+    timer_unit_map: RwLock<HashMap<usize, Arc<Mutex<TimerUnit>>>>, //id->TimerUnit
+    id_table: RwLock<Vec<(usize, usize)>>, //.0是TimerUnit的id,.1是父Unit的id
 }
 
 impl<'a> IntoIterator for &'a mut TimerManager {
@@ -27,7 +37,7 @@ impl<'a> IntoIterator for &'a mut TimerManager {
 impl TimerManager {
     /// ## 添加定时器任务
     ///
-    /// 只有通过这个方式创建的Timer对象才会真正的实现计时
+    /// 只有通过两这个方式载入的Timer或Timer_unit对象才会真正的实现计时
     pub fn push_timer<F>(duration: Duration, callback: F, parent: usize)
     where
         F: FnMut() -> Result<(), RuntimeError> + Send + Sync + 'static,
@@ -39,6 +49,23 @@ impl TimerManager {
             .push(Timer::new(duration, Box::new(callback), parent));
     }
 
+    pub fn push_timer_unit(unit: Arc<Mutex<TimerUnit>>) {
+        let timemanager = TIMER_TASK_MANAGER.write().unwrap();
+        let mut unit_guard = unit.lock().unwrap();
+        let unit_id = unit_guard.unit_id();
+        timemanager
+            .id_table
+            .write()
+            .unwrap()
+            .push((unit_id, unit_guard.get_parent_unit()));
+        drop(unit_guard);
+        timemanager
+            .timer_unit_map
+            .write()
+            .unwrap()
+            .insert(unit_id, unit); //加入到inner_timers_map
+    }
+
     /// ## 检测定时器是否到时,到时则触发
     ///
     /// 该方法在主循环中每循环一次检测一次,是伪计时器的主运行函数
@@ -46,6 +73,33 @@ impl TimerManager {
         let mut writer = TIMER_TASK_MANAGER.write().unwrap();
         //此处触发定时器,若定时器被触发,则移除
         writer.inner_timers.retain_mut(|x| !x.check());
+        drop(writer);
+        //此处触发Timer_unit,不移除
+        let reader = TIMER_TASK_MANAGER.read().unwrap();
+        let timer_unit_map = reader.timer_unit_map.read().unwrap();
+        let mut inactive_unit: Vec<usize> = Vec::new();
+        for (_, timer_unit) in timer_unit_map.iter() {
+            let mut unit_guard = timer_unit.lock().unwrap();
+            if unit_guard.enter_inactive() {
+                inactive_unit.push(unit_guard.unit_id());
+                continue;
+            }
+            if unit_guard.check() {
+                //println!("unit id : {} , parent id : {} ",timer_unit.unit_id(),timer_unit.get_parent_unit());
+                let _ = unit_guard._run(); //运行作出相应操作
+                let id = unit_guard.get_parent_unit();
+                drop(unit_guard);
+                TimerManager::update_next_trigger(id, true); //更新触发时间
+            }
+        }
+
+        for id in inactive_unit {
+            //处理Inactive需要退出的计时器
+            //println!("Prepared to exit...");
+            timer_unit_map.get(&id).unwrap().lock().unwrap().exit();
+
+            TimerManager::remove_timer_unit(id);
+        }
     }
 
     /// ## 取消掉一个unit的所有定时任务,
@@ -58,4 +112,75 @@ impl TimerManager {
             .inner_timers
             .retain(|x| x.parent() == unit_id)
     }
+
+    pub fn is_timer(id: &usize) -> bool {
+        let id_table = &TIMER_TASK_MANAGER.read().unwrap().id_table;
+        for iter in id_table.read().unwrap().iter() {
+            if iter.0 == *id {
+                return true;
+            }
+        }
+        false
+    }
+    /// unit_id:父unit的id  flag:1为exec 0为exit
+    fn adjust_timevalue(unit_id: &usize, flag: bool /*1为启动0为退出 */) -> Vec<usize> {
+        let mut result = Vec::new();
+        let manager = TIMER_TASK_MANAGER.read().unwrap();
+        for (self_id, parent_id) in manager.id_table.read().unwrap().iter() {
+            if unit_id == parent_id {
+                let timer_unit_map = manager.timer_unit_map.read().unwrap();
+                let mut timer_unit = timer_unit_map.get(self_id).unwrap().lock().unwrap();
+                timer_unit.change_stage(flag);
+                result.push(*self_id);
+            }
+        }
+        result
+    }
+
+    /// 从Timer表中删除该Unit
+    pub fn remove_timer_unit(unit_id: usize) {
+        let manager = TIMER_TASK_MANAGER.read().unwrap();
+
+        manager.timer_unit_map.write().unwrap().remove(&unit_id);
+        let mut index: usize = 0;
+        let mut id_table = manager.id_table.write().unwrap();
+        for (self_id, _) in id_table.iter() {
+            //因为id是递增的,后续可优化为二分查找
+            if unit_id == *self_id {
+                id_table.remove(index);
+                println!("remove id:{}", unit_id);
+                return;
+            }
+            index = index + 1
+        }
+    }
+
+    /// 获得该id下的所有计时器
+    pub fn get_timer(parent_id: usize) -> Vec<usize> {
+        let mut result = Vec::new();
+        let timer_manager = TIMER_TASK_MANAGER.read().unwrap();
+        let reader = timer_manager.id_table.read().unwrap();
+        for (timer_id, id) in reader.iter() {
+            if *id == parent_id {
+                result.push(*timer_id);
+            }
+        }
+        result
+    }
+    ///此时传入的是parent_id
+    pub fn update_next_trigger(unit_id: usize, flag: bool) {
+        let timer_vec = Self::adjust_timevalue(&unit_id, flag);
+
+        let timer_manager = TIMER_TASK_MANAGER.read().unwrap();
+        let timer_unit_map = timer_manager.timer_unit_map.read().unwrap();
+        timer_vec.iter().for_each(|id| {
+            timer_unit_map
+                .get(id)
+                .unwrap()
+                .lock()
+                .unwrap()
+                .mut_timer_part()
+                .update_next_trigger();
+        });
+    }
 }

+ 7 - 6
src/manager/unit_manager/mod.rs

@@ -10,22 +10,22 @@ use hashbrown::HashMap;
 use lazy_static::lazy_static;
 
 lazy_static! {
-    // 对于启动后即使退出亦认为其为运行状态的特殊注册类Service,对于这类进程做一个标记
+    /// 对于启动后即使退出亦认为其为运行状态的特殊注册类Service,对于这类进程做一个标记
     static ref FLAG_RUNNING: RwLock<Vec<usize>> = RwLock::new(Vec::new());
 
-    // 任务等待队列,IDLE类型的service入队等待其它任务完成再执行
+    /// 任务等待队列,IDLE类型的service入队等待其它任务完成再执行
     static ref IDLE_SERVIEC_DEQUE: Mutex<VecDeque<usize>> = Mutex::new(VecDeque::new());
 
-    // id到unit的映射表,全局的Unit管理表
+    /// id到unit的映射表,全局的Unit管理表
     pub(super) static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new());
 
-    // 辅助表,通过服务名映射其id
+    /// 辅助表,通过服务名映射其id
     static ref NAME_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new());
 
-    // 全局运行中的Unit表
+    /// 全局运行中的Unit表
     pub(super) static ref RUNNING_TABLE: RwLock<RunningTableManager> = RwLock::new(RunningTableManager { running_table: HashMap::new() });
 
-    // CMD进程表,用于处理Unit的CMD派生进程(ExecStartPre等命令派生进程)
+    /// CMD进程表,用于处理Unit的CMD派生进程(ExecStartPre等命令派生进程)
     pub(super) static ref CMD_PROCESS_TABLE: RwLock<HashMap<u32,Mutex<Child>>> = RwLock::new(HashMap::new());
 }
 
@@ -92,6 +92,7 @@ impl UnitManager {
     }
 
     // 通过id获取到path
+    // ↑感觉是笔误,应该是通过path获取到id
     pub fn get_id_with_path(path: &str) -> Option<usize> {
         let mut hasher = DefaultHasher::new();
         path.hash(&mut hasher);

+ 13 - 3
src/parse/mod.rs

@@ -17,11 +17,13 @@ use lazy_static::lazy_static;
 
 use self::parse_service::ServiceParser;
 use self::parse_target::TargetParser;
+use self::parse_timer::TimerParser;
 use self::parse_util::UnitParseUtil;
 
 pub mod graph;
 pub mod parse_service;
 pub mod parse_target;
+pub mod parse_timer;
 pub mod parse_util;
 
 //对应Unit段类型
@@ -31,6 +33,7 @@ pub enum Segment {
     Unit,
     Install,
     Service,
+    Timer,
 }
 
 lazy_static! {
@@ -42,8 +45,8 @@ lazy_static! {
         table.insert("path", UnitType::Path);
         table.insert("scope", UnitType::Scope);
         table.insert("service", UnitType::Service);
-        table.insert("slice", UnitType::Automount);
-        table.insert("automount", UnitType::Slice);
+        table.insert("slice", UnitType::Automount);//疑似copy错了,稍后修改
+        table.insert("automount", UnitType::Slice);//
         table.insert("socket", UnitType::Socket);
         table.insert("swap", UnitType::Swap);
         table.insert("target", UnitType::Target);
@@ -55,6 +58,8 @@ lazy_static! {
         table.insert("[Unit]", Segment::Unit);
         table.insert("[Install]", Segment::Install);
         table.insert("[Service]", Segment::Service);
+        table.insert("[Timer]", Segment::Timer);
+        // 后续再添加需求的具体字段
         table
     };
     pub static ref INSTALL_UNIT_ATTR_TABLE: HashMap<&'static str, InstallUnitAttr> = {
@@ -147,10 +152,12 @@ lazy_static! {
     };
     pub static ref TIMER_UNIT_ATTR_TABLE: HashMap<&'static str, TimerUnitAttr> = {
         let mut map = HashMap::new();
+        // map.insert("State", TimerUnitAttr::State);
+        // map.insert("Result", TimerUnitAttr::Result);
         map.insert("OnActiveSec", TimerUnitAttr::OnActiveSec);
         map.insert("OnBootSec", TimerUnitAttr::OnBootSec);
         map.insert("OnStartupSec", TimerUnitAttr::OnStartUpSec);
-        map.insert("OnUnitActiveSec", TimerUnitAttr::OnUnitInactiveSec);
+        map.insert("OnUnitActiveSec", TimerUnitAttr::OnUnitActiveSec);
         map.insert("OnUnitInactiveSec", TimerUnitAttr::OnUnitInactiveSec);
         map.insert("OnCalendar", TimerUnitAttr::OnCalendar);
         map.insert("AccuracySec", TimerUnitAttr::AccuarcySec);
@@ -216,6 +223,7 @@ impl UnitParser {
         match unit_type {
             UnitType::Service => ServiceParser::parse(path),
             UnitType::Target => TargetParser::parse(path),
+            UnitType::Timer => TimerParser::parse(path), //新实现的timer_unit
             _ => Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0)),
         }
     }
@@ -318,6 +326,7 @@ impl UnitParser {
             };
             //首先匹配所有unit文件都有的unit段和install段
             if BASE_UNIT_ATTR_TABLE.get(attr_str).is_some() {
+                //匹配Unit字段
                 if segment != Segment::Unit {
                     return Err(ParseError::new(
                         ParseErrorType::EINVAL,
@@ -334,6 +343,7 @@ impl UnitParser {
                     return Err(e);
                 }
             } else if INSTALL_UNIT_ATTR_TABLE.get(attr_str).is_some() {
+                //匹配Install字段
                 if segment != Segment::Install {
                     return Err(ParseError::new(
                         ParseErrorType::EINVAL,

+ 29 - 0
src/parse/parse_timer/mod.rs

@@ -0,0 +1,29 @@
+use super::graph::Graph;
+use super::parse_util::UnitParseUtil;
+
+use crate::error::parse_error::ParseError;
+use crate::manager::UnitManager;
+
+pub struct TimerParser;
+
+impl TimerParser {
+    /// @brief 解析Service类型Unit的
+    ///
+    /// 从path解析Service类型Unit
+    ///
+    /// @param path 需解析的文件路径
+    ///
+    /// @return 成功则返回Ok(id),否则返回Err
+    pub fn parse(path: &str) -> Result<usize, ParseError> {
+        //预先检查是否存在循环依赖
+        let mut graph = Graph::construct_graph(path.to_string())?;
+        let ret = graph.topological_sort()?;
+        for p in ret {
+            UnitParseUtil::parse_unit_no_type(&p)?;
+        }
+
+        let result = UnitManager::get_id_with_path(path).unwrap();
+
+        return Ok(result);
+    }
+}

+ 4 - 2
src/parse/parse_util/mod.rs

@@ -2,9 +2,9 @@ use std::{fs, io::BufRead, os::unix::fs::PermissionsExt, path::Path};
 
 use crate::{
     contants::{AF_INET, AF_INET6, IPV4_MIN_MTU, IPV6_MIN_MTU, PRIO_MAX, PRIO_MIN},
-    error::{parse_error::ParseError, parse_error::ParseErrorType},
+    error::parse_error::{ParseError, ParseErrorType},
     task::cmdtask::CmdTask,
-    unit::{service::ServiceUnit, target::TargetUnit, Unit, UnitType, Url},
+    unit::{service::ServiceUnit, target::TargetUnit, timer::TimerUnit, Unit, UnitType, Url},
     FileDescriptor,
 };
 
@@ -453,6 +453,7 @@ impl UnitParseUtil {
             //TODO: 目前为递归,后续应考虑从DragonReach管理的Unit表中寻找是否有该Unit,并且通过记录消除递归
             "service" => UnitParser::parse::<ServiceUnit>(path, UnitType::Service)?,
             "target" => UnitParser::parse::<TargetUnit>(path, UnitType::Target)?,
+            "timer" => UnitParser::parse::<TimerUnit>(path, UnitType::Timer)?,
             _ => {
                 return Err(ParseError::new(ParseErrorType::EFILE, path.to_string(), 0));
             }
@@ -699,6 +700,7 @@ impl UnitParseUtil {
         match ret {
             "service" => return UnitType::Service,
             "target" => return UnitType::Target,
+            "timer" => return UnitType::Timer,
             //TODO: 添加文件类型
             _ => return UnitType::Unknown,
         }

+ 17 - 1
src/systemctl/ctl_parser/mod.rs

@@ -158,7 +158,7 @@ lazy_static! {
         let mut map = HashMap::new();
         map.insert("list-units", CommandOperation::ListUnits);
         map.insert("list-sockets", CommandOperation::UnSupported);
-        map.insert("list-timers", CommandOperation::UnSupported);
+        map.insert("list-timers", CommandOperation::ListTimers);
         map.insert("start", CommandOperation::Start);
         map.insert("stop", CommandOperation::Stop);
         map.insert("reload", CommandOperation::UnSupported);
@@ -263,6 +263,22 @@ lazy_static! {
 pub struct CtlParser;
 
 impl CtlParser {
+    /// # parse_ctl - 解析控制命令
+    ///
+    /// 该函数用于解析一个字符串形式的控制命令,并将其转换为`Command`
+    ///
+    /// ## 参数
+    ///
+    /// - s: &str,需要解析的控制命令字符串。
+    ///
+    /// ## 返回值
+    ///
+    /// - Ok(Command): 解析成功的控制命令。
+    /// - Err(ParseError): 解析失败时产生的错误。
+    ///
+    /// ## 错误处理
+    ///
+    /// 当输入的字符串不符合预期格式时,函数会返回一个`ParseError`错误。
     pub fn parse_ctl(s: &str) -> Result<Command, ParseError> {
         let mut words = s.split_whitespace().collect::<Vec<&str>>();
         let mut ctl = Command::default();

+ 13 - 2
src/systemctl/listener/mod.rs

@@ -48,10 +48,14 @@ impl Default for Command {
 pub struct Systemctl;
 
 impl Systemctl {
+    /// # 初始化系统服务控制 - 初始化系统服务控制管道
     pub fn init() {
         Self::init_ctl_pipe();
     }
-
+    /// # 初始化监听器 - 初始化系统服务控制命令监听器
+    ///
+    /// 打开系统服务控制命令的管道文件描述符,并设置为非阻塞模式。
+    ///
     pub fn init_listener() -> File {
         let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_RDONLY | libc::O_NONBLOCK) };
         if fd < 0 {
@@ -59,7 +63,10 @@ impl Systemctl {
         }
         unsafe { File::from_raw_fd(fd) }
     }
-
+    /// # 监听控制命令 - 监听系统服务控制命令
+    ///
+    /// 持续从系统服务控制管道中读取命令。
+    ///
     pub fn ctl_listen() {
         let mut guard = CTL_READER.lock().unwrap();
         let mut s = String::new();
@@ -78,6 +85,10 @@ impl Systemctl {
         }
     }
 
+    /// # 检查控制管道是否存在 - 检查系统服务控制管道文件是否存在
+    ///
+    /// 返回管道文件是否存在。
+    ///
     fn is_ctl_exists() -> bool {
         if let Ok(metadata) = fs::metadata(DRAGON_REACH_CTL_PIPE) {
             metadata.is_file()

+ 102 - 0
src/time/calandar/mod.rs

@@ -0,0 +1,102 @@
+//use crate::error::parse_error::ParseError;
+
+#[derive(Debug, Default, Clone)]
+pub struct CalendarComponent {
+    // start: usize,
+    // stop: usize,
+    // repeat: usize,
+    // next: Arc<CalendarComponent>,//暂时不清楚为什么要链式设计
+}
+#[derive(Debug, Default, Clone)]
+pub struct CalendarStandard {
+    //@brief 星期几
+    // weekdays_bits: Vec<WeekdayBits>,
+    // year: usize,
+    // month:  usize,
+    // day: usize,
+    // hour: usize,
+    // minute: usize,
+    // microsecond: usize,
+    // end_of_month: bool,
+    // utc: bool,//是否使用协调世界时(UTC),暂未实现
+    // dst: usize,//夏令时的偏移量,暂未实现
+    // timezone: String,//表示时区的名称,暂未实现
+}
+
+// 使用枚举而不是结构体来模拟C的复杂成员
+
+//
+//pub fn calendar_standard_to_string(spec: &CalendarStandard)->Result<String,ParseError>{
+//    unimplemented!()
+//}
+//pub fn calendar_standard_from_string(spec: &CalendarStandard)->Result<String,ParseError>{
+//    unimplemented!()
+//}
+
+//@brief 解析日历格式,目前功能较弱,只能识别例如 Mon,Tue,Wed 2004-06-10 12:00:00的格式,
+// 且暂不支持"*",
+// pub fn parse_calendar(s: &str) -> Result<CalendarStandard, String> {
+//     // Weekbits YYYY-MM-DD HH:mm:SS ,目前只支持Weekbits用","隔开
+
+// //      OnCalendar=*-*-* 00:00:00:每天的午夜触发。
+// //      OnCalendar=*-*-* 08:00:00:每天早上8点触发。
+// //      OnCalendar=Mon,Tue,Wed *-*-* 12:00:00:每周一、周二和周三的中午12点触发。
+// //      OnCalendar=*-*-1 00:00:00:每个月的第一天午夜触发。
+// //      OnCalendar=2019-01-01 00:00:00:指定的日期(2019年1月1日)触发。
+//     let parts: Vec<&str> = s.split_whitespace().collect();
+
+//      if parts.len() < 2 || parts.len() > 3 {
+//          return Err("Invalid calendar format".to_string());
+//      }
+//      let mut index:usize=0;
+
+//     let mut calendar = CalendarStandard {
+//         weekdays_bits: Vec::default(),
+//         year: 0,
+//         month: 0,
+//         day: 0,
+//         hour: 0,
+//         minute: 0,
+//         microsecond: 0,
+//         // end_of_month: false,
+//         // utc: false,
+//         // dst: 0,
+//         // timezone: String::new(),
+//     };
+
+//     // 解析字符串并填充 calendar 结构体的字段
+//     // 注意:这里的解析逻辑仅供示例,实际情况可能需要更复杂的处理
+
+//     // 解析Weekbits
+//     if parts.len() == 3 {
+//         for day in parts[index].split(",") {
+//             match day.trim() {
+//                 "Mon" =>  calendar.weekdays_bits.push(WeekdayBits::Mon),
+//                 "Tue" =>  calendar.weekdays_bits.push(WeekdayBits::Tue),
+//                 "Wed" =>  calendar.weekdays_bits.push(WeekdayBits::Wed),
+//                 "Thu" =>  calendar.weekdays_bits.push(WeekdayBits::Thu),
+//                 "Fri" =>  calendar.weekdays_bits.push(WeekdayBits::Fri),
+//                 "Sat" =>  calendar.weekdays_bits.push(WeekdayBits::Sat),
+//                 "Sun" =>  calendar.weekdays_bits.push(WeekdayBits::Sun),
+//                 _ => return Err("Invalid weekday".to_string()),
+//             }
+//         }
+//         index+=1;
+//     }
+//       // 解析YYYY-MM-DD
+//       let mut iter = parts[index].split("-");
+
+//       let year = iter.next().unwrap().parse::<i32>().unwrap(); // 提取年并转换为i32类型
+//       let month = iter.next().unwrap().parse::<i32>().unwrap(); // 提取月并转换为i32类型
+//       let day = iter.next().unwrap().parse::<i32>().unwrap(); // 提取日并转换为i32类型
+//       index+=1;
+
+//       //解析HH:mm:SS
+//       let mut iter = parts[index].split(":");
+
+//       let year = iter.next().unwrap().parse::<i32>().unwrap(); // 提取年并转换为i32类型
+//       let month = iter.next().unwrap().parse::<i32>().unwrap(); // 提取月并转换为i32类型
+//       let day = iter.next().unwrap().parse::<i32>().unwrap(); // 提取日并转换为i32类型
+
+//     Ok(calendar)
+// }

+ 1 - 1
src/time/mod.rs

@@ -1,2 +1,2 @@
+pub mod calandar;
 pub mod timer;
-pub mod watchdog;

+ 4 - 2
src/time/timer/mod.rs

@@ -1,6 +1,6 @@
 use std::time::{Duration, Instant};
 
-use crate::error::runtime_error::RuntimeError;
+use crate::{error::runtime_error::RuntimeError, unit::timer::TimerUnit};
 
 /// 伪定时器,结合主循环来实现计时,在计时器触发时,会执行相应的cmd命令
 /// 后续实现线程后,应使用线程实现
@@ -17,11 +17,13 @@ pub struct Timer {
 
 impl Timer {
     /// ## 创建计时任务
+    //要new一个unit!!,查询id命名规则
     pub fn new(
         duration: Duration,
         callback: Box<dyn FnMut() -> Result<(), RuntimeError> + Send + Sync + 'static>,
         parent: usize,
     ) -> Self {
+        let _timerunit = TimerUnit::default();
         Timer {
             instant: Instant::now(),
             callback: callback,
@@ -34,7 +36,7 @@ impl Timer {
     ///
     /// ### return 到时返回true,否则返回false
     pub fn check(&mut self) -> bool {
-        //println!("{},{}",self.instant.elapsed().as_micros(),self.duration.as_micros());
+        // println!("{},{}",self.instant.elapsed().as_micros(),self.duration.as_micros());
         if self.instant.elapsed().saturating_sub(self.duration) > Duration::ZERO {
             // TODO: 未进行错误处理
             if let Err(_e) = (self.callback)() {

+ 0 - 1
src/time/watchdog/mod.rs

@@ -1 +0,0 @@
-

+ 9 - 7
src/unit/service/mod.rs

@@ -44,6 +44,7 @@ impl Default for ServiceType {
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum RestartOption {
+    //ServiceRestart
     AlwaysRestart, //总是重启
     OnSuccess,     //在该服务正常退出时
     OnFailure,     //在该服务启动失败时
@@ -145,12 +146,10 @@ impl Unit for ServiceUnit {
         if segment != Segment::Service {
             return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
         }
-        let attr_type = SERVICE_UNIT_ATTR_TABLE.get(attr).ok_or(ParseError::new(
-            ParseErrorType::EINVAL,
-            String::new(),
-            0,
-        ));
-        return self.service_part.set_attr(attr_type.unwrap(), val);
+        if let Some(attr_type) = SERVICE_UNIT_ATTR_TABLE.get(attr) {
+            return self.service_part.set_attr(attr_type, val);
+        }
+        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
     }
 
     fn set_unit_base(&mut self, base: BaseUnit) {
@@ -213,6 +212,7 @@ impl Unit for ServiceUnit {
 
     fn exit(&mut self) {
         ServiceExecutor::exit(self);
+        //改变计时器内部状态
     }
 
     fn restart(&mut self) -> Result<(), RuntimeError> {
@@ -234,7 +234,8 @@ impl ServiceUnit {
     }
 
     fn exec(&mut self) -> Result<(), RuntimeError> {
-        ServiceExecutor::exec(self)
+        let _ = ServiceExecutor::exec(self);
+        Ok(())
     }
 }
 
@@ -243,6 +244,7 @@ unsafe impl Sync for ServiceUnit {}
 unsafe impl Send for ServiceUnit {}
 
 pub enum ServiceUnitAttr {
+    //ServiceExecCommand+
     None,
     //Service段
     //定义启动时的进程行为

+ 525 - 10
src/unit/timer/mod.rs

@@ -1,34 +1,517 @@
-use super::BaseUnit;
+use super::{BaseUnit, Unit};
+use crate::error::parse_error::{ParseError, ParseErrorType};
+use crate::error::runtime_error::{RuntimeError, RuntimeErrorType};
+use crate::executor::Executor;
+use crate::manager::timer_manager::TimerManager;
+use crate::manager::UnitManager;
+use crate::parse::parse_timer::TimerParser;
+use crate::parse::{Segment, TIMER_UNIT_ATTR_TABLE};
+use crate::time::calandar::CalendarStandard;
+use crate::unit::UnitState;
+use humantime::parse_duration;
+use std::fmt::Debug;
+use std::sync::{Arc, Mutex};
+use std::time::{Duration, Instant};
 
 #[allow(dead_code)]
+#[derive(Clone, Debug)]
 pub struct TimerUnit {
     unit_base: BaseUnit,
     timer_part: TimerPart,
 }
 
+impl Default for TimerUnit {
+    fn default() -> Self {
+        Self {
+            unit_base: Default::default(),
+            timer_part: Default::default(),
+        }
+    }
+}
+
+impl Unit for TimerUnit {
+    /// 初始化计时器单元
+    fn init(&mut self) {
+        // 将单元状态设置为激活中
+        self.unit_base.state = UnitState::Activating;
+        // 更新计时器部分的数据
+
+        // 设置初始触发时间
+        let part = &mut self.timer_part;
+        let now = Instant::now();
+        part.last_trigger = now;
+        part.now_time = now;
+
+        // 如果设置了激活时的秒数,则添加一个计时器值
+        if part.on_active_sec != Default::default() {
+            part.value.push(TimerVal::new(
+                TimerUnitAttr::OnActiveSec,
+                false,
+                part.on_active_sec,
+                Default::default(),
+                Some(now + part.on_active_sec),
+            ));
+        }
+
+        // 实现OnActiveSec的具体逻辑
+
+        // 检查单元是否正在运行
+        let unit_is_running = UnitManager::is_running_unit(&part.unit);
+
+        if part.on_unit_active_sec != Default::default() {
+            let next_trigger = if unit_is_running {
+                Some(now + part.on_unit_active_sec)
+            } else {
+                None
+            };
+            part.value.push(TimerVal::new(
+                TimerUnitAttr::OnUnitActiveSec,
+                !unit_is_running,
+                part.on_unit_active_sec,
+                Default::default(),
+                next_trigger,
+            ));
+        }
+
+        // 实现OnUnitActiveSec的具体逻辑
+
+        if part.on_unit_inactive_sec != Default::default() {
+            part.value.push(TimerVal::new(
+                TimerUnitAttr::OnUnitInactiveSec,
+                true,
+                part.on_unit_inactive_sec,
+                Default::default(),
+                None, /*无论服务是否在运行,这里都不会有值 */
+            ));
+        }
+
+        // 实现OnUnitInactiveSec的具体逻辑
+        part.update_next_trigger();
+        self._init();
+        // 将单元状态设置为激活
+        self.unit_base.state = UnitState::Active;
+    }
+    /// 设置单元的名称
+    fn set_unit_name(&mut self, name: String) {
+        self.unit_base_mut().unit_name = name;
+    }
+    /// 重启单元
+    fn restart(&mut self) -> Result<(), RuntimeError> {
+        self.exit();
+        self.init();
+        Ok(())
+    }
+    /// 从给定的路径解析并创建计时器单元
+    fn from_path(path: &str) -> Result<usize, ParseError>
+    where
+        Self: Sized,
+    {
+        TimerParser::parse(path)
+    }
+    /// 将计时器单元转换为任何类型,用于多态调用
+    fn as_any(&self) -> &dyn std::any::Any {
+        self
+    }
+    /// 将计时器单元转换为任何可变类型,用于多态调用
+    fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
+        self
+    }
+    /// 设置计时器单元的属性
+    fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError> {
+        if segment != Segment::Timer {
+            // 如果段不是计时器段,则返回错误
+            return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+        }
+        if let Some(attr_type) = TIMER_UNIT_ATTR_TABLE.get(attr) {
+            return self.timer_part.set_attr(attr_type, val);
+        }
+        Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0))
+    }
+    /// 设置单元的基础信息
+    fn set_unit_base(&mut self, unit_base: BaseUnit) {
+        self.unit_base = unit_base;
+    }
+    /// 返回单元的类型
+    fn unit_type(&self) -> super::UnitType {
+        self.unit_base.unit_type
+    }
+    /// 返回单元的基础信息
+    fn unit_base(&self) -> &BaseUnit {
+        &self.unit_base
+    }
+    /// 返回单元的基础信息的可变引用
+    fn unit_base_mut(&mut self) -> &mut BaseUnit {
+        &mut self.unit_base
+    }
+    /// 返回单元的ID
+    fn unit_id(&self) -> usize {
+        self.unit_base.unit_id
+    }
+
+    fn run(&mut self) -> Result<(), RuntimeError> {
+        //真正的run在_run中
+        if self.check() && UnitManager::contains_id(&self.timer_part.unit) {
+            // 如果单元检查通过并且单元管理器包含该单元,则运行
+            let _ = self._run(); // 运行单元
+            let id = self.get_parent_unit();
+            // 更新下一个触发器
+            TimerManager::update_next_trigger(id, true);
+        } else if !UnitManager::contains_id(&self.timer_part.unit) {
+            // 如果单元管理器不包含该单元,则打印错误信息
+            println!("task error,unit does not exist")
+        };
+        Ok(())
+    }
+
+    fn exit(&mut self) {
+        UnitManager::try_kill_running(self.unit_id());
+    }
+}
+
+impl TimerUnit {
+    pub fn _run(&mut self) -> Result<(), RuntimeError> {
+        //到这里触发计时器对应的服务
+        let part = &mut self.timer_part;
+        if part.value.is_empty() {
+            //触发次数已尽
+            self.unit_base.state = UnitState::Inactive;
+        } else if matches!(
+            part.value[0].attr,
+            TimerUnitAttr::OnActiveSec | TimerUnitAttr::OnBootSec | TimerUnitAttr::OnStartUpSec
+        ) {
+            part.value.remove(0); //消耗掉此次run时的TimeValue值
+        }
+
+        if UnitManager::is_running_unit(&part.unit) {
+            //如果服务已经启动,则退出
+            return Ok(());
+        }
+
+        //执行相应的unit单元
+        if let Ok(_) = Executor::exec(part.unit) {
+            self.unit_base.state = UnitState::Active;
+            part.last_trigger = Instant::now();
+            return Ok(());
+        } else {
+            self.unit_base.state = UnitState::Failed;
+            return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
+        }
+    }
+    fn _init(&self) {
+        let unit: Arc<Mutex<TimerUnit>> = Arc::new(Mutex::new(self.clone()));
+        TimerManager::push_timer_unit(unit);
+    }
+
+    pub fn check(&mut self) -> bool {
+        let part = &mut self.timer_part;
+        //计时器不可用
+        if part.value.len() == 0 {
+            //不可能再触发
+            self.unit_base.state = UnitState::Inactive;
+        }
+        if self.unit_base.state == UnitState::Inactive
+        //可能是手动停止
+        {
+            return false;
+        }
+        if UnitManager::is_running_unit(&part.unit)  //在运行就不管了
+        || part.next_elapse_monotonic_or_boottime==None
+        //下次触发时间无限大
+        {
+            return false;
+        }
+        part.now_time = Instant::now();
+
+        if part.now_time >= part.next_elapse_monotonic_or_boottime.unwrap() {
+            //检查Timer管理的unit是否存在
+            if let Some(_) = UnitManager::get_unit_with_id(&part.unit) {
+                return true;
+            }
+            println!("task error,unit does not exist");
+        }
+        return false;
+    }
+
+    pub fn unit_base(&self) -> &BaseUnit {
+        &self.unit_base
+    }
+
+    pub fn timer_part(&self) -> &TimerPart {
+        &self.timer_part
+    }
+
+    pub fn mut_timer_part(&mut self) -> &mut TimerPart {
+        &mut self.timer_part
+    }
+
+    pub fn get_parent_unit(&mut self) -> usize {
+        self.timer_part().unit
+    }
+    ///判断计时器是否失效
+    pub fn enter_inactive(&mut self) -> bool {
+        if self.unit_base.state == UnitState::Inactive {
+            return true;
+        }
+        false
+    }
+
+    ///在unit run或exit的时候改变TimerValue中OnUnitInactiveSec和OnUnitActiveSec的状态
+    pub fn change_stage(&mut self, flag: bool /*1为启动0为退出 */) {
+        for val in &mut self.timer_part.value {
+            match val.attr {
+                TimerUnitAttr::OnUnitActiveSec => {
+                    val.disabled = false;
+                    if flag {
+                        val.next_elapse = Some(Instant::now() + val.val);
+                    }
+                }
+                TimerUnitAttr::OnUnitInactiveSec => {
+                    val.disabled = false;
+                    if !flag {
+                        val.next_elapse = Some(Instant::now() + val.val);
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+}
+unsafe impl Sync for TimerUnit {}
+
+unsafe impl Send for TimerUnit {}
 #[allow(dead_code)]
+#[derive(Debug, Clone)]
 pub struct TimerPart {
-    on_active_sec: u64,
-    on_boot_sec: u64,
-    on_start_up_sec: u64,
-    on_unit_inactive_sec: u64,
-    on_calendar: u64,
-    accuarcy_sec: u64,
-    randomized_delay_sec: u64,
+    //TODO! 因此时DragonReach未实现时间事件源的相关功能,目前还是循环确认Timer的情况
+    ///@brief 存储触发计时器的时间集合
+    value: Vec<TimerVal>,
+
+    ///@brief 相对于该单元自身被启动的时间点
+    on_active_sec: Duration,
+
+    ///@brief 相对于机器被启动的时间点
+    on_boot_sec: Duration,
+
+    ///@brief 相对于systemd被首次启动的时间点,也就是内核启动init进程的时间点
+    on_start_up_sec: Duration,
+
+    ///@brief 相对于匹配单元最后一次被启动的时间点
+    on_unit_active_sec: Duration,
+
+    ///@brief 相对于匹配单元 最后一次被停止的时间点
+    on_unit_inactive_sec: Duration,
+
+    ///@brief 定义基于挂钟时间(wallclock)的日历定时器,值是一个日历事件表达式
+    on_calendar: CalendarStandard,
+
+    ///@brief 设置定时器的触发精度,默认1min
+    accuarcy_sec: usize,
+
+    ///@brief 随机延迟一小段时间,默认0表示不延迟
+    randomized_delay_sec: usize,
+
+    ///@brief
     fixed_random_delay: bool,
+
+    ///@brief
     on_clock_change: bool,
-    on_time_zone_change: bool,
+
+    ///@brief
+    on_timezone_change: bool,
+
+    ///@brief 默认值是 与此定时器单元同名的服务单元
     unit: usize,
+
+    ///@brief 若设为"yes",则表示将匹配单元的上次触发时间永久保存在磁盘上,默认no
     persistent: bool,
+
+    ///@brief 若设为"yes", 则表示当某个定时器到达触发时间点时, 唤醒正在休眠的系统并阻止系统进入休眠状态,默认no
     wake_system: bool,
-    remain_after_elapse: bool,
+
+    ///@brief 若设为"yes" ,那么该定时器将不会被再次触发,也就是可以确保仅被触发一次;默认yes
+    remain_after_elapse: bool, //默认yes
+
+    ///@brief 表示计时器下次实时时间触发的时间戳
+    next_elapse_realtime: Instant,
+
+    ///@brief 表示计时器下次单调时间或引导时间触发的时间戳
+    next_elapse_monotonic_or_boottime: Option<Instant>, //None表示无限大
+
+    ///@brief 用于存储计时器最后一次触发的时间戳。
+    last_trigger: Instant,
+
+    ///@brief 用于表示当前的时间。
+    now_time: Instant,
 }
 
+impl Default for TimerPart {
+    fn default() -> Self {
+        Self {
+            value: Default::default(),
+            on_active_sec: Default::default(),
+            on_boot_sec: Default::default(),
+            on_start_up_sec: Default::default(),
+            on_unit_active_sec: Default::default(),
+            on_unit_inactive_sec: Default::default(),
+            on_calendar: CalendarStandard::default(),
+            accuarcy_sec: 60, // 默认设置为 60 秒
+            randomized_delay_sec: 0,
+            fixed_random_delay: false,
+            on_clock_change: false,
+            on_timezone_change: false,
+            unit: Default::default(),
+            persistent: false,
+            wake_system: false,
+            remain_after_elapse: true,
+
+            next_elapse_realtime: Instant::now(),
+            next_elapse_monotonic_or_boottime: None,
+            last_trigger: Instant::now(),
+            now_time: Instant::now(),
+        }
+    }
+}
+
+impl TimerPart {
+    /// 更新下一次的触发时间
+    pub fn update_next_trigger(&mut self) {
+        self.now_time = Instant::now();
+
+        //let unit_is_running=UnitManager::is_running_unit(&self.unit);
+        //检查并更新value
+        let mut index = 0;
+        while index < self.value.len() {
+            let val = &mut self.value[index];
+            match val.attr {
+                TimerUnitAttr::OnUnitInactiveSec | TimerUnitAttr::OnUnitActiveSec => {
+                    //更新OnUnitInactiveSec和OnUnitActiveSec类型的值
+                    if val.disabled || val.next_elapse == None {
+                        //None表示此时无法确认下次触发时间
+                        index = index + 1;
+                        continue;
+                    } else if val.next_elapse.unwrap() < self.now_time {
+                        self.next_elapse_monotonic_or_boottime = val.next_elapse;
+                        val.next_elapse = None;
+                        // println!("Update the time!");
+                        return;
+                    }
+                }
+
+                TimerUnitAttr::OnActiveSec | TimerUnitAttr::OnBootSec => {
+                    if val.next_elapse.unwrap() < self.now_time {
+                        self.next_elapse_monotonic_or_boottime = val.next_elapse;
+                        self.value.remove(index); //在这一步准备把index从value里弹出去
+                        return;
+                    }
+                }
+                //TimerUnitAttr::OnStartUpSec => todo!(),
+                //TimerUnitAttr::OnCalendar => todo!(),
+                _ => todo!(), //暂未支持
+            }
+            index += 1;
+        }
+        // 对value排序,使得最早的定时器时间在最前面,且None类型在最后面
+        self.value.sort_by//(|a, b| a.next_elapse.cmp(&b.next_elapse));
+        (|a, b| match (a.next_elapse, b.next_elapse) {
+        (None, None) => std::cmp::Ordering::Equal,
+        (None, Some(_)) => std::cmp::Ordering::Greater,
+        (Some(_), None) => std::cmp::Ordering::Less,
+        (Some(a), Some(b)) => a.cmp(&b),
+    });
+        if self.value.is_empty() || self.value[0].next_elapse == None {
+            //无法得到下次触发的具体时间
+            return;
+        }
+
+        // 从已排序的Vec中获取最早的定时器时间
+        self.next_elapse_monotonic_or_boottime = self.value[0].next_elapse;
+
+        return;
+    }
+    /// &str->attr的parse
+    pub fn set_attr(&mut self, attr: &TimerUnitAttr, val: &str) -> Result<(), ParseError> {
+        match attr {
+            TimerUnitAttr::OnActiveSec => {
+                self.on_active_sec = {
+                    if let Ok(duration) = parse_duration(val) {
+                        duration
+                    } else {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                    }
+                }
+            }
+
+            TimerUnitAttr::OnBootSec => {
+                self.on_boot_sec = {
+                    if let Ok(duration) = parse_duration(val) {
+                        duration
+                    } else {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                    }
+                }
+            }
+
+            TimerUnitAttr::OnStartUpSec => {
+                self.on_start_up_sec = {
+                    if let Ok(duration) = parse_duration(val) {
+                        duration
+                    } else {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                    }
+                }
+            }
+            TimerUnitAttr::OnUnitInactiveSec => {
+                self.on_unit_inactive_sec = {
+                    if let Ok(duration) = parse_duration(val) {
+                        duration
+                    } else {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                    }
+                }
+            }
+            TimerUnitAttr::OnUnitActiveSec => {
+                self.on_unit_active_sec = {
+                    if let Ok(duration) = parse_duration(val) {
+                        duration
+                    } else {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                    }
+                }
+            }
+            //  TimerUnitAttr::OnCalendar=>self.on_calendar={
+            //     if let Ok(calendar) = parse_calendar(val) {
+            //         calendar
+            //     } else {
+            //         return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+            //     }
+            //  },
+            TimerUnitAttr::Persistent => {
+                self.persistent = {
+                    match val {
+                        "true" => true,
+                        "false" => false,
+                        _ => return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)),
+                    }
+                }
+            }
+            TimerUnitAttr::Unit => self.unit = UnitManager::get_id_with_path(val).unwrap(),
+            _ => {
+                return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+            }
+        }
+        Ok(())
+    }
+}
+#[derive(Debug, Clone, Copy)]
 pub enum TimerUnitAttr {
+    //TimerBase
+    // State,
+    // Result,
     OnActiveSec,
     OnBootSec,
     OnStartUpSec,
     OnUnitInactiveSec,
+    OnUnitActiveSec,
     OnCalendar,
     AccuarcySec,
     RandomizedDelaySec,
@@ -40,3 +523,35 @@ pub enum TimerUnitAttr {
     WakeSystem,
     RemainAfterElapse,
 }
+impl Default for TimerUnitAttr {
+    fn default() -> Self {
+        TimerUnitAttr::OnActiveSec
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct TimerVal {
+    attr: TimerUnitAttr,
+    disabled: bool,
+    val: Duration,
+    //calendar_standard:Vec<CalendarStandard>,//只针对calendar事件
+    next_elapse: Option<Instant>,
+}
+
+impl TimerVal {
+    pub fn new(
+        attr: TimerUnitAttr,
+        disabled: bool,
+        val: Duration,
+        _calendar_standard: Vec<CalendarStandard>, //等待后续迭代
+        next_elapse: Option<Instant>,
+    ) -> TimerVal {
+        TimerVal {
+            attr,
+            disabled,
+            val,
+            //calendar_standard,
+            next_elapse,
+        }
+    }
+}

+ 3 - 1
systemctl/src/main.rs

@@ -1,6 +1,7 @@
 use std::{env, fs::File, io::Write};
 
-const REACH_PIPE_PATH: &str = "/etc/reach/ipc/ctl";
+//const REACH_PIPE_PATH: &str = "/home/fz/myetc/reach/ipc/ctl";
+const REACH_PIPE_PATH: &str = "etc/reach/ipc/ctl";
 
 fn main() {
     let mut args: Vec<String> = env::args().collect();
@@ -21,5 +22,6 @@ fn main() {
     let mut file = File::open(REACH_PIPE_PATH).unwrap();
     if let Err(err) = file.write_all(msg.as_bytes()) {
         eprintln!("write error {}", err);
+        eprintln!("write error {:?}", err);
     }
 }