diff --git a/src/main.rs b/src/main.rs index 106dab4..88c7f24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,13 +27,18 @@ async fn main() -> Result<(), Box> { sender.clone(), Uuid::new_v4().to_string().into(), )), - Arc::new(tiles::Hostname::new( + Arc::new(tiles::Memory::new( 1, sender.clone(), Uuid::new_v4().to_string().into(), )), - Arc::new(tiles::Time::new( + Arc::new(tiles::Hostname::new( 2, + sender.clone(), + Uuid::new_v4().to_string().into(), + )), + Arc::new(tiles::Time::new( + 3, sender, Uuid::new_v4().to_string().into(), )), diff --git a/src/output.rs b/src/output.rs index b079fd8..9bf8e14 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,7 +1,7 @@ use crate::tile::TileData; +use std::convert::Infallible; use tokio::io::{self, AsyncWriteExt}; use tokio::sync::mpsc::Receiver; -use std::convert::Infallible; pub async fn launch(num_tiles: usize, mut receiver: Receiver) -> io::Result { let mut stdout = io::stdout(); diff --git a/src/tile.rs b/src/tile.rs index 1bd0159..ee80be0 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,7 +1,7 @@ -use serde::{Serialize, ser::Serializer}; +use serde::{ser::Serializer, Serialize}; +use smart_default::SmartDefault; use std::sync::Arc; use tokio::task::JoinHandle; -use smart_default::SmartDefault; #[derive(Copy, Clone, Debug, Serialize)] #[serde(rename_all = "lowercase")] @@ -30,7 +30,10 @@ impl Default for Markup { } } -fn arc_default(arc: &Arc, serializer: S) -> Result where S: Serializer { +fn arc_default(arc: &Arc, serializer: S) -> Result +where + S: Serializer, +{ serializer.serialize_str(arc) } @@ -77,6 +80,6 @@ pub struct TileData { pub block: Block, } -pub trait Tile: Send { +pub trait Tile: Send + std::fmt::Debug { fn spawn(self: Arc) -> JoinHandle>>; } diff --git a/src/tiles/hostname.rs b/src/tiles/hostname.rs index 1476c47..640cae5 100644 --- a/src/tiles/hostname.rs +++ b/src/tiles/hostname.rs @@ -6,6 +6,7 @@ use tokio::sync::mpsc::{error::SendError, Sender}; use tokio::sync::RwLock; use tokio::task::JoinHandle; +#[derive(Debug)] pub struct Hostname { sender_id: usize, sender: RwLock>, diff --git a/src/tiles/load.rs b/src/tiles/load.rs index ee183f7..44b4aa6 100644 --- a/src/tiles/load.rs +++ b/src/tiles/load.rs @@ -8,6 +8,7 @@ use tokio::sync::RwLock; use tokio::task::JoinHandle; use tokio::time::interval; +#[derive(Debug)] pub struct Load { sender_id: usize, sender: RwLock>, diff --git a/src/tiles/memory.rs b/src/tiles/memory.rs new file mode 100644 index 0000000..7730ae8 --- /dev/null +++ b/src/tiles/memory.rs @@ -0,0 +1,121 @@ +use crate::tile::{Block, Tile, TileData}; +use std::io; +use std::str; +use std::sync::Arc; +use std::time::Duration; +use tokio::fs::File; +use tokio::prelude::*; +use tokio::sync::mpsc::{error::SendError, Sender}; +use tokio::sync::RwLock; +use tokio::task::JoinHandle; +use tokio::time::interval; + +#[derive(Debug)] +pub struct Memory { + sender_id: usize, + sender: RwLock>, + instance: Arc, +} + +impl Memory { + pub fn new(sender_id: usize, sender: Sender, instance: Arc) -> Memory { + Memory { + sender_id, + sender: RwLock::new(sender), + instance, + } + } + + async fn send(&self, data: TileData) -> Result<(), SendError> { + let mut sender = self.sender.write().await; + sender.send(data).await + } + + fn prettify_kib(kib: u64) -> Box { + if kib > u64::MAX / 1024 { + panic!("Too much memory"); + } + let mut mem = kib; + let mut stages = 0u8; + while mem >= 1024 { + stages += 1; + mem /= 1024; + } + format!( + "{} {}iB", + mem, + match stages { + 0 => 'k', + 1 => 'M', + 2 => 'G', + 3 => 'T', + 4 => 'P', + 5 => 'E', + 6 => 'Z', + _ => panic!("Too much memory, for real this time"), + } + ) + .into_boxed_str() + } + + fn extract_value(line: &str) -> Result> { + let mut parts = line.split_whitespace(); + parts.next(); + Ok(parts + .next() + .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))? + .parse()?) + } + + async fn run(&self) -> Result<(), Box> { + let mut timer = interval(Duration::from_secs(5)); + let mut raw = [0u8; 256]; + loop { + timer.tick().await; + File::open("/proc/meminfo") + .await? + .read_exact(&mut raw) + .await?; + let string_data = str::from_utf8(&raw)?; + let mut lines = string_data.split('\n'); + let mem_total = Memory::prettify_kib(Memory::extract_value( + lines + .next() + .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?, + )?); + lines.next(); + let mem_avail = Memory::prettify_kib(Memory::extract_value( + lines + .next() + .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?, + )?); + + let full_text = format!("{} avail / {}", mem_avail, mem_total).into_boxed_str(); + let short_text = format!("{} / {}", mem_avail, mem_total).into_boxed_str(); + + let block = Block { + full_text, + short_text: Some(short_text), + instance: self.instance.clone(), + name: "memory".into(), + ..Default::default() + }; + let data = TileData { + block, + sender_id: self.sender_id, + }; + self.send(data).await?; + } + } +} + +impl Tile for Memory { + fn spawn(self: Arc) -> JoinHandle>> { + tokio::spawn(async move { + let instance = self; + let result = instance.run().await; + eprintln!("Error in Memory: {:?}", result); + result + }) + } +} diff --git a/src/tiles/mod.rs b/src/tiles/mod.rs index 0862d20..4affbe0 100644 --- a/src/tiles/mod.rs +++ b/src/tiles/mod.rs @@ -1,6 +1,8 @@ pub mod hostname; pub mod load; +pub mod memory; pub mod time; pub use hostname::Hostname; pub use load::Load; +pub use memory::Memory; pub use time::Time; diff --git a/src/tiles/time.rs b/src/tiles/time.rs index 768b9c1..8c753d7 100644 --- a/src/tiles/time.rs +++ b/src/tiles/time.rs @@ -8,6 +8,7 @@ use tokio::sync::RwLock; use tokio::task::JoinHandle; use tokio::time::delay_for; +#[derive(Debug)] pub struct Time { sender_id: usize, sender: RwLock>,