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