Skip to content

Commit

Permalink
Add DiskRefreshKind (#1387)
Browse files Browse the repository at this point in the history
Add `DiskRefreshKind`
  • Loading branch information
dlowe authored Nov 28, 2024
1 parent 5721f84 commit 08dee51
Show file tree
Hide file tree
Showing 12 changed files with 835 additions and 448 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ ntapi = { version = "0.4", optional = true }
windows = { version = ">=0.54, <=0.57", optional = true }

[target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies]
libc = "^0.2.165"
libc = "^0.2.164"

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
core-foundation-sys = "0.8.7"
Expand All @@ -115,6 +115,7 @@ tempfile = "3.9"
serde_json = "1.0" # Used in documentation tests.
bstr = "1.9.0"
tempfile = "3.9"
itertools = "0.13.0"

[[example]]
name = "simple"
Expand Down
138 changes: 126 additions & 12 deletions src/common/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::ffi::OsStr;
use std::fmt;
use std::path::Path;

use crate::common::impl_get_set::impl_get_set;
use crate::DiskUsage;

/// Struct containing a disk information.
Expand Down Expand Up @@ -133,7 +134,9 @@ impl Disk {
self.inner.is_read_only()
}

/// Updates the disk' information.
/// Updates the disk' information with everything loaded.
///
/// Equivalent to <code>[Disk::refresh_specifics]\([DiskRefreshKind::everything]\())</code>.
///
/// ```no_run
/// use sysinfo::Disks;
Expand All @@ -144,7 +147,21 @@ impl Disk {
/// }
/// ```
pub fn refresh(&mut self) -> bool {
self.inner.refresh()
self.refresh_specifics(DiskRefreshKind::everything())
}

/// Updates the disk's information corresponding to the given [`DiskRefreshKind`].
///
/// ```no_run
/// use sysinfo::{Disks, DiskRefreshKind};
///
/// let mut disks = Disks::new_with_refreshed_list();
/// for disk in disks.list_mut() {
/// disk.refresh_specifics(DiskRefreshKind::new());
/// }
/// ```
pub fn refresh_specifics(&mut self, refreshes: DiskRefreshKind) -> bool {
self.inner.refresh_specifics(refreshes)
}

/// Returns number of bytes read and written by the disk
Expand Down Expand Up @@ -244,7 +261,8 @@ impl Disks {
}

/// Creates a new [`Disks`][crate::Disks] type with the disk list loaded.
/// It is a combination of [`Disks::new`] and [`Disks::refresh_list`].
///
/// Equivalent to <code>[Disks::new_with_refreshed_list_specifics]\([DiskRefreshKind::everything]\())</code>.
///
/// ```no_run
/// use sysinfo::Disks;
Expand All @@ -255,8 +273,24 @@ impl Disks {
/// }
/// ```
pub fn new_with_refreshed_list() -> Self {
Self::new_with_refreshed_list_specifics(DiskRefreshKind::everything())
}

/// Creates a new [`Disks`][crate::Disks] type with the disk list loaded
/// and refreshed according to the given [`DiskRefreshKind`]. It is a combination of
/// [`Disks::new`] and [`Disks::refresh_list_specifics`].
///
/// ```no_run
/// use sysinfo::{Disks, DiskRefreshKind};
///
/// let mut disks = Disks::new_with_refreshed_list_specifics(DiskRefreshKind::new());
/// for disk in disks.list() {
/// println!("{disk:?}");
/// }
/// ```
pub fn new_with_refreshed_list_specifics(refreshes: DiskRefreshKind) -> Self {
let mut disks = Self::new();
disks.refresh_list();
disks.refresh_list_specifics(refreshes);
disks
}

Expand Down Expand Up @@ -291,6 +325,13 @@ impl Disks {

/// Refreshes the listed disks' information.
///
/// Equivalent to <code>[Disks::refresh_specifics]\([DiskRefreshKind::everything]\())</code>.
pub fn refresh(&mut self) {
self.refresh_specifics(DiskRefreshKind::everything());
}

/// Refreshes the listed disks' information according to the given [`DiskRefreshKind`].
///
/// ⚠️ If a disk is added or removed, this method won't take it into account. Use
/// [`Disks::refresh_list`] instead.
///
Expand All @@ -304,30 +345,45 @@ impl Disks {
/// // We wait some time...?
/// disks.refresh();
/// ```
pub fn refresh(&mut self) {
self.inner.refresh();
pub fn refresh_specifics(&mut self, refreshes: DiskRefreshKind) {
self.inner.refresh_specifics(refreshes);
}

/// The disk list will be emptied then completely recomputed.
///
/// Equivalent to <code>[Disks::refresh_list_specifics]\([DiskRefreshKind::everything]\())</code>.
///
/// ```no_run
/// use sysinfo::Disks;
///
/// let mut disks = Disks::new();
/// disks.refresh_list();
/// ```
pub fn refresh_list(&mut self) {
self.refresh_list_specifics(DiskRefreshKind::everything());
}

/// The disk list will be emptied then completely recomputed according to the given
/// [`DiskRefreshKind`].
///
/// ## Linux
///
/// ⚠️ On Linux, the [NFS](https://en.wikipedia.org/wiki/Network_File_System) file
/// systems are ignored and the information of a mounted NFS **cannot** be obtained
/// via [`Disks::refresh_list`]. This is due to the fact that I/O function
/// `statvfs` used by [`Disks::refresh_list`] is blocking and
/// via [`Disks::refresh_list_specifics`]. This is due to the fact that I/O function
/// `statvfs` used by [`Disks::refresh_list_specifics`] is blocking and
/// [may hang](https://github.com/GuillaumeGomez/sysinfo/pull/876) in some cases,
/// requiring to call `systemctl stop` to terminate the NFS service from the remote
/// server in some cases.
///
/// ```no_run
/// use sysinfo::Disks;
/// use sysinfo::{Disks, DiskRefreshKind};
///
/// let mut disks = Disks::new();
/// disks.refresh_list();
/// disks.refresh_list_specifics(DiskRefreshKind::new());
/// ```
pub fn refresh_list(&mut self) {
self.inner.refresh_list();
pub fn refresh_list_specifics(&mut self, refreshes: DiskRefreshKind) {
self.inner.refresh_list_specifics(refreshes);
}
}

Expand Down Expand Up @@ -376,3 +432,61 @@ impl fmt::Display for DiskKind {
})
}
}

/// Used to determine what you want to refresh specifically on the [`Disk`] type.
///
/// ```no_run
/// use sysinfo::{Disks, DiskRefreshKind};
///
/// let mut disks = Disks::new_with_refreshed_list_specifics(DiskRefreshKind::everything());
///
/// for disk in disks.list() {
/// assert_eq!(disk.total_space(), 0);
/// }
/// ```
#[derive(Clone, Copy, Debug, Default)]
pub struct DiskRefreshKind {
kind: bool,
details: bool,
io_usage: bool,
}

impl DiskRefreshKind {
/// Creates a new `DiskRefreshKind` with every refresh set to false.
///
/// ```
/// use sysinfo::DiskRefreshKind;
///
/// let r = DiskRefreshKind::new();
///
/// assert_eq!(r.kind(), false);
/// assert_eq!(r.details(), false);
/// assert_eq!(r.io_usage(), false);
/// ```
pub fn new() -> Self {
Self::default()
}

/// Creates a new `DiskRefreshKind` with every refresh set to true.
///
/// ```
/// use sysinfo::DiskRefreshKind;
///
/// let r = DiskRefreshKind::everything();
///
/// assert_eq!(r.kind(), true);
/// assert_eq!(r.details(), true);
/// assert_eq!(r.io_usage(), true);
/// ```
pub fn everything() -> Self {
Self {
kind: true,
details: true,
io_usage: true,
}
}

impl_get_set!(DiskRefreshKind, kind, with_kind, without_kind);
impl_get_set!(DiskRefreshKind, details, with_details, without_details,);
impl_get_set!(DiskRefreshKind, io_usage, with_io_usage, without_io_usage);
}
173 changes: 173 additions & 0 deletions src/common/impl_get_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Take a look at the license at the top of the repository in the LICENSE file.

macro_rules! impl_get_set {
($ty_name:ident, $name:ident, $with:ident, $without:ident $(, $extra_doc:literal)? $(,)?) => {
#[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.")]
$(#[doc = concat!("
", $extra_doc, "
")])?
#[doc = concat!("
```
use sysinfo::", stringify!($ty_name), ";
let r = ", stringify!($ty_name), "::new();
let r = r.with_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), true);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), false);
```")]
pub fn $name(&self) -> bool {
self.$name
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `true`.
```
use sysinfo::", stringify!($ty_name), ";
let r = ", stringify!($ty_name), "::new();
let r = r.with_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), true);
```")]
#[must_use]
pub fn $with(mut self) -> Self {
self.$name = true;
self
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `false`.
```
use sysinfo::", stringify!($ty_name), ";
let r = ", stringify!($ty_name), "::everything();
assert_eq!(r.", stringify!($name), "(), true);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), false);
```")]
#[must_use]
pub fn $without(mut self) -> Self {
self.$name = false;
self
}
};

// To handle `UpdateKind`.
($ty_name:ident, $name:ident, $with:ident, $without:ident, UpdateKind $(, $extra_doc:literal)? $(,)?) => {
#[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.")]
$(#[doc = concat!("
", $extra_doc, "
")])?
#[doc = concat!("
```
use sysinfo::{", stringify!($ty_name), ", UpdateKind};
let r = ", stringify!($ty_name), "::new();
assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
let r = r.with_", stringify!($name), "(UpdateKind::OnlyIfNotSet);
assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
```")]
pub fn $name(&self) -> UpdateKind {
self.$name
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind.
```
use sysinfo::{", stringify!($ty_name), ", UpdateKind};
let r = ", stringify!($ty_name), "::new();
assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
let r = r.with_", stringify!($name), "(UpdateKind::OnlyIfNotSet);
assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
```")]
#[must_use]
pub fn $with(mut self, kind: UpdateKind) -> Self {
self.$name = kind;
self
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `UpdateKind::Never`.
```
use sysinfo::{", stringify!($ty_name), ", UpdateKind};
let r = ", stringify!($ty_name), "::everything();
assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
```")]
#[must_use]
pub fn $without(mut self) -> Self {
self.$name = UpdateKind::Never;
self
}
};

// To handle `*RefreshKind`.
($ty_name:ident, $name:ident, $with:ident, $without:ident, $typ:ty $(,)?) => {
#[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.
```
use sysinfo::{", stringify!($ty_name), ", ", stringify!($typ), "};
let r = ", stringify!($ty_name), "::new();
assert_eq!(r.", stringify!($name), "().is_some(), false);
let r = r.with_", stringify!($name), "(", stringify!($typ), "::everything());
assert_eq!(r.", stringify!($name), "().is_some(), true);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "().is_some(), false);
```")]
pub fn $name(&self) -> Option<$typ> {
self.$name
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `Some(...)`.
```
use sysinfo::{", stringify!($ty_name), ", ", stringify!($typ), "};
let r = ", stringify!($ty_name), "::new();
assert_eq!(r.", stringify!($name), "().is_some(), false);
let r = r.with_", stringify!($name), "(", stringify!($typ), "::everything());
assert_eq!(r.", stringify!($name), "().is_some(), true);
```")]
#[must_use]
pub fn $with(mut self, kind: $typ) -> Self {
self.$name = Some(kind);
self
}

#[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `None`.
```
use sysinfo::", stringify!($ty_name), ";
let r = ", stringify!($ty_name), "::everything();
assert_eq!(r.", stringify!($name), "().is_some(), true);
let r = r.without_", stringify!($name), "();
assert_eq!(r.", stringify!($name), "().is_some(), false);
```")]
#[must_use]
pub fn $without(mut self) -> Self {
self.$name = None;
self
}
};
}

pub(crate) use impl_get_set;
Loading

0 comments on commit 08dee51

Please sign in to comment.