diff --git a/src/libos/src/fs/sgx_impl.rs b/src/libos/src/fs/sgx_impl.rs index 87684676..f25a4ff2 100644 --- a/src/libos/src/fs/sgx_impl.rs +++ b/src/libos/src/fs/sgx_impl.rs @@ -5,11 +5,13 @@ use std::boxed::Box; use std::io::{Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; use std::sgxfs::{remove, OpenOptions, SgxFile}; -use std::sync::SgxMutex as Mutex; +use std::sync::{SgxMutex as Mutex, Arc}; use std::time::{SystemTime, UNIX_EPOCH}; +use std::collections::BTreeMap; pub struct SgxStorage { path: PathBuf, + file_cache: Mutex>, } impl SgxStorage { @@ -17,46 +19,73 @@ impl SgxStorage { // assert!(path.as_ref().is_dir()); SgxStorage { path: path.as_ref().to_path_buf(), + file_cache: Mutex::new(BTreeMap::new()) } } + /// Get file by `file_id`. + /// It lookups cache first, if miss, then call `open_fn` to open one, + /// and add it to cache before return. + fn get(&self, file_id: usize, open_fn: impl FnOnce(&Self) -> LockedFile) -> LockedFile { + // query cache + let mut caches = self.file_cache.lock().unwrap(); + if let Some(locked_file) = caches.get(&file_id) { + // hit, return + return locked_file.clone(); + } + // miss, open one + let locked_file = open_fn(self); + // add to cache + caches.insert(file_id, locked_file.clone()); + locked_file + } } impl Storage for SgxStorage { fn open(&self, file_id: usize) -> DevResult> { - let mut path = self.path.to_path_buf(); - path.push(format!("{}", file_id)); - // TODO: key - let key = [0u8; 16]; - let file = OpenOptions::new() - .read(true) - .update(true) - .open_ex(path, &key) - .expect("failed to open SgxFile"); - Ok(Box::new(LockedFile(Mutex::new(file)))) + let locked_file = self.get(file_id, |this| { + let mut path = this.path.to_path_buf(); + path.push(format!("{}", file_id)); + // TODO: key + let key = [0u8; 16]; + let file = OpenOptions::new() + .read(true) + .update(true) + .open_ex(path, &key) + .expect("failed to open SgxFile"); + LockedFile(Arc::new(Mutex::new(file))) + }); + Ok(Box::new(locked_file)) } fn create(&self, file_id: usize) -> DevResult> { - let mut path = self.path.to_path_buf(); - path.push(format!("{}", file_id)); - // TODO: key - let key = [0u8; 16]; - let file = OpenOptions::new() - .write(true) - .update(true) - .open_ex(path, &key) - .expect("failed to create SgxFile"); - Ok(Box::new(LockedFile(Mutex::new(file)))) + let locked_file = self.get(file_id, |this| { + let mut path = this.path.to_path_buf(); + path.push(format!("{}", file_id)); + // TODO: key + let key = [0u8; 16]; + let file = OpenOptions::new() + .write(true) + .update(true) + .open_ex(path, &key) + .expect("failed to create SgxFile"); + LockedFile(Arc::new(Mutex::new(file))) + }); + Ok(Box::new(locked_file)) } fn remove(&self, file_id: usize) -> DevResult<()> { let mut path = self.path.to_path_buf(); path.push(format!("{}", file_id)); remove(path).expect("failed to remove SgxFile"); + // remove from cache + let mut caches = self.file_cache.lock().unwrap(); + caches.remove(&file_id); Ok(()) } } -pub struct LockedFile(Mutex); +#[derive(Clone)] +pub struct LockedFile(Arc>); // `sgx_tstd::sgxfs::SgxFile` not impl Send ... unsafe impl Send for LockedFile {}