From d36bb9fa9a0322f475f6039948bba6ea8e106d74 Mon Sep 17 00:00:00 2001
From: xuxiaozhou1 <xuxiaozhou1@huawei.com>
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<String> {
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<String> {
+    #[cfg(debug)]
+    return reli_dir_get_debug();
+    #[cfg(not(debug))]
+    return reli_dir_get_release();
+}
+
+#[cfg(not(debug))]
+fn reli_dir_get_release() -> Result<String> {
+    return reli_dir_get_run();
+}
+
+#[cfg(debug)]
+fn reli_dir_get_debug() -> Result<String> {
     // /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<String> {
 /// 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<String> {
     }
 }
 
+#[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<String> {
     let dir_string = out_dir_string_get();
     if let Some(d_str) = dir_string {
@@ -405,6 +432,7 @@ fn reli_dir_get_out() -> Result<String> {
     })
 }
 
+#[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<String> {
     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<String> {
     })
 }
 
+#[cfg(debug)]
 fn out_dir_string_get() -> Option<String> {
     let run = env::var("OUT_DIR").ok();
     let compile: Option<String> = 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

