use std::{fs::OpenOptions, io::{self, Read, Seek, SeekFrom, Write}};
#[derive(Debug)]
pub struct ConstraintHandle {
rapl_root_path: String,
id: u8,
}
#[derive(Debug)]
pub struct Constraint {
handle: ConstraintHandle,
pub name: Option<String>,
pub power_limit_uw: u64,
pub time_window_us: u64,
pub min_power_uw: Option<u64>,
pub max_power_uw: Option<u64>,
pub min_time_window_us: Option<u64>,
pub max_time_window_us: Option<u64>,
}
impl Constraint {
pub fn new(rapl_root: &str, id: u8) -> Option<Self> {
let handle = ConstraintHandle::new(rapl_root, id);
Some(Self {
power_limit_uw: handle.read("power_limit_uw")?,
time_window_us: handle.read("time_window_us")?,
name: handle.read("name"),
min_power_uw: handle.read("min_power_uw"),
max_power_uw: handle.read("max_power_uw"),
min_time_window_us: handle.read("min_time_window_us"),
max_time_window_us: handle.read("max_time_window_us"),
handle,
})
}
pub fn set_power_limit_uw(&mut self, value: u64) -> Result<(), io::Error> {
self.handle.write("power_limit_uw", value)
}
pub fn reset_power_limit(&mut self, default: Option<u64>) -> Result<(), io::Error> {
if let Some(max_power_uw) = self.max_power_uw {
self.set_power_limit_uw(max_power_uw)
} else if let Some(default) = default {
self.set_power_limit_uw(default)
} else {
let e = self.handle.path("power_limit_uw");
Err(io::Error::new(io::ErrorKind::NotFound, e))
}
}
pub fn set_time_window_us(&mut self, value: u64) -> Result<(), io::Error> {
self.handle.write("time_window_us", value)
}
pub fn reset_time_window(&mut self, default: Option<u64>) -> Result<(), io::Error> {
if let Some(max_time_window_us) = self.max_time_window_us {
self.set_time_window_us(max_time_window_us)
} else if let Some(default) = default {
self.set_time_window_us(default)
} else {
let e = self.handle.path("time_window_us");
Err(io::Error::new(io::ErrorKind::NotFound, e))
}
}
}
impl ConstraintHandle {
fn new(rapl_root_path: &str, id: u8) -> Self {
Self { rapl_root_path: rapl_root_path.to_string(), id }
}
fn path(&self, field: &str) -> String {
format!("{}/constraint_{}_{}", self.rapl_root_path, self.id, field)
}
fn read<T: Default + std::str::FromStr>(&self, field: &str) -> Option<T> where T::Err: std::fmt::Debug {
let path = self.path(field);
let mut file = OpenOptions::new().read(true).open(&path).ok()?;
let mut buf = String::new();
if file.read_to_string(&mut buf).is_err() {
return Some(T::default())
}
let buf = buf.trim();
Some(buf.parse::<T>().expect(&format!("Could not parse {}", buf)))
}
fn write(&self, field: &str, value: u64) -> Result<(), io::Error> {
let path = self.path(field);
let mut file = OpenOptions::new().read(true).write(true).open(path)?;
file.seek(SeekFrom::Start(0))?;
write!(file, "{}", value)
}
}