Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
7 changes: 7 additions & 0 deletions parse_test/test_timer_unit.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
Description=a test for timer_unit

[Service]
Type=simple
ExecStart=-/bin/about.elf
ExecStartPre=-/bin/clear
7 changes: 7 additions & 0 deletions parse_test/test_timer_unit.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
Description=a timer for the same_name.service

[Timer]
OnActiveSec=3s
OnUnitActiveSec=5s
Unit=test_timer_unit.service
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}

// 启动完服务后进入主循环
Expand Down
9 changes: 8 additions & 1 deletion src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down Expand Up @@ -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);
Expand Down
137 changes: 131 additions & 6 deletions src/manager/timer_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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,
Expand All @@ -39,13 +49,57 @@ 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
}

/// ## 检测定时器是否到时,到时则触发
///
/// 该方法在主循环中每循环一次检测一次,是伪计时器的主运行函数
pub fn check_timer() {
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的所有定时任务,
Expand All @@ -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();
});
}
}
13 changes: 7 additions & 6 deletions src/manager/unit_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down Expand Up @@ -92,6 +92,7 @@ impl UnitManager {
}

// 通过id获取到path
// ↑感觉是笔误,应该是通过path获取到id
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

哈哈哈笔误,可以直接改一下<

pub fn get_id_with_path(path: &str) -> Option<usize> {
let mut hasher = DefaultHasher::new();
path.hash(&mut hasher);
Expand Down
16 changes: 13 additions & 3 deletions src/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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段类型
Expand All @@ -31,6 +33,7 @@ pub enum Segment {
Unit,
Install,
Service,
Timer,
}

lazy_static! {
Expand All @@ -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);
Expand All @@ -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> = {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)),
}
}
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
Loading
Loading