xref: /DragonOS/kernel/src/driver/block/cache/cached_block_device.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1eb49bb99S曾俊 use alloc::{boxed::Box, vec::Vec};
2eb49bb99S曾俊 use hashbrown::HashMap;
3*2eab6dd7S曾俊 use log::debug;
4eb49bb99S曾俊 
5eb49bb99S曾俊 use crate::{driver::base::block::block_device::BlockId, libs::rwlock::RwLock};
6eb49bb99S曾俊 
7eb49bb99S曾俊 use super::{
8eb49bb99S曾俊     cache_block::{CacheBlock, CacheBlockAddr},
9eb49bb99S曾俊     cache_iter::{BlockIter, FailData},
10eb49bb99S曾俊     BlockCacheError, BLOCK_SIZE, BLOCK_SIZE_LOG, CACHE_THRESHOLD,
11eb49bb99S曾俊 };
12eb49bb99S曾俊 
13eb49bb99S曾俊 static mut CSPACE: Option<LockedCacheSpace> = None;
14eb49bb99S曾俊 static mut CMAPPER: Option<LockedCacheMapper> = None;
15eb49bb99S曾俊 /// # 结构功能
16eb49bb99S曾俊 /// 该结构体向外提供BlockCache服务
17eb49bb99S曾俊 pub struct BlockCache;
18eb49bb99S曾俊 
19eb49bb99S曾俊 unsafe fn mapper() -> Result<&'static mut LockedCacheMapper, BlockCacheError> {
20eb49bb99S曾俊     unsafe {
21eb49bb99S曾俊         match &mut CMAPPER {
22eb49bb99S曾俊             Some(x) => return Ok(x),
23eb49bb99S曾俊             None => return Err(BlockCacheError::StaticParameterError),
24eb49bb99S曾俊         }
25eb49bb99S曾俊     };
26eb49bb99S曾俊 }
27eb49bb99S曾俊 
28eb49bb99S曾俊 unsafe fn space() -> Result<&'static mut LockedCacheSpace, BlockCacheError> {
29eb49bb99S曾俊     unsafe {
30eb49bb99S曾俊         match &mut CSPACE {
31eb49bb99S曾俊             Some(x) => return Ok(x),
32eb49bb99S曾俊             None => return Err(BlockCacheError::StaticParameterError),
33eb49bb99S曾俊         }
34eb49bb99S曾俊     };
35eb49bb99S曾俊 }
36eb49bb99S曾俊 
37eb49bb99S曾俊 impl BlockCache {
38eb49bb99S曾俊     /// # 函数的功能
39eb49bb99S曾俊     /// 初始化BlockCache需要的结构体
40eb49bb99S曾俊     pub fn init() {
41eb49bb99S曾俊         unsafe {
42eb49bb99S曾俊             CSPACE = Some(LockedCacheSpace::new(CacheSpace::new()));
43eb49bb99S曾俊             CMAPPER = Some(LockedCacheMapper::new(CacheMapper::new()));
44eb49bb99S曾俊         }
45*2eab6dd7S曾俊         debug!("BlockCache Initialized!");
46eb49bb99S曾俊     }
47eb49bb99S曾俊     /// # 函数的功能
48eb49bb99S曾俊     /// 使用blockcache进行对块设备进行连续块的读操作
49eb49bb99S曾俊     ///
50eb49bb99S曾俊     /// ## 参数:
51eb49bb99S曾俊     /// - 'lba_id_start' :连续块的起始块的lba_id
52eb49bb99S曾俊     /// - 'count' :从连续块算起需要读多少块
53eb49bb99S曾俊     /// - 'buf' :读取出来的数据存放在buf中
54eb49bb99S曾俊     ///
55eb49bb99S曾俊     /// ## 返回值:
56eb49bb99S曾俊     /// - Ok(usize) :表示读取块的个数
57eb49bb99S曾俊     /// - Err(BlockCacheError::BlockFaultError) :缺块的情况下,返回读取失败的块的数据,利用该返回值可以帮助blockcache插入读取失败的块值(见insert函数)
58eb49bb99S曾俊     /// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题,这种异常会在block_device中得到处理
59eb49bb99S曾俊     pub fn read(
60eb49bb99S曾俊         lba_id_start: BlockId,
61eb49bb99S曾俊         count: usize,
62eb49bb99S曾俊         buf: &mut [u8],
63eb49bb99S曾俊     ) -> Result<usize, BlockCacheError> {
64eb49bb99S曾俊         // 生成一个块迭代器(BlockIter),它可以迭代地给出所有需要块的数据,其中就包括lba_id
65eb49bb99S曾俊         let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
66eb49bb99S曾俊         // 调用检查函数,检查有无缺块,如果没有就可以获得所有块的Cache地址。如果失败了就直接返回FailData向量
67eb49bb99S曾俊         let cache_block_addr = Self::check_able_to_read(block_iter)?;
68eb49bb99S曾俊         // 块地址vec的长度应当等于块迭代器的大小
69eb49bb99S曾俊         assert!(cache_block_addr.len() == block_iter.count());
70eb49bb99S曾俊         // 迭代地读取cache并写入到buf中
71eb49bb99S曾俊         for (index, _) in block_iter.enumerate() {
72eb49bb99S曾俊             Self::read_one_block(cache_block_addr[index], index, buf)?;
73eb49bb99S曾俊         }
74eb49bb99S曾俊         return Ok(count);
75eb49bb99S曾俊     }
76eb49bb99S曾俊 
77eb49bb99S曾俊     /// # 函数的功能
78eb49bb99S曾俊     /// 检查cache中是否有缺块的函数
79eb49bb99S曾俊     ///
80eb49bb99S曾俊     /// ## 参数:
81eb49bb99S曾俊     /// - 'block_iter' :需要检查的块迭代器(因为块迭代器包含了需要读块的信息,所以传入块迭代器)
82eb49bb99S曾俊     ///
83eb49bb99S曾俊     /// ## 返回值:
84eb49bb99S曾俊     /// - Ok(Vec<CacheBlockAddr>) :如果成功了,那么函数会返回每个块的Cache地址,利用Cache地址就可以访问Cache了
85eb49bb99S曾俊     /// - Err(BlockCacheError::BlockFaultError) :如果发现了缺块,那么我们会返回所有缺块的信息(即FailData)
86eb49bb99S曾俊     /// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题
87eb49bb99S曾俊     fn check_able_to_read(block_iter: BlockIter) -> Result<Vec<CacheBlockAddr>, BlockCacheError> {
88eb49bb99S曾俊         // 存放缺块信息的向量
89eb49bb99S曾俊         let mut fail_ans = vec![];
90eb49bb99S曾俊         // 存放命中块地址的向量
91eb49bb99S曾俊         let mut success_ans = vec![];
92eb49bb99S曾俊         // 获取mapper
93eb49bb99S曾俊         let mapper = unsafe { mapper()? };
94eb49bb99S曾俊         for (index, i) in block_iter.enumerate() {
95eb49bb99S曾俊             // 在mapper中寻找块的lba_id,判断是否命中
96eb49bb99S曾俊             match mapper.find(i.lba_id()) {
97eb49bb99S曾俊                 Some(x) => {
98eb49bb99S曾俊                     success_ans.push(x);
99eb49bb99S曾俊                     continue;
100eb49bb99S曾俊                 }
101eb49bb99S曾俊                 // 缺块就放入fail_ans
102eb49bb99S曾俊                 None => fail_ans.push(FailData::new(i.lba_id(), index)),
103eb49bb99S曾俊                 // 缺块不break的原因是,我们需要把所有缺块都找出来,这样才能补上缺块
104eb49bb99S曾俊             }
105eb49bb99S曾俊         }
106eb49bb99S曾俊         // 只要有缺块就认为cache失败,因为需要补块就需要进行io操作
107eb49bb99S曾俊         if !fail_ans.is_empty() {
108eb49bb99S曾俊             return Err(BlockCacheError::BlockFaultError(fail_ans));
109eb49bb99S曾俊         } else {
110eb49bb99S曾俊             return Ok(success_ans);
111eb49bb99S曾俊         }
112eb49bb99S曾俊     }
113eb49bb99S曾俊     /// # 函数的功能
114eb49bb99S曾俊     /// 在cache中读取一个块的数据并放置于缓存的指定位置
115eb49bb99S曾俊     ///
116eb49bb99S曾俊     /// ## 参数:
117eb49bb99S曾俊     /// - 'cache_block_addr' :表示需要读取的cache块的地址
118eb49bb99S曾俊     /// - 'position' :表示该块的数据需要放置在buf的哪个位置,比如position为2,那么读出的数据将放置在buf\[1024..1536\](这里假设块大小是512)
119eb49bb99S曾俊     /// - 'buf' :块数据的缓存
120eb49bb99S曾俊     ///
121eb49bb99S曾俊     /// ## 返回值:
122eb49bb99S曾俊     /// - Ok(usize) :表示读取了多少个字节
123eb49bb99S曾俊     /// - Err(BlockCacheError) :如果输入的cache_block_addr超过了cache的容量,那么将返回Err(由于目前的cache不支持动态变化上限,所以可能出现这种错误;而实际上,由于Cache的地址是由frame_selector给出的,所以正确实现的frame_selector理论上不会出现这种错误)
124eb49bb99S曾俊     fn read_one_block(
125eb49bb99S曾俊         cache_block_addr: CacheBlockAddr,
126eb49bb99S曾俊         position: usize,
127eb49bb99S曾俊         buf: &mut [u8],
128eb49bb99S曾俊     ) -> Result<usize, BlockCacheError> {
129eb49bb99S曾俊         let space = unsafe { space()? };
130eb49bb99S曾俊         space.read(cache_block_addr, position, buf)
131eb49bb99S曾俊     }
132eb49bb99S曾俊     /// # 函数的功能
133eb49bb99S曾俊     /// 根据缺块的数据和io获得的数据,向cache中补充块数据
134eb49bb99S曾俊     ///
135eb49bb99S曾俊     /// ## 参数:
136eb49bb99S曾俊     /// - 'f_data_vec' :这里输入的一般是从read函数中返回的缺块数据
137eb49bb99S曾俊     /// - 'data' :经过一次io后获得的数据
138eb49bb99S曾俊     ///
139eb49bb99S曾俊     /// ## 返回值:
140eb49bb99S曾俊     /// Ok(usize) :表示补上缺页的个数
141eb49bb99S曾俊     /// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
142eb49bb99S曾俊     pub fn insert(f_data_vec: Vec<FailData>, data: &[u8]) -> Result<usize, BlockCacheError> {
143eb49bb99S曾俊         let count = f_data_vec.len();
144eb49bb99S曾俊         for i in f_data_vec {
145eb49bb99S曾俊             let index = i.index();
146eb49bb99S曾俊             Self::insert_one_block(
147eb49bb99S曾俊                 i.lba_id(),
148eb49bb99S曾俊                 data[index * BLOCK_SIZE..(index + 1) * BLOCK_SIZE].to_vec(),
149eb49bb99S曾俊             )?;
150eb49bb99S曾俊         }
151eb49bb99S曾俊         Ok(count)
152eb49bb99S曾俊     }
153eb49bb99S曾俊 
154eb49bb99S曾俊     /// # 函数的功能
155eb49bb99S曾俊     /// 将一个块数据插入到cache中
156eb49bb99S曾俊     ///
157eb49bb99S曾俊     /// ## 参数:
158eb49bb99S曾俊     /// - 'lba_id' :表明该块对应的lba_id,用于建立映射
159eb49bb99S曾俊     /// - 'data' :传入的数据
160eb49bb99S曾俊     ///
161eb49bb99S曾俊     /// ## 返回值:
162eb49bb99S曾俊     /// Ok(()):表示插入成功
163eb49bb99S曾俊     /// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
164eb49bb99S曾俊     fn insert_one_block(lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
165eb49bb99S曾俊         let space = unsafe { space()? };
166eb49bb99S曾俊         space.insert(lba_id, data)
167eb49bb99S曾俊     }
168eb49bb99S曾俊     /// # 函数的功能
169eb49bb99S曾俊     /// 立即回写,这里仅仅作为取消映射的方法,并没有真正写入到cache的功能
170eb49bb99S曾俊     ///
171eb49bb99S曾俊     /// ## 参数:
172eb49bb99S曾俊     /// - 'lba_id_start' :需要读取的连续块的起始块
173eb49bb99S曾俊     /// - 'count' :需要读取块的个数
174eb49bb99S曾俊     /// - '_data' :目前没有写入功能,该参数暂时无用
175eb49bb99S曾俊     ///
176eb49bb99S曾俊     /// ## 返回值:
177eb49bb99S曾俊     /// Ok(usize) :表示写入了多少个块
178eb49bb99S曾俊     /// Err(BlockCacheError) :这里产生错误的原因只有插入时还没有初始化
179eb49bb99S曾俊     pub fn immediate_write(
180eb49bb99S曾俊         lba_id_start: BlockId,
181eb49bb99S曾俊         count: usize,
182eb49bb99S曾俊         _data: &[u8],
183eb49bb99S曾俊     ) -> Result<usize, BlockCacheError> {
184eb49bb99S曾俊         let mapper = unsafe { mapper()? };
185eb49bb99S曾俊         let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
186eb49bb99S曾俊         for i in block_iter {
187eb49bb99S曾俊             mapper.remove(i.lba_id());
188eb49bb99S曾俊         }
189eb49bb99S曾俊         Ok(count)
190eb49bb99S曾俊     }
191eb49bb99S曾俊 }
192eb49bb99S曾俊 
193eb49bb99S曾俊 struct LockedCacheSpace(RwLock<CacheSpace>);
194eb49bb99S曾俊 
195eb49bb99S曾俊 impl LockedCacheSpace {
196eb49bb99S曾俊     pub fn new(space: CacheSpace) -> Self {
197eb49bb99S曾俊         LockedCacheSpace(RwLock::new(space))
198eb49bb99S曾俊     }
199eb49bb99S曾俊 
200eb49bb99S曾俊     pub fn read(
201eb49bb99S曾俊         &self,
202eb49bb99S曾俊         addr: CacheBlockAddr,
203eb49bb99S曾俊         position: usize,
204eb49bb99S曾俊         buf: &mut [u8],
205eb49bb99S曾俊     ) -> Result<usize, BlockCacheError> {
206eb49bb99S曾俊         self.0.read().read(addr, position, buf)
207eb49bb99S曾俊     }
208eb49bb99S曾俊 
209eb49bb99S曾俊     pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
210eb49bb99S曾俊         todo!()
211eb49bb99S曾俊     }
212eb49bb99S曾俊 
213eb49bb99S曾俊     pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
214eb49bb99S曾俊         unsafe { self.0.get_mut().insert(lba_id, data) }
215eb49bb99S曾俊     }
216eb49bb99S曾俊 }
217eb49bb99S曾俊 
218eb49bb99S曾俊 /// # 结构功能
219eb49bb99S曾俊 /// 管理Cache空间的结构体
220eb49bb99S曾俊 struct CacheSpace {
221eb49bb99S曾俊     /// 用于存放CacheBlock,是Cache数据的实际存储空间的向量
222eb49bb99S曾俊     root: Vec<CacheBlock>,
223eb49bb99S曾俊     /// 在块换出换入时,用于选择替换块的结构体
224eb49bb99S曾俊     frame_selector: Box<dyn FrameSelector>,
225eb49bb99S曾俊 }
226eb49bb99S曾俊 
227eb49bb99S曾俊 impl CacheSpace {
228eb49bb99S曾俊     pub fn new() -> Self {
229eb49bb99S曾俊         Self {
230eb49bb99S曾俊             root: Vec::new(),
231eb49bb99S曾俊             // 如果要修改替换算法,可以设计一个结构体实现FrameSelector trait,再在这里替换掉SimpleFrameSelector
232eb49bb99S曾俊             frame_selector: Box::new(SimpleFrameSelector::new()),
233eb49bb99S曾俊         }
234eb49bb99S曾俊     }
235eb49bb99S曾俊     /// # 函数的功能
236eb49bb99S曾俊     /// 将一个块的数据写入到buf的指定位置
237eb49bb99S曾俊     ///
238eb49bb99S曾俊     /// ## 参数:
239eb49bb99S曾俊     /// - 'addr' :请求块在Cache中的地址
240eb49bb99S曾俊     /// - 'position' :表示需要将Cache放入buf中的位置,例如:若position为1,则块的数据放入buf\[512..1024\]
241eb49bb99S曾俊     /// - 'buf' :存放数据的buf
242eb49bb99S曾俊     ///
243eb49bb99S曾俊     /// ## 返回值:
244eb49bb99S曾俊     /// Some(usize):表示读取的字节数(这里默认固定为BLOCK_SIZE)
245eb49bb99S曾俊     /// Err(BlockCacheError):如果你输入地址大于cache的最大上限,那么就返回InsufficientCacheSpace
246eb49bb99S曾俊     pub fn read(
247eb49bb99S曾俊         &self,
248eb49bb99S曾俊         addr: CacheBlockAddr,
249eb49bb99S曾俊         position: usize,
250eb49bb99S曾俊         buf: &mut [u8],
251eb49bb99S曾俊     ) -> Result<usize, BlockCacheError> {
252eb49bb99S曾俊         if addr > self.frame_selector.size() {
253eb49bb99S曾俊             return Err(BlockCacheError::InsufficientCacheSpace);
254eb49bb99S曾俊         } else {
255eb49bb99S曾俊             // CacheBlockAddr就是用于给root寻址的
256eb49bb99S曾俊             return self.root[addr]
257eb49bb99S曾俊                 .data(&mut buf[position * BLOCK_SIZE..(position + 1) * BLOCK_SIZE]);
258eb49bb99S曾俊         }
259eb49bb99S曾俊     }
260eb49bb99S曾俊     /// # 函数的功能
261eb49bb99S曾俊     /// 向cache空间中写入的函数,目前尚未实现
262eb49bb99S曾俊     pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
263eb49bb99S曾俊         todo!()
264eb49bb99S曾俊     }
265eb49bb99S曾俊     /// # 函数的功能
266eb49bb99S曾俊     /// 向cache中插入一个块并建立lba_id到块之间的映射
267eb49bb99S曾俊     ///
268eb49bb99S曾俊     /// ## 参数:
269eb49bb99S曾俊     /// - 'lba_id' :表明你插入的块的lba_id,用于建立映射
270eb49bb99S曾俊     /// - 'data' :要插入块的数据
271eb49bb99S曾俊     ///
272eb49bb99S曾俊     /// ## 返回值:
273eb49bb99S曾俊     /// Ok(())
274eb49bb99S曾俊     pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
275eb49bb99S曾俊         // CacheBlock是cached block的基本单位,这里使用data生成一个CacheBlock用于向Cache空间中插入块
276eb49bb99S曾俊         let data_block = CacheBlock::from_data(lba_id, data);
277eb49bb99S曾俊         let mapper = unsafe { mapper()? };
278eb49bb99S曾俊         // 这里我设计了cache的一个threshold,如果不超过阈值就可以append,否则只能替换
279eb49bb99S曾俊         if self.frame_selector.can_append() {
280eb49bb99S曾俊             // 这是append的操作逻辑:
281eb49bb99S曾俊             // 从frame_selector获得一个CacheBlockAddr
282eb49bb99S曾俊             let index = self.frame_selector.index_append();
283eb49bb99S曾俊             // 直接将块push进去就可以,因为现在是append操作
284eb49bb99S曾俊             self.root.push(data_block);
285eb49bb99S曾俊             assert!(index == self.root.len() - 1);
286eb49bb99S曾俊             // 建立mapper的映射
287eb49bb99S曾俊             mapper.insert(lba_id, index);
288eb49bb99S曾俊             Ok(())
289eb49bb99S曾俊         } else {
290eb49bb99S曾俊             // 这是replace的操作逻辑
291eb49bb99S曾俊             // 从frame_selector获得一个CacheBlockAddr,这次是它替换出来的
292eb49bb99S曾俊             let index = self.frame_selector.index_replace();
293eb49bb99S曾俊             // 获取被替换的块的lba_id,待会用于取消映射
294eb49bb99S曾俊             let removed_id = self.root[index].lba_id();
295eb49bb99S曾俊             // 直接替换原本的块,由于被替换的块没有引用了,所以会被drop
296eb49bb99S曾俊             self.root[index] = data_block;
297eb49bb99S曾俊             // 建立映射插入块的映射
298eb49bb99S曾俊             mapper.insert(lba_id, index);
299eb49bb99S曾俊             // 取消被替换块的映射
300eb49bb99S曾俊             mapper.remove(removed_id);
301eb49bb99S曾俊             Ok(())
302eb49bb99S曾俊         }
303eb49bb99S曾俊     }
304eb49bb99S曾俊 }
305eb49bb99S曾俊 
306eb49bb99S曾俊 struct LockedCacheMapper {
307eb49bb99S曾俊     lock: RwLock<CacheMapper>,
308eb49bb99S曾俊 }
309eb49bb99S曾俊 
310eb49bb99S曾俊 impl LockedCacheMapper {
311eb49bb99S曾俊     pub fn new(inner: CacheMapper) -> Self {
312eb49bb99S曾俊         Self {
313eb49bb99S曾俊             lock: RwLock::new(inner),
314eb49bb99S曾俊         }
315eb49bb99S曾俊     }
316eb49bb99S曾俊 
317eb49bb99S曾俊     pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
318eb49bb99S曾俊         unsafe { self.lock.get_mut().insert(lba_id, caddr) }
319eb49bb99S曾俊     }
320eb49bb99S曾俊 
321eb49bb99S曾俊     pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
322eb49bb99S曾俊         self.lock.read().find(lba_id)
323eb49bb99S曾俊     }
324eb49bb99S曾俊 
325eb49bb99S曾俊     pub fn remove(&mut self, lba_id: BlockId) {
326eb49bb99S曾俊         unsafe { self.lock.get_mut().remove(lba_id) }
327eb49bb99S曾俊     }
328eb49bb99S曾俊 }
329eb49bb99S曾俊 
330eb49bb99S曾俊 /// # 结构功能
331eb49bb99S曾俊 /// 该结构体用于建立lba_id到cached块的映射
332eb49bb99S曾俊 struct CacheMapper {
333eb49bb99S曾俊     // 执行键值对操作的map
334eb49bb99S曾俊     map: HashMap<BlockId, CacheBlockAddr>,
335eb49bb99S曾俊 }
336eb49bb99S曾俊 
337eb49bb99S曾俊 impl CacheMapper {
338eb49bb99S曾俊     pub fn new() -> Self {
339eb49bb99S曾俊         Self {
340eb49bb99S曾俊             map: HashMap::new(),
341eb49bb99S曾俊         }
342eb49bb99S曾俊     }
343eb49bb99S曾俊     /// # 函数的功能
344eb49bb99S曾俊     /// 插入操作
345eb49bb99S曾俊     pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
346eb49bb99S曾俊         self.map.insert(lba_id, caddr)?;
347eb49bb99S曾俊         Some(())
348eb49bb99S曾俊     }
349eb49bb99S曾俊     /// # 函数的功能
350eb49bb99S曾俊     /// 查找操作
351eb49bb99S曾俊     #[inline]
352eb49bb99S曾俊     pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
353eb49bb99S曾俊         Some(*self.map.get(&lba_id)?)
354eb49bb99S曾俊     }
355eb49bb99S曾俊     /// # 函数的功能
356eb49bb99S曾俊     /// 去除操作
357eb49bb99S曾俊     pub fn remove(&mut self, lba_id: BlockId) {
358eb49bb99S曾俊         self.map.remove(&lba_id);
359eb49bb99S曾俊     }
360eb49bb99S曾俊 }
361eb49bb99S曾俊 
362eb49bb99S曾俊 /// # 结构功能
363eb49bb99S曾俊 /// 该trait用于实现块的换入换出算法,需要设计替换算法只需要实现该trait即可
364eb49bb99S曾俊 trait FrameSelector {
365eb49bb99S曾俊     /// # 函数的功能
366eb49bb99S曾俊     /// 给出append操作的index(理论上,如果cache没满,就不需要换出块,就可以使用append操作)
367eb49bb99S曾俊     fn index_append(&mut self) -> CacheBlockAddr;
368eb49bb99S曾俊     /// # 函数的功能
369eb49bb99S曾俊     /// 给出replace操作后的index
370eb49bb99S曾俊     fn index_replace(&mut self) -> CacheBlockAddr;
371eb49bb99S曾俊     /// # 函数的功能
372eb49bb99S曾俊     /// 判断是否可以append
373eb49bb99S曾俊     fn can_append(&self) -> bool;
374eb49bb99S曾俊     /// # 函数的功能
375eb49bb99S曾俊     /// 获取size
376eb49bb99S曾俊     fn size(&self) -> usize;
377eb49bb99S曾俊 }
378eb49bb99S曾俊 
379eb49bb99S曾俊 /// # 结构功能
380eb49bb99S曾俊 /// 该结构体用于管理块的换入换出过程中,CacheBlockAddr的选择,替换算法在这里实现
381eb49bb99S曾俊 struct SimpleFrameSelector {
382eb49bb99S曾俊     // 表示BlockCache的阈值,即最大可以存放多少块,这里目前还不支持动态变化
383eb49bb99S曾俊     threshold: usize,
384eb49bb99S曾俊     // 表示使用过的块帧的数量
385eb49bb99S曾俊     size: usize,
386eb49bb99S曾俊     // 这里使用从头至尾的替换算法,其替换策略为0,1,2,...,threshold,0,1...以此类推(该算法比FIFO还要简陋,后面可以再实现别的:)
387eb49bb99S曾俊     current: usize,
388eb49bb99S曾俊 }
389eb49bb99S曾俊 
390eb49bb99S曾俊 impl SimpleFrameSelector {
391eb49bb99S曾俊     pub fn new() -> Self {
392eb49bb99S曾俊         Self {
393eb49bb99S曾俊             threshold: CACHE_THRESHOLD * (1 << (20 - BLOCK_SIZE_LOG)),
394eb49bb99S曾俊             size: 0,
395eb49bb99S曾俊             current: 0,
396eb49bb99S曾俊         }
397eb49bb99S曾俊     }
398eb49bb99S曾俊 }
399eb49bb99S曾俊 
400eb49bb99S曾俊 impl FrameSelector for SimpleFrameSelector {
401eb49bb99S曾俊     fn index_append(&mut self) -> CacheBlockAddr {
402eb49bb99S曾俊         let ans = self.current;
403eb49bb99S曾俊         self.size += 1;
404eb49bb99S曾俊         self.current += 1;
405eb49bb99S曾俊         self.current %= self.threshold;
406eb49bb99S曾俊         return ans;
407eb49bb99S曾俊     }
408eb49bb99S曾俊 
409eb49bb99S曾俊     fn index_replace(&mut self) -> CacheBlockAddr {
410eb49bb99S曾俊         let ans = self.current;
411eb49bb99S曾俊         self.current += 1;
412eb49bb99S曾俊         self.current %= self.threshold;
413eb49bb99S曾俊         return ans;
414eb49bb99S曾俊     }
415eb49bb99S曾俊 
416eb49bb99S曾俊     fn can_append(&self) -> bool {
417eb49bb99S曾俊         self.size < self.threshold
418eb49bb99S曾俊     }
419eb49bb99S曾俊 
420eb49bb99S曾俊     fn size(&self) -> usize {
421eb49bb99S曾俊         self.size
422eb49bb99S曾俊     }
423eb49bb99S曾俊 }
424