use crate::{is_realtime, Result};
use core::fmt;
use std::convert::Infallible;
use std::str::FromStr;
#[allow(clippy::module_name_repetitions)]
#[derive(Default)]
pub struct SystemConfig(rtsc::system::linux::SystemConfig);
impl SystemConfig {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn set<V: fmt::Display>(mut self, key: &'static str, value: V) -> Self {
if is_realtime() {
self.0 = self.0.set(key, value);
}
self
}
pub fn apply(self) -> Result<rtsc::system::linux::SystemConfigGuard> {
if is_realtime() {
return self.0.apply().map_err(Into::into);
}
Ok(rtsc::system::linux::SystemConfigGuard::default())
}
}
pub struct CpuGovernor(#[allow(dead_code)] rtsc::system::linux::CpuGovernor);
impl CpuGovernor {
pub fn performance<I>(performance_cpus: I) -> Result<CpuGovernor>
where
I: IntoIterator<Item = usize>,
{
if is_realtime() {
let inner = rtsc::system::linux::CpuGovernor::performance(performance_cpus)?;
Ok(Self(inner))
} else {
Ok(Self(rtsc::system::linux::CpuGovernor::default()))
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum StateVariant {
Initializing,
Starting,
Running,
Degraded,
Maintenance,
Stopping,
Other,
}
impl fmt::Display for StateVariant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
StateVariant::Initializing => write!(f, "initializing"),
StateVariant::Starting => write!(f, "starting"),
StateVariant::Running => write!(f, "running"),
StateVariant::Degraded => write!(f, "degraded"),
StateVariant::Maintenance => write!(f, "maintenance"),
StateVariant::Stopping => write!(f, "stopping"),
StateVariant::Other => write!(f, "other"),
}
}
}
impl FromStr for StateVariant {
type Err = Infallible;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(match s {
"initializing" => StateVariant::Initializing,
"starting" => StateVariant::Starting,
"running" => StateVariant::Running,
"degraded" => StateVariant::Degraded,
"maintenance" => StateVariant::Maintenance,
"stopping" => StateVariant::Stopping,
_ => StateVariant::Other,
})
}
}
pub fn state() -> Result<StateVariant> {
std::process::Command::new("systemctl")
.arg("is-system-running")
.output()
.map_err(Into::into)
.and_then(|output| {
let state = std::str::from_utf8(&output.stdout).unwrap_or_default();
state.trim().parse().map_err(Into::into)
})
}
pub fn wait_running_state() -> Result<()> {
loop {
if state()? == StateVariant::Running {
break;
}
std::thread::sleep(std::time::Duration::from_millis(500));
}
Ok(())
}