Mercurial > lbo > hg > leveldb-rs
changeset 286:900210e7d0b0
log: Implement LogWriter::new_with_off() and add tests.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Mon, 25 Sep 2017 20:32:47 +0200 |
parents | b176afa0f765 |
children | b71f43585267 |
files | src/log.rs |
diffstat | 1 files changed, 49 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/src/log.rs Mon Sep 25 20:32:16 2017 +0200 +++ b/src/log.rs Mon Sep 25 20:32:47 2017 +0200 @@ -40,6 +40,14 @@ } } + /// new_with_off opens a writer starting at some offset of an existing log file. The file must + /// have the default block size. + pub fn new_with_off(writer: W, off: usize) -> LogWriter<W> { + let mut w = LogWriter::new(writer); + w.current_block_offset = off % BLOCK_SIZE; + w + } + pub fn add_record(&mut self, r: &[u8]) -> Result<usize> { let mut record = &r[..]; let mut first_frag = true; @@ -118,10 +126,10 @@ } impl<R: Read> LogReader<R> { - pub fn new(src: R, chksum: bool, offset: usize) -> LogReader<R> { + pub fn new(src: R, chksum: bool) -> LogReader<R> { LogReader { src: src, - blk_off: offset, + blk_off: 0, blocksize: BLOCK_SIZE, checksums: chksum, head_scratch: [0; 7], @@ -165,7 +173,7 @@ if self.checksums && !self.check_integrity(typ, &dst[dst_offset..dst_offset + bytes_read], checksum) { - return err(StatusCode::InvalidData, "Invalid Checksum"); + return err(StatusCode::Corruption, "Invalid Checksum"); } dst_offset += length as usize; @@ -193,16 +201,49 @@ #[cfg(test)] mod tests { use super::*; + use std::io::Cursor; #[test] fn test_writer() { - let data = &"hello world. My first log entry.".as_bytes().to_vec(); + let data = &["hello world. My first log entry.", "and my second", "and my third"]; let mut lw = LogWriter::new(Vec::new()); + let total_len = data.iter().fold(0, |l, d| l + d.len()); + + for d in data { + let _ = lw.add_record(d.as_bytes()); + } + + assert_eq!(lw.current_block_offset, total_len + 3 * super::HEADER_SIZE); + } + + #[test] + fn test_writer_append() { + let data = &["hello world. My first log entry.", "and my second", "and my third"]; + + let mut dst = Vec::new(); + dst.resize(1024, 0 as u8); - let _ = lw.add_record(&data); + { + let mut lw = LogWriter::new(Cursor::new(dst.as_mut_slice())); + for d in data { + let _ = lw.add_record(d.as_bytes()); + } + } + + let old = dst.clone(); - assert_eq!(lw.current_block_offset, data.len() + super::HEADER_SIZE); - assert_eq!(&lw.dst[super::HEADER_SIZE..], data.as_slice()); + // Ensure that new_with_off positions the writer correctly. Some ugly mucking about with + // cursors and stuff is required. + { + let offset = data[0].len() + super::HEADER_SIZE; + let mut lw = LogWriter::new_with_off(Cursor::new(&mut dst.as_mut_slice()[offset..]), + offset); + for d in &data[1..] { + let _ = lw.add_record(d.as_bytes()); + } + } + assert_eq!(old, dst); + } #[test] @@ -219,7 +260,7 @@ assert_eq!(lw.dst.len(), 93); - let mut lr = LogReader::new(lw.dst.as_slice(), true, 0); + let mut lr = LogReader::new(lw.dst.as_slice(), true); lr.blocksize = super::HEADER_SIZE + 10; let mut dst = Vec::with_capacity(128); let mut i = 0;