liboj_cgroups/subsystem/
pids.rs1use 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}