1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use crate::error::ProcError;
use crate::scanner::ProcScanner;
use crate::stat::Cpu;
use crate::stat::Stat;
use crate::ProcResult;
use cfg_iif::cfg_iif;
#[derive(Debug, Default, Clone)]
pub(crate) struct StatParser {
cpus_cap: usize,
}
impl StatParser {
pub fn parse(&mut self, sl: &[u8]) -> ProcResult<Stat> {
let mut stat = if self.cpus_cap > 0 {
Stat::with_capacity(self.cpus_cap)
} else {
Stat::default()
};
if sl.is_empty() {
return Ok(stat);
}
//
let mut sc = ProcScanner::new(sl);
//
// cpu
sc.find_and_jump(b"cpu ")?;
stat.cpu.name = "cpu".to_string();
//
{
// content of /proc/stat
// "cpu 15170491 3654501 2781868 219713999 930079 0 101596 0 0 0\n"
// on linux:
// "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n"
stat.cpu.user = sc.next(b' ')?;
stat.cpu.nice = sc.next(b' ')?;
stat.cpu.system = sc.next(b' ')?;
stat.cpu.idle = sc.next(b' ')?;
//
stat.cpu.iowait = sc.next(b' ')?;
stat.cpu.irq = sc.next(b' ')?;
stat.cpu.softirq = sc.next(b' ')?;
if !sc.check(b' ') {
stat.cpu.steal = sc.next(b'\n')?;
// up to here, on linux v2.6.18
} else {
stat.cpu.steal = sc.next(b' ')?;
//
stat.cpu.guest = sc.next(b' ')?;
if !sc.check(b' ') {
stat.cpu.guest_nice = sc.next(b'\n')?;
// up to here, on linux vx.x.x
} else {
stat.cpu.guest_nice = sc.next(b' ')?;
if !sc.check(b' ') {
cfg_iif!(feature = "has_stat_cguest" {
stat.cpu.cguest = sc.next(b'\n')?;
} else {
sc.scan_until(b'\n')?;
});
} else {
sc.scan_until(b'\n')?;
}
}
}
}
// cpu0, cpu1, cpu2 ... cpuN
while sc.find_and_jump_opt(b"cpu") {
// content of /proc/stat
// "cpu0 4291443 513175 595878 55021783 194990 0 6946 0 0 0\n"
// on linux:
// "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu\n"
//
let idx: usize = sc.next(b' ')?;
if idx >= stat.cpus.len() {
stat.cpus.resize(idx + 1, Cpu::default());
}
let cpu_ref: &mut Cpu = stat
.cpus
.get_mut(idx)
.ok_or_else(|| ProcError::UnexpectedFormat("Failed to get CPU mut ref".into()))?;
//
cpu_ref.name = format!("cpu{idx}");
//
cpu_ref.user = sc.next(b' ')?;
cpu_ref.nice = sc.next(b' ')?;
cpu_ref.system = sc.next(b' ')?;
cpu_ref.idle = sc.next(b' ')?;
//
cpu_ref.iowait = sc.next(b' ')?;
cpu_ref.irq = sc.next(b' ')?;
cpu_ref.softirq = sc.next(b' ')?;
if !sc.check(b' ') {
cpu_ref.steal = sc.next(b'\n')?;
// up to here, on linux v2.6.18
} else {
cpu_ref.steal = sc.next(b' ')?;
//
cpu_ref.guest = sc.next(b' ')?;
if !sc.check(b' ') {
cpu_ref.guest_nice = sc.next(b'\n')?;
} else {
cpu_ref.guest_nice = sc.next(b' ')?;
cfg_iif!(feature = "has_stat_cguest" {
cpu_ref.cguest = sc.next(b'\n')?;
} else {
sc.scan_until(b'\n')?;
});
}
}
}
//
// intr: nothing todo
//
//
// content of /proc/stat
// "ctxt 1175115190\n"
// on linux:
// "ctxt %llu\n"
if sc.find_and_jump_opt(b"ctxt ") {
stat.ctxt = sc.next(b'\n')?;
}
//
cfg_iif!(feature = "has_stat_btime" {
if sc.find_and_jump_opt(b"btime ") {
stat.btime = sc.next(b'\n')?;
}
});
//
if sc.find_and_jump_opt(b"processes ") {
stat.processes = sc.next(b'\n')?;
}
//
cfg_iif!(feature = "has_stat_procs_running" {
if sc.find_and_jump_opt(b"procs_running ") {
stat.procs_running = sc.next(b'\n')?;
}
});
//
cfg_iif!(feature = "has_stat_procs_blocked" {
if sc.find_and_jump_opt(b"procs_blocked ") {
stat.procs_blocked = sc.next(b'\n')?;
}
});
//
// optimize the capacity size of the vector
stat.cpus.shrink_to_fit();
self.cpus_cap = stat.cpus.len();
//
Ok(stat)
}
}