Skip to content

Commit d29e761

Browse files
committed
split logic
1 parent a7a6702 commit d29e761

File tree

2 files changed

+177
-83
lines changed

2 files changed

+177
-83
lines changed

src/uu/top/src/header.rs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
use crate::picker::{sysinfo, systemstat};
2+
use bytesize::ByteSize;
3+
use std::sync::{Mutex, OnceLock};
4+
use systemstat::{CPULoad, DelayedMeasurement, Platform};
5+
6+
static LOAD_AVERAGE: OnceLock<Mutex<DelayedMeasurement<CPULoad>>> = OnceLock::new();
7+
8+
pub(crate) fn cpu_load() -> CPULoad {
9+
match LOAD_AVERAGE.get() {
10+
None => {
11+
LOAD_AVERAGE.get_or_init(|| {
12+
Mutex::new(systemstat().read().unwrap().cpu_load_aggregate().unwrap())
13+
});
14+
systemstat()
15+
.read()
16+
.unwrap()
17+
.cpu_load_aggregate()
18+
.unwrap()
19+
.done()
20+
.unwrap()
21+
}
22+
Some(v) => {
23+
let mut v = v.lock().unwrap();
24+
let load = v.done().unwrap();
25+
*v = systemstat().read().unwrap().cpu_load_aggregate().unwrap();
26+
load
27+
}
28+
}
29+
}
30+
31+
pub(crate) fn header() -> String {
32+
format!(
33+
"top - {time} {uptime}, {user}, {load_average}\n\
34+
{task}\n\
35+
{cpu}\n\
36+
{memory}\n\
37+
{swap}",
38+
time = chrono::Local::now().format("%H:%M:%S"),
39+
uptime = uptime(),
40+
user = user(),
41+
load_average = load_average(),
42+
task = task(),
43+
cpu = cpu(),
44+
memory = memory(),
45+
swap = swap(),
46+
)
47+
}
48+
49+
fn todo() -> String {
50+
"TODO".into()
51+
}
52+
53+
fn format_memory(memory_b: u64, unit: u64) -> f64 {
54+
ByteSize::b(memory_b).0 as f64 / unit as f64
55+
}
56+
57+
fn uptime() -> String {
58+
let binding = systemstat().read().unwrap();
59+
60+
let up_seconds = binding.uptime().unwrap().as_secs();
61+
let up_minutes = (up_seconds % (60 * 60)) / 60;
62+
let up_hours = (up_seconds % (24 * 60 * 60)) / (60 * 60);
63+
let up_days = up_seconds / (24 * 60 * 60);
64+
65+
let mut res = String::from("up ");
66+
67+
if up_days > 0 {
68+
res.push_str(&format!(
69+
"{} day{}, ",
70+
up_days,
71+
if up_days > 1 { "s" } else { "" }
72+
));
73+
}
74+
if up_hours > 0 {
75+
res.push_str(&format!("{}:{:0>2}, ", up_hours, up_minutes));
76+
} else {
77+
res.push_str(&format!("{} min, ", up_minutes));
78+
}
79+
80+
res
81+
}
82+
83+
//TODO: Implement active user count
84+
fn user() -> String {
85+
todo()
86+
}
87+
88+
fn load_average() -> String {
89+
let binding = systemstat().read().unwrap();
90+
91+
let load_average = binding.load_average().unwrap();
92+
format!(
93+
"load average: {:.2}, {:.2}, {:.2}",
94+
load_average.one, load_average.five, load_average.fifteen
95+
)
96+
}
97+
98+
fn task() -> String {
99+
let binding = sysinfo().read().unwrap();
100+
101+
let process = binding.processes();
102+
let mut running_process = 0;
103+
let mut sleeping_process = 0;
104+
let mut stopped_process = 0;
105+
let mut zombie_process = 0;
106+
107+
for (_, process) in process.iter() {
108+
match process.status() {
109+
sysinfo::ProcessStatus::Run => running_process += 1,
110+
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
111+
sysinfo::ProcessStatus::Stop => stopped_process += 1,
112+
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
113+
_ => {}
114+
};
115+
}
116+
117+
format!(
118+
"Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie",
119+
process.len(),
120+
running_process,
121+
sleeping_process,
122+
stopped_process,
123+
zombie_process,
124+
)
125+
}
126+
127+
//TODO: Implement hardware interrupt, software interrupt and steal time
128+
fn cpu() -> String {
129+
let cpu = cpu_load();
130+
format!(
131+
"%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa",
132+
cpu.user * 100.0,
133+
cpu.system * 100.0,
134+
cpu.nice * 100.0,
135+
cpu.idle * 100.0,
136+
cpu.platform.iowait * 100.0
137+
)
138+
}
139+
140+
fn memory() -> String {
141+
let binding = sysinfo().read().unwrap();
142+
//TODO: unit from argument
143+
let unit = bytesize::MIB;
144+
145+
format!(
146+
"MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache",
147+
format_memory(binding.total_memory(), unit),
148+
format_memory(binding.free_memory(), unit),
149+
format_memory(binding.used_memory(), unit),
150+
format_memory(binding.total_memory() - binding.free_memory(), unit),
151+
)
152+
}
153+
154+
fn swap() -> String {
155+
let binding = sysinfo().read().unwrap();
156+
//TODO: unit from argument
157+
let unit = bytesize::MIB;
158+
159+
format!(
160+
"MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem",
161+
format_memory(binding.total_swap(), unit),
162+
format_memory(binding.free_swap(), unit),
163+
format_memory(binding.used_swap(), unit),
164+
format_memory(binding.total_memory() - binding.free_memory(), unit),
165+
)
166+
}

src/uu/top/src/top.rs

Lines changed: 11 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

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

2322
mod field;
23+
mod header;
2424
mod picker;
2525

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

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

@@ -102,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
102102
table
103103
};
104104

105-
println!("{}", header(cpu_load));
105+
println!("{}", header());
106106
println!("\n");
107107

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

121-
table.to_string().lines().map(cutter).for_each(|_| {});
122-
// .for_each(|it| println!("{}", it));
121+
table
122+
.to_string()
123+
.lines()
124+
.map(cutter)
125+
.for_each(|it| println!("{}", it));
123126

124127
Ok(())
125128
}
@@ -159,81 +162,6 @@ where
159162
}
160163
}
161164

162-
fn format_uptime(duration: Duration) -> String {
163-
let mut num = duration.as_secs();
164-
if num < 60 {
165-
return format!("{} s", num);
166-
}
167-
168-
num /= 60; //to minutes
169-
if num < 60 {
170-
return format!("{} m", num);
171-
}
172-
if num < 600 {
173-
return format!("{}:{:2}", num / 60, num % 60);
174-
}
175-
176-
num /= 60; //to hours
177-
if num < 24 {
178-
format!("{} h", num)
179-
} else {
180-
num /= 24; //to days
181-
format!("{} d", num)
182-
}
183-
}
184-
185-
// TODO: Implement information collecting.
186-
fn header(cpu_load: CPULoad) -> String {
187-
let systemstat = systemstat().read().unwrap();
188-
let sysinfo = sysinfo().read().unwrap();
189-
let process = sysinfo.processes();
190-
let mut running_process = 0;
191-
let mut sleeping_process = 0;
192-
let mut stopped_process = 0;
193-
let mut zombie_process = 0;
194-
for (_, process) in process.iter() {
195-
match process.status() {
196-
sysinfo::ProcessStatus::Run => running_process += 1,
197-
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
198-
sysinfo::ProcessStatus::Stop => stopped_process += 1,
199-
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
200-
_ => {}
201-
};
202-
}
203-
204-
//, {} hi, {} si, {} st
205-
format!(
206-
"top - {} up {}, %n user, load average: {:.2}, {:.2}, {:.2}\n\
207-
Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie\n\
208-
%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa\n\
209-
MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache\n\
210-
MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem\n",
211-
chrono::Local::now().format("%H:%M:%S"),
212-
format_uptime(systemstat.uptime().unwrap()),
213-
systemstat.load_average().unwrap().one,
214-
systemstat.load_average().unwrap().five,
215-
systemstat.load_average().unwrap().fifteen,
216-
process.len(),
217-
running_process,
218-
sleeping_process,
219-
stopped_process,
220-
zombie_process,
221-
cpu_load.user * 100.0,
222-
cpu_load.system * 100.0,
223-
cpu_load.nice * 100.0,
224-
cpu_load.idle * 100.0,
225-
cpu_load.platform.iowait * 100.0,
226-
ByteSize::b(sysinfo.total_memory()).0 as f64 / bytesize::MIB as f64,
227-
ByteSize::b(sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
228-
ByteSize::b(sysinfo.used_memory()).0 as f64 / bytesize::MIB as f64,
229-
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
230-
ByteSize::b(sysinfo.total_swap()).0 as f64 / bytesize::MIB as f64,
231-
ByteSize::b(sysinfo.free_swap()).0 as f64 / bytesize::MIB as f64,
232-
ByteSize::b(sysinfo.used_swap()).0 as f64 / bytesize::MIB as f64,
233-
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
234-
)
235-
}
236-
237165
// TODO: Implement fields selecting
238166
fn selected_fields() -> Vec<String> {
239167
vec![

0 commit comments

Comments
 (0)