runtime/logger: use blocking wait.

Fixes #84 using the first solution.

If the performance is considered too slow,
we can do the second option later.
This commit is contained in:
pca006132 2020-08-05 16:20:20 +08:00 committed by Gitea
parent 4b6c5d5679
commit c85e85aa6d
2 changed files with 26 additions and 16 deletions

View File

@ -38,7 +38,8 @@ impl<'a> Drop for LogBufferRef<'a> {
pub struct BufferLogger {
buffer: Mutex<LogBuffer<&'static mut [u8]>>,
uart_filter: Cell<LevelFilter>
uart_filter: Cell<LevelFilter>,
buffer_filter: Cell<LevelFilter>,
}
static mut LOGGER: Option<BufferLogger> = None;
@ -48,6 +49,7 @@ impl BufferLogger {
BufferLogger {
buffer: Mutex::new(LogBuffer::new(buffer)),
uart_filter: Cell::new(LevelFilter::Info),
buffer_filter: Cell::new(LevelFilter::Trace),
}
}
@ -76,6 +78,15 @@ impl BufferLogger {
pub fn set_uart_log_level(&self, max_level: LevelFilter) {
self.uart_filter.set(max_level)
}
pub fn buffer_log_level(&self) -> LevelFilter {
self.buffer_filter.get()
}
/// this should be reserverd for mgmt module
pub fn set_buffer_log_level(&self, max_level: LevelFilter) {
self.buffer_filter.set(max_level)
}
}
// required for impl Log
@ -94,7 +105,8 @@ impl Log for BufferLogger {
let seconds = timestamp / 1_000_000;
let micros = timestamp % 1_000_000;
if let Some(mut buffer) = self.buffer.try_lock() {
if record.level() <= self.buffer_log_level() {
let mut buffer = self.buffer.lock();
writeln!(buffer, "[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
record.level(), record.target(), record.args()).unwrap();
}

View File

@ -98,9 +98,9 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
match msg {
Request::GetLog => {
let mut buffer = get_logger_buffer().await;
let buffer = get_logger_buffer().await.extract().as_bytes().to_vec();
write_i8(stream, Reply::LogContent as i8).await?;
write_chunk(stream, buffer.extract().as_bytes()).await?;
write_chunk(stream, &buffer).await?;
}
Request::ClearLog => {
let mut buffer = get_logger_buffer().await;
@ -115,24 +115,22 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
};
loop {
let mut buffer = get_logger_buffer_pred(|b| !b.is_empty()).await;
let bytes = buffer.extract().as_bytes();
if id != *pull_id.borrow() {
// another connection attempts to pull the log...
// abort this connection...
break;
}
write_chunk(stream, bytes).await?;
if log::max_level() == LevelFilter::Trace {
// Hold exclusive access over the logger until we get positive
// acknowledgement; otherwise we get an infinite loop of network
// trace messages being transmitted and causing more network
// trace messages to be emitted.
//
// Any messages unrelated to this management socket that arrive
// while it is flushed are lost, but such is life.
stream.flush().await?;
}
let bytes = buffer.extract().as_bytes().to_vec();
buffer.clear();
core::mem::drop(buffer);
write_chunk(stream, &bytes).await?;
if log::max_level() == LevelFilter::Trace {
// temporarily discard all trace level log
let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
logger.set_buffer_log_level(LevelFilter::Debug);
stream.flush().await?;
logger.set_buffer_log_level(LevelFilter::Trace);
}
}
},
Request::SetLogFilter => {