diff --git a/src/core/directory.rs b/src/core/directory.rs index 53607e0aa..3caa90fa1 100644 --- a/src/core/directory.rs +++ b/src/core/directory.rs @@ -6,12 +6,15 @@ use std::collections::HashMap; use std::fs::File; use std::io; use std::rc::Rc; +use std::ops::Deref; +use std::cell::RefCell; +use std::sync::Arc; #[derive(Clone, Debug)] pub struct SegmentId(String); pub trait Dir { - fn get_file<'a>(&'a self, segment_id: &SegmentId, component: SegmentComponent) -> Result<&'a MemoryPointer, io::Error>; // { + fn get_data(&self, segment_id: &SegmentId, component: SegmentComponent) -> Result; // { } #[derive(Clone)] @@ -44,8 +47,8 @@ impl Directory { } impl Dir for Directory { - fn get_file<'a>(&'a self, segment_id: &SegmentId, component: SegmentComponent) -> Result<&'a MemoryPointer, io::Error> { - self.dir.get_file(segment_id, component) + fn get_data(&self, segment_id: &SegmentId, component: SegmentComponent) -> Result { + self.dir.get_data(segment_id, component) } } @@ -67,34 +70,13 @@ impl Segment { } } - fn get_file<'a>(&'a self, component: SegmentComponent) -> Result<&'a MemoryPointer, io::Error> { - self.directory.get_file(&self.segment_id, component) + fn get_data(&self, component: SegmentComponent) -> Result { + self.directory.get_data(&self.segment_id, component) } } - - - -////////////////////////////////////////////////////////// -// FileDirectory - -pub struct FileDirectory { - index_path: PathBuf, -} - -impl FileDirectory { - pub fn for_path(path: PathBuf)-> FileDirectory { - FileDirectory { - index_path: path, - } - } -} - - - - ///////////////////////////////////////////////////////// // MemoryPointer @@ -121,12 +103,13 @@ impl MemoryPointer for ResidentMemoryPointer { } + ///////////////////////////////////////////////////////// // // -struct MmapMemory(Mmap); +pub struct MmapMemory(Mmap); impl MemoryPointer for MmapMemory { fn len(&self) -> usize { @@ -139,18 +122,51 @@ impl MemoryPointer for MmapMemory { } } +#[derive(Clone)] +pub struct SharedMmapMemory(Arc); + +impl SharedMmapMemory { + pub fn new(mmap_memory: MmapMemory) -> SharedMmapMemory { + SharedMmapMemory(Arc::new(mmap_memory)) + } +} + +////////////////////////////////////////////////////////// +// FileDirectory + +pub struct FileDirectory { + index_path: PathBuf, + mmap_cache: RefCell>, +} + +impl FileDirectory { + pub fn for_path(path: PathBuf)-> FileDirectory { + FileDirectory { + index_path: path, + mmap_cache: RefCell::new(HashMap::new()), + } + } + + fn get_or_open_mmap(&self, filepath: &PathBuf)->Result { + if !self.mmap_cache.borrow().contains_key(filepath) { + let file = try!(File::open(filepath)); + let mmap = MmapMemory(try!(Mmap::open(&file, Protection::Read))); + self.mmap_cache.borrow_mut().insert(filepath.clone(), SharedMmapMemory::new(mmap)); + } + let shared_map: SharedMmapMemory = self.mmap_cache.borrow().get(filepath).unwrap().clone(); + Ok(shared_map) + } +} + impl Dir for FileDirectory { - fn get_file<'a>(&'a self, segment_id: &SegmentId, component: SegmentComponent) -> Result<&'a MemoryPointer, io::Error> { - let mut res = self.index_path.clone(); + fn get_data(&self, segment_id: &SegmentId, component: SegmentComponent) -> Result { + let mut filepath = self.index_path.clone(); let SegmentId(ref segment_id_str) = *segment_id; let filename = String::new() + segment_id_str + "." + Segment::path_suffix(component); - res.push(filename); - let file = try!(File::open(res)); - let mmap = MmapMemory(try!(Mmap::open(&file, Protection::Read))); - // let boxed_mmap: Box = Box::new(mmap); - // Ok(boxed_mmap) - Err(io::Error::new(io::ErrorKind::AddrInUse, "eee")) + filepath.push(filename); + self.get_or_open_mmap(&filepath) } + } ////////////////////////////////////////////////////////// @@ -158,7 +174,7 @@ impl Dir for FileDirectory { // pub struct MemDirectory { - dir: HashMap>, + dir: HashMap, } impl MemDirectory { @@ -170,14 +186,12 @@ impl MemDirectory { } impl Dir for MemDirectory { - fn get_file<'a>(&'a self, segment_id: &SegmentId, component: SegmentComponent) -> Result<&'a MemoryPointer, io::Error> { + fn get_data(&self, segment_id: &SegmentId, component: SegmentComponent) -> Result { let SegmentId(ref segment_id_str) = *segment_id; let mut path = PathBuf::from(segment_id_str); path.push(Segment::path_suffix(component)); match self.dir.get(&path) { - Some(buf) => { - Ok(buf.as_ref()) - }, + Some(buf) => Ok(buf.clone()), None => Err(io::Error::new(io::ErrorKind::NotFound, "File does not exists")), } }