-
Notifications
You must be signed in to change notification settings - Fork 1
feat(fs): MemFs — in-memory Fs implementation for testing and in-memory trees #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
d051b11
303361e
52f701a
8d6033e
3520e08
afeccbd
53d24f0
e8ce4f2
f5b1030
0f599da
74352ee
f9c2a21
9451982
e0b8973
7e0fe3c
8c33e29
adad93e
76f3b67
cf46569
fee8a89
62e1fcf
c20521e
1cc66b4
5662b67
e911497
093765c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| [toolchain] | ||
| channel = "1.94.0" | ||
| channel = "1.94.1" | ||
| components = ["rustfmt", "clippy"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,8 @@ | |
|
|
||
| use crate::GlobalTableId; | ||
| use crate::descriptor_table::DescriptorTable; | ||
| use crate::fs::FsFile; | ||
| use crate::fs::{Fs, FsFile, FsOpenOptions}; | ||
| use std::path::Path; | ||
| use std::sync::Arc; | ||
|
|
||
| /// Allows accessing a file (either cached or pinned) | ||
|
|
@@ -15,46 +16,89 @@ pub enum FileAccessor { | |
| /// This is used in case file descriptor cache is `None` (to skip cache lookups) | ||
| File(Arc<dyn FsFile>), | ||
|
|
||
| /// Access to file descriptor cache | ||
| DescriptorTable(Arc<DescriptorTable>), | ||
| /// Access to file descriptor cache with [`Fs`]-based fallback for | ||
| /// cache misses. | ||
| DescriptorTable { | ||
| /// The FD cache. | ||
| table: Arc<DescriptorTable>, | ||
| /// Filesystem backend for opening files on cache miss. | ||
| fs: Arc<dyn Fs>, | ||
| }, | ||
| } | ||
|
Comment on lines
15
to
32
|
||
|
|
||
| impl FileAccessor { | ||
| #[must_use] | ||
| pub fn as_descriptor_table(&self) -> Option<&DescriptorTable> { | ||
| match self { | ||
| Self::DescriptorTable(d) => Some(d), | ||
| Self::DescriptorTable { table, .. } => Some(table), | ||
| Self::File(_) => None, | ||
| } | ||
| } | ||
|
|
||
| #[must_use] | ||
| pub fn access_for_table(&self, table_id: &GlobalTableId) -> Option<Arc<dyn FsFile>> { | ||
| /// Returns a cached table FD or opens the file via [`Fs`] on cache miss. | ||
| /// | ||
| /// The returned `bool` indicates whether the file descriptor was already | ||
| /// cached (`true`) or freshly opened (`false`). | ||
|
polaz marked this conversation as resolved.
Outdated
|
||
| pub fn get_or_open_table( | ||
| &self, | ||
| table_id: &GlobalTableId, | ||
| path: &Path, | ||
| ) -> std::io::Result<(Arc<dyn FsFile>, bool)> { | ||
| match self { | ||
| Self::File(fd) => Some(fd.clone()), | ||
| Self::DescriptorTable(descriptor_table) => descriptor_table.access_for_table(table_id), | ||
| } | ||
| } | ||
|
|
||
| pub fn insert_for_table(&self, table_id: GlobalTableId, fd: Arc<dyn FsFile>) { | ||
| if let Self::DescriptorTable(descriptor_table) = self { | ||
| descriptor_table.insert_for_table(table_id, fd); | ||
| // Pinned FD — not a descriptor-table cache event; report as miss | ||
| // so metrics reflect only actual cache traffic. | ||
| Self::File(fd) => Ok((fd.clone(), false)), | ||
| Self::DescriptorTable { table, fs } => { | ||
| if let Some(fd) = table.access_for_table(table_id) { | ||
| return Ok((fd, true)); | ||
| } | ||
| let fd: Arc<dyn FsFile> = | ||
|
polaz marked this conversation as resolved.
Outdated
|
||
| Arc::from(fs.open(path, &FsOpenOptions::new().read(true))?); | ||
| table.insert_for_table(*table_id, fd.clone()); | ||
| Ok((fd, false)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[must_use] | ||
| pub fn access_for_blob_file(&self, table_id: &GlobalTableId) -> Option<Arc<dyn FsFile>> { | ||
| /// Returns a cached blob file FD or opens it via [`Fs`] on cache miss. | ||
| /// | ||
| /// The returned `bool` indicates whether the file descriptor was already | ||
| /// cached (`true`) or freshly opened (`false`). | ||
| pub fn get_or_open_blob_file( | ||
| &self, | ||
| table_id: &GlobalTableId, | ||
| path: &Path, | ||
| ) -> std::io::Result<(Arc<dyn FsFile>, bool)> { | ||
| match self { | ||
| Self::File(fd) => Some(fd.clone()), | ||
| Self::DescriptorTable(descriptor_table) => { | ||
| descriptor_table.access_for_blob_file(table_id) | ||
| Self::File(fd) => Ok((fd.clone(), false)), | ||
| Self::DescriptorTable { table, fs } => { | ||
| if let Some(fd) = table.access_for_blob_file(table_id) { | ||
| return Ok((fd, true)); | ||
| } | ||
| let fd: Arc<dyn FsFile> = | ||
| Arc::from(fs.open(path, &FsOpenOptions::new().read(true))?); | ||
| table.insert_for_blob_file(*table_id, fd.clone()); | ||
| Ok((fd, false)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Pre-populates the blob file FD cache after creating a new blob file. | ||
| pub fn insert_for_blob_file(&self, table_id: GlobalTableId, fd: Arc<dyn FsFile>) { | ||
| if let Self::DescriptorTable(descriptor_table) = self { | ||
| descriptor_table.insert_for_blob_file(table_id, fd); | ||
| if let Self::DescriptorTable { table, .. } = self { | ||
| table.insert_for_blob_file(table_id, fd); | ||
| } | ||
| } | ||
|
|
||
| pub fn remove_for_table(&self, table_id: &GlobalTableId) { | ||
| if let Self::DescriptorTable { table, .. } = self { | ||
| table.remove_for_table(table_id); | ||
| } | ||
| } | ||
|
|
||
| pub fn remove_for_blob_file(&self, table_id: &GlobalTableId) { | ||
| if let Self::DescriptorTable { table, .. } = self { | ||
| table.remove_for_blob_file(table_id); | ||
| } | ||
| } | ||
|
polaz marked this conversation as resolved.
|
||
| } | ||
|
|
@@ -63,7 +107,7 @@ impl std::fmt::Debug for FileAccessor { | |
| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
| match self { | ||
| Self::File(_) => write!(f, "FileAccessor::Pinned"), | ||
| Self::DescriptorTable(_) => { | ||
| Self::DescriptorTable { .. } => { | ||
| write!(f, "FileAccessor::Cached") | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.