add cache for SgxFile

This commit is contained in:
WangRunji 2019-04-21 18:04:48 +08:00
parent ad98a1698e
commit f4dacdc01d

@ -5,11 +5,13 @@ use std::boxed::Box;
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sgxfs::{remove, OpenOptions, SgxFile}; 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::time::{SystemTime, UNIX_EPOCH};
use std::collections::BTreeMap;
pub struct SgxStorage { pub struct SgxStorage {
path: PathBuf, path: PathBuf,
file_cache: Mutex<BTreeMap<usize, LockedFile>>,
} }
impl SgxStorage { impl SgxStorage {
@ -17,46 +19,73 @@ impl SgxStorage {
// assert!(path.as_ref().is_dir()); // assert!(path.as_ref().is_dir());
SgxStorage { SgxStorage {
path: path.as_ref().to_path_buf(), 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 { impl Storage for SgxStorage {
fn open(&self, file_id: usize) -> DevResult<Box<File>> { fn open(&self, file_id: usize) -> DevResult<Box<File>> {
let mut path = self.path.to_path_buf(); let locked_file = self.get(file_id, |this| {
path.push(format!("{}", file_id)); let mut path = this.path.to_path_buf();
// TODO: key path.push(format!("{}", file_id));
let key = [0u8; 16]; // TODO: key
let file = OpenOptions::new() let key = [0u8; 16];
.read(true) let file = OpenOptions::new()
.update(true) .read(true)
.open_ex(path, &key) .update(true)
.expect("failed to open SgxFile"); .open_ex(path, &key)
Ok(Box::new(LockedFile(Mutex::new(file)))) .expect("failed to open SgxFile");
LockedFile(Arc::new(Mutex::new(file)))
});
Ok(Box::new(locked_file))
} }
fn create(&self, file_id: usize) -> DevResult<Box<File>> { fn create(&self, file_id: usize) -> DevResult<Box<File>> {
let mut path = self.path.to_path_buf(); let locked_file = self.get(file_id, |this| {
path.push(format!("{}", file_id)); let mut path = this.path.to_path_buf();
// TODO: key path.push(format!("{}", file_id));
let key = [0u8; 16]; // TODO: key
let file = OpenOptions::new() let key = [0u8; 16];
.write(true) let file = OpenOptions::new()
.update(true) .write(true)
.open_ex(path, &key) .update(true)
.expect("failed to create SgxFile"); .open_ex(path, &key)
Ok(Box::new(LockedFile(Mutex::new(file)))) .expect("failed to create SgxFile");
LockedFile(Arc::new(Mutex::new(file)))
});
Ok(Box::new(locked_file))
} }
fn remove(&self, file_id: usize) -> DevResult<()> { fn remove(&self, file_id: usize) -> DevResult<()> {
let mut path = self.path.to_path_buf(); let mut path = self.path.to_path_buf();
path.push(format!("{}", file_id)); path.push(format!("{}", file_id));
remove(path).expect("failed to remove SgxFile"); remove(path).expect("failed to remove SgxFile");
// remove from cache
let mut caches = self.file_cache.lock().unwrap();
caches.remove(&file_id);
Ok(()) Ok(())
} }
} }
pub struct LockedFile(Mutex<SgxFile>); #[derive(Clone)]
pub struct LockedFile(Arc<Mutex<SgxFile>>);
// `sgx_tstd::sgxfs::SgxFile` not impl Send ... // `sgx_tstd::sgxfs::SgxFile` not impl Send ...
unsafe impl Send for LockedFile {} unsafe impl Send for LockedFile {}