use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::OnceLock;
use std::time::Duration;
const PROBE_ENV: &str = "CQLITE_PARTITION_ACCESS_PROBE";
const WINDOW_SECS_ENV: &str = "CQLITE_PARTITION_ACCESS_WINDOW_SECS";
const WINDOW_ACCESSES_ENV: &str = "CQLITE_PARTITION_ACCESS_WINDOW_ACCESSES";
static EFFECTIVE: AtomicU8 = AtomicU8::new(0);
const STATE_UNRESOLVED: u8 = 0;
const STATE_ON: u8 = 1;
const STATE_OFF: u8 = 2;
pub fn parse_probe_flag(raw: &str) -> Option<bool> {
match raw.trim().to_ascii_lowercase().as_str() {
"1" | "true" | "on" | "yes" | "enabled" => Some(true),
"0" | "false" | "off" | "no" | "disabled" | "" => Some(false),
_ => None,
}
}
fn cached_env() -> Option<&'static str> {
static ENV: OnceLock<Option<String>> = OnceLock::new();
ENV.get_or_init(|| std::env::var(PROBE_ENV).ok()).as_deref()
}
fn resolve_from_env() -> bool {
match cached_env() {
None => false,
Some(raw) => match parse_probe_flag(raw) {
Some(v) => v,
None => {
tracing::error!(
value = raw,
"unrecognised {PROBE_ENV} value — the partition access-distribution \
probe stays OFF; accepted values are 1/true/on/yes/enabled and \
0/false/off/no/disabled"
);
false
}
},
}
}
#[inline]
pub fn enabled() -> bool {
match EFFECTIVE.load(Ordering::Relaxed) {
STATE_ON => true,
STATE_OFF => false,
_ => {
let resolved = if resolve_from_env() {
STATE_ON
} else {
STATE_OFF
};
match EFFECTIVE.compare_exchange(
STATE_UNRESOLVED,
resolved,
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_) => resolved == STATE_ON,
Err(STATE_ON) => true,
Err(STATE_OFF) => false,
Err(_) => resolved == STATE_ON,
}
}
}
}
pub fn set_probe_enabled(state: Option<bool>) {
let v = match state {
Some(true) => STATE_ON,
Some(false) => STATE_OFF,
None => STATE_UNRESOLVED,
};
EFFECTIVE.store(v, Ordering::Relaxed);
}
pub const DEFAULT_MAX_PREFIX_BITS: u32 = 20;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WindowConfig {
pub duration: Duration,
pub max_accesses: u64,
pub max_prefix_bits: u32,
}
impl Default for WindowConfig {
fn default() -> Self {
Self {
duration: Duration::from_secs(60),
max_accesses: 5_000_000,
max_prefix_bits: DEFAULT_MAX_PREFIX_BITS,
}
}
}
pub fn window_config_from_env() -> WindowConfig {
let mut config = WindowConfig::default();
if let Ok(raw) = std::env::var(WINDOW_SECS_ENV) {
match raw.trim().parse::<u64>() {
Ok(secs) if secs > 0 => config.duration = Duration::from_secs(secs),
_ => tracing::error!(
value = raw,
"unrecognised {WINDOW_SECS_ENV} value — keeping the default window length; expected a positive whole number of seconds"
),
}
}
if let Ok(raw) = std::env::var(WINDOW_ACCESSES_ENV) {
match raw.trim().parse::<u64>() {
Ok(n) if n > 0 => config.max_accesses = n,
_ => tracing::error!(
value = raw,
"unrecognised {WINDOW_ACCESSES_ENV} value — keeping the default access bound; expected a positive whole number"
),
}
}
config
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex, MutexGuard};
static GATE: Mutex<()> = Mutex::new(());
struct GateGuard(#[allow(dead_code)] MutexGuard<'static, ()>);
impl GateGuard {
fn acquire() -> Self {
Self(GATE.lock().unwrap_or_else(|poisoned| poisoned.into_inner()))
}
}
impl Drop for GateGuard {
fn drop(&mut self) {
set_probe_enabled(None);
}
}
#[test]
fn a_programmatic_enable_wins_against_a_concurrent_env_resolution() {
let _gate = GateGuard::acquire();
for _ in 0..200 {
set_probe_enabled(None);
let barrier = Arc::new(Barrier::new(2));
let resolved = Arc::new(AtomicBool::new(false));
let reader = {
let barrier = Arc::clone(&barrier);
let resolved = Arc::clone(&resolved);
std::thread::spawn(move || {
barrier.wait();
resolved.store(enabled(), Ordering::Relaxed);
})
};
let writer = {
let barrier = Arc::clone(&barrier);
std::thread::spawn(move || {
barrier.wait();
set_probe_enabled(Some(true));
})
};
reader.join().expect("reader thread");
writer.join().expect("writer thread");
assert!(
enabled(),
"an explicit programmatic enable must outrank a concurrent env \
resolution; the probe read back as OFF"
);
}
}
#[test]
fn a_programmatic_setting_survives_repeated_reads() {
let _gate = GateGuard::acquire();
set_probe_enabled(Some(true));
for _ in 0..1_000 {
assert!(enabled(), "a resolution must never clobber a pinned state");
}
set_probe_enabled(Some(false));
for _ in 0..1_000 {
assert!(!enabled());
}
}
}