use std::fs;
use std::io;
use std::path::Path;
use std::str::FromStr;
use super::Controller;
use crate::{
attr_file::{AttrFile, ReadAttr, WriteAttr},
hierarchy::HierarchyNode,
};
#[derive(PartialEq, Eq, Debug)]
pub enum State {
Thawed,
Freezing,
Frozen,
}
impl FromStr for State {
type Err = io::Error;
fn from_str(s: &str) -> io::Result<State> {
match s {
"THAWED" => Ok(State::Thawed),
"FREEZING" => Ok(State::Freezing),
"FROZEN" => Ok(State::Frozen),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("failed to parse cgroup freezer state \"{}\"", s),
)),
}
}
}
pub trait FreezerController: Controller {
fn state(&self) -> Box<dyn '_ + AttrFile<State>>;
fn self_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>>;
fn parent_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>>;
}
impl FreezerController for HierarchyNode {
fn state(&self) -> Box<dyn '_ + AttrFile<State>> {
let file = self.as_path().join("freezer.state");
Box::new(StateFile(file))
}
fn self_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>> {
let file = self.as_path().join("freezer.self_freezing");
Box::new(FreezingFile(file))
}
fn parent_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>> {
let file = self.as_path().join("freezer.parent_freezing");
Box::new(FreezingFile(file))
}
}
struct StateFile<P: AsRef<Path>>(P);
impl<P: AsRef<Path>> ReadAttr<State> for StateFile<P> {
fn read(&self) -> io::Result<State> {
let s = fs::read_to_string(&self.0)?;
Ok(s.trim().parse()?)
}
}
impl<P: AsRef<Path>> WriteAttr<State> for StateFile<P> {
fn write(&self, state: &State) -> io::Result<()> {
let file = self.0.as_ref();
match state {
State::Thawed => fs::write(&file, "THAWED"),
State::Frozen => fs::write(&file, "FROZEN"),
State::Freezing => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("can not write FREEZING state to {}", file.display()),
)),
}
}
}
struct FreezingFile<P: AsRef<Path>>(P);
impl<P: AsRef<Path>> ReadAttr<bool> for FreezingFile<P> {
fn read(&self) -> io::Result<bool> {
let file = self.0.as_ref();
let s = fs::read_to_string(&file)?;
match s.trim() {
"0" => Ok(false),
"1" => Ok(true),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("failed to parse freezing state from {}", file.display()),
)),
}
}
}