Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DiskRefreshKind #1387

Merged
merged 17 commits into from
Nov 28, 2024
Merged
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"
dlowe marked this conversation as resolved.
Show resolved Hide resolved

[[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