From d36bb9fa9a0322f475f6039948bba6ea8e106d74 Mon Sep 17 00:00:00 2001 From: xuxiaozhou1 Date: Sun, 2 Jul 2023 17:32:25 +0800 Subject: [PATCH] fix: isolate debugging code through configuration predicate 'debug' --- build.rs | 8 +++ core/libsysmaster/rel/api.rs | 106 ++++++++------------------------- core/libsysmaster/rel/base.rs | 40 +++++++++++-- core/libsysmaster/rel/debug.rs | 106 +++++++++++++++++++++++++++++++++ core/libsysmaster/rel/mod.rs | 6 +- 5 files changed, 178 insertions(+), 88 deletions(-) create mode 100644 core/libsysmaster/rel/debug.rs diff --git a/build.rs b/build.rs index 05296f5..15c2a21 100644 --- a/build.rs +++ b/build.rs @@ -14,6 +14,8 @@ // if use env out_dir need add build.rs use std::{env, process::Command}; +const RELEASE: &str = "release"; + macro_rules! warn { ($message:expr) => { println!("cargo:warning={}", $message); @@ -45,4 +47,10 @@ fn main() { println!("cargo:rerun-if-changed=build.sh"); println!("cargo:rerun-if-changed=build.rs"); // println!("cargo:rerun-if-changed=config.service"); + + // turn on "debug" for non-release build + let profile = env::var("PROFILE").unwrap(); + if profile != RELEASE { + println!("cargo:rustc-cfg=debug"); + } } diff --git a/core/libsysmaster/rel/api.rs b/core/libsysmaster/rel/api.rs index 94f9015..ad7743a 100644 --- a/core/libsysmaster/rel/api.rs +++ b/core/libsysmaster/rel/api.rs @@ -10,6 +10,8 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. +#[cfg(debug)] +use super::debug::{self, ReliDebug}; use super::{ enable::{self, ReliEnable}, history::{self, ReliHistory}, @@ -19,24 +21,9 @@ use super::{ ReDbTable, ReStation, ReStationKind, }; use crate::{error::*, rel::base}; -use basic::do_entry_or_return_io_error; use heed::Database; use nix::sys::stat::{self, Mode}; -use std::{ - fs::{self, File}, - path::Path, - rc::Rc, - thread, - time::Duration, -}; - -const RELI_DEBUG_SWITCH_FILE: &str = "switch.debug"; -const RELI_DEBUG_CLEAR_FILE: &str = "clear.debug"; -const RELI_DEBUG_CFIRST_FILE: &str = "clear_first.debug"; -const RELI_DEBUG_ENABLE_FILE: &str = "enable.debug"; -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"; +use std::rc::Rc; /// the configuration of reliability instance pub struct ReliConf { @@ -76,8 +63,11 @@ impl Default for ReliConf { /// reliability instance #[derive(Debug)] pub struct Reliability { + // debug + #[cfg(debug)] + debug: ReliDebug, + // control data - dir_string: String, enable: ReliEnable, // output data @@ -102,7 +92,8 @@ impl Reliability { pub fn new(conf: &ReliConf) -> Reliability { let dir_s = reli_prepare().expect("reliability prepare"); let reli = Reliability { - dir_string: dir_s.clone(), + #[cfg(debug)] + debug: ReliDebug::new(&dir_s), enable: ReliEnable::new(&dir_s), last: ReliLast::new(&dir_s), history: ReliHistory::new(&dir_s, conf.map_size, conf.max_dbs), @@ -250,8 +241,8 @@ impl Reliability { /// do the debug action: enable the recover process pub fn debug_enable(&self) { - let enable = Path::new(&self.dir_string).join(RELI_DEBUG_ENABLE_FILE); - if enable.exists() { + #[cfg(debug)] + if self.debug.enable() { log::info!("reliability debug: enable data..."); self.set_enable(true); } @@ -259,53 +250,25 @@ impl Reliability { /// do the debug action: clear data excluding enable pub fn debug_clear(&self) { - let clear = Path::new(&self.dir_string).join(RELI_DEBUG_CLEAR_FILE); - if clear.exists() { - log::info!("reliability debug: clear data..."); - let cfirst = Path::new(&self.dir_string).join(RELI_DEBUG_CFIRST_FILE); - if cfirst.exists() { - // do nothing - log::info!("reliability debug_clear: non-first time, do nothing."); - } else { - log::info!("reliability debug_clear: first time, try clear."); - File::create(&cfirst).unwrap(); - log::debug!("Successfully created {cfirst:?}"); - log::info!("reliability debug_clear: first time, clear ..."); - - // clear data excluding enable - let enable = self.enable(); - self.data_clear(); - self.set_enable(enable); - } + #[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) { - let panic = Path::new(&self.dir_string).join(RELI_DEBUG_PANIC_FILE); - if panic.exists() { - log::info!("reliability debug: panic..."); - let pfirst = Path::new(&self.dir_string).join(RELI_DEBUG_PFIRST_FILE); - if pfirst.exists() { - // do nothing - log::info!("reliability debug_panic: non-first time, do nothing."); - } else { - log::info!("reliability debug_panic: first time, try panic."); - File::create(&pfirst).unwrap(); - log::debug!("Successfully created {pfirst:?}"); - log::info!("reliability debug_panic: first time, panic ..."); - panic!("first debug_panic."); - } - } + #[cfg(debug)] + self.debug.panic(); } /// do the debug action: sleep pub fn debug_sleep(&self) { - let sleep = Path::new(&self.dir_string).join(RELI_DEBUG_SLEEP_FILE); - if sleep.exists() { - log::info!("reliability debug: sleep..."); - thread::sleep(Duration::from_secs(3600)); - } + #[cfg(debug)] + self.debug.sleep(); } fn input_rebuild(&self) { @@ -365,31 +328,12 @@ impl Reliability { } } -/// do the debug action: enable or disable switch flag. effective after restart. -#[allow(dead_code)] -pub fn reli_debug_enable_switch(enable: bool) -> Result<()> { - log::info!("reliability debug: enable[{}] switch.", enable); - - let dir_string = base::reli_dir_get().unwrap(); - let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); - // touch switch.debug if enable - if enable && !switch.exists() { - do_entry_or_return_io_error!(File::create, switch, "create"); - } - // remove switch.debug if disable - if !enable && switch.exists() { - do_entry_or_return_io_error!(fs::remove_file, switch, "remove"); - } - - Ok(()) -} - /// get the debug flag of switch pub fn reli_debug_get_switch() -> bool { - let dir_string = base::reli_dir_get().expect("guaranteed by caller."); - let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); - log::info!("reliability debug: get switch file: {:?}.", switch); - switch.exists() + #[cfg(debug)] + return debug::switch(); + #[cfg(not(debug))] + return true; } fn reli_prepare() -> Result { diff --git a/core/libsysmaster/rel/base.rs b/core/libsysmaster/rel/base.rs index 65307e0..bcc8a21 100644 --- a/core/libsysmaster/rel/base.rs +++ b/core/libsysmaster/rel/base.rs @@ -20,10 +20,12 @@ use serde::de::DeserializeOwned; use serde::Serialize; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; +#[cfg(debug)] +use std::env; use std::fmt::Debug; +use std::fs; use std::hash::Hash; use std::path::Path; -use std::{env, fs}; /// the reliability database /// K & V that can be deserialized without borrowing any data from the deserializer. @@ -275,7 +277,21 @@ pub trait ReDbTable { const RELI_PATH_DIR: &str = "/run/sysmaster/reliability"; +/// get the directory for reliability. pub fn reli_dir_get() -> Result { + #[cfg(debug)] + return reli_dir_get_debug(); + #[cfg(not(debug))] + return reli_dir_get_release(); +} + +#[cfg(not(debug))] +fn reli_dir_get_release() -> Result { + return reli_dir_get_run(); +} + +#[cfg(debug)] +fn reli_dir_get_debug() -> Result { // /run/sysmaster/reliability/ let ret_run = reli_dir_get_run(); if ret_run.is_ok() { @@ -303,17 +319,26 @@ pub fn reli_dir_get() -> Result { /// prepare the directory for reliability. /// the reliability path is prepared and searched according to the following priority, from high to low: /// 1. /run/sysmaster/reliability/: the real running directory. -/// 2. OUT_DIR/../reliability/: make CI happy, which is target/debug/reliability/ or target/release/reliability/ usually. -/// 3. PROCESS_RELI_PATH: the path customized. +/// 2. [debug-only]OUT_DIR/../reliability/: make CI happy, which is target/debug/reliability/ or target/release/reliability/ usually. +/// 3. [debug-only]ROCESS_RELI_PATH: the path customized. pub fn reli_dir_prepare() -> Result<()> { // create '/run/sysmaster/reliability' or 'xxx/reliability' with mode 700 let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); - let ret = reli_dir_prepare_body(); + #[cfg(debug)] + let ret = reli_dir_prepare_debug(); + #[cfg(not(debug))] + let ret = reli_dir_prepare_release(); let _ = stat::umask(old_mask); ret } -fn reli_dir_prepare_body() -> Result<()> { +#[cfg(not(debug))] +fn reli_dir_prepare_release() -> Result<()> { + return reli_dir_prepare_run(); +} + +#[cfg(debug)] +fn reli_dir_prepare_debug() -> Result<()> { // // /run/sysmaster/reliability/ let ret_run = reli_dir_prepare_run(); if ret_run.is_ok() { @@ -373,6 +398,7 @@ fn reli_dir_get_run() -> Result { } } +#[cfg(debug)] fn reli_dir_prepare_out() -> Result<()> { let dir_string = out_dir_string_get(); if let Some(d_str) = dir_string { @@ -390,6 +416,7 @@ fn reli_dir_prepare_out() -> Result<()> { }) } +#[cfg(debug)] fn reli_dir_get_out() -> Result { let dir_string = out_dir_string_get(); if let Some(d_str) = dir_string { @@ -405,6 +432,7 @@ fn reli_dir_get_out() -> Result { }) } +#[cfg(debug)] fn reli_dir_prepare_customize() -> Result<()> { let dir_string = env::var("PROCESS_LIB_LOAD_PATH").ok(); if let Some(d_str) = dir_string { @@ -425,6 +453,7 @@ fn reli_dir_prepare_customize() -> Result<()> { }) } +#[cfg(debug)] fn reli_dir_get_customize() -> Result { let dir_string = env::var("PROCESS_LIB_LOAD_PATH").ok(); if let Some(d_str) = dir_string { @@ -443,6 +472,7 @@ fn reli_dir_get_customize() -> Result { }) } +#[cfg(debug)] fn out_dir_string_get() -> Option { let run = env::var("OUT_DIR").ok(); let compile: Option = option_env!("OUT_DIR").map(String::from); diff --git a/core/libsysmaster/rel/debug.rs b/core/libsysmaster/rel/debug.rs new file mode 100644 index 0000000..fff3463 --- /dev/null +++ b/core/libsysmaster/rel/debug.rs @@ -0,0 +1,106 @@ +use super::base::{self}; +use crate::error::*; +use basic::do_entry_or_return_io_error; +use std::fs::{self, File}; +use std::path::Path; +use std::thread; +use std::time::Duration; + +const RELI_DEBUG_SWITCH_FILE: &str = "switch.debug"; +const RELI_DEBUG_CLEAR_FILE: &str = "clear.debug"; +const RELI_DEBUG_CFIRST_FILE: &str = "clear_first.debug"; +const RELI_DEBUG_ENABLE_FILE: &str = "enable.debug"; +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"; + +#[derive(Debug)] +pub(crate) struct ReliDebug { + hdir: String, // home-directory +} + +impl ReliDebug { + pub(crate) fn new(dir_str: &str) -> ReliDebug { + ReliDebug { + hdir: String::from(dir_str), + } + } + + pub(crate) fn enable(&self) -> bool { + let enable = Path::new(&self.hdir).join(RELI_DEBUG_ENABLE_FILE); + enable.exists() + } + + pub(crate) fn clear(&self) -> bool { + let clear = Path::new(&self.hdir).join(RELI_DEBUG_CLEAR_FILE); + if clear.exists() { + let cfirst = Path::new(&self.hdir).join(RELI_DEBUG_CFIRST_FILE); + if cfirst.exists() { + // do nothing + log::info!("reliability debug_clear: non-first time, do nothing."); + false + } else { + File::create(&cfirst).unwrap(); + log::debug!("Successfully created {cfirst:?}"); + + // clear data + log::info!("reliability debug_clear: first time, clear ..."); + true + } + } else { + false + } + } + + pub(crate) fn panic(&self) { + let panic = Path::new(&self.hdir).join(RELI_DEBUG_PANIC_FILE); + if panic.exists() { + let pfirst = Path::new(&self.hdir).join(RELI_DEBUG_PFIRST_FILE); + if pfirst.exists() { + // do nothing + log::info!("reliability debug_panic: non-first time, do nothing."); + } else { + File::create(&pfirst).unwrap(); + log::debug!("Successfully created {pfirst:?}"); + + // panic + log::info!("reliability debug_panic: first time, panic ..."); + panic!("first debug_panic."); + } + } + } + + pub(crate) fn sleep(&self) { + let sleep = Path::new(&self.hdir).join(RELI_DEBUG_SLEEP_FILE); + if sleep.exists() { + log::info!("reliability debug: sleep..."); + thread::sleep(Duration::from_secs(3600)); + } + } +} + +#[allow(dead_code)] +pub(crate) fn enable_switch(enable: bool) -> Result<()> { + // do the debug action: enable or disable switch flag. effective after restart. + log::info!("reliability debug: enable[{}] switch.", enable); + + let dir_string = base::reli_dir_get().unwrap(); + let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); + // touch switch.debug if enable + if enable && !switch.exists() { + do_entry_or_return_io_error!(File::create, switch, "create"); + } + // remove switch.debug if disable + if !enable && switch.exists() { + do_entry_or_return_io_error!(fs::remove_file, switch, "remove"); + } + + Ok(()) +} + +pub(crate) fn switch() -> bool { + let dir_string = base::reli_dir_get().expect("guaranteed by caller."); + let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); + log::info!("reliability debug: get switch file: {:?}.", switch); + switch.exists() +} diff --git a/core/libsysmaster/rel/mod.rs b/core/libsysmaster/rel/mod.rs index 07470e4..2ae515a 100644 --- a/core/libsysmaster/rel/mod.rs +++ b/core/libsysmaster/rel/mod.rs @@ -11,15 +11,17 @@ // See the Mulan PSL v2 for more details. //! reliability module -pub use api::{reli_debug_enable_switch, reli_debug_get_switch, ReliConf, Reliability}; +pub use api::{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}; use std::convert::TryFrom; -// dependency: base -> {enable | last | history | pending | station} -> api +// dependency: base -> {enable | last | history | pending | station} -> debug -> api mod api; mod base; +#[cfg(debug)] +mod debug; mod enable; mod history; mod last; -- 2.33.0