Mercurial > lbo > hg > leveldb-rs
changeset 183:98bfd5147ded
Write test for TableCache making use of MemEnv.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 12 Aug 2017 17:11:09 +0200 |
parents | d7e4693effba |
children | b3da8e0fe92d |
files | src/mem_env.rs src/options.rs src/table_cache.rs src/table_reader.rs |
diffstat | 4 files changed, 44 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/src/mem_env.rs Sat Aug 12 16:26:40 2017 +0200 +++ b/src/mem_env.rs Sat Aug 12 17:11:09 2017 +0200 @@ -238,7 +238,7 @@ pub struct MemEnv(MemFS); impl MemEnv { - fn new() -> MemEnv { + pub fn new() -> MemEnv { MemEnv(MemFS::new()) } }
--- a/src/options.rs Sat Aug 12 16:26:40 2017 +0200 +++ b/src/options.rs Sat Aug 12 17:11:09 2017 +0200 @@ -78,9 +78,14 @@ /// DO NOT set the comparator after having written any record with a different comparator. /// If the comparator used differs from the one used when writing a database that is being /// opened, the library is free to panic. - pub fn set_comparator<C: Cmp>(&mut self, c: Box<Cmp>) { + pub fn set_comparator(&mut self, c: Box<Cmp>) { self.cmp = Arc::new(c); } + + /// Set the environment to use. The default is PosixDiskEnv. + pub fn set_env(&mut self, e: Box<Env>) { + self.env = Arc::new(e); + } } /// Supplied to DB read operations.
--- a/src/table_cache.rs Sat Aug 12 16:26:40 2017 +0200 +++ b/src/table_cache.rs Sat Aug 12 17:11:09 2017 +0200 @@ -23,18 +23,14 @@ buf } -struct TableAndFile { - file: Arc<Box<RandomAccess>>, - table: Table, -} - pub struct TableCache { dbname: String, - cache: Cache<TableAndFile>, + cache: Cache<Table>, opts: Options, } impl TableCache { + /// Create a new TableCache for the database named `db`, caching up to `entries` tables. pub fn new(db: &str, opt: Options, entries: usize) -> TableCache { TableCache { dbname: String::from(db), @@ -42,32 +38,25 @@ opts: opt, } } - pub fn evict(&mut self, id: u64) { - self.cache.remove(&filenum_to_key(id)); - } /// Return a table from cache, or open the backing file, then cache and return it. - pub fn get_table(&mut self, file_num: u64, file_size: usize) -> Result<Table> { + pub fn get_table(&mut self, file_num: u64) -> Result<Table> { let key = filenum_to_key(file_num); - match self.cache.get(&key) { - Some(t) => return Ok(t.table.clone()), - _ => {} + if let Some(t) = self.cache.get(&key) { + return Ok(t.clone()); } - self.open_table(file_num, file_size) + self.open_table(file_num) } /// Open a table on the file system and read it. - fn open_table(&mut self, file_num: u64, file_size: usize) -> Result<Table> { + fn open_table(&mut self, file_num: u64) -> Result<Table> { let name = table_name(&self.dbname, file_num, DEFAULT_SUFFIX); let path = Path::new(&name); let file = Arc::new(self.opts.env.open_random_access_file(&path)?); + let file_size = self.opts.env.size_of(&path)?; // No SSTable file name compatibility. - let table = Table::new(self.opts.clone(), file.clone(), file_size)?; - self.cache.insert(&filenum_to_key(file_num), - TableAndFile { - file: file.clone(), - table: table.clone(), - }); + let table = Table::new(self.opts.clone(), file, file_size)?; + self.cache.insert(&filenum_to_key(file_num), table.clone()); Ok(table) } } @@ -76,10 +65,9 @@ mod tests { use super::*; use cache; + use mem_env::MemEnv; use table_builder::TableBuilder; - use std::io::Write; - #[test] fn test_table_name() { assert_eq!("abc/000122.ldb", table_name("abc", 122, "ldb")); @@ -97,10 +85,9 @@ assert_eq!(make_key(1, 2, 3), filenum_to_key(0x030201)); } - fn write_table_to(w: Box<Write>) { - let mut opt = Options::default(); - opt.block_restart_interval = 3; - let mut b = TableBuilder::new_raw(opt, w); + fn write_table_to(o: Options, p: &Path) { + let w = o.env.open_writable_file(p).unwrap(); + let mut b = TableBuilder::new_raw(o, w); let data = vec![("abc", "def"), ("abd", "dee"), ("bcd", "asa"), ("bsr", "a00")]; @@ -110,7 +97,23 @@ b.finish(); } - // TODO: Write tests after memenv has been implemented. #[test] - fn test_table_cache() {} + fn test_table_cache() { + // Tests that a table can be written to a MemFS file, read back by the table cache and + // parsed/iterated by the table reader. + let mut opt = Options::default(); + opt.set_env(Box::new(MemEnv::new())); + let dbname = "testdb1"; + let tablename = table_name(dbname, 123, DEFAULT_SUFFIX); + let tblpath = Path::new(&tablename); + + write_table_to(opt.clone(), tblpath); + assert!(opt.env.exists(tblpath).unwrap()); + assert!(opt.env.size_of(tblpath).unwrap() > 20); + + let mut cache = TableCache::new(dbname, opt.clone(), 10); + assert_eq!(cache.get_table(123).unwrap().iter().count(), 4); + // Test cached table. + assert_eq!(cache.get_table(123).unwrap().iter().count(), 4); + } }
--- a/src/table_reader.rs Sat Aug 12 16:26:40 2017 +0200 +++ b/src/table_reader.rs Sat Aug 12 17:11:09 2017 +0200 @@ -153,8 +153,9 @@ } } - let rfile = self.file.as_ref().as_ref(); - let b = try!(TableBlock::read_block(self.opt.clone(), rfile, location)); + let rfile = self.file.clone(); + // Two times as_ref(): First time to get a ref from Arc<>, then one from Box<>. + let b = try!(TableBlock::read_block(self.opt.clone(), rfile.as_ref().as_ref(), location)); if !b.verify() { return Err(Status::new(StatusCode::InvalidData, "Data block failed verification")); @@ -181,8 +182,8 @@ return self.footer.meta_index.offset(); } - // Iterators read from the file; thus only one iterator can be borrowed (mutably) per scope - fn iter<'a>(&'a mut self) -> TableIterator<'a> { + /// Iterators read from the file; thus only one iterator can be borrowed (mutably) per scope + pub fn iter<'a>(&'a mut self) -> TableIterator<'a> { let iter = TableIterator { current_block: self.indexblock.iter(), init: false,