Clement Tsang 9edde9b133
refactor: migrate disk collection code off of heim, remove heim (#1064)
Migrates existing heim-based disk data collection code off of it to either sysinfo or vendored code based on heim/sysinfo/other sources. This also allows us to remove heim completely from bottom.

---

* refactor: fix some refresh code

* remove async from the freebsd code

* some file/implementation organization

Turns out sysinfo lacks a lot of data I need. I can still use it for the
Windows disk usage implementation, but I'm probably going to manually
implement macos/linux usage and all io usage stats.

* more restructuring

* Some other fixes

* remove futures

* ready for some big changes?

* big changes

* linux io + reads

* use lossy conversion for mount point

* add windows refresh

* so long heim, and thanks for all the fish

* fix filter behaviour, remove string allocation when reading lines

* rename unix -> system for more accurate file struct representation

* fix freebsd

* port generic unix partition code

* add bindings and fix errors

* finish macOS bindings for I/O

* disable conform check, this seems to... make disk I/O work on macOS?????

* fix linux

* add safety comments

* more comments

* update changelog

* changelog

* We're going full 0.9.0 for this

* update lock

* fix some typing

* bleh

* some file management

* hoist out get_disk_usage

* fix some stuff for Windows

* typing and remove dead code allow lint

* unify typing

* fix

* fix 2

* macOS fix

* Add bindings file for windows

* add windows implementation

* fix macos
2023-04-10 05:52:46 -04:00

50 lines
2.3 KiB
Rust

//! Based on [heim's implementation](https://github.com/heim-rs/heim/blob/master/heim-disk/src/sys/macos/counters.rs).
use super::io_kit::{self, get_dict, get_disks, get_i64, get_string};
use crate::app::data_harvester::disks::IoCounters;
fn get_device_io(device: io_kit::IoObject) -> anyhow::Result<IoCounters> {
let parent = device.service_parent()?;
// XXX: Re: Conform check being disabled.
//
// Okay, so this is weird.
//
// The problem is that if I have this check - this is what sources like psutil use, for
// example (see https://github.com/giampaolo/psutil/blob/7eadee31db2f038763a3a6f978db1ea76bbc4674/psutil/_psutil_osx.c#LL1422C20-L1422C20)
// then this will only return stuff like disk0.
//
// The problem with this is that there is *never* a disk0 *disk* entry to correspond to this,
// so there will be entries like disk1 or whatnot. Someone's done some digging on the gopsutil
// repo (https://github.com/shirou/gopsutil/issues/855#issuecomment-610016435), and it seems
// like this is a consequence of how Apple does logical volumes.
//
// So with all that said, what I've found is that I *can* still get a mapping - but I have
// to disable the conform check, which... is weird. I'm not sure if this is valid at all. But
// it *does* seem to match Activity Monitor with regards to disk activity, so... I guess we
// can leave this for now...?
// if !parent.conforms_to_block_storage_driver() {
// anyhow::bail!("{parent:?}, the parent of {device:?} does not conform to IOBlockStorageDriver")
// }
let disk_props = device.properties()?;
let parent_props = parent.properties()?;
let name = get_string(&disk_props, "BSD Name")?;
let stats = get_dict(&parent_props, "Statistics")?;
let read_bytes = get_i64(&stats, "Bytes (Read)")? as u64;
let write_bytes = get_i64(&stats, "Bytes (Write)")? as u64;
// let read_count = stats.get_i64("Operations (Read)")? as u64;
// let write_count = stats.get_i64("Operations (Write)")? as u64;
Ok(IoCounters::new(name, read_bytes, write_bytes))
}
/// Returns an iterator of disk I/O stats. Pulls data through IOKit.
pub fn io_stats() -> anyhow::Result<Vec<anyhow::Result<IoCounters>>> {
Ok(get_disks()?.map(get_device_io).collect())
}