matdb 0.1.0

An experimental embedded SQL-like DBMS
Documentation
use std::io::{Read, Seek, SeekFrom};

use anyhow::{bail, Result};

use crate::{Db, CACHE_SIZE, PAGE_SIZE};

impl Db {
    pub(super) fn invalidate_cache(&mut self, page_number: u64) {
        if let Some((time, _)) = self.cached_pages.remove(&page_number) {
            self.time_to_page.remove(&time).unwrap();
        }
    }

    fn cache_page(&mut self, page_number: u64, page: &[u8]) {
        let this_time = self.next_time;
        self.next_time += 1;

        if self.cached_pages.len() >= CACHE_SIZE {
            let (&least_used_time, &least_used_page_number) =
                self.time_to_page.first_key_value().unwrap();
            self.time_to_page.remove(&least_used_time).unwrap();

            self.cached_pages.remove(&least_used_page_number).unwrap();
        }

        self.cached_pages
            .insert(page_number, (this_time, page.to_vec()));
        self.time_to_page.insert(this_time, page_number);
    }

    fn get_cached_page(&mut self, page_number: u64) -> Option<Vec<u8>> {
        let this_time = self.next_time;
        self.next_time += 1;

        let (previous_time, page) = self.cached_pages.remove(&page_number)?;
        self.cached_pages
            .insert(page_number, (this_time, page.clone()));
        self.time_to_page.remove(&previous_time).unwrap();
        self.time_to_page.insert(this_time, page_number);

        Some(page)
    }

    pub(super) fn get_page(&mut self, page_number: u64) -> Result<Vec<u8>> {
        if let Some(page) = self.get_cached_page(page_number) {
            return Ok(page);
        } else if let Some(page) = self.write_pages.get(&page_number).cloned() {
            self.cache_page(page_number, &page);
            Ok(page)
        } else if let Some(file) = self.file.as_mut() {
            let mut v = vec![0u8; PAGE_SIZE];

            file.seek(SeekFrom::Start(page_number * PAGE_SIZE as u64))?;

            file.read_exact(&mut v)?;

            self.cache_page(page_number, &v);

            Ok(v)
        } else {
            bail!("in memory database somehow lost a page")
        }
    }
}