tablestg 0.4.17

Storage for database tables
Documentation
// use crate::VarValAddr;
use crate::{Arc, /*BuckMap, BuckMapInfo,*/ Data /* DataType, Rc, make_obj_dt*/};

use page_store::*;

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

impl PageSet {
    pub fn new(wapd: AccessPagedData) -> Self {
        Self {
            wapd,
            clean: HashMap::default(),
            changed: 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 free_page(&mut self, pnum: u64) {
        self.clean.remove(&pnum);
        self.changed.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(data) = self.clean.remove(&pnum) {
            PData::new(pnum, data, false)
        } else if let Some(data) = self.changed.remove(&pnum) {
            PData::new(pnum, data, true)
        } else {
            let data = self.wapd.get_data(pnum - 1);
            PData::new(pnum, data, false)
        }
    }

    /// Returns page loaded page data.
    pub fn note(&mut self, mut pd: PData) {
        if pd.pnum == 0 {
            // Do nothing
        } else if pd.changed {
            self.changed.insert(pd.pnum, pd.take_data());
        } else {
            self.clean.insert(pd.pnum, pd.take_data());
        }
        pd.no_drop = false;
    }

    /// Save all the changed pages.
    pub fn save(&mut self) {
        for (pnum, data) in self.changed.drain() {
            println!("Saving data pnum={} len={}", pnum, data.len());
            self.wapd.set_data(pnum - 1, data);
        }
        self.wapd.save(SaveOp::Save);
    }
}

/// returned by [PageSet::load].
#[derive(Default)]
pub struct PData {
    pub data: Data,
    pnum: u64,
    pub changed: bool,
    /// Causes panic if [PageSet::note] is not called (debug diagnostic).
    no_drop: bool,
}

impl PData {
    pub fn new(pnum: u64, data: Data, changed: bool) -> Self {
        Self {
            pnum,
            data,
            changed,
            no_drop: true,
        }
    }
    pub fn take_data(&mut self) -> Data {
        std::mem::take(&mut self.data)
    }
    pub fn make_mut(&mut self) -> &mut Vec<u8> {
        Arc::make_mut(&mut self.data)
    }
}

impl Drop for PData {
    fn drop(&mut self) {
        assert!(!self.no_drop); // Could be debug_assert eventually, but leave for now.
    }
}