use crate::disks::IoBlock;
use std::io::{Error, ErrorKind};
use std::{
fs::File,
io::{BufRead, BufReader},
path::Path,
};
const DISK_SECTOR_SIZE: u64 = 512;
#[inline]
fn _get_ioblocks(physical: bool) -> Result<Vec<IoBlock>, Error> {
let file = File::open("/proc/diskstats")?;
let mut v_ioblocks: Vec<IoBlock> = Vec::new();
let mut file = BufReader::with_capacity(2048, file);
let mut line = String::with_capacity(256);
while file.read_line(&mut line)? != 0 {
let mut fields = line.split_whitespace();
let name = nth!(fields, 2)?;
if physical && !Path::new(&format!("/sys/block/{}/device", name.replace('/', "!"))).exists()
{
line.clear();
continue;
}
let read_count = nth!(fields, 0)?;
let read_bytes = nth!(fields, 1)?;
let write_count = nth!(fields, 0)?;
let write_bytes = nth!(fields, 1)?;
let busy_time = nth!(fields, 2)?;
if fields.count() < 2 {
return Err(Error::new(ErrorKind::Other, "Invalid /proc/diskstats"));
}
v_ioblocks.push(IoBlock {
device_name: name.to_owned(),
read_count: read_count.parse().unwrap(),
read_bytes: read_bytes.parse::<u64>().unwrap() * DISK_SECTOR_SIZE,
write_count: write_count.parse().unwrap(),
write_bytes: write_bytes.parse::<u64>().unwrap() * DISK_SECTOR_SIZE,
busy_time: busy_time.parse().unwrap(),
});
line.clear();
}
Ok(v_ioblocks)
}
pub fn get_ioblocks() -> Result<Vec<IoBlock>, Error> {
_get_ioblocks(false)
}
pub fn get_physical_ioblocks() -> Result<Vec<IoBlock>, Error> {
_get_ioblocks(true)
}