use page::Page;
use pagedfile::{PagedFile, PagedFileIterator};
use error::Error;
use pref::PRef;
use std::collections::HashSet;
pub struct LogFile {
file: Box<dyn PagedFile>,
logged: HashSet<PRef>,
source_len: u64
}
impl LogFile {
pub fn new(rw: Box<dyn PagedFile>) -> LogFile {
LogFile { file: rw, logged: HashSet::new(), source_len:0 }
}
pub fn init(&mut self, data_len: u64, table_len: u64, link_len: u64) -> Result<(), Error> {
self.truncate(0)?;
let mut first = Page::new();
first.write_pref(0, PRef::from(data_len));
first.write_pref(6, PRef::from(table_len));
first.write_pref(12, PRef::from(link_len));
self.append_page(first)?;
self.flush()?;
Ok(())
}
pub fn page_iter(&self) -> PagedFileIterator {
PagedFileIterator::new(self, PRef::from(0))
}
pub fn log_page(&mut self, pref: PRef, source: &dyn PagedFile) -> Result<(), Error>{
if pref.as_u64() < self.source_len && self.logged.insert(pref) {
if let Some(page) = source.read_page(pref)? {
self.append_page(page)?;
}
}
Ok(())
}
pub fn reset(&mut self, len: u64) {
self.source_len = len;
self.logged.clear();
}
}
impl PagedFile for LogFile {
fn read_page(&self, pref: PRef) -> Result<Option<Page>, Error> {
self.file.read_page(pref)
}
fn len(&self) -> Result<u64, Error> {
self.file.len()
}
fn truncate(&mut self, len: u64) -> Result<(), Error> {
self.file.truncate(len)
}
fn sync(&self) -> Result<(), Error> {
self.file.sync()
}
fn shutdown(&mut self) {}
fn append_page(&mut self, page: Page) -> Result<(), Error> {
self.file.append_page(page)
}
fn update_page(&mut self, _: Page) -> Result<u64, Error> {
unimplemented!()
}
fn flush(&mut self) -> Result<(), Error> {
Ok(self.file.flush()?)
}
}