use try_read_for() with timeout for tui status updates (header and pool stats) (#3129)

* use try_read_for with timeout for tui status updates (header and pool stats)

* rework based on feedback
This commit is contained in:
Antioch Peverell 2019-11-22 12:46:07 +00:00 committed by GitHub
parent 32609fc542
commit 78220febed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 46 deletions

View file

@ -1216,21 +1216,23 @@ impl Chain {
.map_err(|e| ErrorKind::StoreErr(e, "chain tail".to_owned()).into()) .map_err(|e| ErrorKind::StoreErr(e, "chain tail".to_owned()).into())
} }
/// Tip (head) of the header chain if read lock can be acquired right now. /// Tip (head) of the header chain if read lock can be acquired reasonably quickly.
pub fn try_header_head(&self) -> Result<Option<Tip>, Error> { /// Used by the TUI when updating stats to avoid locking the TUI up.
match self.header_pmmr.try_read() { pub fn try_header_head(&self, timeout: Duration) -> Result<Option<Tip>, Error> {
Some(lock) => { self.header_pmmr
let hash = lock.head_hash()?; .try_read_for(timeout)
let header = self.store.get_block_header(&hash)?; .map(|ref pmmr| self.read_header_head(pmmr).map(|x| Some(x)))
Ok(Some(Tip::from_header(&header))) .unwrap_or(Ok(None))
}
None => Ok(None),
}
} }
/// Tip (head) of the header chain. /// Tip (head) of the header chain.
pub fn header_head(&self) -> Result<Tip, Error> { pub fn header_head(&self) -> Result<Tip, Error> {
let hash = self.header_pmmr.read().head_hash()?; self.read_header_head(&self.header_pmmr.read())
}
/// Read head from the provided PMMR handle.
fn read_header_head(&self, pmmr: &txhashset::PMMRHandle<BlockHeader>) -> Result<Tip, Error> {
let hash = pmmr.head_hash()?;
let header = self.store.get_block_header(&hash)?; let header = self.store.get_block_header(&hash)?;
Ok(Tip::from_header(&header)) Ok(Tip::from_header(&header))
} }

View file

@ -63,7 +63,7 @@ pub struct ServerStats {
/// Difficulty calculation statistics /// Difficulty calculation statistics
pub diff_stats: DiffStats, pub diff_stats: DiffStats,
/// Transaction pool statistics /// Transaction pool statistics
pub tx_stats: TxStats, pub tx_stats: Option<TxStats>,
/// Disk usage in GB /// Disk usage in GB
pub disk_usage_gb: String, pub disk_usage_gb: String,
} }

View file

@ -23,7 +23,7 @@ use std::path::Path;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use std::{ use std::{
thread::{self, JoinHandle}, thread::{self, JoinHandle},
time, time::{self, Duration},
}; };
use fs2::FileExt; use fs2::FileExt;
@ -480,23 +480,16 @@ impl Server {
.map(|p| PeerStats::from_peer(&p)) .map(|p| PeerStats::from_peer(&p))
.collect(); .collect();
let tx_stats = { // Updating TUI stats should not block any other processing so only attempt to
let pool = self.tx_pool.try_read(); // acquire various read locks with a timeout.
match pool { let read_timeout = Duration::from_millis(500);
Some(pool) => TxStats {
tx_pool_size: pool.txpool.size(), let tx_stats = self.tx_pool.try_read_for(read_timeout).map(|pool| TxStats {
tx_pool_kernels: pool.txpool.kernel_count(), tx_pool_size: pool.txpool.size(),
stem_pool_size: pool.stempool.size(), tx_pool_kernels: pool.txpool.kernel_count(),
stem_pool_kernels: pool.stempool.kernel_count(), stem_pool_size: pool.stempool.size(),
}, stem_pool_kernels: pool.stempool.kernel_count(),
None => TxStats { });
tx_pool_size: 0,
tx_pool_kernels: 0,
stem_pool_size: 0,
stem_pool_kernels: 0,
},
}
};
let head = self.chain.head_header()?; let head = self.chain.head_header()?;
let head_stats = ChainStats { let head_stats = ChainStats {
@ -506,16 +499,15 @@ impl Server {
total_difficulty: head.total_difficulty(), total_difficulty: head.total_difficulty(),
}; };
let header_stats = match self.chain.try_header_head()? { let header_stats = match self.chain.try_header_head(read_timeout)? {
Some(tip) => { Some(head) => self.chain.get_block_header(&head.hash()).map(|header| {
let header = self.chain.get_block_header(&tip.hash())?;
Some(ChainStats { Some(ChainStats {
latest_timestamp: header.timestamp, latest_timestamp: header.timestamp,
height: header.height, height: header.height,
last_block_h: header.prev_hash, last_block_h: header.prev_hash,
total_difficulty: header.total_difficulty(), total_difficulty: header.total_difficulty(),
}) })
} })?,
_ => None, _ => None,
}; };

View file

@ -284,18 +284,20 @@ impl TUIStatusListener for TUIStatusView {
t.set_content(header_stats.latest_timestamp.to_string()); t.set_content(header_stats.latest_timestamp.to_string());
}); });
} }
c.call_on_id("tx_pool_size", |t: &mut TextView| { if let Some(tx_stats) = &stats.tx_stats {
t.set_content(stats.tx_stats.tx_pool_size.to_string()); c.call_on_id("tx_pool_size", |t: &mut TextView| {
}); t.set_content(tx_stats.tx_pool_size.to_string());
c.call_on_id("stem_pool_size", |t: &mut TextView| { });
t.set_content(stats.tx_stats.stem_pool_size.to_string()); c.call_on_id("stem_pool_size", |t: &mut TextView| {
}); t.set_content(tx_stats.stem_pool_size.to_string());
c.call_on_id("tx_pool_kernels", |t: &mut TextView| { });
t.set_content(stats.tx_stats.tx_pool_kernels.to_string()); c.call_on_id("tx_pool_kernels", |t: &mut TextView| {
}); t.set_content(tx_stats.tx_pool_kernels.to_string());
c.call_on_id("stem_pool_kernels", |t: &mut TextView| { });
t.set_content(stats.tx_stats.stem_pool_kernels.to_string()); c.call_on_id("stem_pool_kernels", |t: &mut TextView| {
}); t.set_content(tx_stats.stem_pool_kernels.to_string());
});
}
} }
} }