cargo fmt for async-fat32
This commit is contained in:
parent
3baa556e34
commit
8ae2d0c4c3
|
@ -1,48 +1,51 @@
|
|||
//! 块缓冲层实现
|
||||
use core::mem::MaybeUninit;
|
||||
use alloc::sync::Arc;
|
||||
use spin::Mutex;
|
||||
use crate::AsyncBlockDevive;
|
||||
use super::cache::{Cache, Node, LFUCache};
|
||||
use super::cache::{Cache, LFUCache, Node};
|
||||
use super::config::*;
|
||||
use crate::AsyncBlockDevive;
|
||||
use alloc::sync::Arc;
|
||||
use core::mem::MaybeUninit;
|
||||
use spin::Mutex;
|
||||
|
||||
// B: 一个块中的字节数
|
||||
// N: 块缓冲层的块数
|
||||
pub struct BlockCache<C: Cache<N, Key = usize, Value = [u8; B]>, const B: usize, const N: usize> {
|
||||
block_device: Arc<dyn AsyncBlockDevive + Send + Sync>,
|
||||
cache: Mutex<C>
|
||||
cache: Mutex<C>,
|
||||
}
|
||||
|
||||
impl BlockCache<LFUCache<usize, [u8; BLOCK_SIZE], CACHE_SIZE>, BLOCK_SIZE, CACHE_SIZE> {
|
||||
pub fn init(device: Arc<dyn AsyncBlockDevive + Send + Sync>) -> Self {
|
||||
let mut data: [MaybeUninit<Node<usize, [u8; BLOCK_SIZE]>>; CACHE_SIZE] = unsafe {
|
||||
MaybeUninit::uninit().assume_init()
|
||||
};
|
||||
let mut data: [MaybeUninit<Node<usize, [u8; BLOCK_SIZE]>>; CACHE_SIZE] =
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
for elem in &mut data[..] {
|
||||
*elem = MaybeUninit::new(Node::new(0, [0; BLOCK_SIZE]));
|
||||
}
|
||||
let nodes = unsafe { core::mem::transmute::<_, [Node<usize, [u8; BLOCK_SIZE]>; CACHE_SIZE]>(data) };
|
||||
let nodes =
|
||||
unsafe { core::mem::transmute::<_, [Node<usize, [u8; BLOCK_SIZE]>; CACHE_SIZE]>(data) };
|
||||
let lfu_cache = LFUCache::empty(nodes);
|
||||
Self {
|
||||
block_device: device,
|
||||
cache: Mutex::new(lfu_cache)
|
||||
cache: Mutex::new(lfu_cache),
|
||||
}
|
||||
}
|
||||
pub async fn read_block(&self, block_id: usize) -> [u8; BLOCK_SIZE] {
|
||||
{ // 申请锁
|
||||
{
|
||||
// 申请锁
|
||||
let mut s = self.cache.lock();
|
||||
if let Some(block) = s.get(&block_id) { // 如果想要读取的块在缓冲层中,则读出来直接返回,不用读写块设备
|
||||
if let Some(block) = s.get(&block_id) {
|
||||
// 如果想要读取的块在缓冲层中,则读出来直接返回,不用读写块设备
|
||||
return block;
|
||||
}
|
||||
} // 释放锁
|
||||
// 如果要读取的块不在缓冲层中,则需要从块设备读取
|
||||
// 如果要读取的块不在缓冲层中,则需要从块设备读取
|
||||
let mut data = [0; BLOCK_SIZE];
|
||||
self.block_device.read(block_id, &mut data).await;
|
||||
// 将读取到的块写入到缓冲层
|
||||
let mut s = self.cache.lock(); // 申请锁
|
||||
let write_back = s.put(&block_id, data.clone());
|
||||
drop(s); // 释放锁
|
||||
if let Some((id, mut block)) = write_back { // 如果有需要写回到块设备的数据,这里写回
|
||||
if let Some((id, mut block)) = write_back {
|
||||
// 如果有需要写回到块设备的数据,这里写回
|
||||
self.block_device.write(id, &mut block).await;
|
||||
}
|
||||
data
|
||||
|
@ -73,4 +76,4 @@ impl BlockCache<LFUCache<usize, [u8; BLOCK_SIZE], CACHE_SIZE>, BLOCK_SIZE, CACHE
|
|||
|
||||
// lazy_static::lazy_static! {
|
||||
// pub static ref AsyncBlockCache: BlockCache<LFUCache<usize, [u8; BLOCK_SIZE], CACHE_SIZE>, BLOCK_SIZE, CACHE_SIZE> = BlockCache::init(Arc::new(TestDevice::default()));
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -17,7 +17,7 @@ enum BootSectorOffset {
|
|||
/// Volume label
|
||||
VolLab = 71,
|
||||
/// One of the strings "FAT12", "FAT16", "FAT32"
|
||||
FilSysType = 82
|
||||
FilSysType = 82,
|
||||
}
|
||||
|
||||
/// BPB 各字段的偏移
|
||||
|
@ -64,5 +64,5 @@ enum BPBOffset {
|
|||
/// ignored
|
||||
BkBootSec = 50,
|
||||
/// Reserved
|
||||
Reserved = 52
|
||||
}
|
||||
Reserved = 52,
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ pub struct Node<K: Eq + PartialEq + Copy, V: Clone> {
|
|||
value: V,
|
||||
cnt: usize,
|
||||
time: usize,
|
||||
dirty: bool
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
impl<K: Eq + PartialEq + Copy, V: Clone> Node<K, V> {
|
||||
|
@ -29,7 +29,7 @@ impl<K: Eq + PartialEq + Copy, V: Clone> Node<K, V> {
|
|||
value,
|
||||
cnt: 0,
|
||||
time: 0,
|
||||
dirty: false
|
||||
dirty: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ impl<K: Eq + PartialEq + Copy, V: Clone> Eq for Node<K, V> {}
|
|||
|
||||
impl<K: Eq + PartialEq + Copy, V: Clone> Ord for Node<K, V> {
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
self.cnt.cmp(&other.cnt).then_with(|| self.time.cmp(&other.time))
|
||||
self.cnt
|
||||
.cmp(&other.cnt)
|
||||
.then_with(|| self.time.cmp(&other.time))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,7 @@ impl<K: Eq + PartialEq + Copy, V: Clone> PartialOrd for Node<K, V> {
|
|||
pub struct LFUCache<K: Eq + PartialEq + Copy, V: Clone, const N: usize> {
|
||||
data: [Node<K, V>; N],
|
||||
size: usize,
|
||||
time: usize
|
||||
time: usize,
|
||||
}
|
||||
|
||||
impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> LFUCache<K, V, N> {
|
||||
|
@ -66,7 +68,7 @@ impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> LFUCache<K, V, N> {
|
|||
Self {
|
||||
data,
|
||||
size: N,
|
||||
time: 0
|
||||
time: 0,
|
||||
}
|
||||
}
|
||||
// todo: 用 `maybuninit`
|
||||
|
@ -74,7 +76,7 @@ impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> LFUCache<K, V, N> {
|
|||
Self {
|
||||
data,
|
||||
size: 0,
|
||||
time: 0
|
||||
time: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,12 +87,15 @@ impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> Cache<N> for LFUCache<K
|
|||
fn get(&mut self, key: &Self::Key) -> Option<Self::Value> {
|
||||
self.time += 1;
|
||||
let time = self.time;
|
||||
self.data[0..self.size].iter_mut().find(|i| i.key == *key).map(|node| {
|
||||
// 更新结点时间和访问次数
|
||||
node.time = time;
|
||||
node.cnt += 1;
|
||||
node.value.clone()
|
||||
})
|
||||
self.data[0..self.size]
|
||||
.iter_mut()
|
||||
.find(|i| i.key == *key)
|
||||
.map(|node| {
|
||||
// 更新结点时间和访问次数
|
||||
node.time = time;
|
||||
node.cnt += 1;
|
||||
node.value.clone()
|
||||
})
|
||||
}
|
||||
fn put(&mut self, key: &Self::Key, value: Self::Value) -> Option<(Self::Key, Self::Value)> {
|
||||
self.time += 1;
|
||||
|
@ -99,17 +104,19 @@ impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> Cache<N> for LFUCache<K
|
|||
node.cnt += 1;
|
||||
node.time = self.time;
|
||||
// 写脏
|
||||
node.dirty = true;
|
||||
node.dirty = true;
|
||||
return None;
|
||||
} else {
|
||||
if self.size < N { // 缓存未满
|
||||
if self.size < N {
|
||||
// 缓存未满
|
||||
self.data[self.size].key = *key;
|
||||
self.data[self.size].value = value;
|
||||
self.data[self.size].cnt = 1;
|
||||
self.data[self.size].time = self.time;
|
||||
self.size += 1;
|
||||
return None;
|
||||
} else { // 缓存已满
|
||||
} else {
|
||||
// 缓存已满
|
||||
// 顺序排序
|
||||
self.data[0..self.size].sort_by(|a, b| a.cmp(b));
|
||||
// 淘汰第一项
|
||||
|
@ -122,19 +129,18 @@ impl<K: Eq + PartialEq + Copy, V: Clone, const N: usize> Cache<N> for LFUCache<K
|
|||
// 如果数据已经被写脏,现在需要写回
|
||||
match node.dirty {
|
||||
true => Some(write_back),
|
||||
false => None
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn lfu_cache_test() {
|
||||
let nodes = [Node::new(0, 0); 2];
|
||||
let mut lfu_cache = LFUCache::empty(nodes);
|
||||
|
||||
|
||||
assert!(lfu_cache.get(&0).is_none());
|
||||
assert!(lfu_cache.get(&1).is_none());
|
||||
assert!(lfu_cache.get(&2).is_none());
|
||||
|
@ -150,4 +156,4 @@ fn lfu_cache_test() {
|
|||
assert_eq!(lfu_cache.get(&1), None);
|
||||
assert_eq!(lfu_cache.get(&3), Some(3));
|
||||
assert_eq!(lfu_cache.get(&4), Some(4));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub const BLOCK_SIZE: usize = 512;
|
||||
pub const CACHE_SIZE: usize = 100;
|
||||
pub const CACHE_SIZE: usize = 100;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//! Async FAT32 File System Implemetation
|
||||
|
||||
mod block_cache;
|
||||
mod bs_bpb;
|
||||
mod cache;
|
||||
mod block_cache;
|
||||
mod config;
|
||||
|
||||
extern crate alloc;
|
||||
|
@ -13,4 +13,4 @@ use async_trait::async_trait;
|
|||
pub trait AsyncBlockDevive {
|
||||
async fn read(&self, block_id: usize, buf: &mut [u8]);
|
||||
async fn write(&self, block_id: usize, buf: &[u8]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue