mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
Rename DirEntryVec to SlotVec
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
0fc707d38c
commit
0abe40e0f8
@ -2,9 +2,10 @@ use alloc::string::String;
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
use jinux_util::slot_vec::SlotVec;
|
||||||
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirEntryVec, DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ pub struct ProcDir<D: DirOps> {
|
|||||||
inner: D,
|
inner: D,
|
||||||
this: Weak<ProcDir<D>>,
|
this: Weak<ProcDir<D>>,
|
||||||
parent: Option<Weak<dyn Inode>>,
|
parent: Option<Weak<dyn Inode>>,
|
||||||
cached_children: RwLock<DirEntryVec<(String, Arc<dyn Inode>)>>,
|
cached_children: RwLock<SlotVec<(String, Arc<dyn Inode>)>>,
|
||||||
info: ProcInodeInfo,
|
info: ProcInodeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ impl<D: DirOps> ProcDir<D> {
|
|||||||
inner: dir,
|
inner: dir,
|
||||||
this: weak_self.clone(),
|
this: weak_self.clone(),
|
||||||
parent,
|
parent,
|
||||||
cached_children: RwLock::new(DirEntryVec::new()),
|
cached_children: RwLock::new(SlotVec::new()),
|
||||||
info,
|
info,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ impl<D: DirOps> ProcDir<D> {
|
|||||||
self.parent.as_ref().and_then(|p| p.upgrade())
|
self.parent.as_ref().and_then(|p| p.upgrade())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cached_children(&self) -> &RwLock<DirEntryVec<(String, Arc<dyn Inode>)>> {
|
pub fn cached_children(&self) -> &RwLock<SlotVec<(String, Arc<dyn Inode>)>> {
|
||||||
&self.cached_children
|
&self.cached_children
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
|||||||
self.inner.populate_children(self.this.clone());
|
self.inner.populate_children(self.this.clone());
|
||||||
let cached_children = self.cached_children.read();
|
let cached_children = self.cached_children.read();
|
||||||
for (idx, (name, child)) in cached_children
|
for (idx, (name, child)) in cached_children
|
||||||
.idxes_and_entries()
|
.idxes_and_items()
|
||||||
.map(|(idx, (name, child))| (idx + 2, (name, child)))
|
.map(|(idx, (name, child))| (idx + 2, (name, child)))
|
||||||
{
|
{
|
||||||
if idx < *offset {
|
if idx < *offset {
|
||||||
|
@ -5,12 +5,12 @@ use core::any::Any;
|
|||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
use jinux_util::slot_vec::SlotVec;
|
||||||
use spin::{RwLock, RwLockWriteGuard};
|
use spin::{RwLock, RwLockWriteGuard};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirEntryVec, DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
|
||||||
Metadata, SuperBlock,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RamFS {
|
pub struct RamFS {
|
||||||
@ -164,7 +164,7 @@ impl Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DirEntry {
|
struct DirEntry {
|
||||||
children: DirEntryVec<(Str256, Arc<RamInode>)>,
|
children: SlotVec<(Str256, Arc<RamInode>)>,
|
||||||
this: Weak<RamInode>,
|
this: Weak<RamInode>,
|
||||||
parent: Weak<RamInode>,
|
parent: Weak<RamInode>,
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ struct DirEntry {
|
|||||||
impl DirEntry {
|
impl DirEntry {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
children: DirEntryVec::new(),
|
children: SlotVec::new(),
|
||||||
this: Weak::default(),
|
this: Weak::default(),
|
||||||
parent: Weak::default(),
|
parent: Weak::default(),
|
||||||
}
|
}
|
||||||
@ -205,13 +205,13 @@ impl DirEntry {
|
|||||||
Some((1, self.parent.upgrade().unwrap()))
|
Some((1, self.parent.upgrade().unwrap()))
|
||||||
} else {
|
} else {
|
||||||
self.children
|
self.children
|
||||||
.idxes_and_entries()
|
.idxes_and_items()
|
||||||
.find(|(_, (child, _))| child == &Str256::from(name))
|
.find(|(_, (child, _))| child == &Str256::from(name))
|
||||||
.map(|(idx, (_, inode))| (idx + 2, inode.clone()))
|
.map(|(idx, (_, inode))| (idx + 2, inode.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_entry(&mut self, name: &str, inode: Arc<RamInode>) {
|
fn append_entry(&mut self, name: &str, inode: Arc<RamInode>) -> usize {
|
||||||
self.children.put((Str256::from(name), inode))
|
self.children.put((Str256::from(name), inode))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ impl DirEntry {
|
|||||||
// Read the normal child entries.
|
// Read the normal child entries.
|
||||||
for (offset, (name, child)) in self
|
for (offset, (name, child)) in self
|
||||||
.children
|
.children
|
||||||
.idxes_and_entries()
|
.idxes_and_items()
|
||||||
.map(|(offset, (name, child))| (offset + 2, (name, child)))
|
.map(|(offset, (name, child))| (offset + 2, (name, child)))
|
||||||
{
|
{
|
||||||
if offset < *idx {
|
if offset < *idx {
|
||||||
|
@ -1,87 +1,7 @@
|
|||||||
use super::Inode;
|
use super::Inode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// DirEntryVec is used to store the entries of a directory.
|
use jinux_util::slot_vec::SlotVec;
|
||||||
/// It can guarantee that the index of one dir entry remains unchanged during
|
|
||||||
/// adding or deleting other dir entries of it.
|
|
||||||
pub struct DirEntryVec<T> {
|
|
||||||
// The slots to store dir entries.
|
|
||||||
slots: Vec<Option<T>>,
|
|
||||||
// The number of occupied slots.
|
|
||||||
// The i-th slot is occupied if `self.slots[i].is_some()`.
|
|
||||||
num_occupied: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DirEntryVec<T> {
|
|
||||||
/// New an empty vec.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
slots: Vec::new(),
|
|
||||||
num_occupied: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the vec contains no entries.
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.num_occupied == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Put a dir entry into the vec.
|
|
||||||
/// it may be put into an existing empty slot or the back of the vec.
|
|
||||||
pub fn put(&mut self, entry: T) {
|
|
||||||
if self.num_occupied == self.slots.len() {
|
|
||||||
self.slots.push(Some(entry));
|
|
||||||
} else {
|
|
||||||
let idx = self.slots.iter().position(|x| x.is_none()).unwrap();
|
|
||||||
self.slots[idx] = Some(entry);
|
|
||||||
}
|
|
||||||
self.num_occupied += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes and returns the entry at position `idx`.
|
|
||||||
/// Returns `None` if `idx` is out of bounds or the entry has been removed.
|
|
||||||
pub fn remove(&mut self, idx: usize) -> Option<T> {
|
|
||||||
if idx >= self.slots.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut del_entry = None;
|
|
||||||
core::mem::swap(&mut del_entry, &mut self.slots[idx]);
|
|
||||||
if del_entry.is_some() {
|
|
||||||
debug_assert!(self.num_occupied > 0);
|
|
||||||
self.num_occupied -= 1;
|
|
||||||
}
|
|
||||||
del_entry
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Put and returns the entry at position `idx`.
|
|
||||||
/// Returns `None` if `idx` is out of bounds or the entry has been removed.
|
|
||||||
pub fn put_at(&mut self, idx: usize, entry: T) -> Option<T> {
|
|
||||||
if idx >= self.slots.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut sub_entry = Some(entry);
|
|
||||||
core::mem::swap(&mut sub_entry, &mut self.slots[idx]);
|
|
||||||
if sub_entry.is_none() {
|
|
||||||
self.num_occupied += 1;
|
|
||||||
}
|
|
||||||
sub_entry
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an iterator which gives both of the index and the dir entry.
|
|
||||||
/// The index may not be continuous.
|
|
||||||
pub fn idxes_and_entries(&self) -> impl Iterator<Item = (usize, &'_ T)> {
|
|
||||||
self.slots
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, x)| x.is_some())
|
|
||||||
.map(|(idx, x)| (idx, x.as_ref().unwrap()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an iterator which gives the dir entry.
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &'_ T> {
|
|
||||||
self.slots.iter().filter_map(|x| x.as_ref())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DirEntryVecExt {
|
pub trait DirEntryVecExt {
|
||||||
/// If the entry is not found by `name`, use `f` to get the inode, then put the entry into vec.
|
/// If the entry is not found by `name`, use `f` to get the inode, then put the entry into vec.
|
||||||
@ -92,7 +12,7 @@ pub trait DirEntryVecExt {
|
|||||||
fn remove_entry_by_name(&mut self, name: &str) -> Option<(String, Arc<dyn Inode>)>;
|
fn remove_entry_by_name(&mut self, name: &str) -> Option<(String, Arc<dyn Inode>)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirEntryVecExt for DirEntryVec<(String, Arc<dyn Inode>)> {
|
impl DirEntryVecExt for SlotVec<(String, Arc<dyn Inode>)> {
|
||||||
fn put_entry_if_not_found(&mut self, name: &str, f: impl Fn() -> Arc<dyn Inode>) {
|
fn put_entry_if_not_found(&mut self, name: &str, f: impl Fn() -> Arc<dyn Inode>) {
|
||||||
if self
|
if self
|
||||||
.iter()
|
.iter()
|
||||||
@ -106,7 +26,7 @@ impl DirEntryVecExt for DirEntryVec<(String, Arc<dyn Inode>)> {
|
|||||||
|
|
||||||
fn remove_entry_by_name(&mut self, name: &str) -> Option<(String, Arc<dyn Inode>)> {
|
fn remove_entry_by_name(&mut self, name: &str) -> Option<(String, Arc<dyn Inode>)> {
|
||||||
let idx = self
|
let idx = self
|
||||||
.idxes_and_entries()
|
.idxes_and_items()
|
||||||
.find(|(_, (child_name, _))| child_name == name)
|
.find(|(_, (child_name, _))| child_name == name)
|
||||||
.map(|(idx, _)| idx);
|
.map(|(idx, _)| idx);
|
||||||
if let Some(idx) = idx {
|
if let Some(idx) = idx {
|
||||||
|
@ -5,7 +5,7 @@ pub use channel::{Channel, Consumer, Producer};
|
|||||||
pub use creation_flags::CreationFlags;
|
pub use creation_flags::CreationFlags;
|
||||||
pub use dentry_cache::Dentry;
|
pub use dentry_cache::Dentry;
|
||||||
pub use dirent_visitor::DirentVisitor;
|
pub use dirent_visitor::DirentVisitor;
|
||||||
pub use direntry_vec::{DirEntryVec, DirEntryVecExt};
|
pub use direntry_vec::DirEntryVecExt;
|
||||||
pub use fcntl::FcntlCmd;
|
pub use fcntl::FcntlCmd;
|
||||||
pub use file_creation_mask::FileCreationMask;
|
pub use file_creation_mask::FileCreationMask;
|
||||||
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod frame_ptr;
|
pub mod frame_ptr;
|
||||||
|
pub mod slot_vec;
|
||||||
pub mod union_read_ptr;
|
pub mod union_read_ptr;
|
||||||
|
119
services/libs/jinux-util/src/slot_vec.rs
Normal file
119
services/libs/jinux-util/src/slot_vec.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
/// SlotVec is the variant of Vector.
|
||||||
|
/// It guarantees that the index of one item remains unchanged during adding
|
||||||
|
/// or deleting other items of the vector.
|
||||||
|
pub struct SlotVec<T> {
|
||||||
|
// The slots to store items.
|
||||||
|
slots: Vec<Option<T>>,
|
||||||
|
// The number of occupied slots.
|
||||||
|
// The i-th slot is occupied if `self.slots[i].is_some()`.
|
||||||
|
num_occupied: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SlotVec<T> {
|
||||||
|
/// New an empty vector.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
slots: Vec::new(),
|
||||||
|
num_occupied: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the vector contains no items.
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.num_occupied == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of items.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.num_occupied
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of slots.
|
||||||
|
pub fn slots_len(&self) -> usize {
|
||||||
|
self.slots.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the item at position `idx`.
|
||||||
|
///
|
||||||
|
/// Return `None` if `idx` is out of bounds or the item is not exist.
|
||||||
|
pub fn get(&self, idx: usize) -> Option<&T> {
|
||||||
|
if idx >= self.slots.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.slots[idx].as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Put an item into the vector.
|
||||||
|
/// It may be put into any existing empty slots or the back of the vector.
|
||||||
|
///
|
||||||
|
/// Return the index of the inserted item.
|
||||||
|
pub fn put(&mut self, entry: T) -> usize {
|
||||||
|
let idx = if self.num_occupied == self.slots.len() {
|
||||||
|
self.slots.push(Some(entry));
|
||||||
|
self.slots.len() - 1
|
||||||
|
} else {
|
||||||
|
let idx = self.slots.iter().position(|x| x.is_none()).unwrap();
|
||||||
|
self.slots[idx] = Some(entry);
|
||||||
|
idx
|
||||||
|
};
|
||||||
|
self.num_occupied += 1;
|
||||||
|
idx
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Put and return the item at position `idx`.
|
||||||
|
///
|
||||||
|
/// Return `None` if the item is not exist.
|
||||||
|
pub fn put_at(&mut self, idx: usize, item: T) -> Option<T> {
|
||||||
|
if idx >= self.slots.len() {
|
||||||
|
self.slots.resize_with(idx + 1, Default::default);
|
||||||
|
}
|
||||||
|
let mut sub_item = Some(item);
|
||||||
|
core::mem::swap(&mut sub_item, &mut self.slots[idx]);
|
||||||
|
if sub_item.is_none() {
|
||||||
|
self.num_occupied += 1;
|
||||||
|
}
|
||||||
|
sub_item
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove and return the item at position `idx`.
|
||||||
|
///
|
||||||
|
/// Return `None` if `idx` is out of bounds or the item has been removed.
|
||||||
|
pub fn remove(&mut self, idx: usize) -> Option<T> {
|
||||||
|
if idx >= self.slots.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut del_item = None;
|
||||||
|
core::mem::swap(&mut del_item, &mut self.slots[idx]);
|
||||||
|
if del_item.is_some() {
|
||||||
|
debug_assert!(self.num_occupied > 0);
|
||||||
|
self.num_occupied -= 1;
|
||||||
|
}
|
||||||
|
del_item
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an iterator which gives both of the index and the item.
|
||||||
|
/// The index may not be continuous.
|
||||||
|
pub fn idxes_and_items(&self) -> impl Iterator<Item = (usize, &'_ T)> {
|
||||||
|
self.slots
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, x)| x.is_some())
|
||||||
|
.map(|(idx, x)| (idx, x.as_ref().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an iterator which just gives the item.
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &'_ T> {
|
||||||
|
self.slots.iter().filter_map(|x| x.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Clone for SlotVec<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
slots: self.slots.clone(),
|
||||||
|
num_occupied: self.num_occupied.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user