summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2021-08-29 17:49:02 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2021-08-29 19:33:13 -0400
commit1ec203caa23e2ff4ca3f4cd488d80ee32ee231e7 (patch)
tree8d04acc310d876469a1b2a2bc651d11c0121b2a6
parent74293aa243b6e442c25619c62a85236871d20960 (diff)
refactor: Add data updating to process widget
-rw-r--r--src/app.rs4
-rw-r--r--src/app/data_farmer.rs15
-rw-r--r--src/app/data_harvester/processes/unix.rs4
-rw-r--r--src/app/widgets/base/sort_text_table.rs13
-rw-r--r--src/app/widgets/base/text_table.rs8
-rw-r--r--src/app/widgets/process.rs93
-rw-r--r--src/data_conversion.rs49
7 files changed, 134 insertions, 52 deletions
diff --git a/src/app.rs b/src/app.rs
index aee57db8..5f03cb5f 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -123,9 +123,6 @@ pub struct AppState {
pub is_expanded: bool,
- #[cfg(target_family = "unix")]
- pub user_table: processes::UserTable,
-
pub used_widgets: UsedWidgets,
pub filters: DataFilters,
pub app_config_fields: AppConfigFields,
@@ -196,7 +193,6 @@ impl AppState {
canvas_data: Default::default(),
data_collection: Default::default(),
is_expanded: Default::default(),
- user_table: Default::default(),
delete_dialog_state: Default::default(),
help_dialog_state: Default::default(),
cpu_state: Default::default(),
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs
index 931ab96f..f2d4c957 100644
--- a/src/app/data_farmer.rs
+++ b/src/app/data_farmer.rs
@@ -14,14 +14,17 @@
/// more points as this is used!
use once_cell::sync::Lazy;
-use std::{time::Instant, vec::Vec};
+use std::{cell::RefCell, collections::HashMap, time::Instant, vec::Vec};
use crate::{
data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data},
utils::gen_util::{get_decimal_bytes, GIGA_LIMIT},
+ Pid,
};
use regex::Regex;
+use super::data_harvester::processes::UserTable;
+
pub type TimeOffset = f64;
pub type Value = f64;
@@ -55,12 +58,15 @@ pub struct DataCollection {
pub cpu_harvest: cpu::CpuHarvest,
pub load_avg_harvest: cpu::LoadAvgHarvest,
pub process_harvest: Vec<processes::ProcessHarvest>,
+ pub process_count_mapping: HashMap<String, Pid>,
pub disk_harvest: Vec<disks::DiskHarvest>,
pub io_harvest: disks::IoHarvest,
pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>,
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
pub battery_harvest: Vec<batteries::BatteryHarvest>,
+ #[cfg(target_family = "unix")]
+ pub user_table: RefCell<UserTable>,
}
impl Default for DataCollection {
@@ -75,12 +81,15 @@ impl Default for DataCollection {
cpu_harvest: cpu::CpuHarvest::default(),
load_avg_harvest: cpu::LoadAvgHarvest::default(),
process_harvest: Vec::default(),
+ process_count_mapping: HashMap::default(),
disk_harvest: Vec::default(),
io_harvest: disks::IoHarvest::default(),
io_labels_and_prev: Vec::default(),
io_labels: Vec::default(),
temp_harvest: Vec::default(),
battery_harvest: Vec::default(),
+ #[cfg(target_family = "unix")]
+ user_table: RefCell::new(UserTable::default()),
}
}
}
@@ -98,6 +107,10 @@ impl DataCollection {
self.io_labels_and_prev = Vec::default();
self.temp_harvest = Vec::default();
self.battery_harvest = Vec::default();
+ #[cfg(target_family = "unix")]
+ {
+ *self.user_table.borrow_mut() = UserTable::default();
+ }
}
pub fn set_frozen_time(&mut self) {
diff --git a/src/app/data_harvester/processes/unix.rs b/src/app/data_harvester/processes/unix.rs
index 8fadc590..a563c88a 100644
--- a/src/app/data_harvester/processes/unix.rs
+++ b/src/app/data_harvester/processes/unix.rs
@@ -1,10 +1,12 @@
//! Unix-specific parts of process collection.
+use std::collections::HashMap;
+
use crate::utils::error;
#[derive(Debug, Default)]
pub struct UserTable {
- pub uid_user_mapping: std::collections::HashMap<libc::uid_t, String>,
+ pub uid_user_mapping: HashMap<libc::uid_t, String>,
}
impl UserTable {
diff --git a/src/app/widgets/base/sort_text_table.rs b/src/app/widgets/base/sort_text_table.rs
index 4a60504a..e5d8c8a2 100644
--- a/src/app/widgets/base/sort_text_table.rs
+++ b/src/app/widgets/base/sort_text_table.rs
@@ -266,6 +266,14 @@ where
self.table.current_index()
}
+ pub fn columns(&self) -> &[S] {
+ &self.table.columns
+ }
+
+ pub fn set_column(&mut self, column: S, index: usize) {
+ self.table.set_column(index, column)
+ }
+
fn set_sort_index(&mut self, new_index: usize) {
if new_index == self.sort_index {
if let Some(column) = self.table.columns.get_mut(self.sort_index) {
@@ -313,11 +321,6 @@ where
self.table
.draw_tui_table(painter, f, data, block, block_area, show_selected_entry);
}
-
- /// Creates a [`Table`] representing the sort list.
- pub fn create_sort_list(&mut self) -> (Table<'_>, TableState) {
- todo!()
- }
}
impl<S> Component for SortableTextTable<S>
diff --git a/src/app/widgets/base/text_table.rs b/src/app/widgets/base/text_table.rs
index 3ce3092d..2eaf444c 100644
--- a/src/app/widgets/base/text_table.rs
+++ b/src/app/widgets/base/text_table.rs
@@ -169,18 +169,18 @@ where
self
}
- pub fn displayed_column_names(&self) -> Vec<Cow<'static, str>> {
+ fn displayed_column_names(&self) -> Vec<Cow<'static, str>> {
self.columns
.iter()
.map(|column| column.display_name())
.collect()
}
- pub fn update_num_items(&mut self, num_items: usize) {
+ pub fn set_num_items(&mut self, num_items: usize) {
self.scrollable.update_num_items(num_items);
}
- pub fn update_single_column(&mut self, index: usize, column: C) {
+ pub fn set_column(&mut self, index: usize, column: C) {
if let Some(c) = self.columns.get_mut(index) {
*c = column;
}
@@ -360,7 +360,7 @@ where
1
};
- self.update_num_items(data.len());
+ self.set_num_items(data.len());
self.set_bounds(inner_area);
let table_extras = 1 + table_gap;
let scrollable_height = inner_area.height.saturating_sub(table_extras);
diff --git a/src/app/widgets/process.rs b/src/app/widgets/process.rs
index 1d86f02c..c4c4651e 100644
--- a/src/app/widgets/process.rs
+++ b/src/app/widgets/process.rs
@@ -17,8 +17,10 @@ use crate::{
DataCollection,
},
canvas::Painter,
+ data_conversion::{get_disk_io_strings, get_string_with_bytes},
data_harvester::processes::{self, ProcessSorting},
options::ProcessDefaults,
+ utils::gen_util::{get_binary_bytes, GIBI_LIMIT},
};
use ProcessSorting::*;
@@ -706,7 +708,7 @@ impl ProcessSortType {
match self {
ProcessSortType::Pid => Hard(Some(7)),
ProcessSortType::Count => Hard(Some(8)),
- ProcessSortType::Name => Flex(0.3),
+ ProcessSortType::Name => Flex(0.4),
ProcessSortType::Command => Flex(0.7),
ProcessSortType::Cpu => Hard(Some(8)),
ProcessSortType::Mem => Hard(Some(8)),
@@ -715,8 +717,8 @@ impl ProcessSortType {
ProcessSortType::Wps => Hard(Some(8)),
ProcessSortType::TotalRead => Hard(Some(7)),
ProcessSortType::TotalWrite => Hard(Some(8)),
- ProcessSortType::User => Flex(0.1),
- ProcessSortType::State => Flex(0.2),
+ ProcessSortType::User => Flex(0.075),
+ ProcessSortType::State => Hard(Some(1)),
}
}
@@ -1078,5 +1080,88 @@ impl Widget for ProcessManager {
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
}
- fn update_data(&mut self, data_collection: &DataCollection) {}
+ fn update_data(&mut self, data_collection: &DataCollection) {
+ self.display_data = data_collection
+ .process_harvest
+ .iter()
+ .filter_map(|process| {
+ let row = self
+ .process_table
+ .columns()
+ .iter()
+ .map(|column| match &column.sort_type {
+ ProcessSortType::Pid => (process.pid.to_string().into(), None, None),
+ ProcessSortType::Count => ("".into(), None, None),
+ ProcessSortType::Name => (process.name.clone().into(), None, None),
+ ProcessSortType::Command => (process.command.clone().into(), None, None),
+ ProcessSortType::Cpu => (
+ format!("{:.1}%", process.cpu_usage_percent).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::Mem => (
+ get_string_with_bytes(process.mem_usage_bytes).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::MemPercent => (
+ format!("{:.1}%", process.mem_usage_percent).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::Rps => (
+ get_string_with_bytes(process.read_bytes_per_sec).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::Wps => (
+ get_string_with_bytes(process.write_bytes_per_sec).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::TotalRead => (
+ get_string_with_bytes(process.total_read_bytes).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::TotalWrite => (
+ get_string_with_bytes(process.total_write_bytes).into(),
+ None,
+ None,
+ ),
+ ProcessSortType::User => {
+ let user = {
+ #[cfg(target_family = "unix")]
+ {
+ if let Some(uid) = process.uid {
+ data_collection
+ .user_table
+ .borrow_mut()
+ .get_uid_to_username_mapping(uid)
+ .map(|s| s.into())
+ .unwrap_or("N/A".into())
+ } else {
+ "N/A".into()
+ }
+ }
+ #[cfg(not(target_family = "unix"))]
+ {
+ "N/A".into()
+ }
+ };
+
+ (user, None, None)
+ }
+ ProcessSortType::State => (
+ process.process_state.clone().into(),
+ Some(process.process_state_char.to_string().into()),
+ None,
+ ),
+ })
+ .collect::<Vec<_>>();
+
+ Some(row)
+ })
+ .collect::<Vec<_>>();
+ }
}
diff --git a/src/data_conversion.rs b/src/data_conversion.rs
index de593952..61422b66 100644
--- a/src/data_conversion.rs
+++ b/src/data_conversion.rs
@@ -573,45 +573,28 @@ pub enum ProcessNamingType {
}
/// Given read/s, write/s, total read, and total write values, return 4 strings that represent read/s, write/s, total read, and total write
-fn get_disk_io_strings(
+pub fn get_disk_io_strings(
rps: u64, wps: u64, total_read: u64, total_write: u64,
) -> (String, String, String, String) {
- // Note we always use bytes for total read/write here (for now).
- let converted_rps = get_decimal_bytes(rps);
- let converted_wps = get_decimal_bytes(wps);
- let converted_total_read = get_decimal_bytes(total_read);
- let converted_total_write = get_decimal_bytes(total_write);
-
(
- if rps >= GIGA_LIMIT {
- format!("{:.*}{}/s", 1, converted_rps.0, converted_rps.1)
- } else {
- format!("{:.*}{}/s", 0, converted_rps.0, converted_rps.1)
- },
- if wps >= GIGA_LIMIT {
- format!("{:.*}{}/s", 1, converted_wps.0, converted_wps.1)
- } else {
- format!("{:.*}{}/s", 0, converted_wps.0, converted_wps.1)
- },
- if total_read >= GIGA_LIMIT {
- format!("{:.*}{}", 1, converted_total_read.0, converted_total_read.1)
- } else {
- format!("{:.*}{}", 0, converted_total_read.0, converted_total_read.1)
- },
- if total_write >= GIGA_LIMIT {
- format!(
- "{:.*}{}",
- 1, converted_total_write.0, converted_total_write.1
- )
- } else {
- format!(
- "{:.*}{}",
- 0, converted_total_write.0, converted_total_write.1
- )
- },
+ get_string_with_bytes(rps),
+ get_string_with_bytes(wps),
+ get_string_with_bytes(total_read),
+ get_string_with_bytes(total_write),
)
}
+/// Returns a string given a value that is converted to the closest SI-variant.
+/// If the value is greater than a giga-X, then it will return a decimal place.
+pub fn get_string_with_bytes(value: u64) -> String {
+ let converted_values = get_decimal_bytes(value);
+ if value >= GIGA_LIMIT {
+ format!("{:.*}{}/s", 1, converted_values.0, converted_values.1)
+ } else {
+ format!("{:.*}{}/s", 0, converted_values.0, converted_values.1)
+ }
+}
+
/// Because we needed to UPDATE data entries rather than REPLACING entries, we instead update
/// the existing vector.
pub fn convert_process_data(