fix: docker update mem&cpu use binate value

spawn_id for mem&cpu use the current binate value, to enable two concurrent executes from the same docker container id
This commit is contained in:
Jack Wills
2022-09-07 04:18:30 +00:00
parent fd0081ee7f
commit 7ec58e79a1
3 changed files with 62 additions and 51 deletions
+2 -2
View File
@@ -443,7 +443,7 @@ impl AppData {
if f.starts_with('/') { if f.starts_with('/') {
f.remove(0); f.remove(0);
} }
f.to_string() f.clone()
}) })
}); });
@@ -457,7 +457,7 @@ impl AppData {
.as_ref() .as_ref()
.map_or("".to_owned(), |f| f.trim().to_owned()); .map_or("".to_owned(), |f| f.trim().to_owned());
let image = i.image.as_ref().map_or("".to_owned(), |f| f.clone()); let image = i.image.as_ref().map_or("".to_owned(), std::clone::Clone::clone);
if let Some(current_container) = self.get_container_by_id(id) { if let Some(current_container) = self.get_container_by_id(id) {
if current_container.name != name { if current_container.name != name {
+43 -32
View File
@@ -7,7 +7,6 @@ use futures_util::StreamExt;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@@ -24,19 +23,28 @@ use crate::{
mod message; mod message;
pub use message::DockerMessage; pub use message::DockerMessage;
#[derive(Debug, Hash, Clone, PartialEq, Eq)] #[derive(Debug, Hash, Clone, PartialEq, Eq)]
enum SpawnId { enum SpawnId {
Stats(String), Stats((String, Binate)),
Log(String), Log(String),
} }
impl fmt::Display for SpawnId { /// Cpu & Mem stats take twice as long as the update interval to get a value, so will have two being executed at the same time
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// SpawnId::Stats takes container_id and binate value to enable both cycles of the same container to be inserted into the hashmap
let disp = match self { /// Binate value is toggled when all join handles have been spawned off
Self::Stats(id) => format!("stats::{id}"), #[derive(Debug, Hash, Clone, PartialEq, Eq)]
Self::Log(id) => format!("logs::{id}"), enum Binate {
One,
Two
}
impl Binate {
fn toggle(&mut self) {
*self = match self {
Self::One => Self::Two,
Self::Two => Self::One,
}; };
write!(f, "{}", disp)
} }
} }
@@ -49,6 +57,7 @@ pub struct DockerData {
receiver: Receiver<DockerMessage>, receiver: Receiver<DockerMessage>,
spawns: Arc<Mutex<HashMap<SpawnId, JoinHandle<()>>>>, spawns: Arc<Mutex<HashMap<SpawnId, JoinHandle<()>>>>,
timestamps: bool, timestamps: bool,
binate: Binate
} }
impl DockerData { impl DockerData {
@@ -88,6 +97,7 @@ impl DockerData {
app_data: Arc<Mutex<AppData>>, app_data: Arc<Mutex<AppData>>,
is_running: bool, is_running: bool,
spawns: Arc<Mutex<HashMap<SpawnId, JoinHandle<()>>>>, spawns: Arc<Mutex<HashMap<SpawnId, JoinHandle<()>>>>,
spawn_id: SpawnId,
) { ) {
let mut stream = docker let mut stream = docker
.stats( .stats(
@@ -110,14 +120,15 @@ impl DockerData {
let cpu_stats = Self::calculate_usage(&stats); let cpu_stats = Self::calculate_usage(&stats);
let no_bytes = (0, 0); let no_bytes = || (0, 0);
let (rx, tx) = if let Some(key) = some_key { let (rx, tx) = if let Some(key) = some_key {
match stats.networks.unwrap_or_default().get(&key) { match stats.networks.unwrap_or_default().get(&key) {
Some(data) => (data.rx_bytes.to_owned(), data.tx_bytes.to_owned()), Some(data) => (data.rx_bytes, data.tx_bytes),
None => no_bytes, None => no_bytes(),
} }
} else { } else {
no_bytes no_bytes()
}; };
if is_running { if is_running {
@@ -134,7 +145,7 @@ impl DockerData {
.lock() .lock()
.update_stats(&id, None, None, mem_limit, rx, tx); .update_stats(&id, None, None, mem_limit, rx, tx);
} }
spawns.lock().remove(&SpawnId::Stats(id.clone())); spawns.lock().remove(&spawn_id);
} }
} }
@@ -147,19 +158,21 @@ impl DockerData {
let is_running = *is_running; let is_running = *is_running;
let id = id.clone(); let id = id.clone();
let key = SpawnId::Stats(id.clone()); let key = SpawnId::Stats((id.clone(), self.binate.clone()));
let spawn_contains_id = spawns.lock().contains_key(&key);
let s = tokio::spawn(Self::update_container_stat( let spawn_key = key.clone();
self.spawns.lock().entry(key).or_insert_with(|| {
tokio::spawn(Self::update_container_stat(
docker, docker,
id.clone(), id.clone(),
app_data, app_data,
is_running, is_running,
spawns, spawns,
)); spawn_key
if !spawn_contains_id { ))
self.spawns.lock().insert(key, s); });
}
} }
self.binate.toggle()
} }
/// Get all current containers, handle into ContainerItem in the app_data struct rather than here /// Get all current containers, handle into ContainerItem in the app_data struct rather than here
@@ -252,37 +265,34 @@ impl DockerData {
let app_data = Arc::clone(&self.app_data); let app_data = Arc::clone(&self.app_data);
let spawns = Arc::clone(&self.spawns); let spawns = Arc::clone(&self.spawns);
let key = SpawnId::Log(id.clone()); let key = SpawnId::Log(id.clone());
let join_handle = tokio::spawn(Self::update_log( self.spawns.lock().insert(key, tokio::spawn(Self::update_log(
docker, id, timestamps, 0, app_data, spawns, docker, id, timestamps, 0, app_data, spawns,
)); )));
self.spawns.lock().insert(key, join_handle);
} }
} }
/// Update all cpu_mem, and selected container log (if a log update join_handle isn't currently being executed)
async fn update_everything(&mut self) { async fn update_everything(&mut self) {
let all_ids = self.update_all_containers().await; let all_ids = self.update_all_containers().await;
let optional_index = self.app_data.lock().get_selected_log_index(); let optional_index = self.app_data.lock().get_selected_log_index();
if let Some(index) = optional_index { if let Some(index) = optional_index {
// this could be neater
let id = self.app_data.lock().containers.items[index].id.clone(); let id = self.app_data.lock().containers.items[index].id.clone();
let key = SpawnId::Log(id.clone()); let key = SpawnId::Log(id.clone());
let running = self.spawns.lock().contains_key(&key);
if !running { self.spawns.lock().entry(key).or_insert_with(|| {
let since = self.app_data.lock().containers.items[index].last_updated as i64; let since = self.app_data.lock().containers.items[index].last_updated as i64;
let docker = Arc::clone(&self.docker); let docker = Arc::clone(&self.docker);
let timestamps = self.timestamps; let timestamps = self.timestamps;
let app_data = Arc::clone(&self.app_data); let app_data = Arc::clone(&self.app_data);
let spawns = Arc::clone(&self.spawns); let spawns = Arc::clone(&self.spawns);
let s = tokio::spawn(Self::update_log( tokio::spawn(Self::update_log(
docker, id, timestamps, since, app_data, spawns, docker, id, timestamps, since, app_data, spawns,
)); ))
self.spawns.lock().insert(key, s); });
}
}; };
self.update_all_container_stats(&all_ids).await; self.update_all_container_stats(&all_ids).await;
} }
/// Animate the loading icon /// Animate the loading icon
@@ -413,6 +423,7 @@ impl DockerData {
spawns: Arc::new(Mutex::new(HashMap::new())), spawns: Arc::new(Mutex::new(HashMap::new())),
timestamps: args.timestamp, timestamps: args.timestamp,
is_running, is_running,
binate: Binate::One
}; };
inner.initialise_container_data().await; inner.initialise_container_data().await;
+10 -10
View File
@@ -143,8 +143,8 @@ impl InputHandler {
if show_error { if show_error {
match key_code { match key_code {
KeyCode::Char('q') | KeyCode::Char('Q') => self.quit().await, KeyCode::Char('q' | 'Q') => self.quit().await,
KeyCode::Char('c') | KeyCode::Char('C') => { KeyCode::Char('c' | 'C') => {
self.app_data.lock().show_error = false; self.app_data.lock().show_error = false;
self.app_data.lock().remove_error(); self.app_data.lock().remove_error();
} }
@@ -152,9 +152,9 @@ impl InputHandler {
} }
} else if show_info { } else if show_info {
match key_code { match key_code {
KeyCode::Char('q') | KeyCode::Char('Q') => self.quit().await, KeyCode::Char('q' | 'Q') => self.quit().await,
KeyCode::Char('h') | KeyCode::Char('H') => self.gui_state.lock().show_help = false, KeyCode::Char('h' | 'H') => self.gui_state.lock().show_help = false,
KeyCode::Char('m') | KeyCode::Char('M') => self.m_button(), KeyCode::Char('m' | 'M') => self.m_button(),
_ => (), _ => (),
} }
} else { } else {
@@ -169,9 +169,9 @@ impl InputHandler {
KeyCode::Char('7') => self.sort(Header::Image), KeyCode::Char('7') => self.sort(Header::Image),
KeyCode::Char('8') => self.sort(Header::Rx), KeyCode::Char('8') => self.sort(Header::Rx),
KeyCode::Char('9') => self.sort(Header::Tx), KeyCode::Char('9') => self.sort(Header::Tx),
KeyCode::Char('q') | KeyCode::Char('Q') => self.quit().await, KeyCode::Char('q' | 'Q') => self.quit().await,
KeyCode::Char('h') | KeyCode::Char('H') => self.gui_state.lock().show_help = true, KeyCode::Char('h' | 'H') => self.gui_state.lock().show_help = true,
KeyCode::Char('m') | KeyCode::Char('M') => self.m_button(), KeyCode::Char('m' | 'M') => self.m_button(),
KeyCode::Tab => { KeyCode::Tab => {
// Skip control panel if no containers, could be refactored // Skip control panel if no containers, could be refactored
let has_containers = self.app_data.lock().get_container_len() == 0; let has_containers = self.app_data.lock().get_container_len() == 0;
@@ -216,13 +216,13 @@ impl InputHandler {
SelectablePanel::Commands => locked_data.docker_command_end(), SelectablePanel::Commands => locked_data.docker_command_end(),
} }
} }
KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => self.previous(), KeyCode::Up | KeyCode::Char('k' | 'K') => self.previous(),
KeyCode::PageUp => { KeyCode::PageUp => {
for _ in 0..=6 { for _ in 0..=6 {
self.previous(); self.previous();
} }
} }
KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => self.next(), KeyCode::Down | KeyCode::Char('j' | 'J') => self.next(),
KeyCode::PageDown => { KeyCode::PageDown => {
for _ in 0..=6 { for _ in 0..=6 {
self.next(); self.next();