Skip to main content

liboj_cgroups/subsystem/
pids.rs

1use std::fs;
2use std::io;
3use std::path::Path;
4
5use lazy_static::lazy_static;
6use regex::Regex;
7
8use super::Controller;
9use crate::{
10    attr_file::{AttrFile, ReadAttr, WriteAttr},
11    hierarchy::HierarchyNode,
12};
13
14pub trait PidsController: Controller {
15    fn current(&self) -> Box<dyn '_ + ReadAttr<usize>>;
16    fn max(&self) -> Box<dyn '_ + AttrFile<Option<usize>>>;
17    fn events(&self) -> Box<dyn '_ + ReadAttr<usize>>;
18}
19
20impl PidsController for HierarchyNode {
21    fn current(&self) -> Box<dyn '_ + ReadAttr<usize>> {
22        let file = self.as_path().join("pids.current");
23        Box::new(CurrentFile(file))
24    }
25
26    fn max(&self) -> Box<dyn '_ + AttrFile<Option<usize>>> {
27        let file = self.as_path().join("pids.max");
28        Box::new(MaxFile(file))
29    }
30
31    fn events(&self) -> Box<dyn '_ + ReadAttr<usize>> {
32        let file = self.as_path().join("pids.events");
33        Box::new(EventFile(file))
34    }
35}
36
37struct CurrentFile<P: AsRef<Path>>(P);
38
39impl<P: AsRef<Path>> ReadAttr<usize> for CurrentFile<P> {
40    fn read(&self) -> io::Result<usize> {
41        let file = self.0.as_ref();
42        let s = fs::read_to_string(&file)?;
43        match s.trim().parse() {
44            Ok(number) => Ok(number),
45            Err(_) => Err(io::Error::new(
46                io::ErrorKind::InvalidData,
47                format!("failed to parse number of pids from {}", file.display()),
48            )),
49        }
50    }
51}
52
53struct MaxFile<P: AsRef<Path>>(P);
54
55impl<P: AsRef<Path>> ReadAttr<Option<usize>> for MaxFile<P> {
56    fn read(&self) -> io::Result<Option<usize>> {
57        lazy_static! {
58            static ref RE: Regex = Regex::new(r"^(max|\d+)$").unwrap();
59        }
60        let file = self.0.as_ref();
61        let s = fs::read_to_string(&file)?;
62        match RE.captures(&s.trim()) {
63            Some(cap) => match &cap[1] {
64                "max" => Ok(None),
65                number => Ok(Some(number.parse().unwrap())),
66            },
67            None => Err(io::Error::new(
68                io::ErrorKind::InvalidData,
69                format!("failed to read max pids limit from {}", file.display()),
70            )),
71        }
72    }
73}
74
75impl<P: AsRef<Path>> WriteAttr<Option<usize>> for MaxFile<P> {
76    fn write(&self, max: &Option<usize>) -> io::Result<()> {
77        match max {
78            Some(max) => fs::write(&self.0, format!("{}", max)),
79            None => fs::write(&self.0, b"max"),
80        }
81    }
82}
83
84struct EventFile<P: AsRef<Path>>(P);
85
86impl<P: AsRef<Path>> ReadAttr<usize> for EventFile<P> {
87    fn read(&self) -> io::Result<usize> {
88        lazy_static! {
89            static ref RE: Regex = Regex::new(r"^max (\d+)$").unwrap();
90        }
91        let file = self.0.as_ref();
92        let s = fs::read_to_string(&file)?;
93        match RE.captures(&s.trim()) {
94            Some(cap) => Ok(cap[1].parse().unwrap()),
95            None => Err(io::Error::new(
96                io::ErrorKind::InvalidData,
97                format!("failed to read pids event from {}", file.display()),
98            )),
99        }
100    }
101}