Skip to content

Commit

Permalink
fix(Judger): ⚡ fix locking scheme
Browse files Browse the repository at this point in the history
  • Loading branch information
Eason0729 committed May 2, 2024
1 parent 6abdd30 commit 11d9659
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 367 deletions.
30 changes: 0 additions & 30 deletions judger/src/filesystem/fuse.rs

This file was deleted.

4 changes: 2 additions & 2 deletions judger/src/filesystem/overlay/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::future::Future;
use std::io;
use std::{
io::SeekFrom,
ops::{Deref, DerefMut},
ops::Deref,
pin::{pin, Pin},
sync::Arc,
task::{Context, Poll},
Expand All @@ -13,7 +13,7 @@ use tokio::{
sync::{Mutex, OwnedMutexGuard},
};

const MEMBLOCK_BLOCKSIZE: usize = 4096;
pub const MEMBLOCK_BLOCKSIZE: usize = 4096;

#[derive(Debug, Default)]
enum MemStage {
Expand Down
130 changes: 113 additions & 17 deletions judger/src/filesystem/overlay/entry.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,134 @@
use std::{ffi::OsString, sync::Arc};
use std::{
ffi::{OsStr, OsString},
sync::Arc,
};

use tokio::io::{AsyncRead, AsyncSeek};

use crate::{
filesystem::{tar::Entry, INODE},
semaphore::*,
use crate::filesystem::{
table::{INodeTable, Identified},
tar::Entry as RoEntry,
tree::ArcNode,
};

use super::block::MemBlock;

pub type ArcEntry<F> = Arc<tokio::sync::Mutex<MixedEntry<F>>>;
type ArcEntry<F> = ArcNode<EntryKind<F>>;

/// Entry from tar file, it's a replacement of Entry
pub enum MutEntry {
#[derive(Default)]
pub enum RwEntry {
SymLink(OsString),
HardLink(INODE),
HardLink(u64),
#[default]
Directory,
File(MemBlock),
Removed,
}

/// A workaround to not use dynamic dispatch and compact the size of Entry
pub enum MixedEntry<F>
pub enum EntryKind<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
Rw(ArcNode<RwEntry>),
Ro(ArcNode<RoEntry<F>>),
}

impl<F> Clone for EntryKind<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
fn clone(&self) -> Self {
match self {
Self::Rw(arg0) => Self::Rw(arg0.clone()),
Self::Ro(arg0) => Self::Ro(arg0.clone()),
}
}
}

impl<F> EntryKind<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
Mut(Permit, Arc<MutEntry>),
Immut(Entry<F>),
pub async fn get_child_by_componment(&self, component: &OsStr) -> Option<Self> {
match self {
Self::Rw(node) => (node.read().await.get_by_component(component)).map(Self::Rw),
Self::Ro(node) => todo!(),
}
}
}

// operation that's per file
// impl MixedEntry {
// pub async fn read(){}
// pub async fn write(){}
// pub async fn flush(){}
// pub async fn close(){}
// }
pub struct Entry<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
pub kind: EntryKind<F>,
inode: u64,
}

impl<F> Identified for Entry<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
fn get_id(&self) -> usize {
match &self.kind {
EntryKind::Rw(x) => Arc::as_ptr(x) as usize,
EntryKind::Ro(x) => Arc::as_ptr(x) as usize,
}
}
}

impl<F> Clone for Entry<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
fn clone(&self) -> Self {
Self {
kind: self.kind.clone(),
inode: self.inode.clone(),
}
}
}

impl<F> Entry<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
#[inline]
pub fn from_kind(kind: EntryKind<F>, inode: u64) -> Self {
Self { kind, inode }
}
#[inline]
pub fn get_inode(&self) -> u64 {
self.inode
}
}

impl<F> INodeTable<Entry<F>>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
pub fn add_entry_rw(&self, entry: ArcNode<RwEntry>) -> Entry<F> {
self.allocate(|x| Entry::from_kind(EntryKind::Rw(entry.clone()), x))
}
pub fn add_entry_ro(&self, entry: ArcNode<RoEntry<F>>) -> Entry<F> {
self.allocate(|x| Entry::from_kind(EntryKind::Ro(entry.clone()), x))
}
pub fn add_entry_kind(&self, kind: EntryKind<F>) -> Entry<F> {
self.allocate(|x| Entry::from_kind(kind.clone(), x))
}
pub fn lookup(&self, inode: u64) -> Option<Entry<F>> {
self.get(inode)
}
pub async fn get_child_by_componment(&self, inode: u64, component: &OsStr) -> Option<Entry<F>> {
if let Some(entry) = self.get(inode) {
return entry
.kind
.get_child_by_componment(component)
.await
.map(|kind| self.add_entry_kind(kind));
}
None
}
}
39 changes: 39 additions & 0 deletions judger/src/filesystem/overlay/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,43 @@
mod block;
mod entry;
mod reply;

pub use block::MEMBLOCK_BLOCKSIZE as BLOCKSIZE;
pub use entry::*;
pub use reply::Parsable;
use tokio::io::{AsyncRead, AsyncSeek};

use super::{
table::{HandleTable, INodeTable},
tar::TarLayer,
};

pub struct Overlay<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
tar: TarLayer<F>,
pub inode: INodeTable<Entry<F>>,
pub handle: HandleTable<Entry<F>>,
}

impl<F> Overlay<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
pub async fn new(tar: TarLayer<F>) -> Self {
let inode = INodeTable::new();
inode.add_entry_ro(tar.get_root().await);
Self {
tar,
inode,
handle: HandleTable::new(),
}
}
pub fn get_root(&self) -> Entry<F> {
self.inode.get(1).unwrap()
}
pub fn lookup(&self, inode: u64) -> Option<Entry<F>> {
self.inode.get(inode)
}
}
40 changes: 40 additions & 0 deletions judger/src/filesystem/overlay/reply.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::time::Duration;

use fuse3::{raw::{reply::*, Request}, Timestamp};
use tokio::io::{AsyncRead, AsyncSeek};

use super::Entry;

pub trait Parsable<F>
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
fn parse(request: Request, entry: Entry<F>) -> Self;
}

impl<F> Parsable<F> for ReplyEntry
where
F: AsyncRead + AsyncSeek + Unpin + 'static,
{
fn parse(request: Request, entry: Entry<F>) -> Self {
Self {
ttl: Duration::from_secs(30),
attr: FileAttr {
ino: entry.get_inode(),
size: 0,
blocks: 0,
atime: Timestamp::new(0, 0),
mtime: Timestamp::new(0, 0),
ctime: Timestamp::new(0, 0),
kind: todo!(),
perm: todo!(),
nlink: todo!(),
uid: todo!(),
gid: todo!(),
rdev: todo!(),
blksize: todo!(),
},
generation: 1,
}
}
}
Loading

0 comments on commit 11d9659

Please sign in to comment.