Add memory tile

This commit is contained in:
Artemis Tosini 2020-06-03 02:38:26 +00:00
parent 8e93d7e363
commit 46d0f41f0f
Signed by: artemist
GPG key ID: EE5227935FE3FF18
8 changed files with 141 additions and 7 deletions

View file

@ -27,13 +27,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
sender.clone(), sender.clone(),
Uuid::new_v4().to_string().into(), Uuid::new_v4().to_string().into(),
)), )),
Arc::new(tiles::Hostname::new( Arc::new(tiles::Memory::new(
1, 1,
sender.clone(), sender.clone(),
Uuid::new_v4().to_string().into(), Uuid::new_v4().to_string().into(),
)), )),
Arc::new(tiles::Time::new( Arc::new(tiles::Hostname::new(
2, 2,
sender.clone(),
Uuid::new_v4().to_string().into(),
)),
Arc::new(tiles::Time::new(
3,
sender, sender,
Uuid::new_v4().to_string().into(), Uuid::new_v4().to_string().into(),
)), )),

View file

@ -1,7 +1,7 @@
use crate::tile::TileData; use crate::tile::TileData;
use std::convert::Infallible;
use tokio::io::{self, AsyncWriteExt}; use tokio::io::{self, AsyncWriteExt};
use tokio::sync::mpsc::Receiver; use tokio::sync::mpsc::Receiver;
use std::convert::Infallible;
pub async fn launch(num_tiles: usize, mut receiver: Receiver<TileData>) -> io::Result<Infallible> { pub async fn launch(num_tiles: usize, mut receiver: Receiver<TileData>) -> io::Result<Infallible> {
let mut stdout = io::stdout(); let mut stdout = io::stdout();

View file

@ -1,7 +1,7 @@
use serde::{Serialize, ser::Serializer}; use serde::{ser::Serializer, Serialize};
use smart_default::SmartDefault;
use std::sync::Arc; use std::sync::Arc;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use smart_default::SmartDefault;
#[derive(Copy, Clone, Debug, Serialize)] #[derive(Copy, Clone, Debug, Serialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
@ -30,7 +30,10 @@ impl Default for Markup {
} }
} }
fn arc_default<S>(arc: &Arc<str>, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { fn arc_default<S>(arc: &Arc<str>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(arc) serializer.serialize_str(arc)
} }
@ -77,6 +80,6 @@ pub struct TileData {
pub block: Block, pub block: Block,
} }
pub trait Tile: Send { pub trait Tile: Send + std::fmt::Debug {
fn spawn(self: Arc<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>>; fn spawn(self: Arc<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>>;
} }

View file

@ -6,6 +6,7 @@ use tokio::sync::mpsc::{error::SendError, Sender};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
#[derive(Debug)]
pub struct Hostname { pub struct Hostname {
sender_id: usize, sender_id: usize,
sender: RwLock<Sender<TileData>>, sender: RwLock<Sender<TileData>>,

View file

@ -8,6 +8,7 @@ use tokio::sync::RwLock;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tokio::time::interval; use tokio::time::interval;
#[derive(Debug)]
pub struct Load { pub struct Load {
sender_id: usize, sender_id: usize,
sender: RwLock<Sender<TileData>>, sender: RwLock<Sender<TileData>>,

121
src/tiles/memory.rs Normal file
View file

@ -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<Sender<TileData>>,
instance: Arc<str>,
}
impl Memory {
pub fn new(sender_id: usize, sender: Sender<TileData>, instance: Arc<str>) -> Memory {
Memory {
sender_id,
sender: RwLock::new(sender),
instance,
}
}
async fn send(&self, data: TileData) -> Result<(), SendError<TileData>> {
let mut sender = self.sender.write().await;
sender.send(data).await
}
fn prettify_kib(kib: u64) -> Box<str> {
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<u64, Box<dyn std::error::Error + Send + Sync>> {
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<dyn std::error::Error + Send + Sync>> {
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<Self>) -> JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
tokio::spawn(async move {
let instance = self;
let result = instance.run().await;
eprintln!("Error in Memory: {:?}", result);
result
})
}
}

View file

@ -1,6 +1,8 @@
pub mod hostname; pub mod hostname;
pub mod load; pub mod load;
pub mod memory;
pub mod time; pub mod time;
pub use hostname::Hostname; pub use hostname::Hostname;
pub use load::Load; pub use load::Load;
pub use memory::Memory;
pub use time::Time; pub use time::Time;

View file

@ -8,6 +8,7 @@ use tokio::sync::RwLock;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tokio::time::delay_for; use tokio::time::delay_for;
#[derive(Debug)]
pub struct Time { pub struct Time {
sender_id: usize, sender_id: usize,
sender: RwLock<Sender<TileData>>, sender: RwLock<Sender<TileData>>,