use crate::{Arc, Data, DataType, LRc, Store, Table, RTable};
use std::cell::RefCell;
use page_store::*;
pub struct PageSet {
wapd: AccessPagedData,
pages: HashMap<u64, PData>,
pub sys_store: LRc<RefCell<Store>>,
pub tables: HashMap<i64, RTable>,
}
impl PageSet {
pub fn new(wapd: AccessPagedData) -> Self {
Self {
wapd,
pages: HashMap::default(),
sys_store: LRc::new(RefCell::new(Store::default())),
tables: HashMap::default(),
}
}
pub fn test() -> Self {
use page_store::*;
let limits = Limits::default();
let file = atom_file::MultiFileStorage::new("test.db");
let upd = atom_file::FastFileStorage::new("test.upd");
let af = atom_file::AtomicFile::new_with_limits(file, upd, &limits.af_lim);
let ps = BlockPageStg::new(af, &limits);
let _is_new = ps.is_new();
let spd = SharedPagedData::new_from_ps(ps);
if false {
let psi = &spd.psi;
println!("max page size={}", psi.max_size_page());
for i in 0..psi.sizes() {
println!("page size={}", psi.size(1 + i));
}
}
Self::new(spd.new_writer())
}
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 }
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);
}
pub fn load(&mut self, pnum: u64) -> PData {
if pnum == 0 {
pdata_default() } 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
}
}
pub fn load_table(&mut self, tid: i64, dt: &Arc<DataType>) -> RTable {
if let Some(t) = self.tables.get(&tid) {
t.clone()
} else {
let t = Table::restore(tid, self, dt.clone());
let t = LRc::new(RefCell::new(t));
self.tables.insert(tid, t.clone());
t
}
}
pub fn save(&mut self) {
let tables = std::mem::take(&mut self.tables);
for (tid, table) in &tables {
table.borrow_mut().save(*tid, self);
}
self.tables = tables;
for (pnum, data) in self.pages.drain() {
if data.borrow().changed {
if false {
println!(
"PageSet save pnum={} len={}",
pnum,
data.borrow().data.len()
);
}
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,
pub 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()))
}