mprober_lib/memory/
mod.rs

1use std::io::ErrorKind;
2
3use crate::scanner_rust::{generic_array::typenum::U768, ScannerAscii, ScannerError};
4
5#[derive(Default, Debug, Clone)]
6pub struct Mem {
7    pub total:     usize,
8    /// total - free - buffers - cached - total_cached; total_cached = cached + slab - s_unreclaim
9    pub used:      usize,
10    pub free:      usize,
11    pub shared:    usize,
12    pub buffers:   usize,
13    pub cache:     usize,
14    pub available: usize,
15}
16
17#[derive(Default, Debug, Clone)]
18pub struct Swap {
19    pub total: usize,
20    /// swap_total - swap_free - swap_cached
21    pub used:  usize,
22    pub free:  usize,
23    pub cache: usize,
24}
25
26#[derive(Default, Debug, Clone)]
27pub struct Free {
28    pub mem:  Mem,
29    pub swap: Swap,
30}
31
32/// Get memory information like the `free` command by reading the `/proc/meminfo` file.
33///
34/// ```rust
35/// use mprober_lib::memory;
36///
37/// let free = memory::free().unwrap();
38///
39/// println!("{free:#?}");
40/// ```
41pub fn free() -> Result<Free, ScannerError> {
42    const USEFUL_ITEMS: [&[u8]; 11] = [
43        b"MemTotal",
44        b"MemFree",
45        b"MemAvailable",
46        b"Buffers",
47        b"Cached",
48        b"SwapCached",
49        b"SwapTotal",
50        b"SwapFree",
51        b"Shmem",
52        b"Slab",
53        b"SUnreclaim",
54    ];
55
56    let mut sc: ScannerAscii<_, U768> = ScannerAscii::scan_path2("/proc/meminfo")?;
57
58    let mut item_values = [0usize; USEFUL_ITEMS.len()];
59
60    for (i, &item) in USEFUL_ITEMS.iter().enumerate() {
61        loop {
62            let label = sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?;
63
64            if label.starts_with(item) {
65                let value = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)?;
66
67                item_values[i] = value * 1024;
68
69                sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
70
71                break;
72            } else {
73                sc.drop_next_line()?.ok_or(ErrorKind::UnexpectedEof)?;
74            }
75        }
76    }
77
78    let total = item_values[0];
79    let free = item_values[1];
80    let available = item_values[2];
81    let buffers = item_values[3];
82    let cached = item_values[4];
83    let swap_cached = item_values[5];
84    let swap_total = item_values[6];
85    let swap_free = item_values[7];
86    let shmem = item_values[8];
87    let slab = item_values[9];
88    let s_unreclaim = item_values[10];
89
90    let total_cached = cached + slab - s_unreclaim;
91
92    let mem = Mem {
93        total,
94        used: total - free - buffers - total_cached,
95        free,
96        shared: shmem,
97        buffers,
98        cache: total_cached,
99        available,
100    };
101
102    let swap = Swap {
103        total: swap_total,
104        used:  swap_total - swap_free - swap_cached,
105        free:  swap_free,
106        cache: swap_cached,
107    };
108
109    Ok(Free {
110        mem,
111        swap,
112    })
113}