Skip to content

Commit

Permalink
feat: concurrency aww yeah
Browse files Browse the repository at this point in the history
  • Loading branch information
sstelfox committed Feb 14, 2024
1 parent faf283e commit 5466a11
Show file tree
Hide file tree
Showing 9 changed files with 654 additions and 74 deletions.
529 changes: 515 additions & 14 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ default = ["strict"]
strict = []

[dependencies]
async-std = "^1"
async-trait = "^0.1"
futures = "^0.3"
thiserror = "^1"
Expand Down
162 changes: 116 additions & 46 deletions src/filesystem/drive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::collections::HashMap;
use std::path::{Component, Path};
use std::sync::Arc;

use async_std::sync::RwLock;
use elliptic_curve::rand_core::CryptoRngCore;
use slab::Slab;

Expand All @@ -8,25 +11,30 @@ use crate::codec::header::KeyAccessSettingsBuilder;
use crate::codec::meta::{ActorId, FilesystemId};
use crate::filesystem::nodes::NodeKind;
use crate::filesystem::operations::*;
use crate::filesystem::{DriveAccess, Node, NodeBuilder, NodeId, PermanentNodeId};
use crate::filesystem::{DriveAccess, Node, NodeBuilder, NodeId, PermanentId};

pub struct Drive {
current_key: SigningKey,

filesystem_id: FilesystemId,
access: DriveAccess,
inner: Arc<RwLock<InnerDrive>>,
}

struct InnerDrive {
access: DriveAccess,
nodes: Slab<Node>,
root_node_id: NodeId,
permanent_id_map: HashMap<PermanentId, NodeId>,
}

impl Drive {
pub fn has_realized_view_access(&self, actor_id: ActorId) -> bool {
self.access.has_realized_view_access(actor_id)
pub async fn has_realized_view_access(&self, actor_id: ActorId) -> bool {
let inner = self.inner.read().await;
inner.access.has_realized_view_access(actor_id)
}

pub fn has_write_access(&self, actor_id: ActorId) -> bool {
self.access.has_write_access(actor_id)
pub async fn has_write_access(&self, actor_id: ActorId) -> bool {
let inner = self.inner.read().await;
inner.access.has_write_access(actor_id)
}

//pub async fn encode_private<W: AsyncWrite + Unpin + Send>(
Expand Down Expand Up @@ -79,71 +87,133 @@ impl Drive {
access.register_actor(verifying_key, kas);

let mut nodes = Slab::with_capacity(32);
let mut permanent_id_map = HashMap::new();

let node_entry = nodes.vacant_entry();
let root_node_id = node_entry.key();

let directory = NodeBuilder::directory(root_node_id, actor_id).build(rng);
permanent_id_map.insert(directory.permanent_id(), root_node_id);
node_entry.insert(directory);

Self {
current_key,

filesystem_id,
access,

nodes,
root_node_id,
inner: Arc::new(RwLock::new(InnerDrive {
access,
nodes,
root_node_id,
permanent_id_map,
})),
}
}

pub(crate) fn root_directory(&mut self) -> Directory {
Directory::new(self, self.root_node_id)
pub async fn mkdir(
&mut self,
_rng: &mut impl CryptoRngCore,
_path: &Path,
_recursive: bool,
) -> Result<Directory, OperationError> {
todo!()
}

pub(crate) async fn root_directory(&mut self) -> Directory {
let inner_read = self.inner.read().await;
let root_node_id = inner_read.root_node_id;
drop(inner_read);

Directory::new(&self.current_key, root_node_id, self.inner.clone()).await
}
}

pub struct Directory<'a> {
drive: &'a mut Drive,
node_id: NodeId,
current_key: &'a SigningKey,
cwd_id: NodeId,
inner: Arc<RwLock<InnerDrive>>,
}

impl<'a> Directory<'a> {
//async fn ls(mut self, path: &Path) -> Result<Vec<(String, PermanentNodeId)>, OperationError> {
// let mut components = path.components();

// let mut active_path = components.next();
// if let Some(Component::RootDir) = active_path {
// self.node_id = self.drive.root_node_id;
// active_path = components.next();
// }

// let node_children = match self.drive.nodes[self.node_id].kind() {
// NodeKind::Directory { children, .. } => children,
// _ => return Err(OperationError::IncompatibleType("ls")),
// };

// if active_path.is_none() || active_path == Some(Component::CurDir) {
// let contents: Vec<_> = node_children
// .iter()
// .map(|(name, pid)| (name.clone(), pid.clone()))
// .collect();

// return Ok(contents);
// }
//
// // todo: need to get the next node id , validate its a directory and then continue

// self.ls(components.as_path()).await
//}
async fn walk_directory(&self, path: &Path) -> Result<NodeId, OperationError> {
let mut components = path.components();
let mut cwd_id = self.cwd_id;

loop {
let mut active_path = match components.next() {
Some(path) => path,
None => return Err(OperationError::UnexpectedEmptyPath),
};

match active_path {
Component::RootDir => {
cwd_id = self.inner.read().await.root_node_id;
}
_ => (),
}

let node_children = match self.inner.read().await.nodes[cwd_id].kind() {
NodeKind::Directory { children, .. } => children,
_ => return Err(OperationError::IncompatibleType("ls")),
};

todo!()
}
}

async fn ls(mut self, path: &Path) -> Result<Vec<(String, PermanentId)>, OperationError> {
let mut components = path.components();
let mut cwd_id = self.cwd_id;

let inner_read = self.inner.read().await;

loop {
let mut active_path = components.next();
if let Some(Component::RootDir) = active_path {
cwd_id = inner_read.root_node_id;
active_path = components.next();
}

let node_children = match inner_read.nodes[cwd_id].kind() {
NodeKind::Directory { children, .. } => children,
_ => return Err(OperationError::IncompatibleType("ls")),
};

match active_path {
Some(Component::CurDir) => (),
None => {
let contents: Vec<_> = node_children
.iter()
.map(|(name, pid)| (name.clone(), *pid))
.collect();

return Ok(contents);
}
_ => (),
}

todo!()
}
}

pub async fn new(
current_key: &'a SigningKey,
cwd_id: NodeId,
inner: Arc<RwLock<InnerDrive>>,
) -> Self {
let inner_read = inner.read().await;

pub fn new(drive: &'a mut Drive, node_id: NodeId) -> Self {
debug_assert!(drive.nodes.contains(node_id));
debug_assert!(inner_read.nodes.contains(cwd_id));
debug_assert!(matches!(
drive.nodes[node_id].kind(),
inner_read.nodes[cwd_id].kind(),
NodeKind::Directory { .. }
));
drop(inner_read);

Self { drive, node_id }
Self {
current_key,
cwd_id,
inner,
}
}

pub fn mkdir(
Expand Down
2 changes: 1 addition & 1 deletion src/filesystem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub(crate) mod nodes;

pub(crate) use content_reference::ContentReference;
pub(crate) use file_content::FileContent;
pub(crate) use nodes::{Node, NodeBuilder, NodeId, PermanentNodeId};
pub(crate) use nodes::{Node, NodeBuilder, NodeId, PermanentId};
pub(crate) use vector_clock::VectorClock;

pub use drive::Drive;
Expand Down
8 changes: 6 additions & 2 deletions src/filesystem/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ use crate::codec::meta::ActorId;

pub(crate) type NodeId = usize;

pub(crate) type PermanentNodeId = [u8; 16];
pub(crate) type PermanentId = [u8; 16];

pub struct Node {
node_id: NodeId,
parent_id: Option<NodeId>,

owner_id: ActorId,
permanent_id: PermanentNodeId,
permanent_id: PermanentId,

created_at: OffsetDateTime,
modified_at: OffsetDateTime,
Expand All @@ -37,6 +37,10 @@ impl Node {
self.owner_id
}

pub fn permanent_id(&self) -> PermanentId {
self.permanent_id
}

pub fn set_attribute(&mut self, key: String, value: Vec<u8>) -> Option<Vec<u8>> {
self.metadata.insert(key, value)
}
Expand Down
4 changes: 2 additions & 2 deletions src/filesystem/nodes/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;
use time::OffsetDateTime;

use crate::codec::meta::ActorId;
use crate::filesystem::nodes::{Node, NodeId, NodeKind, PermanentNodeId};
use crate::filesystem::nodes::{Node, NodeId, NodeKind, PermanentId};

pub(crate) struct NodeBuilder {
node_id: NodeId,
Expand All @@ -30,7 +30,7 @@ impl NodeBuilder {
}

pub fn build(self, rng: &mut impl CryptoRngCore) -> Node {
let permanent_id: PermanentNodeId = rng.gen();
let permanent_id: PermanentId = rng.gen();

Node {
node_id: self.node_id,
Expand Down
4 changes: 2 additions & 2 deletions src/filesystem/nodes/node_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::codec::filesystem::DirectoryPermissions;
use crate::codec::filesystem::FilePermissions;
use crate::filesystem::FileContent;
use crate::filesystem::PermanentNodeId;
use crate::filesystem::PermanentId;

pub enum NodeKind {
File {
Expand All @@ -12,7 +12,7 @@ pub enum NodeKind {
},
Directory {
permissions: DirectoryPermissions,
children: HashMap<String, PermanentNodeId>,
children: HashMap<String, PermanentId>,
children_size: u64,
},
}
Expand Down
3 changes: 3 additions & 0 deletions src/filesystem/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub(crate) trait Movable {
pub enum OperationError {
#[error("the {0} operation is not supported by this node type")]
IncompatibleType(&'static str),

#[error("unable to make use of an empty path")]
UnexpectedEmptyPath,
}

#[async_trait]
Expand Down
15 changes: 8 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ async fn main() -> BanyanFsResult<()> {
let verifying_key = signing_key.verifying_key();
let actor_id = verifying_key.actor_id();

let drive = Drive::initialize_private(&mut rng, signing_key.clone());
let mut drive = Drive::initialize_private(&mut rng, signing_key.clone());

if !drive.has_realized_view_access(actor_id) {
if !drive.has_realized_view_access(actor_id).await {
tracing::error!("key doesn't have access to the drive");
return Err(BanyanFsError("key doesn't have access to the drive"));
}

if drive.has_write_access(actor_id) {
// if let Err(err) = drive.mkdir(&mut rng, &["testing", "paths"], true) {
// tracing::error!("failed to create directory: {}", err);
// return Ok(());
// }
if drive.has_write_access(actor_id).await {
let path_buf = std::path::PathBuf::from("/testing/paths");
if let Err(err) = drive.mkdir(&mut rng, path_buf.as_path(), true).await {
tracing::error!("failed to create directory: {}", err);
return Ok(());
}

// // let fh = drive.open("/root/testing/deep/paths/file.txt")?;
// // fh.write(b"hello world")?;
Expand Down

0 comments on commit 5466a11

Please sign in to comment.