Speed up procfs scanning
[bustd.git] / src / memory / mem_info.rs
blob5a6a33cbc1dc6f49dd4cc078ba03ba6c72994e52
1 use std::{fmt, mem};
3 use libc::sysinfo;
5 use crate::{
6     checked_ffi,
7     error::{Error, Result},
8     utils::bytes_to_megabytes,
9 };
11 #[derive(Debug, Default)]
12 pub struct MemoryInfo {
13     pub total_ram_mb: u64,
14     pub total_swap_mb: u64,
15     pub available_ram_mb: u64,
16     pub available_swap_mb: u64,
17     pub available_ram_percent: u8,
18     pub available_swap_percent: u8,
21 /// Simple wrapper over libc's sysinfo
22 fn sys_info() -> Result<sysinfo> {
23     // Safety: the all-zero byte pattern is a valid sysinfo struct
24     let mut sys_info: sysinfo = unsafe { mem::zeroed() };
26     // Safety: sysinfo() is safe and must not fail when passed a valid reference
27     let ret_val = checked_ffi! { libc::sysinfo(&mut sys_info) };
29     if ret_val != 0 {
30         // The only error that sysinfo() can have happens when
31         // it is supplied an invalid struct sysinfo pointer
32         //
33         // This error should really not happen during this function
34         return Err(Error::SysInfoFailed);
35     }
37     Ok(sys_info)
40 impl MemoryInfo {
41     pub fn new() -> Result<MemoryInfo> {
42         let sysinfo {
43             mem_unit,
44             freeram,
45             totalram,
46             totalswap,
47             freeswap,
48             ..
49         } = sys_info()?;
51         let ratio = |x, y| ((x as f32 / y as f32) * 100.0) as u8;
53         let available_ram_mb = bytes_to_megabytes(freeram, mem_unit);
54         let total_ram_mb = bytes_to_megabytes(totalram, mem_unit);
55         let total_swap_mb = bytes_to_megabytes(totalswap, mem_unit);
56         let available_swap_mb = bytes_to_megabytes(freeswap, mem_unit);
58         let available_ram_percent = ratio(available_ram_mb, total_ram_mb);
59         let available_swap_percent = if total_swap_mb != 0 {
60             ratio(available_swap_mb, total_swap_mb)
61         } else {
62             0
63         };
65         Ok(MemoryInfo {
66             total_ram_mb,
67             available_ram_mb,
68             total_swap_mb,
69             available_swap_mb,
70             available_ram_percent,
71             available_swap_percent,
72         })
73     }
76 impl fmt::Display for MemoryInfo {
77     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78         writeln!(f, "Total RAM: {} MB", self.total_ram_mb)?;
79         writeln!(
80             f,
81             "Available RAM: {} MB ({}%)",
82             self.available_ram_mb, self.available_ram_percent
83         )?;
84         writeln!(f, "Total swap: {} MB", self.total_swap_mb)?;
85         writeln!(
86             f,
87             "Available swap: {} MB ({} %)",
88             self.available_swap_mb, self.available_swap_percent
89         )
90     }