Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Reduce overhead when FAILPOINTS is empty #71

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ use std::collections::HashMap;
use std::env::VarError;
use std::fmt::Debug;
use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, TryLockError};
use std::time::{Duration, Instant};
use std::{env, thread};
Expand Down Expand Up @@ -528,6 +528,9 @@ use once_cell::sync::Lazy;
static REGISTRY: Lazy<FailPointRegistry> = Lazy::new(FailPointRegistry::default);
static SCENARIO: Lazy<Mutex<&'static FailPointRegistry>> = Lazy::new(|| Mutex::new(&REGISTRY));

#[doc(hidden)]
pub static REGISTRY_IS_EMPTY: AtomicBool = AtomicBool::new(true);

/// Test scenario with configured fail points.
#[derive(Debug)]
pub struct FailScenario<'a> {
Expand Down Expand Up @@ -580,6 +583,7 @@ impl<'a> FailScenario<'a> {
}
}
}
update_registry_is_empty(&registry);
Self { scenario_guard }
}

Expand All @@ -601,6 +605,7 @@ impl<'a> FailScenario<'a> {
p.set_actions("", vec![]);
}
registry.clear();
update_registry_is_empty(registry);
}
}

Expand Down Expand Up @@ -675,7 +680,9 @@ pub fn eval<R, F: FnOnce(Option<String>) -> R>(name: &str, f: F) -> Option<R> {
/// that fail point, including those set via the `FAILPOINTS` environment variable.
pub fn cfg<S: Into<String>>(name: S, actions: &str) -> Result<(), String> {
let mut registry = REGISTRY.registry.write().unwrap();
set(&mut registry, name.into(), actions)
set(&mut registry, name.into(), actions)?;
update_registry_is_empty(&registry);
Ok(())
}

/// Configure the actions for a fail point at runtime.
Expand All @@ -694,6 +701,7 @@ where
let action = Action::from_callback(f);
let actions = vec![action];
p.set_actions("callback", actions);
update_registry_is_empty(&registry);
Ok(())
}

Expand Down Expand Up @@ -762,6 +770,10 @@ fn set(
Ok(())
}

fn update_registry_is_empty(registry: &HashMap<String, Arc<FailPoint>>) {
REGISTRY_IS_EMPTY.store(registry.is_empty(), Ordering::Release);
}

/// Define a fail point (requires `failpoints` feature).
///
/// The `fail_point!` macro has three forms, and they all take a name as the
Expand Down Expand Up @@ -827,13 +839,17 @@ fn set(
#[cfg(feature = "failpoints")]
macro_rules! fail_point {
($name:expr) => {{
$crate::eval($name, |_| {
panic!("Return is not supported for the fail point \"{}\"", $name);
});
if !$crate::REGISTRY_IS_EMPTY.load(::std::sync::atomic::Ordering::Acquire) {
$crate::eval($name, |_| {
panic!("Return is not supported for the fail point \"{}\"", $name);
});
}
}};
($name:expr, $e:expr) => {{
if let Some(res) = $crate::eval($name, $e) {
return res;
if !$crate::REGISTRY_IS_EMPTY.load(::std::sync::atomic::Ordering::Acquire) {
if let Some(res) = $crate::eval($name, $e) {
return res;
}
}
}};
($name:expr, $cond:expr, $e:expr) => {{
Expand Down