diff --git a/core/coms/mount/src/rentry.rs b/core/coms/mount/src/rentry.rs index bc66676712b60fb236535f414d7e1655c1417980..3408c4c68b742798caf7d6388fcbac249e80fb95 100644 --- a/core/coms/mount/src/rentry.rs +++ b/core/coms/mount/src/rentry.rs @@ -10,7 +10,7 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -use core::rel::{ReDb, ReDbRwTxn, ReDbTable, Reliability}; +use core::rel::{ReDb, ReDbRwTxn, ReDbTable, ReliSwitch, Reliability}; use macros::EnumDisplay; use serde::{Deserialize, Serialize}; use std::rc::Rc; @@ -103,7 +103,7 @@ impl ReDbTable for MountReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -111,7 +111,7 @@ impl ReDbTable for MountReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } @@ -125,7 +125,7 @@ impl ReDbTable for MountReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -133,7 +133,7 @@ impl ReDbTable for MountReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } diff --git a/core/coms/service/src/rentry.rs b/core/coms/service/src/rentry.rs index b4f18e580fc73be91d64f9ba6763cd07b29368bc..914d122c993abc0d7d4fd34054f180e1b42ad5e4 100644 --- a/core/coms/service/src/rentry.rs +++ b/core/coms/service/src/rentry.rs @@ -30,7 +30,7 @@ use unit_parser::internal::UnitEntry; use core::error::*; use core::exec::{ExecCommand, Rlimit, RuntimeDirectory, StateDirectory, WorkingDirectory}; -use core::rel::{ReDb, ReDbRwTxn, ReDbTable, Reliability}; +use core::rel::{ReDb, ReDbRwTxn, ReDbTable, ReliSwitch, Reliability}; use core::unit::KillMode; use basic::EXEC_RUNTIME_PREFIX; @@ -892,7 +892,7 @@ impl ReDbTable for ServiceReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -900,7 +900,7 @@ impl ReDbTable for ServiceReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } @@ -914,7 +914,7 @@ impl ReDbTable for ServiceReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -922,7 +922,7 @@ impl ReDbTable for ServiceReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } diff --git a/core/coms/socket/src/rentry.rs b/core/coms/socket/src/rentry.rs index baa7c6df76d5348d559fc992fb33841d593f1a8d..f05067dc5e4c4ed2f5ef0ca730db96b6655f8277 100644 --- a/core/coms/socket/src/rentry.rs +++ b/core/coms/socket/src/rentry.rs @@ -12,7 +12,7 @@ // #![allow(non_snake_case)] use core::exec::ExecCommand; -use core::rel::{ReDb, ReDbRwTxn, ReDbTable, Reliability}; +use core::rel::{ReDb, ReDbRwTxn, ReDbTable, ReliSwitch, Reliability}; use core::unit::KillMode; use macros::EnumDisplay; use nix::unistd::Pid; @@ -348,7 +348,7 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -356,7 +356,7 @@ impl ReDbTable for SocketReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } @@ -370,7 +370,7 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -378,7 +378,7 @@ impl ReDbTable for SocketReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } @@ -392,7 +392,7 @@ impl ReDbTable for SocketReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -400,7 +400,7 @@ impl ReDbTable for SocketReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } diff --git a/core/coms/target/src/rentry.rs b/core/coms/target/src/rentry.rs index dd2013a66d02dfa4c38b63b7e853685bc4f6aa8c..fc0fe8472d3f8fda26abc3214059d516ad418446 100644 --- a/core/coms/target/src/rentry.rs +++ b/core/coms/target/src/rentry.rs @@ -10,7 +10,7 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -use core::rel::{ReDb, ReDbRwTxn, ReDbTable, Reliability}; +use core::rel::{ReDb, ReDbRwTxn, ReDbTable, ReliSwitch, Reliability}; use macros::EnumDisplay; use serde::{Deserialize, Serialize}; use std::rc::Rc; @@ -77,7 +77,7 @@ impl ReDbTable for TargetReDb { self.0.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.0.data_2_db(db_wtxn, switch); } @@ -85,7 +85,7 @@ impl ReDbTable for TargetReDb { self.0.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.0.switch_buffer(switch); } } diff --git a/core/libcore/Cargo.toml b/core/libcore/Cargo.toml index d063e0f83297c8637e0762f6a045a737ee2ed272..3711b223800b25d4c8f7d53f0d4f1fc7b173c4bb 100644 --- a/core/libcore/Cargo.toml +++ b/core/libcore/Cargo.toml @@ -37,3 +37,4 @@ snafu = { version = "0.7", default-features = false } [features] default = ["noplugin"] noplugin = [] +norecovery = [] diff --git a/core/libcore/src/rel/api_comm.rs b/core/libcore/src/rel/api_comm.rs new file mode 100755 index 0000000000000000000000000000000000000000..b2cc9e3bc5e970c60e8e8967b3955f4fe3efe965 --- /dev/null +++ b/core/libcore/src/rel/api_comm.rs @@ -0,0 +1,170 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#[cfg(debug)] +use super::debug::{self}; +use crate::{error::*, rel::base}; +use base::{RELI_DIR, RELI_INTERNAL_MAX_DBS}; +use basic::do_entry_or_return_io_error; +use heed::{Env, EnvOpenOptions}; +use nix::sys::stat::{self, Mode}; +use std::fs::{self}; +use std::path::{Path, PathBuf}; + +/// the configuration of reliability instance +#[derive(Clone)] +pub struct ReliConf { + // history + pub(super) map_size: Option, + pub(super) 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() + } +} + +/// get the debug flag of switch +pub fn reli_debug_get_switch() -> bool { + #[cfg(debug)] + return debug::switch(); + #[cfg(not(debug))] + return true; +} + +pub(super) fn reli_prepare() -> Result { + // directory + base::reli_dir_prepare()?; // again + let dir_string = base::reli_dir_get().unwrap(); + + // sub-directory + /* create '/run/sysmaster/reliability/sub_dir' or 'xxx/reliability/sub_dir' with mode 700 */ + let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); + let ret = reli_subdir_prepare(&dir_string); + let _ = stat::umask(old_mask); + if let Err(e) = ret { + log::error!("reliability prepare failed: dir{:?}, {}", dir_string, e); + return Err(e); + } + + Ok(dir_string) +} + +const RELI_SUB_A_DIR: &str = "a"; +const RELI_SUB_B_DIR: &str = "b"; +const RELI_BFLAG_FILE: &str = "b.effect"; + +fn reli_subdir_prepare(hdir: &str) -> Result<()> { + // sub-directory: reliability.mdb + let hpath = hpath_path_get(hdir); + #[cfg(debug)] + if debug::empty() { + // delete it with 'empty' flag, meaning that preparation without history database. + if hpath.exists() { + do_entry_or_return_io_error!(fs::remove_dir_all, hpath, "remove"); + } + } + + if !hpath.exists() { + do_entry_or_return_io_error!(fs::create_dir_all, hpath, "create"); + } + + // a + b + let a = hpath.join(RELI_SUB_A_DIR); + if !a.exists() { + do_entry_or_return_io_error!(fs::create_dir_all, a, "create"); + } + + let b = hpath.join(RELI_SUB_B_DIR); + if !b.exists() { + do_entry_or_return_io_error!(fs::create_dir_all, b, "create"); + } + + Ok(()) +} + +pub(super) fn create_env(conf: &ReliConf, hdir: &str, b_exist: bool) -> heed::Result { + let hpath = hpath_path_get(hdir); + let path = hpath.join(subdir_cur_get(b_exist)); + open_env(path, conf.map_size, conf.max_dbs) +} + +fn open_env(path: PathBuf, map_size: Option, max_dbs: Option) -> heed::Result { + let mut eoo = EnvOpenOptions::new(); + + // size + if let Some(size) = map_size { + eoo.map_size(size); + } + + // dbs + let mut max = RELI_INTERNAL_MAX_DBS; + if let Some(m) = max_dbs { + max += m; + } + eoo.max_dbs(max); + + // open + eoo.open(path) +} + +#[allow(dead_code)] +pub(super) fn subdir_next_get(b_exist: bool) -> String { + if b_exist { + // b->a + String::from(RELI_SUB_A_DIR) + } else { + // a->b + String::from(RELI_SUB_B_DIR) + } +} + +pub(super) fn subdir_cur_get(b_exist: bool) -> String { + if b_exist { + // b + String::from(RELI_SUB_B_DIR) + } else { + // a + String::from(RELI_SUB_A_DIR) + } +} + +pub(super) fn bflag_path_get(hpath: PathBuf) -> PathBuf { + hpath.join(RELI_BFLAG_FILE) +} + +pub(super) fn hpath_path_get(hdir: &str) -> PathBuf { + Path::new(hdir).join(RELI_DIR) +} diff --git a/core/libcore/src/rel/api_norecov.rs b/core/libcore/src/rel/api_norecov.rs new file mode 100755 index 0000000000000000000000000000000000000000..d4a3ebf2bff47e53a1cdcc251e552ec63d62c7c1 --- /dev/null +++ b/core/libcore/src/rel/api_norecov.rs @@ -0,0 +1,328 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#[cfg(debug)] +use super::debug::ReliDebug; +use super::{ + api_comm::{bflag_path_get, create_env, hpath_path_get, reli_prepare, ReliConf}, + base::ReliSwitch, + //enable::ReliEnable, + history::ReliHistory, + //last::ReliLast, + //pending::ReliPending, + station::ReliStation, + ReDbTable, + ReStation, + ReStationKind, +}; +use crate::error::*; +use crate::utils::fd as fd_util; +use heed::Env; +use std::rc::Rc; +use std::{cell::RefCell, fmt}; + +/// reliability instance +pub struct Reliability { + // debug + #[cfg(debug)] + debug: ReliDebug, + + // environment + env: RefCell>>, + + // configuration + config: ReliConf, + + // directory + b_exist: bool, + hdir: String, // home-directory + + // output data + history: ReliHistory, + + // input & recover + station: ReliStation, +} + +impl fmt::Debug for Reliability { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Reliability") + .field("env", &self.env.borrow().is_some()) + .field("history", &self.history) + .field("station", &self.station) + .finish() + } +} + +impl Drop for Reliability { + fn drop(&mut self) { + log::debug!("Reliability drop, clear."); + // repeating protection + self.clear(); + } +} + +impl Reliability { + /// create reliability instance + pub fn new(conf: &ReliConf) -> Reliability { + // init environment, path: dir/reliability.mdb/(a|b)/ + let hdir = reli_prepare().expect("reliability prepare"); + let hpath = hpath_path_get(&hdir); + let b_exist = bflag_path_get(hpath.clone()).exists(); + + let reli = Reliability { + #[cfg(debug)] + debug: ReliDebug::new(&hdir), + env: RefCell::new(None), + config: conf.clone(), + b_exist, + hdir, + history: ReliHistory::new(), + station: ReliStation::new(), + }; + reli.debug_enable(); + reli + } + + /// set the enable flag + pub fn set_enable(&self, _enable: bool) { + // do nothing + } + + /// set the last unit + pub fn set_last_unit(&self, _unit_id: &str) { + // do nothing + } + + /// clear the last unit + pub fn clear_last_unit(&self) { + // do nothing + } + + /// set the last frame + pub fn set_last_frame(&self, _f1: u32, _f2: Option, _f3: Option) { + // do nothing + } + + /// set the last frame with just one parameter + pub fn set_last_frame1(&self, f1: u32) { + self.set_last_frame(f1, None, None); + } + + /// set the last frame with two parameters + pub fn set_last_frame2(&self, f1: u32, f2: u32) { + self.set_last_frame(f1, Some(f2), None); + } + + /// clear the last frame + pub fn clear_last_frame(&self) { + // do nothing + } + + /// register history database + pub fn history_db_register(&self, name: &str, db: Rc) { + self.history.db_register(name, db); + } + + /// set the fd's 'cloexec' flag and record it + pub fn fd_cloexec(&self, fd: i32, cloexec: bool) -> Result<()> { + // just set the fd's 'cloexec' flag + fd_util::fd_cloexec(fd, cloexec).context(NixSnafu)?; + Ok(()) + } + + /// take the fd away + pub fn fd_take(&self, fd: i32) -> i32 { + // do nothing + fd + } + + /// register a station + pub fn station_register(&self, name: &str, kind: ReStationKind, station: Rc) { + self.station.station_register(name, kind, station); + } + + /// [process reentrant] recover the data + /// if reload is true, only map result class parameters. + pub fn recover(&self, reload: bool) { + self.history_import(); + self.input_rebuild(); + self.db_compensate(); + self.db_map(reload); + self.make_consistent(reload); + } + + /// flush to the database + pub fn flush(&self) -> Result<()> { + self.db_flush(true)?; + Ok(()) + } + + /// compact the database + pub fn compact(&self) -> Result<()> { + // do nothing + Ok(()) + } + + /// get the enable flag + pub fn enable(&self) -> bool { + false + } + + /// get env + pub(super) fn env(&self) -> Option> { + self.env.borrow().clone() + } + + /// get the last unit + pub fn last_unit(&self) -> Option { + None + } + + /// get the last frame + pub fn last_frame(&self) -> Option<(u32, Option, Option)> { + None + } + + /// clear all data + pub fn data_clear(&self) { + // data-only + /* output */ + let env = create_env(&self.config, &self.hdir, self.b_exist).unwrap(); + self.env.replace(Some(Rc::new(env))); + self.history.data_clear(&self.env().unwrap()); + self.env.replace(None); + } + + /// [repeating protection] clear all registers + pub fn clear(&self) { + self.history.clear(); + self.station.clear(); + } + + /// get the ignore flag of last data + pub fn last_ignore(&self) -> bool { + true + } + + /// get the switch flag of history data + pub fn history_switch(&self) -> ReliSwitch { + self.history.switch() + } + + /// do the debug action: enable the recover process + pub fn debug_enable(&self) { + #[cfg(debug)] + if self.debug.enable() { + log::info!("reliability debug: enable data..."); + self.set_enable(true); + } + } + + /// do the debug action: clear data excluding enable + pub fn debug_clear(&self) { + #[cfg(debug)] + if self.debug.clear() { + // clear data excluding enable + let enable = self.enable(); + self.data_clear(); + self.set_enable(enable); + } + } + + /// do the debug action: panic + pub fn debug_panic(&self) { + #[cfg(debug)] + self.debug.panic(); + } + + /// do the debug action: sleep + pub fn debug_sleep(&self) { + #[cfg(debug)] + self.debug.sleep(); + } + + fn history_import(&self) { + let env = create_env(&self.config, &self.hdir, self.b_exist).unwrap(); + self.env.replace(Some(Rc::new(env))); + self.history.import(); + self.env.replace(None); + } + + fn input_rebuild(&self) { + self.history.switch_set(ReliSwitch::Ignore); + + self.station.input_rebuild(); + + self.history.switch_set(ReliSwitch::CacheAll); + } + + fn db_compensate(&self) { + // get last + let lframe = self.last_frame(); + let lunit = self.last_unit(); + + log::debug!("db_compensate, lframe:{:?}, lunit{:?}.", lframe, lunit); + self.station.db_compensate(lframe, lunit); + } + + /// map data from database + /// reload determine whether the configuration needs to be reloaded based on the situation. + fn db_map(&self, reload: bool) { + self.history.switch_set(ReliSwitch::Ignore); + + self.station.db_map(reload); + + self.history.switch_set(ReliSwitch::CacheAll); + } + + fn make_consistent(&self, _reload: bool) { + let lframe = self.last_frame(); + let lunit = self.last_unit(); + log::debug!("make_consistent, lframe:{:?}, lunit{:?}.", lframe, lunit); + + // make consistent + self.station.make_consistent(lframe, lunit); + + self.db_flush(false).expect("flush db"); + self.data_clear(); + } + + fn db_flush(&self, force: bool) -> Result<()> { + let ret; + + if force { + self.history.switch_set(ReliSwitch::Buffer); // clear data before using buffer + + // update all changes to buffer + self.station.db_insert(); + + // clear db, submit data from all buffers to db, clear buffer + ret = self.history_flush(ReliSwitch::Buffer); + + self.history.switch_set(ReliSwitch::Ignore); + } else { + ret = self.history_flush(ReliSwitch::CacheAll); + self.history.switch_set(ReliSwitch::Ignore); + } + + ret + } + + fn history_flush(&self, switch: ReliSwitch) -> Result<()> { + let env = Rc::new(create_env(&self.config, &self.hdir, self.b_exist).context(HeedSnafu)?); + self.env.replace(Some(Rc::clone(&env))); + self.history.flush(&env, switch); + self.env.replace(None); + Ok(()) + } +} diff --git a/core/libcore/src/rel/api.rs b/core/libcore/src/rel/api_recov.rs old mode 100644 new mode 100755 similarity index 67% rename from core/libcore/src/rel/api.rs rename to core/libcore/src/rel/api_recov.rs index ec996bed230e5e40a4b440d57b57ad4d247a1abd..12e73ed2bf9782ff2ec666b0b4f922dbea0a3f74 --- a/core/libcore/src/rel/api.rs +++ b/core/libcore/src/rel/api_recov.rs @@ -11,9 +11,13 @@ // See the Mulan PSL v2 for more details. #[cfg(debug)] -use super::debug::{self, ReliDebug}; +use super::debug::ReliDebug; use super::{ - base::{RELI_DATA_FILE, RELI_DIR, RELI_INTERNAL_MAX_DBS, RELI_LOCK_FILE}, + api_comm::{ + bflag_path_get, create_env, hpath_path_get, reli_prepare, subdir_cur_get, subdir_next_get, + ReliConf, + }, + base::{ReliSwitch, RELI_DATA_FILE, RELI_LOCK_FILE}, enable::ReliEnable, history::ReliHistory, last::ReliLast, @@ -21,50 +25,14 @@ use super::{ station::ReliStation, ReDbTable, ReStation, ReStationKind, }; -use crate::{error::*, rel::base}; +use crate::error::*; use basic::{do_entry_log, do_entry_or_return_io_error}; -use heed::{CompactionOption, Env, EnvOpenOptions}; +use heed::{CompactionOption, Env}; use nix::sys::stat::{self, Mode}; use std::fmt; use std::fs::{self, File}; -use std::path::{Path, PathBuf}; use std::rc::Rc; -/// 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 pub struct Reliability { // debug @@ -119,7 +87,7 @@ impl Reliability { let hpath = hpath_path_get(&hdir); let b_exist = bflag_path_get(hpath.clone()).exists(); let path = hpath.join(subdir_cur_get(b_exist)); - let e = Rc::new(open_env(path.clone(), conf.map_size, conf.max_dbs).expect("open env")); + let e = Rc::new(create_env(conf, &hdir, b_exist).expect("open env")); log::info!("open with path {:?} successfully.", path); let reli = Reliability { @@ -130,7 +98,7 @@ impl Reliability { hdir, enable: ReliEnable::new(&e), last: ReliLast::new(&e), - history: ReliHistory::new(&e), + history: ReliHistory::new(), pending: ReliPending::new(&e), station: ReliStation::new(), }; @@ -150,7 +118,7 @@ impl Reliability { /// clear the last unit pub fn clear_last_unit(&self) { - self.history.commit(); + self.history.commit(&self.env); self.last.clear_unit(); } @@ -161,17 +129,17 @@ impl Reliability { /// set the last frame with just one parameter pub fn set_last_frame1(&self, f1: u32) { - self.last.set_frame(f1, None, None); + self.set_last_frame(f1, None, None); } /// set the last frame with two parameters pub fn set_last_frame2(&self, f1: u32, f2: u32) { - self.last.set_frame(f1, Some(f2), None); + self.set_last_frame(f1, Some(f2), None); } /// clear the last frame pub fn clear_last_frame(&self) { - self.history.commit(); + self.history.commit(&self.env); self.last.clear_frame(); } @@ -215,6 +183,12 @@ impl Reliability { self.last.clear_frame(); } + /// flush to the database + pub fn flush(&self) -> Result<()> { + // do nothing, all data has been exported by 'commit'. + Ok(()) + } + /// compact the database pub fn compact(&self) -> Result<()> { // action with mode 700, excluding group and other users @@ -265,8 +239,8 @@ impl Reliability { } /// get env - pub(super) fn env(&self) -> &Env { - &self.env + pub(super) fn env(&self) -> Option> { + Some(Rc::clone(&self.env)) } /// get the last unit @@ -286,7 +260,7 @@ impl Reliability { self.enable.data_clear(); /* output */ self.last.data_clear(); - self.history.data_clear(); + self.history.data_clear(&self.env); self.pending.data_clear(); } @@ -302,7 +276,7 @@ impl Reliability { } /// get the switch flag of history data - pub fn history_switch(&self) -> Option { + pub fn history_switch(&self) -> ReliSwitch { self.history.switch() } @@ -339,11 +313,11 @@ impl Reliability { } fn input_rebuild(&self) { - self.history.switch_set(Some(true)); + self.history.switch_set(ReliSwitch::Ignore); self.station.input_rebuild(); - self.history.switch_set(Some(false)); + self.history.switch_set(ReliSwitch::CacheAll); } fn db_compensate(&self) { @@ -353,17 +327,17 @@ impl Reliability { log::debug!("db_compensate, lframe:{:?}, lunit{:?}.", lframe, lunit); self.station.db_compensate(lframe, lunit); - self.history.commit(); + self.history.commit(&self.env); } /// map data from database /// reload determine whether the configuration needs to be reloaded based on the situation. fn db_map(&self, reload: bool) { - self.history.switch_set(Some(true)); + self.history.switch_set(ReliSwitch::Ignore); self.station.db_map(reload); - self.history.switch_set(Some(false)); + self.history.switch_set(ReliSwitch::CacheAll); } fn make_consistent(&self, reload: bool) { @@ -379,133 +353,26 @@ impl Reliability { // make consistent and commit self.pending.make_consistent(); self.station.make_consistent(lframe, lunit); - self.history.commit(); + self.history.commit(&self.env); // flush data with switch 'false'(cache) unconditionally. self.db_flush(false); } - fn db_flush(&self, reload: bool) { - if reload { - self.history.switch_set(Some(true)); // clear data before using buffer + fn db_flush(&self, force: bool) { + if force { + self.history.switch_set(ReliSwitch::Buffer); // clear data before using buffer // update all changes to buffer self.station.db_insert(); // clear db, submit data from all buffers to db, clear buffer - self.history.flush(true); // switch = true + self.history.flush(&self.env, ReliSwitch::Buffer); - self.history.switch_set(Some(false)); + self.history.switch_set(ReliSwitch::CacheAll); } else { - self.history.flush(false); // switch = false - - self.history.switch_set(None); + self.history.flush(&self.env, ReliSwitch::CacheAll); + self.history.switch_set(ReliSwitch::CacheVar); } } } - -/// get the debug flag of switch -pub fn reli_debug_get_switch() -> bool { - #[cfg(debug)] - return debug::switch(); - #[cfg(not(debug))] - return true; -} - -fn reli_prepare() -> Result { - // directory - base::reli_dir_prepare()?; // again - let dir_string = base::reli_dir_get().unwrap(); - - // sub-directory - /* create '/run/sysmaster/reliability/sub_dir' or 'xxx/reliability/sub_dir' with mode 700 */ - let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); - let ret = reli_subdir_prepare(&dir_string); - let _ = stat::umask(old_mask); - if let Err(e) = ret { - log::error!("reliability prepare failed: dir{:?}, {}", dir_string, e); - return Err(e); - } - - Ok(dir_string) -} - -const RELI_SUB_A_DIR: &str = "a"; -const RELI_SUB_B_DIR: &str = "b"; -const RELI_BFLAG_FILE: &str = "b.effect"; - -fn reli_subdir_prepare(hdir: &str) -> Result<()> { - // sub-directory: reliability.mdb - let hpath = hpath_path_get(hdir); - #[cfg(debug)] - if debug::empty() { - // delete it with 'empty' flag, meaning that preparation without history database. - if hpath.exists() { - do_entry_or_return_io_error!(fs::remove_dir_all, hpath, "remove"); - } - } - - if !hpath.exists() { - do_entry_or_return_io_error!(fs::create_dir_all, hpath, "create"); - } - - // a + b - let a = hpath.join(RELI_SUB_A_DIR); - if !a.exists() { - do_entry_or_return_io_error!(fs::create_dir_all, a, "create"); - } - - let b = hpath.join(RELI_SUB_B_DIR); - if !b.exists() { - do_entry_or_return_io_error!(fs::create_dir_all, b, "create"); - } - - Ok(()) -} - -fn open_env(path: PathBuf, map_size: Option, max_dbs: Option) -> heed::Result { - let mut eoo = EnvOpenOptions::new(); - - // size - if let Some(size) = map_size { - eoo.map_size(size); - } - - // dbs - let mut max = RELI_INTERNAL_MAX_DBS; - if let Some(m) = max_dbs { - max += m; - } - eoo.max_dbs(max); - - // open - eoo.open(path) -} - -fn subdir_next_get(b_exist: bool) -> String { - if b_exist { - // b->a - String::from(RELI_SUB_A_DIR) - } else { - // a->b - String::from(RELI_SUB_B_DIR) - } -} - -fn subdir_cur_get(b_exist: bool) -> String { - if b_exist { - // b - String::from(RELI_SUB_B_DIR) - } else { - // a - String::from(RELI_SUB_A_DIR) - } -} - -fn bflag_path_get(hpath: PathBuf) -> PathBuf { - hpath.join(RELI_BFLAG_FILE) -} - -fn hpath_path_get(hdir: &str) -> PathBuf { - Path::new(hdir).join(RELI_DIR) -} diff --git a/core/libcore/src/rel/base.rs b/core/libcore/src/rel/base.rs index 840b3f90da49e45cd53829c7fc94f2ebe68da464..d3287897e50955dc8febdb5f02e4a158110e6c8b 100644 --- a/core/libcore/src/rel/base.rs +++ b/core/libcore/src/rel/base.rs @@ -27,6 +27,19 @@ use std::hash::Hash; use std::path::Path; use std::rc::Rc; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// the switch of the reliability database, which control the caching behavior. +pub enum ReliSwitch { + /// record to cache, including variable(add + del) and snapshot(snapshot) + CacheAll, + /// record to variable cache(add + del) only + CacheVar, + /// record to buffer + Buffer, + /// ignore the input + Ignore, +} + /// the reliability database /// K & V that can be deserialized without borrowing any data from the deserializer. pub struct ReDb { @@ -34,14 +47,14 @@ pub struct ReDb { reli: Rc, // control - switch: RefCell>, // Some(true): buffer, Some(false): cache, None: none + switch: RefCell, // data /* database: create in use */ /* db: Database, SerdeBincode>; */ /* cache */ - cache: RefCell>, // the copy of db + snapshot: RefCell>, // the copy of db add: RefCell>, del: RefCell>, @@ -65,7 +78,7 @@ where self.cache_2_db(db_wtxn); } - fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: bool) { + fn flush(&self, db_wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { self.data_2_db(db_wtxn, switch); } @@ -73,7 +86,7 @@ where self.db_2_cache(); } - fn switch_set(&self, switch: Option) { + fn switch_set(&self, switch: ReliSwitch) { self.switch_buffer(switch); } } @@ -87,8 +100,8 @@ where pub fn new(relir: &Rc, db_name: &str) -> ReDb { ReDb { reli: Rc::clone(relir), - switch: RefCell::new(None), - cache: RefCell::new(HashMap::new()), + switch: RefCell::new(ReliSwitch::CacheAll), + snapshot: RefCell::new(HashMap::new()), add: RefCell::new(HashMap::new()), del: RefCell::new(HashSet::new()), buffer: RefCell::new(HashMap::new()), @@ -103,11 +116,11 @@ where } self.add.borrow_mut().clear(); self.del.borrow_mut().clear(); - // Do not clear the cache and buffer, because their data are transient. + // Do not clear the snapshot and buffer, because their data are transient. } /// switch between cache and buffer - pub fn switch_buffer(&self, switch: Option) { + pub fn switch_buffer(&self, switch: ReliSwitch) { // Before using the buffer, data needs to be cleared. self.buffer.borrow_mut().clear(); *self.switch.borrow_mut() = switch; @@ -125,23 +138,26 @@ where ); match switch { - Some(true) => { - // update buffer only - self.buffer.borrow_mut().insert(k, v); - } - Some(false) => { + ReliSwitch::CacheAll => { // 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 snapshot + self.snapshot.borrow_mut().insert(k, v); } - None => { + ReliSwitch::CacheVar => { // remove "del" + insert "add" self.del.borrow_mut().remove(&k); self.add.borrow_mut().insert(k, v); } + ReliSwitch::Buffer => { + // update buffer only + self.buffer.borrow_mut().insert(k, v); + } + ReliSwitch::Ignore => { + // do nothing + } } } @@ -152,29 +168,32 @@ where log::debug!("remove with switch:{:?}.", switch); match switch { - Some(true) => { - // update buffer only - self.buffer.borrow_mut().remove(k); - } - Some(false) => { + ReliSwitch::CacheAll => { // 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 snapshot + self.snapshot.borrow_mut().remove(k); } - None => { + ReliSwitch::CacheVar => { // remove "add" + insert "del" self.add.borrow_mut().remove(k); self.del.borrow_mut().insert(k.clone()); } + ReliSwitch::Buffer => { + // update buffer only + self.buffer.borrow_mut().remove(k); + } + ReliSwitch::Ignore => { + // do nothing + } } } /// get a entry pub fn get(&self, k: &K) -> Option { - let value = self.cache.borrow().get(k).cloned(); + let value = self.snapshot.borrow().get(k).cloned(); let n = &self.name; log::debug!("ReDb[{}] get, key: {:?}, value: {:?}.", n, k, &value); value @@ -183,7 +202,7 @@ where /// get all keys pub fn keys(&self) -> Vec { let keys = self - .cache + .snapshot .borrow() .iter() .map(|(k, _)| k.clone()) @@ -195,7 +214,7 @@ where /// get all entries pub fn entries(&self) -> Vec<(K, V)> { let entries = self - .cache + .snapshot .borrow() .iter() .map(|(k, v)| (k.clone(), v.clone())) @@ -222,20 +241,26 @@ where } /// flush internal data to database - pub fn data_2_db(&self, wtxn: &mut ReDbRwTxn, switch: bool) { - if switch { - // clear all data, including "db" and "add" + "del" - self.do_clear(wtxn); - - // "buffer" -> db.put + clear "buffer" - let db = self.open_db(wtxn).unwrap(); - for (k, v) in self.buffer.borrow().iter() { - db.put(&mut wtxn.0, k, v).expect("history.put"); + pub fn data_2_db(&self, wtxn: &mut ReDbRwTxn, switch: ReliSwitch) { + match switch { + ReliSwitch::CacheAll | ReliSwitch::CacheVar => { + // clear "snapshot" only, which is the same with db. + self.snapshot.borrow_mut().clear(); + } + ReliSwitch::Buffer => { + // clear all data, including "db" and "add" + "del" + self.do_clear(wtxn); + + // "buffer" -> db.put + clear "buffer" + let db = self.open_db(wtxn).unwrap(); + for (k, v) in self.buffer.borrow().iter() { + db.put(&mut wtxn.0, k, v).expect("history.put"); + } + self.buffer.borrow_mut().clear(); + } + ReliSwitch::Ignore => { + // do nothing } - self.buffer.borrow_mut().clear(); - } else { - // clear "cache" only, which is the same with db - self.cache.borrow_mut().clear(); } } @@ -245,44 +270,38 @@ where K: DeserializeOwned, V: DeserializeOwned, { - // clear "add" + "del" + "cache" + // clear "add" + "del" + "snapshot" self.add.borrow_mut().clear(); self.del.borrow_mut().clear(); - self.cache.borrow_mut().clear(); + self.snapshot.borrow_mut().clear(); - // db(open only) -> cache - if let Some(db) = self - .reli - .env() + // db(open only) -> snapshot + let env = self.reli.env().expect("get env"); + if let Some(db) = env .open_database::, SerdeBincode>(Some(&self.name)) .unwrap_or(None) { - let rtxn = ReDbRoTxn::new(self.reli.env()).expect("db_2_cache.ro_txn"); + let rtxn = ReDbRoTxn::new(&env).expect("db_2_cache.ro_txn"); let iter = db.iter(&rtxn.0).unwrap(); for entry in iter { let (k, v) = entry.unwrap(); - self.cache.borrow_mut().insert(k, v); + self.snapshot.borrow_mut().insert(k, v); } } } fn open_db(&self, wtxn: &mut ReDbRwTxn) -> Result, SerdeBincode>> { - let database = self - .reli - .env() - .open_database(Some(&self.name)) - .context(HeedSnafu)?; + let env = self.reli.env().expect("get env"); + let database = env.open_database(Some(&self.name)).context(HeedSnafu)?; if let Some(db) = database { Ok(db) } else { - self.reli - .env() - .create_database_with_txn(Some(&self.name), &mut wtxn.0) + env.create_database_with_txn(Some(&self.name), &mut wtxn.0) .context(HeedSnafu) } } - fn switch(&self) -> Option { + fn switch(&self) -> ReliSwitch { *self.switch.borrow() } } @@ -314,15 +333,17 @@ pub trait ReDbTable { /// export the changed data to database fn export(&self, wtxn: &mut ReDbRwTxn); /// flush data to database - fn flush(&self, wtxn: &mut ReDbRwTxn, switch: bool); + fn flush(&self, wtxn: &mut ReDbRwTxn, switch: ReliSwitch); /// import all data from database fn import(&self); /// set the switch flag of data, does switch control whether to use buffer, cache, or none - fn switch_set(&self, switch: Option); + fn switch_set(&self, switch: ReliSwitch); } pub(super) const RELI_DIR: &str = "reliability.mdb"; +#[allow(dead_code)] pub(super) const RELI_DATA_FILE: &str = "data.mdb"; +#[allow(dead_code)] pub(super) const RELI_LOCK_FILE: &str = "lock.mdb"; pub(super) const RELI_INTERNAL_DB_ENABLE: &str = "enable"; diff --git a/core/libcore/src/rel/history.rs b/core/libcore/src/rel/history.rs index be8961793701abefdf801f2de8700c3bfa1f19df..4880e0f4c2fc0d15f138561b6c74930d982c97c9 100644 --- a/core/libcore/src/rel/history.rs +++ b/core/libcore/src/rel/history.rs @@ -10,7 +10,7 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -use super::base::{ReDbRwTxn, ReDbTable}; +use super::base::{ReDbRwTxn, ReDbTable, ReliSwitch}; use heed::Env; use std::cell::RefCell; use std::collections::HashMap; @@ -18,11 +18,8 @@ use std::fmt; use std::rc::Rc; pub struct ReliHistory { - // associated objects - env: Rc, - // control - switch: RefCell>, + switch: RefCell, // database: multi-instance(N) dbs: RefCell>>, // key: name, value: db @@ -31,23 +28,21 @@ pub struct ReliHistory { impl fmt::Debug for ReliHistory { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ReliHistory") - .field("env.path", &self.env.path()) .field("env.dbs.len", &self.dbs.borrow().len()) .finish() } } impl ReliHistory { - pub fn new(envr: &Rc) -> ReliHistory { + pub fn new() -> ReliHistory { ReliHistory { - switch: RefCell::new(None), - env: Rc::clone(envr), + switch: RefCell::new(ReliSwitch::CacheAll), dbs: RefCell::new(HashMap::new()), } } - pub fn data_clear(&self) { - let mut db_wtxn = ReDbRwTxn::new(&self.env).expect("history.write_txn"); + pub fn data_clear(&self, env: &Env) { + let mut db_wtxn = ReDbRwTxn::new(env).expect("history.write_txn"); for (_, db) in self.dbs.borrow().iter() { db.clear(&mut db_wtxn); } @@ -58,9 +53,10 @@ impl ReliHistory { self.dbs.borrow_mut().insert(name.to_string(), db); } - pub fn commit(&self) { + #[allow(dead_code)] + pub fn commit(&self, env: &Env) { // create transaction - let mut db_wtxn = ReDbRwTxn::new(&self.env).expect("history.write_txn"); + let mut db_wtxn = ReDbRwTxn::new(env).expect("history.write_txn"); // export to db for (_, db) in self.dbs.borrow().iter() { @@ -71,9 +67,9 @@ impl ReliHistory { db_wtxn.0.commit().expect("history.commit"); } - pub(super) fn flush(&self, switch: bool) { + pub(super) fn flush(&self, env: &Env, switch: ReliSwitch) { // create transaction - let mut db_wtxn = ReDbRwTxn::new(&self.env).expect("history.write_txn"); + let mut db_wtxn = ReDbRwTxn::new(env).expect("history.write_txn"); // flush to db for (_, db) in self.dbs.borrow().iter() { @@ -91,7 +87,7 @@ impl ReliHistory { } } - pub fn switch_set(&self, switch: Option) { + pub fn switch_set(&self, switch: ReliSwitch) { *self.switch.borrow_mut() = switch; for (_, db) in self.dbs.borrow().iter() { db.switch_set(switch); @@ -102,7 +98,7 @@ impl ReliHistory { self.dbs.borrow_mut().clear(); } - pub fn switch(&self) -> Option { + pub fn switch(&self) -> ReliSwitch { *self.switch.borrow() } } diff --git a/core/libcore/src/rel/mod.rs b/core/libcore/src/rel/mod.rs index 03f4c9a7edc9af0270e26d21fc4790bd0eea2654..06c981151dc832a872cac1707d49e3493c07ce34 100644 --- a/core/libcore/src/rel/mod.rs +++ b/core/libcore/src/rel/mod.rs @@ -11,20 +11,31 @@ // See the Mulan PSL v2 for more details. //! reliability module -pub use api::{reli_debug_get_switch, ReliConf, Reliability}; -pub use base::{reli_dir_prepare, ReDb, ReDbRoTxn, ReDbRwTxn, ReDbTable}; +pub use api_comm::{reli_debug_get_switch, ReliConf}; +#[cfg(feature = "norecovery")] +pub use api_norecov::Reliability; +#[cfg(not(feature = "norecovery"))] +pub use api_recov::Reliability; +pub use base::{reli_dir_prepare, ReDb, ReDbRoTxn, ReDbRwTxn, ReDbTable, ReliSwitch}; use serde::{Deserialize, Serialize}; pub use station::{ReStation, ReStationKind}; use std::convert::TryFrom; -// dependency: base -> {enable | last | history | pending | station} -> debug -> api -mod api; +// dependency: base -> {enable | last | history | pending | station} -> debug -> api(comm -> {recov or norecov}) +mod api_comm; +#[cfg(feature = "norecovery")] +mod api_norecov; +#[cfg(not(feature = "norecovery"))] +mod api_recov; mod base; #[cfg(debug)] mod debug; +#[cfg(not(feature = "norecovery"))] mod enable; mod history; +#[cfg(not(feature = "norecovery"))] mod last; +#[cfg(not(feature = "norecovery"))] mod pending; mod station; diff --git a/core/sysmaster/Cargo.toml b/core/sysmaster/Cargo.toml index a01c0496f2e34e4e75e150d4585b0b05720a0241..2bc2ec87be9560629389a36dd46014822efbb52a 100644 --- a/core/sysmaster/Cargo.toml +++ b/core/sysmaster/Cargo.toml @@ -141,6 +141,7 @@ hongmeng = [] linux = [] noplugin = [] plugin = ["dynamic_reload"] +norecovery = [] [[bin]] path = "src/main.rs" diff --git a/core/sysmaster/src/main.rs b/core/sysmaster/src/main.rs index 0f5fd3f4a542d76353c1a50a0e471d4543cd69f2..261831eeb2d7bbb1db44994f6b29785ebb1d655e 100644 --- a/core/sysmaster/src/main.rs +++ b/core/sysmaster/src/main.rs @@ -45,7 +45,7 @@ use clap::Parser; use constants::LOG_FILE_PATH; use core::error::*; use core::rel; -use libc::{c_int, getpid, getppid, prctl, PR_SET_CHILD_SUBREAPER}; +use libc::{c_int, PR_SET_CHILD_SUBREAPER}; use log::{self, Level}; use nix::sys::signal::{self, SaFlags, SigAction, SigHandler, SigSet, Signal}; use std::cell::RefCell; @@ -171,7 +171,7 @@ fn initialize_runtime(self_recovery_enable: bool) -> Result<()> { } fn set_child_reaper() { - let ret = unsafe { prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) }; + let ret = unsafe { libc::prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) }; if ret < 0 { log::warn!("failed to set child reaper, errno: {}", ret); @@ -243,16 +243,27 @@ fn install_crash_handler() { } } +#[cfg(not(feature = "norecovery"))] extern "C" fn crash(signo: c_int, siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) { let signal = Signal::try_from(signo).unwrap(); // debug - if (signal == Signal::SIGABRT && unsafe { (*siginfo).si_pid() == getppid() }) - || unsafe { (*siginfo).si_pid() == getpid() } + if (signal == Signal::SIGABRT && unsafe { (*siginfo).si_pid() == libc::getppid() }) + || unsafe { (*siginfo).si_pid() == libc::getpid() } { let args: Vec = env::args().collect(); do_reexecute(&args, false); } } +#[cfg(feature = "norecovery")] +extern "C" fn crash(_signo: c_int, _siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) { + // debug + + // freeze + loop { + nix::unistd::pause(); + } +} + fn execarg_build_default() -> (String, Vec) { let path = env::current_exe().unwrap(); let str_path = String::from(path.to_str().unwrap()); @@ -267,7 +278,7 @@ fn execarg_build_default() -> (String, Vec) { extern "C" fn crash_reexec(_signo: c_int, siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) { unsafe { - if (*siginfo).si_pid() == getppid() { + if (*siginfo).si_pid() == libc::getppid() { let args: Vec = env::args().collect(); do_reexecute(&args, false); } diff --git a/core/sysmaster/src/manager/mod.rs b/core/sysmaster/src/manager/mod.rs index a757b6084448989427cc5060976a026f84c4ccf7..f1062e317d4ab2496900f0479a9d7eec378be38c 100644 --- a/core/sysmaster/src/manager/mod.rs +++ b/core/sysmaster/src/manager/mod.rs @@ -313,7 +313,7 @@ impl Manager { /* register entire external events */ self.register_ex(); /* register entry's external events */ - if restore { + if reload || restore { self.um.entry_coldplug(); } @@ -391,17 +391,24 @@ impl Manager { false, ); - self.run_generators(); + // flush db + if let Err(e) = self.reli.flush() { + log::error!("flush failed with error:{:?}, try next reload.", e); + } else { + log::info!("reload start."); - // clear data - self.um.entry_clear(); + self.run_generators(); - // recover entry - self.reli.recover(true); + // clear data + self.um.entry_clear(); - // rebuild external connections - /* register entry's external events */ - self.um.entry_coldplug(); + // recover entry + self.reli.recover(true); + + // rebuild external connections + /* register entry's external events */ + self.um.entry_coldplug(); + } // it's ok now self.set_state(State::Ok); @@ -428,6 +435,9 @@ impl Manager { // restore external resource, like: fd, ... // do nothing now + // flush db + self.reli.flush()?; + // compact db self.reli.compact()?; Ok(())