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
use crate::sensors::Sensor;
use crate::sensors::Topology;
use procfs::{modules, KernelModule};
use regex::Regex;
use std::collections::HashMap;
use std::error::Error;
use std::{env, fs};
pub struct PowercapRAPLSensor {
base_path: String,
buffer_per_socket_max_kbytes: u16,
buffer_per_domain_max_kbytes: u16,
virtual_machine: bool,
}
impl PowercapRAPLSensor {
pub fn new(
buffer_per_socket_max_kbytes: u16,
buffer_per_domain_max_kbytes: u16,
virtual_machine: bool,
) -> PowercapRAPLSensor {
let mut powercap_path = String::from("/sys/class/powercap");
if virtual_machine {
powercap_path = String::from("/var/scaphandre");
if let Ok(val) = env::var("SCAPHANDRE_POWERCAP_PATH") {
powercap_path = val;
}
warn!("Powercap_rapl path is: {}", powercap_path);
}
PowercapRAPLSensor {
base_path: powercap_path,
buffer_per_socket_max_kbytes,
buffer_per_domain_max_kbytes,
virtual_machine,
}
}
pub fn check_module() -> Result<String, String> {
let modules = modules().unwrap();
let rapl_modules = modules
.iter()
.filter(|(_, v)| {
v.name == "intel_rapl"
|| v.name == "intel_rapl_msr"
|| v.name == "intel_rapl_common"
})
.collect::<HashMap<&String, &KernelModule>>();
if !rapl_modules.is_empty() {
Ok(String::from(
"intel_rapl or intel_rapl_msr+intel_rapl_common modules found.",
))
} else {
Err(String::from(
"None of intel_rapl, intel_rapl_common or intel_rapl_msr kernel modules found.",
))
}
}
}
impl Sensor for PowercapRAPLSensor {
fn generate_topology(&self) -> Result<Topology, Box<dyn Error>> {
let modules_state = PowercapRAPLSensor::check_module();
if modules_state.is_err() && !self.virtual_machine {
panic!("Couldn't find intel_rapl modules.");
}
let mut topo = Topology::new();
let re_domain = Regex::new(r"^.*/intel-rapl:\d+:\d+$").unwrap();
for folder in fs::read_dir(&self.base_path).unwrap() {
let folder_name = String::from(folder.unwrap().path().to_str().unwrap());
if re_domain.is_match(&folder_name) {
let mut splitted = folder_name.split(':');
let _ = splitted.next();
let socket_id = String::from(splitted.next().unwrap()).parse().unwrap();
let domain_id = String::from(splitted.next().unwrap()).parse().unwrap();
topo.safe_add_socket(
socket_id,
vec![],
vec![],
format!("{}/intel-rapl:{}/energy_uj", self.base_path, socket_id),
self.buffer_per_socket_max_kbytes,
);
if let Ok(domain_name) = &fs::read_to_string(format!("{}/name", folder_name)) {
topo.safe_add_domain_to_socket(
socket_id,
domain_id,
domain_name,
&format!(
"{}/intel-rapl:{}:{}/energy_uj",
self.base_path, socket_id, domain_id
),
self.buffer_per_domain_max_kbytes,
);
}
}
}
topo.add_cpu_cores();
Ok(topo)
}
fn get_topology(&mut self) -> Box<Option<Topology>> {
let topology = self.generate_topology().ok();
if topology.is_none() {
panic!("Couldn't generate the topology !");
}
Box::new(topology)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::any::type_name;
fn type_of<T>(_: T) -> &'static str {
type_name::<T>()
}
#[test]
fn get_topology_returns_topology_type() {
let mut sensor = PowercapRAPLSensor::new(1, 1, false);
let topology = sensor.get_topology();
assert_eq!(
"alloc::boxed::Box<core::option::Option<&scaphandre::sensors::Topology>>",
type_of(topology)
)
}
}