xref: /DragonOS/kernel/src/filesystem/procfs/kmsg.rs (revision 9284987850c1da2ce607a539eeae8a353a8f6df9)
1 use super::log::{LogLevel, LogMessage};
2 
3 use crate::libs::spinlock::SpinLock;
4 
5 use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
6 
7 use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer};
8 
9 use system_error::SystemError;
10 
11 /// 缓冲区容量
12 const KMSG_BUFFER_CAPACITY: usize = 1024;
13 
14 /// 全局环形缓冲区
15 pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
16 
17 /// 初始化KMSG
18 pub fn kmsg_init() {
19     let kmsg = SpinLock::new(Kmsg::new());
20     unsafe { KMSG = Some(kmsg) };
21 }
22 
23 /// 日志
24 pub struct Kmsg {
25     /// 环形缓冲区
26     buffer: AllocRingBuffer<LogMessage>,
27     /// 缓冲区字节数组
28     data: Vec<u8>,
29     /// 能够输出到控制台的日志级别,当console_loglevel为DEFAULT时,表示可以打印所有级别的日志消息到控制台
30     console_loglevel: LogLevel,
31     /// 判断buffer在上一次转成字节数组之后是否发生变动
32     is_changed: bool,
33 }
34 
35 impl Kmsg {
36     pub fn new() -> Self {
37         Kmsg {
38             buffer: AllocRingBuffer::new(KMSG_BUFFER_CAPACITY),
39             data: Vec::new(),
40             console_loglevel: LogLevel::DEFAULT,
41             is_changed: false,
42         }
43     }
44 
45     /// 添加日志消息
46     pub fn push(&mut self, msg: LogMessage) {
47         self.buffer.push(msg);
48         self.is_changed = true;
49     }
50 
51     /// 读取缓冲区
52     pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
53         self.tobytes();
54 
55         match self.console_loglevel {
56             LogLevel::DEFAULT => self.read_all(buf),
57             _ => self.read_level(buf),
58         }
59     }
60 
61     /// 读取缓冲区所有日志消息
62     fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
63         let len = self.data.len().min(buf.len());
64 
65         // 拷贝数据
66         let src = &self.data[0..len];
67         buf[0..src.len()].copy_from_slice(src);
68 
69         return Ok(src.len());
70     }
71 
72     /// 读取缓冲区特定level的日志消息
73     fn read_level(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
74         let mut data_level: Vec<u8> = Vec::new();
75 
76         for msg in self.buffer.iter() {
77             if msg.level() == self.console_loglevel {
78                 data_level.append(&mut msg.to_string().as_bytes().to_owned());
79             }
80         }
81 
82         let len = data_level.len().min(buf.len());
83 
84         // 拷贝数据
85         let src = &data_level[0..len];
86         buf[0..src.len()].copy_from_slice(src);
87 
88         // 将控制台输出日志level改回默认,否则之后都是打印特定level的日志消息
89         self.console_loglevel = LogLevel::DEFAULT;
90 
91         return Ok(data_level.len());
92     }
93 
94     /// 读取并清空缓冲区
95     pub fn read_clear(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
96         let r = self.read_all(buf);
97         self.clear()?;
98 
99         return r;
100     }
101 
102     /// 清空缓冲区
103     pub fn clear(&mut self) -> Result<usize, SystemError> {
104         self.buffer.clear();
105         self.data.clear();
106 
107         return Ok(0);
108     }
109 
110     /// 设置输出到控制台的日志级别
111     pub fn set_level(&mut self, log_level: usize) -> Result<usize, SystemError> {
112         let log_level = log_level - 1;
113 
114         self.console_loglevel = match log_level {
115             0 => LogLevel::EMERG,
116             1 => LogLevel::ALERT,
117             2 => LogLevel::CRIT,
118             3 => LogLevel::ERR,
119             4 => LogLevel::WARN,
120             5 => LogLevel::NOTICE,
121             6 => LogLevel::INFO,
122             7 => LogLevel::DEBUG,
123             8 => LogLevel::DEFAULT,
124             _ => return Err(SystemError::EINVAL),
125         };
126 
127         return Ok(0);
128     }
129 
130     /// 将环形缓冲区的日志消息转成字节数组以拷入用户buf
131     fn tobytes(&mut self) -> usize {
132         if self.is_changed {
133             self.data.clear();
134 
135             if self.console_loglevel == LogLevel::DEFAULT {
136                 for msg in self.buffer.iter() {
137                     self.data.append(&mut msg.to_string().as_bytes().to_owned());
138                 }
139             }
140 
141             self.is_changed = false;
142         }
143 
144         return self.data.len();
145     }
146 
147     // 返回内核缓冲区所占字节数
148     pub fn data_size(&mut self) -> Result<usize, SystemError> {
149         return Ok(self.tobytes());
150     }
151 }
152