From 2c9a53516432d039501bc58652b9f05b57356373 Mon Sep 17 00:00:00 2001 From: xuxiaozhou1 Date: Mon, 5 Jun 2023 20:33:00 +0800 Subject: [PATCH] fix: support for adjusting the memory usage of database --- coms/mount/src/rentry.rs | 12 +-- coms/service/src/rentry.rs | 12 +-- coms/socket/src/rentry.rs | 18 ++-- coms/target/src/rentry.rs | 6 +- core/bin/job/junit.rs | 34 ++++++-- core/bin/job/manager.rs | 9 +- core/bin/job/notify.rs | 6 +- core/bin/job/stat.rs | 6 +- core/bin/job/table.rs | 6 +- core/bin/job/transaction.rs | 10 ++- core/bin/main.rs | 2 +- core/bin/manager/config.rs | 5 ++ core/bin/manager/mod.rs | 11 ++- core/bin/unit/datastore/child.rs | 14 ++- core/bin/unit/datastore/deps.rs | 14 ++- core/bin/unit/datastore/sets.rs | 18 ++-- core/bin/unit/entry/uentry.rs | 6 +- core/bin/unit/manager.rs | 5 +- core/bin/unit/runtime.rs | 14 ++- core/lib/rel/api.rs | 52 +++++++++-- core/lib/rel/base.rs | 115 ++++++++++++------------ core/lib/rel/history.rs | 144 ++++++++++++++++++++++++++----- core/lib/rel/mod.rs | 2 +- docs/man/sysmaster.conf.md | 8 ++ 24 files changed, 376 insertions(+), 153 deletions(-) mode change 100644 => 100755 core/bin/unit/datastore/child.rs diff --git a/coms/mount/src/rentry.rs b/coms/mount/src/rentry.rs index 45c0ce0..bf0004e 100644 --- a/coms/mount/src/rentry.rs +++ b/coms/mount/src/rentry.rs @@ -103,8 +103,8 @@ impl ReDbTable for MountReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -112,7 +112,7 @@ impl ReDbTable for MountReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } @@ -125,8 +125,8 @@ impl ReDbTable for MountReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -134,6 +134,6 @@ impl ReDbTable for MountReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } diff --git a/coms/service/src/rentry.rs b/coms/service/src/rentry.rs index a68a3df..7099e01 100644 --- a/coms/service/src/rentry.rs +++ b/coms/service/src/rentry.rs @@ -623,8 +623,8 @@ impl ReDbTable for ServiceReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -632,7 +632,7 @@ impl ReDbTable for ServiceReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } @@ -645,8 +645,8 @@ impl ReDbTable for ServiceReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -654,6 +654,6 @@ impl ReDbTable for ServiceReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } diff --git a/coms/socket/src/rentry.rs b/coms/socket/src/rentry.rs index 44f5be3..c0f5818 100644 --- a/coms/socket/src/rentry.rs +++ b/coms/socket/src/rentry.rs @@ -335,8 +335,8 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -344,7 +344,7 @@ impl ReDbTable for SocketReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } @@ -357,8 +357,8 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -366,7 +366,7 @@ impl ReDbTable for SocketReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } @@ -379,8 +379,8 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -388,6 +388,6 @@ impl ReDbTable for SocketReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } diff --git a/coms/target/src/rentry.rs b/coms/target/src/rentry.rs index 9d3f90c..9e218b3 100644 --- a/coms/target/src/rentry.rs +++ b/coms/target/src/rentry.rs @@ -77,8 +77,8 @@ impl ReDbTable for TargetReDb { self.0.cache_2_db(db_wtxn); } - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.0.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.0.buffer_2_db(db_wtxn); } fn import<'a>(&self, db_rtxn: &ReDbRoTxn) { @@ -86,6 +86,6 @@ impl ReDbTable for TargetReDb { } fn switch_set(&self, switch: bool) { - self.0.set_switch(switch); + self.0.switch_buffer(switch); } } diff --git a/core/bin/job/junit.rs b/core/bin/job/junit.rs index f1a55b6..b56ec11 100644 --- a/core/bin/job/junit.rs +++ b/core/bin/job/junit.rs @@ -817,11 +817,13 @@ mod tests { use crate::unit::{JobMode, UnitRe}; use basic::logger; use event::Events; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn juv_api_len() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(JobRe::new(&reli)); let unit_test1 = prepare_unit(&reli); let mut id: u128 = 0; @@ -848,7 +850,9 @@ mod tests { #[test] fn juv_api_merge() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let (_, job_start, _, _, _) = prepare_jobs(&reli, &unit_test1, JobMode::Replace); let (_, stage_start, _, _, _) = prepare_jobs(&reli, &unit_test1, JobMode::Replace); @@ -881,7 +885,9 @@ mod tests { #[test] fn juv_api_reshuffle() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let (job_nop, job_start, job_reload, job_restart, _) = prepare_jobs(&reli, &unit_test1, JobMode::Replace); @@ -923,7 +929,9 @@ mod tests { #[test] fn juv_api_replace_with_unirreversible() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let mode = JobMode::Replace; let (_, uv_start, _, _, uv_stop) = prepare_jobs(&reli, &unit_test1, mode); @@ -958,7 +966,9 @@ mod tests { #[test] fn juv_api_replace_with_irreversible() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let mode = JobMode::ReplaceIrreversible; let (_, uv_start, _, _, uv_stop) = prepare_jobs(&reli, &unit_test1, mode); @@ -993,7 +1003,9 @@ mod tests { #[test] fn juv_api_order_with_unignore() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let mode = JobMode::Replace; let (uv_nop, uv_start, _, _, uv_stop) = prepare_jobs(&reli, &unit_test1, mode); @@ -1093,7 +1105,9 @@ mod tests { #[test] fn juv_api_order_with_ignore() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let mode = JobMode::IgnoreDependencies; let (uv_nop, uv_start, _, _, uv_stop) = prepare_jobs(&reli, &unit_test1, mode); @@ -1192,7 +1206,9 @@ mod tests { #[test] fn juv_calc_ready() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let unit_test1 = prepare_unit(&reli); let (job_nop, job_start, _, _, _) = prepare_jobs(&reli, &unit_test1, JobMode::Replace); let uv = JobUnit::new(Rc::clone(&unit_test1)); diff --git a/core/bin/job/manager.rs b/core/bin/job/manager.rs index 028c4d5..85af037 100755 --- a/core/bin/job/manager.rs +++ b/core/bin/job/manager.rs @@ -814,12 +814,15 @@ mod tests { use crate::unit::DataManager; use crate::unit::{UnitRe, UnitRelations}; use basic::logger; + use sysmaster::rel::ReliConf; //#[test] #[allow(dead_code)] fn job_reli() { logger::init_log_to_console("test_unit_load", log::LevelFilter::Trace); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let event = Rc::new(Events::new().unwrap()); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); @@ -1148,7 +1151,9 @@ mod tests { ) { let event = Rc::new(Events::new().unwrap()); let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let name_test1 = String::from("test1.service"); diff --git a/core/bin/job/notify.rs b/core/bin/job/notify.rs index 271b648..8678633 100644 --- a/core/bin/job/notify.rs +++ b/core/bin/job/notify.rs @@ -147,7 +147,7 @@ mod tests { use crate::unit::UnitX; use basic::logger; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn jn_api() { @@ -178,7 +178,9 @@ mod tests { fn prepare_unit_single() -> (Rc, Rc, Rc) { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let name_test1 = String::from("test1.service"); diff --git a/core/bin/job/stat.rs b/core/bin/job/stat.rs index 1163d00..2711412 100644 --- a/core/bin/job/stat.rs +++ b/core/bin/job/stat.rs @@ -450,7 +450,7 @@ mod tests { use crate::unit::UnitX; use basic::logger; use event::Events; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn js_api() { @@ -486,7 +486,9 @@ mod tests { fn prepare_unit_single() -> (Rc, Rc, Rc) { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let name_test1 = String::from("test1.service"); diff --git a/core/bin/job/table.rs b/core/bin/job/table.rs index 7b77b1a..5a9f7b2 100644 --- a/core/bin/job/table.rs +++ b/core/bin/job/table.rs @@ -1022,12 +1022,14 @@ mod tests { use crate::unit::UnitRe; use basic::logger; use event::Events; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn job_table_record_suspend() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let job_rentry = Rc::new(JobRe::new(&reli)); diff --git a/core/bin/job/transaction.rs b/core/bin/job/transaction.rs index b79e6ff..c4842c4 100644 --- a/core/bin/job/transaction.rs +++ b/core/bin/job/transaction.rs @@ -420,7 +420,7 @@ mod tests { use crate::unit::{UnitRe, UnitRelations}; use basic::logger; use event::Events; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn jt_api_expand_check() {} @@ -682,7 +682,9 @@ mod tests { relation: UnitRelations, ) -> (Rc, Rc, Rc, Rc) { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let name_test1 = String::from("test1.service"); @@ -699,7 +701,9 @@ mod tests { fn prepare_unit_single() -> (Rc, Rc, Rc) { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let name_test1 = String::from("test1.service"); diff --git a/core/bin/main.rs b/core/bin/main.rs index eb06ed6..0239ce9 100644 --- a/core/bin/main.rs +++ b/core/bin/main.rs @@ -117,10 +117,10 @@ fn main() -> Result<()> { if !switch { if !args.deserialize { manager.debug_clear_restore(); + log::info!("debug: clear data restored."); } // if switch is false unregister init's reexec signal. register_reexec_signal(false); - log::info!("debug: clear data restored."); } manager.setup_cgroup()?; diff --git a/core/bin/manager/config.rs b/core/bin/manager/config.rs index b5b2857..8b7aaab 100644 --- a/core/bin/manager/config.rs +++ b/core/bin/manager/config.rs @@ -15,6 +15,7 @@ use confique::Config; pub const SYSTEM_CONFIG: &str = "/etc/sysmaster/system.toml"; +const RELI_HISTORY_MAPSIZE_DEFAULT: usize = 1048576; // 1M #[derive(Config, Debug)] pub struct ManagerConfig { @@ -29,6 +30,9 @@ pub struct ManagerConfig { pub LogTarget: String, #[config(default = "")] pub LogFile: String, + + #[config(default = 1048576)] // RELI_HISTORY_MAPSIZE_DEFAULT + pub DbSize: usize, } impl ManagerConfig { @@ -51,6 +55,7 @@ impl Default for ManagerConfig { LogLevel: log::LevelFilter::Debug, LogTarget: "console".to_string(), LogFile: String::new(), + DbSize: RELI_HISTORY_MAPSIZE_DEFAULT, } } } diff --git a/core/bin/manager/mod.rs b/core/bin/manager/mod.rs index 17a2e29..ee49efa 100644 --- a/core/bin/manager/mod.rs +++ b/core/bin/manager/mod.rs @@ -40,7 +40,7 @@ use std::collections::HashSet; use std::path::PathBuf; use std::rc::Rc; use sysmaster::error::*; -use sysmaster::rel::{ReliLastFrame, Reliability}; +use sysmaster::rel::{ReliConf, ReliLastFrame, Reliability}; use alive_timer::AliveTimer; @@ -203,7 +203,11 @@ impl Manager { /// create factory instance pub fn new(mode: Mode, action: Action, manager_config: Rc) -> Self { let event = Rc::new(Events::new().unwrap()); - let reli = Rc::new(Reliability::new(rentry::RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new() + .set_map_size(manager_config.DbSize) + .set_max_dbs(rentry::RELI_HISTORY_MAX_DBS), + )); let mut l_path = LookupPaths::new(); l_path.init_lookup_paths(); let lookup_path = Rc::new(l_path); @@ -386,6 +390,9 @@ impl Manager { fn prepare_reexec(&self) -> Result<()> { // restore external resource, like: fd, ... // do nothing now + + // compact db + self.reli.compact()?; Ok(()) } diff --git a/core/bin/unit/datastore/child.rs b/core/bin/unit/datastore/child.rs old mode 100644 new mode 100755 index f4460f0..be29470 --- a/core/bin/unit/datastore/child.rs +++ b/core/bin/unit/datastore/child.rs @@ -167,12 +167,14 @@ mod tests { use crate::unit::rentry::UnitRe; use crate::unit::test::test_utils; use basic::logger; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] #[should_panic] fn child_add_watch_pid_empty() { - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test3 = String::from("test3.service"); @@ -185,7 +187,9 @@ mod tests { #[test] fn child_add_watch_pid() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); @@ -210,7 +214,9 @@ mod tests { #[test] fn child_unwatch_pid() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); diff --git a/core/bin/unit/datastore/deps.rs b/core/bin/unit/datastore/deps.rs index 80836ef..cd934b7 100644 --- a/core/bin/unit/datastore/deps.rs +++ b/core/bin/unit/datastore/deps.rs @@ -392,12 +392,14 @@ mod tests { use crate::unit::data::DataManager; use crate::unit::test::test_utils; use basic::logger; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn dep_insert() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let dep = UnitDep::new(&rentry, &Rc::new(sets)); @@ -440,7 +442,9 @@ mod tests { #[test] fn dep_gets_atom() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let dep = UnitDep::new(&rentry, &Rc::new(sets)); @@ -495,7 +499,9 @@ mod tests { #[test] fn dep_is_dep_atom_with() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let dep = UnitDep::new(&rentry, &Rc::new(sets)); diff --git a/core/bin/unit/datastore/sets.rs b/core/bin/unit/datastore/sets.rs index 9a94a4b..4e105e7 100644 --- a/core/bin/unit/datastore/sets.rs +++ b/core/bin/unit/datastore/sets.rs @@ -89,12 +89,14 @@ mod tests { use crate::unit::rentry::UnitRe; use crate::unit::test::test_utils; use basic::logger; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn sets_insert() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); @@ -115,7 +117,9 @@ mod tests { #[test] fn sets_remove() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); @@ -142,7 +146,9 @@ mod tests { #[test] fn sets_get() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); @@ -167,7 +173,9 @@ mod tests { #[test] fn sets_getall() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let sets = UnitSets::new(); let name_test1 = String::from("test1.service"); diff --git a/core/bin/unit/entry/uentry.rs b/core/bin/unit/entry/uentry.rs index 0c6e044..5b93e97 100644 --- a/core/bin/unit/entry/uentry.rs +++ b/core/bin/unit/entry/uentry.rs @@ -763,13 +763,15 @@ mod tests { use crate::unit::test::test_utils::UmIfD; use basic::{logger, path_lookup::LookupPaths}; use std::rc::Rc; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; use sysmaster::unit::UnitType; use crate::{plugin::Plugin, unit::data::DataManager, unit::util::UnitFile}; fn unit_init() -> Rc { logger::init_log_to_console("test_unit_entry", log::LevelFilter::Trace); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let mut l_path = LookupPaths::new(); diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs index d5c3e10..505a051 100644 --- a/core/bin/unit/manager.rs +++ b/core/bin/unit/manager.rs @@ -1404,6 +1404,7 @@ mod tests { use nix::sys::wait::WaitStatus; use std::thread; use std::time::Duration; + use sysmaster::rel::ReliConf; use sysmaster::unit::UnitActiveState; fn init_dm_for_test() -> (Rc, Rc, Rc) { @@ -1414,7 +1415,9 @@ mod tests { let event = Rc::new(Events::new().unwrap()); let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let state = Rc::new(RefCell::new(State::Init)); let um = UnitManager::new( &event, diff --git a/core/bin/unit/runtime.rs b/core/bin/unit/runtime.rs index 215a5a7..5c4f45e 100644 --- a/core/bin/unit/runtime.rs +++ b/core/bin/unit/runtime.rs @@ -380,12 +380,14 @@ mod tests { use crate::unit::rentry::UnitRe; use crate::unit::test; use basic::logger; - use sysmaster::rel::Reliability; + use sysmaster::rel::{ReliConf, Reliability}; #[test] fn rt_push_load_queue() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let rt = UnitRT::new(&reli, &rentry, &db); @@ -412,7 +414,9 @@ mod tests { #[test] fn rt_dispatch_load_queue() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let rt = UnitRT::new(&reli, &rentry, &db); @@ -430,7 +434,9 @@ mod tests { #[test] fn rt_dispatch_target_dep_queue() { let dm = Rc::new(DataManager::new()); - let reli = Rc::new(Reliability::new(RELI_HISTORY_MAX_DBS)); + let reli = Rc::new(Reliability::new( + ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), + )); let rentry = Rc::new(UnitRe::new(&reli)); let db = Rc::new(UnitDb::new(&rentry)); let rt = UnitRT::new(&reli, &rentry, &db); diff --git a/core/lib/rel/api.rs b/core/lib/rel/api.rs index 60a3543..59e4ac9 100644 --- a/core/lib/rel/api.rs +++ b/core/lib/rel/api.rs @@ -36,6 +36,41 @@ const RELI_DEBUG_PANIC_FILE: &str = "panic.debug"; const RELI_DEBUG_PFIRST_FILE: &str = "panic_first.debug"; const RELI_DEBUG_SLEEP_FILE: &str = "sleep.debug"; +/// the configuration of reliability instance +pub struct ReliConf { + // history + map_size: Option, + max_dbs: Option, +} + +impl ReliConf { + /// create the configuration + pub fn new() -> ReliConf { + ReliConf { + map_size: None, + max_dbs: None, + } + } + + /// set the map size + pub fn set_map_size(&mut self, map_size: usize) -> &mut Self { + self.map_size = Some(map_size); + self + } + + /// set the max numbers of db + pub fn set_max_dbs(&mut self, max_dbs: u32) -> &mut Self { + self.max_dbs = Some(max_dbs); + self + } +} + +impl Default for ReliConf { + fn default() -> Self { + ReliConf::new() + } +} + /// reliability instance #[derive(Debug)] pub struct Reliability { @@ -62,13 +97,13 @@ impl Drop for Reliability { impl Reliability { /// create reliability instance - pub fn new(max_db: u32) -> Reliability { + pub fn new(conf: &ReliConf) -> Reliability { let dir_s = reli_prepare().expect("reliability prepare"); let reli = Reliability { dir_string: dir_s.clone(), enable: ReliEnable::new(&dir_s), last: ReliLast::new(&dir_s), - history: ReliHistory::new(&dir_s, max_db), + history: ReliHistory::new(&dir_s, conf.map_size, conf.max_dbs), pending: ReliPending::new(&dir_s), station: ReliStation::new(), }; @@ -154,7 +189,7 @@ impl Reliability { if reload { // If daemon-reload or daemon-reexec, we need to update all changes, clear db, and submit all changes to db. self.db_insert(); - self.history.reflush(); + self.history.flush(); // Due to changes in db, we need to reload the data from db to cache. self.history.import(); } @@ -168,6 +203,11 @@ impl Reliability { self.last.clear_frame(); } + /// compact the database + pub fn compact(&self) -> Result<()> { + self.history.compact() + } + /// get the enable flag pub fn enable(&self) -> bool { self.enable.enable() @@ -205,9 +245,9 @@ impl Reliability { self.last.ignore() } - /// get the ignore flag of history data - pub fn history_ignore(&self) -> bool { - self.history.ignore() + /// get the switch flag of history data + pub fn history_switch(&self) -> bool { + self.history.switch() } /// do the debug action: enable the recover process diff --git a/core/lib/rel/base.rs b/core/lib/rel/base.rs index 274b504..29200df 100644 --- a/core/lib/rel/base.rs +++ b/core/lib/rel/base.rs @@ -31,13 +31,19 @@ pub struct ReDb { switch: RefCell, // data + /* database */ db: Database, SerdeBincode>, + + /* cache */ cache: RefCell>, add: RefCell>, del: RefCell>, + + /* buffer */ + buffer: RefCell>, // daemon-reload or daemon-reexec will temporarily store the data here first, and finally refreshes it to db. + + /* property */ name: String, - buf: RefCell>, // daemon-reload or daemon-reexec will temporarily store the data here first, and finally refreshes it to db. - //_phantom: PhantomData<&'a K>, } impl ReDbTable for ReDb @@ -53,9 +59,8 @@ where self.cache_2_db(db_wtxn); } - /// daemon-reload or daemon-reexec export all data to database - fn reexport(&self, db_wtxn: &mut ReDbRwTxn) { - self.rebuf_2_db(db_wtxn); + fn flush(&self, db_wtxn: &mut ReDbRwTxn) { + self.buffer_2_db(db_wtxn); } fn import(&self, db_rtxn: &ReDbRoTxn) { @@ -63,7 +68,7 @@ where } fn switch_set(&self, switch: bool) { - self.set_switch(switch); + self.switch_buffer(switch); } } @@ -81,9 +86,8 @@ where cache: RefCell::new(HashMap::new()), add: RefCell::new(HashMap::new()), del: RefCell::new(HashSet::new()), + buffer: RefCell::new(HashMap::new()), name: String::from(db_name), - buf: RefCell::new(HashMap::new()), - //_phantom: PhantomData, } } @@ -95,52 +99,56 @@ where self.del.borrow_mut().clear(); } - /// set the ignore flag of data - pub fn set_switch(&self, switch: bool) { + /// set the buffer-switch flag of data + pub fn switch_buffer(&self, switch: bool) { *self.switch.borrow_mut() = switch; } /// insert a entry pub fn insert(&self, k: K, v: V) { let switch = self.switch(); - log::debug!( - "ReDb[{}] switch:{:?} insert, key:{:?}, value:{:?}.", - &self.name, - switch, - &k, - &v - ); + log::debug!("ReDb[{}] insert, key:{:?}, value:{:?}.", &self.name, &k, &v); + log::debug!("insert with switch:{:?}.", switch); if switch { - self.buf.borrow_mut().insert(k, v); - return; - } - - // remove "del" + insert "add" - self.del.borrow_mut().remove(&k); - self.add.borrow_mut().insert(k.clone(), v.clone()); + // update buffer only + self.buffer.borrow_mut().insert(k, v); + } else { + // remove "del" + insert "add" + self.del.borrow_mut().remove(&k); + self.add.borrow_mut().insert(k.clone(), v.clone()); - // update cache - self.cache.borrow_mut().insert(k, v); + // update cache + self.cache.borrow_mut().insert(k, v); + } } /// remove a entry pub fn remove(&self, k: &K) { - let n = &self.name; let switch = self.switch(); - log::debug!("ReDb[{}] switch:{:?}, remove, key:{:?}.", n, switch, &k); + log::debug!("ReDb[{}] remove, key:{:?}.", &self.name, &k); + log::debug!("remove with switch:{:?}.", switch); if switch { - self.buf.borrow_mut().remove(k); - return; - } + // update buffer only + self.buffer.borrow_mut().remove(k); + } else { + // remove "add" + insert "del" + self.add.borrow_mut().remove(k); + self.del.borrow_mut().insert(k.clone()); - // remove "add" + insert "del" - self.add.borrow_mut().remove(k); - self.del.borrow_mut().insert(k.clone()); + // update cache + self.cache.borrow_mut().remove(k); + } + } - // update cache - self.cache.borrow_mut().remove(k); + /// get the existence of the key + pub fn contains_key(&self, k: &K) -> bool { + if self.switch() { + self.buffer.borrow().contains_key(k) + } else { + self.cache.borrow().contains_key(k) + } } /// get a entry @@ -151,15 +159,6 @@ where value } - /// get the existence of the key - pub fn contains_key(&self, k: &K) -> bool { - if self.switch() { - return self.buf.borrow().contains_key(k); - } - - self.cache.borrow().contains_key(k) - } - /// get all keys pub fn keys(&self) -> Vec { let keys = self @@ -184,7 +183,7 @@ where entries } - /// export all data from cache to database + /// export changed data from cache to database pub fn cache_2_db(&self, wtxn: &mut ReDbRwTxn) { // "add" -> db.put + clear "add" for (k, v) in self.add.borrow().iter() { @@ -199,17 +198,19 @@ where self.del.borrow_mut().clear(); } - /// export all data from cache to database - pub fn rebuf_2_db(&self, wtxn: &mut ReDbRwTxn) { - // "buf" -> db.put + clear "buf" - for (k, v) in self.buf.borrow().iter() { + /// flush all data from buffer to database + pub fn buffer_2_db(&self, wtxn: &mut ReDbRwTxn) { + // clear all data, including "db" and "cache" + self.do_clear(wtxn); + + // "buffer" -> db.put + clear "buffer" + for (k, v) in self.buffer.borrow().iter() { self.db.put(&mut wtxn.0, k, v).expect("history.put"); } - - self.buf.borrow_mut().clear(); + self.buffer.borrow_mut().clear(); } - /// emport all data from database to cache + /// import all data from database to cache pub fn db_2_cache(&self, rtxn: &ReDbRoTxn) where K: DeserializeOwned, @@ -257,13 +258,13 @@ impl<'e> ReDbRoTxn<'e> { pub trait ReDbTable { /// clear all data fn clear(&self, wtxn: &mut ReDbRwTxn); - /// export all data to database + /// export the changed data to database fn export(&self, wtxn: &mut ReDbRwTxn); - /// daemon-reload or daemon-reexec export all data to database - fn reexport(&self, wtxn: &mut ReDbRwTxn); + /// flush all data to database + fn flush(&self, wtxn: &mut ReDbRwTxn); /// import all data from database fn import(&self, rtxn: &ReDbRoTxn); - /// set the switch flag of data, does switch control whether to use cache or buf + /// set the switch flag of data, does switch control whether to use cache or buffer fn switch_set(&self, switch: bool); } diff --git a/core/lib/rel/history.rs b/core/lib/rel/history.rs index 846f8c5..f9e2146 100644 --- a/core/lib/rel/history.rs +++ b/core/lib/rel/history.rs @@ -12,18 +12,29 @@ use super::base::{ReDbRoTxn, ReDbRwTxn, ReDbTable}; use crate::error::*; -use heed::{Env, EnvOpenOptions}; +use heed::{CompactionOption, Env, EnvOpenOptions}; use std::cell::RefCell; use std::collections::HashMap; -use std::path::Path; +use std::fmt; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::{fmt, fs}; + +const RELI_HISTORY_A_DIR: &str = "a"; +const RELI_HISTORY_B_DIR: &str = "b"; +const RELI_HISTORY_BFLAG_FILE: &str = "b.effect"; const RELI_HISTORY_DIR: &str = "history.mdb"; +const RELI_HISTORY_DATA_FILE: &str = "data.mdb"; +const RELI_HISTORY_LOCK_FILE: &str = "lock.mdb"; pub struct ReliHistory { // control - ignore: RefCell, + switch: RefCell, + + // directory + b_exist: bool, + hdir: String, // home-directory // environment env: Env, @@ -42,18 +53,19 @@ impl fmt::Debug for ReliHistory { } impl ReliHistory { - pub fn new(dir_str: &str, max: u32) -> ReliHistory { - // init environment - let path = Path::new(dir_str).join(RELI_HISTORY_DIR); - let env = EnvOpenOptions::new() - .map_size(10 * 1024 * 1024) - .max_dbs(max) - .open(path) - .unwrap(); + pub fn new(dir_str: &str, map_size: Option, max_dbs: Option) -> ReliHistory { + // init environment, path: dir/history.mdb/(a|b)/ + let history = history_path_get(dir_str); + let b_exist = bflag_path_get(history.clone()).exists(); + let path = history.join(&subdir_cur_get(b_exist)); + let env = open_env(path.clone(), map_size, max_dbs).expect("history open env"); + log::info!("history with path {:?} successfully.", path); // return ReliHistory { - ignore: RefCell::new(false), + switch: RefCell::new(false), + b_exist, + hdir: String::from(dir_str), env, dbs: RefCell::new(HashMap::new()), } @@ -75,7 +87,7 @@ impl ReliHistory { // create transaction let mut db_wtxn = ReDbRwTxn::new(&self.env).expect("history.write_txn"); - // flush to db + // export to db for (_, db) in self.dbs.borrow().iter() { db.export(&mut db_wtxn); } @@ -84,15 +96,13 @@ impl ReliHistory { db_wtxn.0.commit().expect("history.commit"); } - /// daemon-reload or daemon-reexec clear db and data reflush to db - pub fn reflush(&self) { + pub(super) fn flush(&self) { // create transaction let mut db_wtxn = ReDbRwTxn::new(&self.env).expect("history.write_txn"); // flush to db for (_, db) in self.dbs.borrow().iter() { - db.clear(&mut db_wtxn); - db.reexport(&mut db_wtxn); + db.flush(&mut db_wtxn); } // commit @@ -108,9 +118,48 @@ impl ReliHistory { } } + pub(super) fn compact(&self) -> Result<()> { + // a -> b or b -> a + // prepare next + let history = history_path_get(&self.hdir); + let next_path = history.join(&subdir_next_get(self.b_exist)); + let next_file = next_path.join(RELI_HISTORY_DATA_FILE); + + // clear next: delete and re-create the whole directory + fs::remove_dir_all(next_path.clone()).context(IoSnafu)?; + fs::create_dir_all(next_path).context(IoSnafu)?; + + // copy to next + self.env + .copy_to_path(next_file.clone(), CompactionOption::Disabled) + .context(HeedSnafu)?; + log::info!("compact to file {:?} successfully.", next_file); + + // remark the next flag at last: the another one + let bflag = bflag_path_get(history.clone()); + if self.b_exist { + fs::remove_file(bflag).context(IoSnafu)?; + } else { + File::create(bflag).context(IoSnafu)?; + } + + // try to clear previous: it would be done in the next re-exec, but we try to delete it as soon as possible. + let cur_path = history.join(subdir_cur_get(self.b_exist)); + let cur_data = cur_path.join(RELI_HISTORY_DATA_FILE); + let cur_lock = cur_path.join(RELI_HISTORY_LOCK_FILE); + if let Err(e) = fs::remove_file(cur_data.clone()) { + log::error!("remove data file {:?} failed, err = {:?}", cur_data, e); + } + if let Err(e) = fs::remove_file(cur_lock.clone()) { + log::error!("remove lock file {:?} failed, err = {:?}", cur_lock, e); + } + + Ok(()) + } + pub fn switch_set(&self, switch: bool) { // set switch - *self.ignore.borrow_mut() = switch; + *self.switch.borrow_mut() = switch; for (_, db) in self.dbs.borrow().iter() { db.switch_set(switch); } @@ -124,16 +173,67 @@ impl ReliHistory { self.dbs.borrow_mut().clear(); } - pub fn ignore(&self) -> bool { - *self.ignore.borrow() + pub fn switch(&self) -> bool { + *self.switch.borrow() } } pub fn prepare(dir_str: &str) -> Result<()> { - let history = Path::new(dir_str).join(RELI_HISTORY_DIR); + // directory + let history = history_path_get(dir_str); if !history.exists() { fs::create_dir_all(&history).context(IoSnafu)?; } + // sub-directory + let a = history.join(RELI_HISTORY_A_DIR); + if !a.exists() { + fs::create_dir_all(&a).context(IoSnafu)?; + } + + let b = history.join(RELI_HISTORY_B_DIR); + if !b.exists() { + fs::create_dir_all(&b).context(IoSnafu)?; + } + Ok(()) } + +fn open_env(path: PathBuf, map_size: Option, max_dbs: Option) -> heed::Result { + let mut eoo = EnvOpenOptions::new(); + if let Some(size) = map_size { + eoo.map_size(size); + } + if let Some(max) = max_dbs { + eoo.max_dbs(max); + } + eoo.open(path) +} + +fn subdir_next_get(b_exist: bool) -> String { + if b_exist { + // b->a + String::from(RELI_HISTORY_A_DIR) + } else { + // a->b + String::from(RELI_HISTORY_B_DIR) + } +} + +fn subdir_cur_get(b_exist: bool) -> String { + if b_exist { + // b + String::from(RELI_HISTORY_B_DIR) + } else { + // a + String::from(RELI_HISTORY_A_DIR) + } +} + +fn bflag_path_get(history: PathBuf) -> PathBuf { + history.join(RELI_HISTORY_BFLAG_FILE) +} + +fn history_path_get(dir: &str) -> PathBuf { + Path::new(dir).join(RELI_HISTORY_DIR) +} diff --git a/core/lib/rel/mod.rs b/core/lib/rel/mod.rs index 757a74b..07470e4 100644 --- a/core/lib/rel/mod.rs +++ b/core/lib/rel/mod.rs @@ -11,7 +11,7 @@ // See the Mulan PSL v2 for more details. //! reliability module -pub use api::{reli_debug_enable_switch, reli_debug_get_switch, Reliability}; +pub use api::{reli_debug_enable_switch, reli_debug_get_switch, ReliConf, Reliability}; pub use base::{reli_dir_prepare, ReDb, ReDbRoTxn, ReDbRwTxn, ReDbTable}; use serde::{Deserialize, Serialize}; pub use station::{ReStation, ReStationKind}; diff --git a/docs/man/sysmaster.conf.md b/docs/man/sysmaster.conf.md index 039b543..2b91f34 100644 --- a/docs/man/sysmaster.conf.md +++ b/docs/man/sysmaster.conf.md @@ -19,3 +19,11 @@ sysmaster支持从`/etc/sysmaster/system.toml`中读取系统配置,用于配 ### LogFile 支持配置为`"`括起来的绝对路径,仅当`"LogTarget"`配置为`"file"`时生效。如果配置为空或不配置,将强制修改`LogTarget`为`"console"`。 + +## 外置db配置 + +支持通过`DbSize`等配置调整外置db参量。 + +### DbSize + +DbSize参量支持配置为最大内存占用规格,单位为字节。当配置值小于当前sysmaster所用内存值时,以当前sysmaster所用内存值为准。此配置在系统启动或者daemon-reexec后生效。 -- 2.33.0