tablestg 0.4.20

Storage for database tables
Documentation
// use crate::VarValAddr;
use crate::{Data, LRc};
use std::cell::RefCell;

use page_store::*;

/// Set of working pages, clean and changed.
pub struct PageSet {
    wapd: AccessPagedData,
    pages: HashMap<u64, PData>,
}

impl PageSet {
    pub fn new(wapd: AccessPagedData) -> Self {
        Self {
            wapd,
            pages: HashMap::default(),
        }
    }

    pub fn compute_size(&self, size: usize) -> usize {
        let psi = &self.wapd.spd.psi;
        if size > psi.max_size_page() {
            return 0;
        }
        let ix = psi.index(size);
        psi.size(ix)
    }

    pub fn new_page(&self) -> u64 {
        self.wapd.alloc_page() + 1 // Add 1 so that zero can be used as null page.
    }

    pub fn new_pdata(&mut self, pnum: u64, data: Data) {
        let pdata = LRc::new(RefCell::new(PDataInner {
            data,
            changed: true,
        }));
        self.pages.insert(pnum, pdata);
    }

    pub fn free_page(&mut self, pnum: u64) {
        self.pages.remove(&pnum);
        self.wapd.free_page(pnum - 1);
    }

    /// Loads page data, the PData must later be returned by calling note.
    pub fn load(&mut self, pnum: u64) -> PData {
        if pnum == 0 {
            pdata_default() // Convenient for some read operations that read unitialised pages.
        } else if let Some(pdata) = self.pages.get(&pnum) {
            pdata.clone()
        } else {
            let data = self.wapd.get_data(pnum - 1);
            let pdata = LRc::new(RefCell::new(PDataInner {
                data,
                changed: false,
            }));
            self.pages.insert(pnum, pdata.clone());
            pdata
        }
    }

    /// Save all the changed pages.
    pub fn save(&mut self) {
        for (pnum, data) in self.pages.drain() {
            if data.borrow().changed {
                self.wapd.set_data(pnum - 1, take_data(&data));
            }
        }
        self.wapd.save(SaveOp::Save);
    }
}

pub type PData = LRc<RefCell<PDataInner>>;

#[derive(Default)]
pub struct PDataInner {
    pub data: Data,
    changed: bool,
}

pub fn set_changed(pdata: &PData) {
    pdata.borrow_mut().changed = true;
}

pub fn take_data(pdata: &PData) -> Data {
    std::mem::take(&mut pdata.borrow_mut().data)
}

pub fn set_data(pdata: &PData, data: Data) {
    pdata.borrow_mut().data = data;
}

pub fn pdata_default() -> PData {
    LRc::new(RefCell::new(PDataInner::default()))
}