liboj_cgroups/subsystem/
freezer.rs

1use std::fs;
2use std::io;
3use std::path::Path;
4use std::str::FromStr;
5
6use super::Controller;
7use crate::{
8    attr_file::{AttrFile, ReadAttr, WriteAttr},
9    hierarchy::HierarchyNode,
10};
11
12#[derive(PartialEq, Eq, Debug)]
13pub enum State {
14    Thawed,
15    Freezing,
16    Frozen,
17}
18
19impl FromStr for State {
20    type Err = io::Error;
21
22    fn from_str(s: &str) -> io::Result<State> {
23        match s {
24            "THAWED" => Ok(State::Thawed),
25            "FREEZING" => Ok(State::Freezing),
26            "FROZEN" => Ok(State::Frozen),
27            _ => Err(io::Error::new(
28                io::ErrorKind::InvalidData,
29                format!("failed to parse cgroup freezer state \"{}\"", s),
30            )),
31        }
32    }
33}
34
35pub trait FreezerController: Controller {
36    fn state(&self) -> Box<dyn '_ + AttrFile<State>>;
37    fn self_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>>;
38    fn parent_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>>;
39}
40
41impl FreezerController for HierarchyNode {
42    fn state(&self) -> Box<dyn '_ + AttrFile<State>> {
43        let file = self.as_path().join("freezer.state");
44        Box::new(StateFile(file))
45    }
46
47    fn self_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>> {
48        let file = self.as_path().join("freezer.self_freezing");
49        Box::new(FreezingFile(file))
50    }
51
52    fn parent_freezing(&self) -> Box<dyn '_ + ReadAttr<bool>> {
53        let file = self.as_path().join("freezer.parent_freezing");
54        Box::new(FreezingFile(file))
55    }
56}
57
58struct StateFile<P: AsRef<Path>>(P);
59
60impl<P: AsRef<Path>> ReadAttr<State> for StateFile<P> {
61    fn read(&self) -> io::Result<State> {
62        let s = fs::read_to_string(&self.0)?;
63        Ok(s.trim().parse()?)
64    }
65}
66
67impl<P: AsRef<Path>> WriteAttr<State> for StateFile<P> {
68    fn write(&self, state: &State) -> io::Result<()> {
69        let file = self.0.as_ref();
70        match state {
71            State::Thawed => fs::write(&file, "THAWED"),
72            State::Frozen => fs::write(&file, "FROZEN"),
73            State::Freezing => Err(io::Error::new(
74                io::ErrorKind::InvalidData,
75                format!("can not write FREEZING state to {}", file.display()),
76            )),
77        }
78    }
79}
80
81struct FreezingFile<P: AsRef<Path>>(P);
82
83impl<P: AsRef<Path>> ReadAttr<bool> for FreezingFile<P> {
84    fn read(&self) -> io::Result<bool> {
85        let file = self.0.as_ref();
86        let s = fs::read_to_string(&file)?;
87        match s.trim() {
88            "0" => Ok(false),
89            "1" => Ok(true),
90            _ => Err(io::Error::new(
91                io::ErrorKind::InvalidData,
92                format!("failed to parse freezing state from {}", file.display()),
93            )),
94        }
95    }
96}