//! Datatypes for the program use super::*; use std::fs::Metadata; use tokio::time::Duration; /// How many unprocessed insertion requests are allowed in the backlog before the insertion stream backpressures? pub const CACHE_SEND_BUFFER_SIZE: usize = 30; /// How many insertion requests should be grouped before emitting them all as blocks downstream. pub const CACHE_GATE_BUFFER_SIZE: usize = 80; /// How long should a partial block be kept in the gate buffer with an open upstream before being sent by force. pub const CACHE_GATE_TIMEOUT: Duration = duration!(100 ms); /// How long should the insertion stream be forced to wait before accepting new blocks to insert. pub const CACHE_GATED_LAG: Duration = duration!(10 ms); mod cache; pub use cache::Cache; pub mod graph; pub use graph::{ INodeInfoGraph, HierarchicalINodeGraph, FsObjKind as FsKind, INodeInfoGraphEntry, }; /// A raw file or directory inode number /// /// Ususally created from the `.inode()` extension method on `fs::Metadata` found in prelude. /// Can also be created with `new()` from a `fs::Metadata` reference, or created unsafely from an arbitrary `u64` with `new_unchecked`. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] #[cfg_attr(feature="inspect", derive(serde::Serialize, serde::Deserialize))] #[repr(transparent)] pub struct INode(u64); impl INode { /// Create a new `INode` wrapper from any `u64` without checking if it is a real inode. #[inline] pub const unsafe fn new_unchecked(ino: u64) -> Self { Self(ino) } /// Get `ino` from an `fs::Metadata` object. #[inline] pub fn new(meta: &Metadata) -> Self { use std::os::unix::fs::MetadataExt as _; Self(meta.ino()) } /// Convert into raw `u64` inode number. #[inline] pub const fn into_inner(self) -> u64 { self.0 } } impl<'a> From<&'a Metadata> for INode { #[inline] fn from(from: &'a Metadata) -> Self { from.inode() } } impl From for u64 { #[inline] fn from(from: INode) -> Self { from.0 } } /// A valid file system info /// /// # Note /// This does not contains the INode of the fs object itself, that is considered that key to the table. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum FsInfo { File(u64, INode), //Size, parent dir inode Directory(INode), // Parent dir inode } impl FsInfo { /// Is this entry a directory #[inline] pub fn is_dir(&self) -> bool { if let Self::Directory(_) = self { true } else { false } } } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn cache_insert_and_consume() { let mut cache = Cache::new(); for x in 0..500 { cache.insert(unsafe { INode::new_unchecked(x) }, FsInfo::Directory).await; } let output = cache.try_complete().await.unwrap(); assert_eq!(output.len(), 500); for x in 0..500 { assert_eq!(output.get(&unsafe { INode::new_unchecked(x) }).unwrap(), &FsInfo::Directory); } } }