use std::sync::OnceLock;
use crate::directories::OwnedBytes;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PinMode {
Mlock,
Copy,
}
#[derive(Debug, Clone, Copy)]
pub struct PinPolicy {
pub budget_bytes: u64,
pub mode: PinMode,
}
impl PinPolicy {
pub const fn disabled() -> Self {
Self {
budget_bytes: 0,
mode: PinMode::Mlock,
}
}
pub fn is_enabled(&self) -> bool {
self.budget_bytes > 0
}
fn from_env() -> Self {
let budget_mb: u64 = std::env::var("HERMES_PIN_METADATA_BUDGET_MB")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(0);
let mode = match std::env::var("HERMES_PIN_MODE").as_deref() {
Ok("copy") => PinMode::Copy,
Ok("mlock") | Err(_) => PinMode::Mlock,
Ok(other) => {
log::warn!("HERMES_PIN_MODE '{}' unknown; using mlock", other);
PinMode::Mlock
}
};
Self {
budget_bytes: budget_mb * 1024 * 1024,
mode,
}
}
}
static PIN_POLICY: OnceLock<PinPolicy> = OnceLock::new();
pub fn set_pin_policy(policy: PinPolicy) -> bool {
let ok = PIN_POLICY.set(policy).is_ok();
if !ok {
log::warn!("pin policy already initialized; set_pin_policy ignored");
}
ok
}
pub fn pin_policy() -> &'static PinPolicy {
PIN_POLICY.get_or_init(PinPolicy::from_env)
}
#[derive(Debug, Default, Clone, Copy)]
pub struct PinReport {
pub intended_bytes: u64,
pub pinned_bytes: u64,
pub skipped_budget_bytes: u64,
pub failed_bytes: u64,
}
pub(crate) fn pin_section(
bytes: &mut OwnedBytes,
label: &str,
mode: PinMode,
remaining: &mut u64,
report: &mut PinReport,
) {
if !bytes.is_mmap() || bytes.is_empty() {
return;
}
let len = bytes.len() as u64;
report.intended_bytes += len;
if len > *remaining {
report.skipped_budget_bytes += len;
log::debug!(
"[pin] budget exhausted: skipping {} ({} bytes, {} remaining)",
label,
len,
*remaining
);
return;
}
match mode {
PinMode::Mlock => {
if bytes.mlock() {
*remaining -= len;
report.pinned_bytes += len;
} else {
report.failed_bytes += len;
log::warn!(
"[pin] mlock failed for {} ({} bytes) — check RLIMIT_MEMLOCK; \
continuing unpinned",
label,
len
);
}
}
PinMode::Copy => {
*bytes = OwnedBytes::new(bytes.to_vec());
*remaining -= len;
report.pinned_bytes += len;
}
}
}