Skip to content

Commit

Permalink
split logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluemangoo committed Jan 13, 2025
1 parent a7a6702 commit d29e761
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 83 deletions.
166 changes: 166 additions & 0 deletions src/uu/top/src/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use crate::picker::{sysinfo, systemstat};
use bytesize::ByteSize;
use std::sync::{Mutex, OnceLock};
use systemstat::{CPULoad, DelayedMeasurement, Platform};

static LOAD_AVERAGE: OnceLock<Mutex<DelayedMeasurement<CPULoad>>> = OnceLock::new();

pub(crate) fn cpu_load() -> CPULoad {
match LOAD_AVERAGE.get() {
None => {
LOAD_AVERAGE.get_or_init(|| {
Mutex::new(systemstat().read().unwrap().cpu_load_aggregate().unwrap())
});
systemstat()
.read()
.unwrap()
.cpu_load_aggregate()
.unwrap()
.done()
.unwrap()
}
Some(v) => {
let mut v = v.lock().unwrap();
let load = v.done().unwrap();
*v = systemstat().read().unwrap().cpu_load_aggregate().unwrap();
load
}
}
}

pub(crate) fn header() -> String {
format!(
"top - {time} {uptime}, {user}, {load_average}\n\
{task}\n\
{cpu}\n\
{memory}\n\
{swap}",
time = chrono::Local::now().format("%H:%M:%S"),
uptime = uptime(),
user = user(),
load_average = load_average(),
task = task(),
cpu = cpu(),
memory = memory(),
swap = swap(),
)
}

fn todo() -> String {
"TODO".into()
}

fn format_memory(memory_b: u64, unit: u64) -> f64 {
ByteSize::b(memory_b).0 as f64 / unit as f64
}

fn uptime() -> String {
let binding = systemstat().read().unwrap();

let up_seconds = binding.uptime().unwrap().as_secs();
let up_minutes = (up_seconds % (60 * 60)) / 60;
let up_hours = (up_seconds % (24 * 60 * 60)) / (60 * 60);
let up_days = up_seconds / (24 * 60 * 60);

let mut res = String::from("up ");

if up_days > 0 {
res.push_str(&format!(
"{} day{}, ",
up_days,
if up_days > 1 { "s" } else { "" }
));
}
if up_hours > 0 {
res.push_str(&format!("{}:{:0>2}, ", up_hours, up_minutes));
} else {
res.push_str(&format!("{} min, ", up_minutes));
}

res
}

//TODO: Implement active user count
fn user() -> String {
todo()
}

fn load_average() -> String {
let binding = systemstat().read().unwrap();

let load_average = binding.load_average().unwrap();
format!(
"load average: {:.2}, {:.2}, {:.2}",
load_average.one, load_average.five, load_average.fifteen
)
}

fn task() -> String {
let binding = sysinfo().read().unwrap();

let process = binding.processes();
let mut running_process = 0;
let mut sleeping_process = 0;
let mut stopped_process = 0;
let mut zombie_process = 0;

for (_, process) in process.iter() {
match process.status() {
sysinfo::ProcessStatus::Run => running_process += 1,
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
sysinfo::ProcessStatus::Stop => stopped_process += 1,
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
_ => {}
};
}

format!(
"Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie",
process.len(),
running_process,
sleeping_process,
stopped_process,
zombie_process,
)
}

//TODO: Implement hardware interrupt, software interrupt and steal time
fn cpu() -> String {
let cpu = cpu_load();
format!(
"%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa",
cpu.user * 100.0,
cpu.system * 100.0,
cpu.nice * 100.0,
cpu.idle * 100.0,
cpu.platform.iowait * 100.0
)
}

fn memory() -> String {
let binding = sysinfo().read().unwrap();
//TODO: unit from argument
let unit = bytesize::MIB;

format!(
"MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache",
format_memory(binding.total_memory(), unit),
format_memory(binding.free_memory(), unit),
format_memory(binding.used_memory(), unit),
format_memory(binding.total_memory() - binding.free_memory(), unit),
)
}

fn swap() -> String {
let binding = sysinfo().read().unwrap();
//TODO: unit from argument
let unit = bytesize::MIB;

format!(
"MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem",
format_memory(binding.total_swap(), unit),
format_memory(binding.free_swap(), unit),
format_memory(binding.used_swap(), unit),
format_memory(binding.total_memory() - binding.free_memory(), unit),
)
}
94 changes: 11 additions & 83 deletions src/uu/top/src/top.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

use crate::picker::systemstat;
use bytesize::ByteSize;
use crate::header::cpu_load;
use clap::{arg, crate_version, value_parser, ArgAction, ArgGroup, ArgMatches, Command};
use header::header;
use picker::pickers;
use picker::sysinfo;
use prettytable::{format::consts::FORMAT_CLEAN, Row, Table};
use std::{thread::sleep, time::Duration};
use sysinfo::{Pid, Users};
use systemstat::{CPULoad, Platform};
use uucore::{
error::{UResult, USimpleError},
format_usage, help_about, help_usage,
Expand All @@ -21,6 +20,7 @@ const ABOUT: &str = help_about!("top.md");
const USAGE: &str = help_usage!("top.md");

mod field;
mod header;
mod picker;

#[allow(unused)]
Expand Down Expand Up @@ -56,10 +56,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// Must refresh twice.
// https://docs.rs/sysinfo/0.31.2/sysinfo/struct.System.html#method.refresh_cpu_usage
picker::sysinfo().write().unwrap().refresh_all();
let cpu_load = systemstat().read().unwrap().cpu_load_aggregate()?;
// Similar to the above.
cpu_load();
sleep(Duration::from_millis(200));
picker::sysinfo().write().unwrap().refresh_all();
let cpu_load = cpu_load.done()?;

let settings = Settings::new(&matches);

Expand Down Expand Up @@ -102,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
table
};

println!("{}", header(cpu_load));
println!("{}", header());
println!("\n");

let cutter = {
Expand All @@ -118,8 +118,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
};

table.to_string().lines().map(cutter).for_each(|_| {});
// .for_each(|it| println!("{}", it));
table
.to_string()
.lines()
.map(cutter)
.for_each(|it| println!("{}", it));

Ok(())
}
Expand Down Expand Up @@ -159,81 +162,6 @@ where
}
}

fn format_uptime(duration: Duration) -> String {
let mut num = duration.as_secs();
if num < 60 {
return format!("{} s", num);
}

num /= 60; //to minutes
if num < 60 {
return format!("{} m", num);
}
if num < 600 {
return format!("{}:{:2}", num / 60, num % 60);
}

num /= 60; //to hours
if num < 24 {
format!("{} h", num)
} else {
num /= 24; //to days
format!("{} d", num)
}
}

// TODO: Implement information collecting.
fn header(cpu_load: CPULoad) -> String {
let systemstat = systemstat().read().unwrap();
let sysinfo = sysinfo().read().unwrap();
let process = sysinfo.processes();
let mut running_process = 0;
let mut sleeping_process = 0;
let mut stopped_process = 0;
let mut zombie_process = 0;
for (_, process) in process.iter() {
match process.status() {
sysinfo::ProcessStatus::Run => running_process += 1,
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
sysinfo::ProcessStatus::Stop => stopped_process += 1,
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
_ => {}
};
}

//, {} hi, {} si, {} st
format!(
"top - {} up {}, %n user, load average: {:.2}, {:.2}, {:.2}\n\
Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie\n\
%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa\n\
MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache\n\
MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem\n",
chrono::Local::now().format("%H:%M:%S"),
format_uptime(systemstat.uptime().unwrap()),
systemstat.load_average().unwrap().one,
systemstat.load_average().unwrap().five,
systemstat.load_average().unwrap().fifteen,
process.len(),
running_process,
sleeping_process,
stopped_process,
zombie_process,
cpu_load.user * 100.0,
cpu_load.system * 100.0,
cpu_load.nice * 100.0,
cpu_load.idle * 100.0,
cpu_load.platform.iowait * 100.0,
ByteSize::b(sysinfo.total_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.used_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.free_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.used_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
)
}

// TODO: Implement fields selecting
fn selected_fields() -> Vec<String> {
vec![
Expand Down

0 comments on commit d29e761

Please sign in to comment.