use std::io::{Seek, SeekFrom, Write};
use anyhow::Result;
use crate::{Db, PAGE_SIZE, WRITE_SIZE};
use super::free::FreeStyle;
impl Db {
pub(super) fn flush(&mut self) -> Result<()> {
if let Some(file) = self.file.as_mut() {
file.set_len(self.page_count * PAGE_SIZE as u64)?;
for (no, page) in &self.write_pages {
file.seek(SeekFrom::Start(no * PAGE_SIZE as u64))?;
file.write_all(&page)?;
}
self.write_pages.clear();
}
Ok(())
}
pub(super) fn append_or_overwrite_page(
&mut self,
page_number: u64,
page: &[u8],
) -> Result<Option<u64>> {
Ok(
if let FreeStyle::CanBeFreed = self.can_be_freed(page_number)? {
self.set_page(page_number, page)?;
None
} else {
Some(self.append_page(page)?)
},
)
}
fn set_page(&mut self, page_number: u64, page: &[u8]) -> Result<u64> {
self.written_anything_this_tx = true;
assert_eq!(PAGE_SIZE, page.len());
if self.file.is_some() && self.write_pages.len() >= WRITE_SIZE {
self.flush()?;
}
self.invalidate_cache(page_number);
self.write_pages.insert(page_number, page.to_vec());
Ok(page_number)
}
pub(super) fn set_first_page(&mut self, page: &[u8]) -> Result<()> {
self.set_page(0, page)?;
if self.page_count == 0 {
self.page_count += 1;
}
Ok(())
}
pub(super) fn append_page_at_end(&mut self, page: &[u8]) -> Result<u64> {
let pre_page_count = self.page_count;
self.page_count += 1;
self.set_page(pre_page_count, page)
}
pub(super) fn append_page(&mut self, page: &[u8]) -> Result<u64> {
if let Some(free_page) = self
.free_list
.pop_last()
.map(|p| Ok(p))
.or_else(|| {
self.load_next_freelist()
.map(|_| self.free_list.pop_last())
.transpose()
})
.transpose()?
{
self.set_page(free_page, page)
} else {
self.append_page_at_end(page)
}
}
}