use cursive::utils::markup::StyledString;
use itertools::Itertools;
use model::Queriable;
use model::SingleProcessModel;
use crate::process_view::ProcessState;
use crate::render::ViewItem;
use crate::stats_view::ColumnTitles;
use crate::stats_view::StateCommon;
type ProcessViewItem = ViewItem<model::SingleProcessModelFieldId>;
#[derive(Clone)]
pub struct ProcessTab {
pub view_items: Vec<ProcessViewItem>,
}
impl ProcessTab {
fn new(view_items: Vec<ProcessViewItem>) -> Self {
Self { view_items }
}
fn get_process_field_line(
&self,
model: &SingleProcessModel,
offset: Option<usize>,
) -> StyledString {
let mut line = StyledString::new();
line.append(default_tabs::COMM_VIEW_ITEM.render(model));
line.append_plain(" ");
for item in std::iter::once(&*default_tabs::CGROUP_VIEW_ITEM)
.chain(self.view_items.iter())
.skip(offset.unwrap_or(0))
{
line.append(item.render(model));
line.append_plain(" ");
}
line
}
pub fn get_titles(&self) -> ColumnTitles {
ColumnTitles {
titles: std::iter::once(&*default_tabs::COMM_VIEW_ITEM)
.chain(std::iter::once(&*default_tabs::CGROUP_VIEW_ITEM))
.chain(self.view_items.iter())
.map(|item| item.config.render_title())
.collect(),
pinned_titles: 1,
}
}
pub fn get_rows(
&self,
state: &ProcessState,
offset: Option<usize>,
) -> Vec<(StyledString, i32)> {
let unknown = "?".to_string();
let unknown_pid: i32 = -1;
let process_model = state.get_model();
let mut processes: Vec<&SingleProcessModel> = process_model.processes.values().collect();
if let Some(sort_order) = state.sort_order.as_ref() {
model::sort_queriables(&mut processes, sort_order, state.reverse);
}
processes
.iter()
.filter(|spm| {
if let Some(f) = &state.pids_filter {
f.contains(&spm.pid.unwrap_or(unknown_pid))
} else {
true
}
})
.filter(|spm| {
if let Some(f) = &state.cgroup_filter {
spm.cgroup.as_ref().unwrap_or(&unknown).starts_with(f)
} else {
true
}
})
.filter(|spm| {
if let Some((field_id, filter)) = &state.filter_info {
match spm.query(field_id) {
None => true,
Some(value) => value.to_string().contains(filter),
}
} else {
true
}
})
.copied()
.batching(|it| {
if state.fold {
it.next().map(|first| {
it.fold(first.clone(), |acc, spm| {
SingleProcessModel::fold(&acc, spm)
})
})
} else {
it.next().cloned()
}
})
.map(|spm| {
(
self.get_process_field_line(&spm, offset),
spm.pid.unwrap_or(0),
)
})
.collect()
}
}
pub mod default_tabs {
use model::ProcessCpuModelFieldId::NumThreads;
use model::ProcessCpuModelFieldId::SystemPct;
use model::ProcessCpuModelFieldId::UsagePct;
use model::ProcessCpuModelFieldId::UserPct;
use model::ProcessIoModelFieldId::RbytesPerSec;
use model::ProcessIoModelFieldId::RwbytesPerSec;
use model::ProcessIoModelFieldId::WbytesPerSec;
use model::ProcessMemoryModelFieldId::Anon;
use model::ProcessMemoryModelFieldId::File;
use model::ProcessMemoryModelFieldId::HugeTlb;
use model::ProcessMemoryModelFieldId::Lock;
use model::ProcessMemoryModelFieldId::MajorfaultsPerSec;
use model::ProcessMemoryModelFieldId::MinorfaultsPerSec;
use model::ProcessMemoryModelFieldId::Pin;
use model::ProcessMemoryModelFieldId::Pte;
use model::ProcessMemoryModelFieldId::RssBytes;
use model::ProcessMemoryModelFieldId::Shmem;
use model::ProcessMemoryModelFieldId::Swap;
use model::ProcessMemoryModelFieldId::VmSize;
use model::SingleProcessModelFieldId::Cgroup;
use model::SingleProcessModelFieldId::Cmdline;
use model::SingleProcessModelFieldId::Comm;
use model::SingleProcessModelFieldId::Cpu;
use model::SingleProcessModelFieldId::Io;
use model::SingleProcessModelFieldId::Mem;
use model::SingleProcessModelFieldId::NsTgid;
use model::SingleProcessModelFieldId::Pid;
use model::SingleProcessModelFieldId::Ppid;
use model::SingleProcessModelFieldId::State;
use model::SingleProcessModelFieldId::UptimeSecs;
use once_cell::sync::Lazy;
use super::*;
pub static COMM_VIEW_ITEM: Lazy<ProcessViewItem> = Lazy::new(|| ViewItem::from_default(Comm));
pub static CGROUP_VIEW_ITEM: Lazy<ProcessViewItem> =
Lazy::new(|| ViewItem::from_default(Cgroup));
pub static PROCESS_GENERAL_TAB: Lazy<ProcessTab> = Lazy::new(|| {
ProcessTab::new(vec![
ViewItem::from_default(Pid),
ViewItem::from_default(Ppid),
ViewItem::from_default(NsTgid),
ViewItem::from_default(State),
ViewItem::from_default(Cpu(UsagePct)),
ViewItem::from_default(Cpu(UserPct)),
ViewItem::from_default(Cpu(SystemPct)),
ViewItem::from_default(Mem(RssBytes)),
ViewItem::from_default(Mem(MinorfaultsPerSec)),
ViewItem::from_default(Mem(MajorfaultsPerSec)),
ViewItem::from_default(Io(RbytesPerSec)),
ViewItem::from_default(Io(WbytesPerSec)),
ViewItem::from_default(UptimeSecs),
ViewItem::from_default(Cpu(NumThreads)),
ViewItem::from_default(Io(RwbytesPerSec)),
ViewItem::from_default(Cmdline),
])
});
pub static PROCESS_CPU_TAB: Lazy<ProcessTab> = Lazy::new(|| {
ProcessTab::new(vec![
ViewItem::from_default(Cpu(UserPct)),
ViewItem::from_default(Cpu(SystemPct)),
ViewItem::from_default(Cpu(NumThreads)),
ViewItem::from_default(Cpu(UsagePct)),
])
});
pub static PROCESS_MEM_TAB: Lazy<ProcessTab> = Lazy::new(|| {
ProcessTab::new(vec![
ViewItem::from_default(Mem(RssBytes)),
ViewItem::from_default(Mem(VmSize)),
ViewItem::from_default(Mem(Swap)),
ViewItem::from_default(Mem(Anon)),
ViewItem::from_default(Mem(File)),
ViewItem::from_default(Mem(Shmem)),
ViewItem::from_default(Mem(Pte)),
ViewItem::from_default(Mem(Lock)),
ViewItem::from_default(Mem(Pin)),
ViewItem::from_default(Mem(HugeTlb)),
ViewItem::from_default(Mem(MinorfaultsPerSec)),
ViewItem::from_default(Mem(MajorfaultsPerSec)),
])
});
pub static PROCESS_IO_TAB: Lazy<ProcessTab> = Lazy::new(|| {
ProcessTab::new(vec![
ViewItem::from_default(Io(RbytesPerSec)),
ViewItem::from_default(Io(WbytesPerSec)),
ViewItem::from_default(Io(RwbytesPerSec)),
])
});
}