Implemented dd for grouped processes.

This commit is contained in:
ClementTsang 2020-01-08 22:36:36 -05:00
parent 6cf8f0d98f
commit c171cd0e0b
5 changed files with 80 additions and 56 deletions

View File

@ -49,7 +49,7 @@ pub struct App {
pub show_help: bool,
pub show_dd: bool,
pub dd_err: Option<String>,
to_delete_process: Option<ConvertedProcessData>,
to_delete_process_list: Option<Vec<ConvertedProcessData>>,
pub is_frozen: bool,
pub left_legend: bool,
pub use_current_cpu_total: bool,
@ -88,7 +88,7 @@ impl App {
show_help: false,
show_dd: false,
dd_err: None,
to_delete_process: None,
to_delete_process_list: None,
is_frozen: false,
left_legend,
use_current_cpu_total,
@ -102,7 +102,7 @@ impl App {
self.reset_multi_tap_keys();
self.show_help = false;
self.show_dd = false;
self.to_delete_process = None;
self.to_delete_process_list = None;
self.dd_err = None;
}
@ -122,9 +122,6 @@ impl App {
self.enable_grouping = !(self.enable_grouping);
}
}
// TODO: Note that we have to handle this in a way such that it will only update
// with the correct formatted vectors... that is, only update the canvas after...?
}
pub fn is_grouped(&self) -> bool {
@ -167,9 +164,29 @@ impl App {
self.awaiting_second_char = false;
self.second_char = ' ';
let current_process = &self.canvas_data.process_data
[self.currently_selected_process_position as usize];
self.to_delete_process = Some(current_process.clone());
let current_process = if self.is_grouped() {
let mut res: Vec<ConvertedProcessData> = Vec::new();
for pid in &self.canvas_data.grouped_process_data
[self.currently_selected_process_position as usize]
.group
{
let result = self
.canvas_data
.process_data
.iter()
.find(|p| p.pid == *pid);
if let Some(process) = result {
res.push((*process).clone());
}
}
res
} else {
vec![self.canvas_data.process_data
[self.currently_selected_process_position as usize]
.clone()]
};
self.to_delete_process_list = Some(current_process);
self.show_dd = true;
self.reset_multi_tap_keys();
} else {
@ -261,18 +278,18 @@ impl App {
pub fn kill_highlighted_process(&mut self) -> Result<()> {
// Technically unnecessary but this is a good check...
if let ApplicationPosition::Process = self.current_application_position {
if self.enable_grouping {
// TODO: Enable grouping pid deletion
} else if let Some(current_selected_process) = &(self.to_delete_process) {
process_killer::kill_process_given_pid(current_selected_process.pid)?;
if let Some(current_selected_processes) = &(self.to_delete_process_list) {
for current_selected_process in current_selected_processes {
process_killer::kill_process_given_pid(current_selected_process.pid)?;
}
}
self.to_delete_process = None;
self.to_delete_process_list = None;
}
Ok(())
}
pub fn get_current_highlighted_process(&self) -> Option<ConvertedProcessData> {
self.to_delete_process.clone()
pub fn get_current_highlighted_process_list(&self) -> Option<Vec<ConvertedProcessData>> {
self.to_delete_process_list.clone()
}
// For now, these are hard coded --- in the future, they shouldn't be!

View File

@ -24,8 +24,8 @@ pub struct ProcessData {
pub cpu_usage_percent: f64,
pub mem_usage_percent: Option<f64>,
pub mem_usage_kb: Option<u64>,
pub command: String,
pub pid_vec: Option<Vec<u32>>, // Note that this is literally never unless we are in grouping mode. This is to save rewriting time.
pub name: String,
pub pid_vec: Option<Vec<u32>>,
}
fn cpu_usage_calculation(
@ -186,7 +186,7 @@ fn convert_ps(
if process.trim().to_string().is_empty() {
return Ok(ProcessData {
pid: 0,
command: "".to_string(),
name: "".to_string(),
mem_usage_percent: None,
mem_usage_kb: None,
cpu_usage_percent: 0_f64,
@ -199,7 +199,7 @@ fn convert_ps(
.to_string()
.parse::<u32>()
.unwrap_or(0);
let command = (&process[11..61]).trim().to_string();
let name = (&process[11..61]).trim().to_string();
let mem_usage_percent = Some(
(&process[62..])
.trim()
@ -210,7 +210,7 @@ fn convert_ps(
Ok(ProcessData {
pid,
command,
name,
mem_usage_percent,
mem_usage_kb: None,
cpu_usage_percent: linux_cpu_usage(
@ -252,7 +252,7 @@ pub fn get_sorted_processes_list(
prev_pid_stats,
use_current_cpu_total,
) {
if !process_object.command.is_empty() {
if !process_object.name.is_empty() {
process_vector.push(process_object);
}
}
@ -264,7 +264,7 @@ pub fn get_sorted_processes_list(
} else {
let process_hashmap = sys.get_process_list();
for process_val in process_hashmap.values() {
let command_name = if process_val.name().is_empty() {
let name = if process_val.name().is_empty() {
let process_cmd = process_val.cmd();
if process_cmd.len() > 1 {
process_cmd[0].clone()
@ -287,7 +287,7 @@ pub fn get_sorted_processes_list(
process_vector.push(ProcessData {
pid: process_val.pid() as u32,
command: command_name,
name,
mem_usage_percent: None,
mem_usage_kb: Some(process_val.memory()),
cpu_usage_percent: f64::from(process_val.cpu_usage()),
@ -303,7 +303,7 @@ pub fn sort_processes(
process_vector: &mut Vec<ProcessData>, sorting_method: &ProcessSorting, reverse_order: bool,
) {
// Always sort alphabetically first!
process_vector.sort_by(|a, b| get_ordering(&a.command, &b.command, false));
process_vector.sort_by(|a, b| get_ordering(&a.name, &b.name, false));
match sorting_method {
ProcessSorting::CPU => {
@ -320,7 +320,7 @@ pub fn sort_processes(
process_vector.sort_by(|a, b| get_ordering(a.pid, b.pid, reverse_order));
}
ProcessSorting::NAME => {
process_vector.sort_by(|a, b| get_ordering(&a.command, &b.command, reverse_order))
process_vector.sort_by(|a, b| get_ordering(&a.name, &b.name, reverse_order))
}
}
}

View File

@ -193,26 +193,37 @@ pub fn draw_data<B: backend::Backend>(
.alignment(Alignment::Center)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
} else if let Some(process) = app_state.get_current_highlighted_process() {
let dd_text = [
Text::raw(format!(
"\nAre you sure you want to kill process {} with PID {}?",
process.name, process.pid
)),
} else if let Some(process_list) = app_state.get_current_highlighted_process_list() {
if let Some(process) = process_list.first() {
let dd_text = [
if app_state.is_grouped() {
Text::raw(format!(
"\nAre you sure you want to kill {} process(es) with name {}?",
process_list.len(), process.name
))
} else {
Text::raw(format!(
"\nAre you sure you want to kill process {} with PID {}?",
process.name, process.pid
))
},
Text::raw("\n\nPress ENTER to proceed, ESC to exit."),
Text::raw("\nNote that if bottom is frozen, it must be unfrozen for changes to be shown."),
];
Paragraph::new(dd_text.iter())
.block(
Block::default()
.title("Kill Process Confirmation (Press Esc to close)")
.borders(Borders::ALL),
)
.style(Style::default().fg(Color::Gray))
.alignment(Alignment::Center)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
Paragraph::new(dd_text.iter())
.block(
Block::default()
.title("Kill Process Confirmation (Press Esc to close)")
.borders(Borders::ALL),
)
.style(Style::default().fg(Color::Gray))
.alignment(Alignment::Center)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
} else {
app_state.show_dd = false;
}
} else {
// This is a bit nasty, but it works well... I guess.
app_state.show_dd = false;
@ -774,7 +785,7 @@ fn draw_processes_table<B: backend::Backend>(
let process_rows = sliced_vec.iter().map(|process| {
let stringified_process_vec: Vec<String> = vec![
if app_state.is_grouped() {
process.group_count.to_string()
process.group.len().to_string()
} else {
process.pid.to_string()
},

View File

@ -21,7 +21,7 @@ pub struct ConvertedProcessData {
pub name: String,
pub cpu_usage: String,
pub mem_usage: String,
pub group_count: u32,
pub group: Vec<u32>,
}
#[derive(Clone, Default, Debug)]
@ -144,7 +144,7 @@ pub fn update_process_row(
.iter()
.map(|process| ConvertedProcessData {
pid: process.pid,
name: process.command.to_string(),
name: process.name.to_string(),
cpu_usage: format!("{:.1}%", process.cpu_usage_percent),
mem_usage: format!(
"{:.1}%",
@ -160,11 +160,7 @@ pub fn update_process_row(
0_f64
}
),
group_count: if let Some(pid_vec) = &process.pid_vec {
pid_vec.len() as u32
} else {
0
},
group: vec![],
})
.collect::<Vec<_>>();
@ -174,7 +170,7 @@ pub fn update_process_row(
.iter()
.map(|process| ConvertedProcessData {
pid: process.pid,
name: process.command.to_string(),
name: process.name.to_string(),
cpu_usage: format!("{:.1}%", process.cpu_usage_percent),
mem_usage: format!(
"{:.1}%",
@ -190,10 +186,10 @@ pub fn update_process_row(
0_f64
}
),
group_count: if let Some(pid_vec) = &process.pid_vec {
pid_vec.len() as u32
group: if let Some(pid_vec) = &process.pid_vec {
pid_vec.to_vec()
} else {
0
vec![]
},
})
.collect::<Vec<_>>();

View File

@ -326,7 +326,7 @@ fn handle_process_sorting(app: &mut app::App) {
for process in &app.data.list_of_processes {
let entry_val =
process_map
.entry(process.command.clone())
.entry(process.name.clone())
.or_insert((0.0, None, None, vec![]));
if let Some(mem_usage) = process.mem_usage_percent {
entry_val.0 += process.cpu_usage_percent;
@ -353,7 +353,7 @@ fn handle_process_sorting(app: &mut app::App) {
cpu_usage_percent: data.0,
mem_usage_percent: data.1,
mem_usage_kb: data.2,
command: name.clone(),
name: name.clone(),
pid_vec: Some(data.3.clone()),
}
})