129 lines
4.6 KiB
Rust
129 lines
4.6 KiB
Rust
//! Storage protocol: a client `Attach`es to get a shared buffer; paths and
|
|
//! data travel through it, message words carry only lengths and handles.
|
|
|
|
use server_framework::{Decode, Encode};
|
|
use crate::filesystem::FileHandle;
|
|
|
|
pub use types::storage::{BUFFER_PAGES, BUFFER_SIZE, DIR_ENTRY_SIZE, DIR_NAME_SIZE, MAX_PATH};
|
|
use types::storage::{op, reply};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum StorageRequest {
|
|
Attach,
|
|
/// The path is the first `path_len` bytes of the buffer.
|
|
Open { path_len: usize },
|
|
/// Reads up to `len` bytes into the buffer.
|
|
Read { handle: FileHandle, len: usize },
|
|
/// Writes the first `len` bytes of the buffer.
|
|
Write { handle: FileHandle, len: usize },
|
|
Close { handle: FileHandle },
|
|
FileSize { handle: FileHandle },
|
|
/// Fills the buffer with `DIR_ENTRY_SIZE` records.
|
|
ListDir { path_len: usize },
|
|
Create { path_len: usize },
|
|
Delete { path_len: usize },
|
|
Mkdir { path_len: usize },
|
|
/// Carries the endpoint to print to.
|
|
SetLog,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum StorageResponse {
|
|
/// Carries the buffer capability; `size` bytes are usable.
|
|
Attached { size: usize },
|
|
Handle(FileHandle),
|
|
Data { bytes: usize },
|
|
Written { bytes: usize },
|
|
Ok,
|
|
DirEntries { count: usize },
|
|
Size(usize),
|
|
NotFound,
|
|
Error,
|
|
/// The disk cannot be written.
|
|
ReadOnly,
|
|
/// The client has not attached a buffer yet.
|
|
NotAttached,
|
|
}
|
|
|
|
fn handle(word: usize) -> Option<FileHandle> {
|
|
u16::try_from(word).ok().map(FileHandle::new)
|
|
}
|
|
|
|
impl Encode for StorageRequest {
|
|
fn encode(&self) -> [usize; 4] {
|
|
use StorageRequest::*;
|
|
match *self {
|
|
Attach => [op::ATTACH, 0, 0, 0],
|
|
Open { path_len } => [op::OPEN, path_len, 0, 0],
|
|
Read { handle, len } => [op::READ, handle.raw() as usize, len, 0],
|
|
Write { handle, len } => [op::WRITE, handle.raw() as usize, len, 0],
|
|
Close { handle } => [op::CLOSE, handle.raw() as usize, 0, 0],
|
|
FileSize { handle } => [op::FILE_SIZE, handle.raw() as usize, 0, 0],
|
|
ListDir { path_len } => [op::LIST_DIR, path_len, 0, 0],
|
|
Create { path_len } => [op::CREATE, path_len, 0, 0],
|
|
Delete { path_len } => [op::DELETE, path_len, 0, 0],
|
|
Mkdir { path_len } => [op::MKDIR, path_len, 0, 0],
|
|
SetLog => [op::SET_LOG, 0, 0, 0],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Decode for StorageRequest {
|
|
fn decode(w: [usize; 4]) -> Option<Self> {
|
|
use StorageRequest::*;
|
|
Some(match w[0] {
|
|
op::ATTACH => Attach,
|
|
op::OPEN => Open { path_len: w[1] },
|
|
op::READ => Read { handle: handle(w[1])?, len: w[2] },
|
|
op::WRITE => Write { handle: handle(w[1])?, len: w[2] },
|
|
op::CLOSE => Close { handle: handle(w[1])? },
|
|
op::FILE_SIZE => FileSize { handle: handle(w[1])? },
|
|
op::LIST_DIR => ListDir { path_len: w[1] },
|
|
op::CREATE => Create { path_len: w[1] },
|
|
op::DELETE => Delete { path_len: w[1] },
|
|
op::MKDIR => Mkdir { path_len: w[1] },
|
|
op::SET_LOG => SetLog,
|
|
_ => return None,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Encode for StorageResponse {
|
|
fn encode(&self) -> [usize; 4] {
|
|
use StorageResponse::*;
|
|
match *self {
|
|
Attached { size } => [reply::ATTACHED, size, 0, 0],
|
|
Handle(h) => [reply::HANDLE, h.raw() as usize, 0, 0],
|
|
Data { bytes } => [reply::DATA, bytes, 0, 0],
|
|
Written { bytes } => [reply::WRITTEN, bytes, 0, 0],
|
|
Ok => [reply::OK, 0, 0, 0],
|
|
DirEntries { count } => [reply::DIR_ENTRIES, count, 0, 0],
|
|
Size(s) => [reply::SIZE, s, 0, 0],
|
|
NotFound => [reply::NOT_FOUND, 0, 0, 0],
|
|
Error => [reply::ERROR, 0, 0, 0],
|
|
ReadOnly => [reply::READ_ONLY, 0, 0, 0],
|
|
NotAttached => [reply::NOT_ATTACHED, 0, 0, 0],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Decode for StorageResponse {
|
|
fn decode(w: [usize; 4]) -> Option<Self> {
|
|
use StorageResponse::*;
|
|
Some(match w[0] {
|
|
reply::ATTACHED => Attached { size: w[1] },
|
|
reply::HANDLE => Handle(handle(w[1])?),
|
|
reply::DATA => Data { bytes: w[1] },
|
|
reply::WRITTEN => Written { bytes: w[1] },
|
|
reply::OK => Ok,
|
|
reply::DIR_ENTRIES => DirEntries { count: w[1] },
|
|
reply::SIZE => Size(w[1]),
|
|
reply::NOT_FOUND => NotFound,
|
|
reply::ERROR => Error,
|
|
reply::READ_ONLY => ReadOnly,
|
|
reply::NOT_ATTACHED => NotAttached,
|
|
_ => return None,
|
|
})
|
|
}
|
|
}
|