Mercurial > lbo > hg > leveldb-rs
changeset 373:24a2501732de
block_builder: Move BlockBuilder into dedicated module.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 08 Oct 2017 15:36:45 +0200 |
parents | 0c2ec9035654 |
children | 07043da88acf |
files | src/block.rs src/block_builder.rs src/lib.rs src/table_builder.rs |
diffstat | 4 files changed, 167 insertions(+), 123 deletions(-) [+] |
line wrap: on
line diff
--- a/src/block.rs Sun Oct 08 13:54:01 2017 +0200 +++ b/src/block.rs Sun Oct 08 15:36:45 2017 +0200 @@ -298,114 +298,10 @@ } } -pub struct BlockBuilder { - opt: Options, - buffer: Vec<u8>, - restarts: Vec<u32>, - - last_key: Vec<u8>, - counter: usize, -} - -impl BlockBuilder { - pub fn new(o: Options) -> BlockBuilder { - let mut restarts = vec![0]; - restarts.reserve(1023); - - BlockBuilder { - buffer: Vec::with_capacity(o.block_size), - opt: o, - restarts: restarts, - last_key: Vec::new(), - counter: 0, - } - } - - pub fn entries(&self) -> usize { - self.counter - } - - pub fn last_key<'a>(&'a self) -> &'a [u8] { - &self.last_key - } - - pub fn size_estimate(&self) -> usize { - self.buffer.len() + 4 * self.restarts.len() + 4 - } - - pub fn reset(&mut self) { - self.buffer.clear(); - self.restarts.clear(); - self.last_key.clear(); - self.counter = 0; - } - - pub fn add(&mut self, key: &[u8], val: &[u8]) { - assert!(self.counter <= self.opt.block_restart_interval); - assert!(self.buffer.is_empty() || - self.opt.cmp.cmp(self.last_key.as_slice(), key) == Ordering::Less); - - let mut shared = 0; - - if self.counter < self.opt.block_restart_interval { - let smallest = if self.last_key.len() < key.len() { - self.last_key.len() - } else { - key.len() - }; - - while shared < smallest && self.last_key[shared] == key[shared] { - shared += 1; - } - } else { - self.restarts.push(self.buffer.len() as u32); - self.last_key.resize(0, 0); - self.counter = 0; - } - - let non_shared = key.len() - shared; - - let mut buf = [0 as u8; 4]; - - let mut sz = shared.encode_var(&mut buf[..]); - self.buffer.extend_from_slice(&buf[0..sz]); - sz = non_shared.encode_var(&mut buf[..]); - self.buffer.extend_from_slice(&buf[0..sz]); - sz = val.len().encode_var(&mut buf[..]); - self.buffer.extend_from_slice(&buf[0..sz]); - - self.buffer.extend_from_slice(&key[shared..]); - self.buffer.extend_from_slice(val); - - // Update key - self.last_key.resize(shared, 0); - self.last_key.extend_from_slice(&key[shared..]); - - self.counter += 1; - } - - pub fn finish(mut self) -> BlockContents { - // 1. Append RESTARTS - let mut i = self.buffer.len(); - self.buffer.resize(i + self.restarts.len() * 4 + 4, 0); - - for r in self.restarts.iter() { - r.encode_fixed(&mut self.buffer[i..i + 4]); - i += 4; - } - - // 2. Append N_RESTARTS - (self.restarts.len() as u32).encode_fixed(&mut self.buffer[i..i + 4]); - - // done - self.buffer - } -} - - #[cfg(test)] mod tests { use super::*; + use block_builder::BlockBuilder; use options; use test_util::{test_iterator_properties, LdbIteratorIter}; use types::{current_key_val, LdbIterator}; @@ -435,23 +331,6 @@ } #[test] - fn test_block_builder() { - let mut o = options::for_test(); - o.block_restart_interval = 3; - - let mut builder = BlockBuilder::new(o); - - for &(k, v) in get_data().iter() { - builder.add(k, v); - assert!(builder.counter <= 3); - assert_eq!(builder.last_key(), k); - } - - let block = builder.finish(); - assert_eq!(block.len(), 149); - } - - #[test] fn test_block_empty() { let mut o = options::for_test(); o.block_restart_interval = 16;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/block_builder.rs Sun Oct 08 15:36:45 2017 +0200 @@ -0,0 +1,163 @@ +use std::cmp::Ordering; + +use block::BlockContents; +use options::Options; + +use integer_encoding::FixedInt; +use integer_encoding::VarInt; + +/// BlockBuilder contains functionality for building a block consisting of consecutive key-value +/// entries. +pub struct BlockBuilder { + opt: Options, + buffer: Vec<u8>, + restarts: Vec<u32>, + + last_key: Vec<u8>, + counter: usize, +} + +impl BlockBuilder { + pub fn new(o: Options) -> BlockBuilder { + let mut restarts = vec![0]; + restarts.reserve(1023); + + BlockBuilder { + buffer: Vec::with_capacity(o.block_size), + opt: o, + restarts: restarts, + last_key: Vec::new(), + counter: 0, + } + } + + pub fn entries(&self) -> usize { + self.counter + } + + pub fn last_key<'a>(&'a self) -> &'a [u8] { + &self.last_key + } + + pub fn size_estimate(&self) -> usize { + self.buffer.len() + 4 * self.restarts.len() + 4 + } + + pub fn reset(&mut self) { + self.buffer.clear(); + self.restarts.clear(); + self.last_key.clear(); + self.counter = 0; + } + + pub fn add(&mut self, key: &[u8], val: &[u8]) { + assert!(self.counter <= self.opt.block_restart_interval); + assert!(self.buffer.is_empty() || + self.opt.cmp.cmp(self.last_key.as_slice(), key) == Ordering::Less); + + let mut shared = 0; + + if self.counter < self.opt.block_restart_interval { + let smallest = if self.last_key.len() < key.len() { + self.last_key.len() + } else { + key.len() + }; + + while shared < smallest && self.last_key[shared] == key[shared] { + shared += 1; + } + } else { + self.restarts.push(self.buffer.len() as u32); + self.last_key.resize(0, 0); + self.counter = 0; + } + + let non_shared = key.len() - shared; + + let mut buf = [0 as u8; 4]; + + let mut sz = shared.encode_var(&mut buf[..]); + self.buffer.extend_from_slice(&buf[0..sz]); + sz = non_shared.encode_var(&mut buf[..]); + self.buffer.extend_from_slice(&buf[0..sz]); + sz = val.len().encode_var(&mut buf[..]); + self.buffer.extend_from_slice(&buf[0..sz]); + + self.buffer.extend_from_slice(&key[shared..]); + self.buffer.extend_from_slice(val); + + // Update key + self.last_key.resize(shared, 0); + self.last_key.extend_from_slice(&key[shared..]); + + self.counter += 1; + } + + pub fn finish(mut self) -> BlockContents { + // 1. Append RESTARTS + let mut i = self.buffer.len(); + self.buffer.resize(i + self.restarts.len() * 4 + 4, 0); + + for r in self.restarts.iter() { + r.encode_fixed(&mut self.buffer[i..i + 4]); + i += 4; + } + + // 2. Append N_RESTARTS + (self.restarts.len() as u32).encode_fixed(&mut self.buffer[i..i + 4]); + + // done + self.buffer + } +} + +#[cfg(test)] +mod tests { + use super::*; + use options; + + fn get_data() -> Vec<(&'static [u8], &'static [u8])> { + vec![("key1".as_bytes(), "value1".as_bytes()), + ("loooooooooooooooooooooooooooooooooongerkey1".as_bytes(), "shrtvl1".as_bytes()), + ("medium length key 1".as_bytes(), "some value 2".as_bytes()), + ("prefix_key1".as_bytes(), "value".as_bytes()), + ("prefix_key2".as_bytes(), "value".as_bytes()), + ("prefix_key3".as_bytes(), "value".as_bytes())] + } + + #[test] + fn test_block_builder_sanity() { + let mut o = options::for_test(); + o.block_restart_interval = 3; + + let mut builder = BlockBuilder::new(o); + + for &(k, v) in get_data().iter() { + builder.add(k, v); + assert!(builder.counter <= 3); + assert_eq!(builder.last_key(), k); + } + + assert_eq!(149, builder.size_estimate()); + let block = builder.finish(); + assert_eq!(block.len(), 149); + } + + #[test] + #[should_panic] + fn test_block_builder_panics() { + let mut d = get_data(); + // Identical key as d[3]. + d[4].0 = b"prefix_key1"; + + let mut builder = BlockBuilder::new(options::for_test()); + for &(k, v) in d.iter() { + builder.add(k, v); + assert_eq!(k, builder.last_key()); + } + assert_eq!(d.len(), builder.entries()); + } + + // Additional test coverage is provided by tests in block.rs. +}
--- a/src/lib.rs Sun Oct 08 13:54:01 2017 +0200 +++ b/src/lib.rs Sun Oct 08 15:36:45 2017 +0200 @@ -11,6 +11,7 @@ extern crate time_test; mod block; +mod block_builder; mod blockhandle; mod cache; mod cmp;
--- a/src/table_builder.rs Sun Oct 08 13:54:01 2017 +0200 +++ b/src/table_builder.rs Sun Oct 08 15:36:45 2017 +0200 @@ -1,4 +1,5 @@ -use block::{BlockBuilder, BlockContents}; +use block::BlockContents; +use block_builder::BlockBuilder; use blockhandle::BlockHandle; use cmp::InternalKeyCmp; use error::Result;