use std::collections::BTreeSet;
use bytes::Bytes;
use crate::Result;
use crate::btree::BTree;
use crate::vfs::Vfs;
use super::core::{Db, WriterState};
pub(super) struct CarriedHistory {
pub root_page_id: u64,
pub root_version: u64,
pub entry_count: Option<u64>,
pub next_page_id: u64,
pub released_page_ids: BTreeSet<u64>,
}
impl<V: Vfs + Clone> Db<V> {
pub(super) async fn carry_commit_history(
&self,
state: &WriterState,
delta_page_ids: &BTreeSet<u64>,
target_page_ids: &BTreeSet<u64>,
history_version: u64,
alloc_cursor: u64,
) -> Result<CarriedHistory> {
let unmoved = CarriedHistory {
root_page_id: state.commit_history_root_page_id,
root_version: state.commit_history_root_version,
entry_count: state.commit_history_count,
next_page_id: alloc_cursor,
released_page_ids: BTreeSet::new(),
};
if state.commit_history_root_page_id == 0 {
return Ok(unmoved);
}
let base_tree = BTree::open(
self.pager.clone(),
self.realm_id,
state.commit_history_root_page_id,
state.next_page_id,
self.page_size,
);
let mut occupied = BTreeSet::new();
base_tree.collect_all_page_ids(&mut occupied).await?;
if occupied.is_disjoint(delta_page_ids) {
return Ok(unmoved);
}
let rows: Vec<(Vec<u8>, Bytes)> = base_tree
.collect_all()
.await?
.into_iter()
.map(|(key, value)| (key.to_vec(), value))
.collect();
let entry_count = u64::try_from(rows.len()).ok();
let mut relocated = BTree::open(
self.pager.clone(),
self.realm_id,
0,
alloc_cursor,
self.page_size,
);
relocated.bulk_load(rows).await?;
let released_page_ids: BTreeSet<u64> =
occupied.difference(target_page_ids).copied().collect();
Ok(CarriedHistory {
root_page_id: relocated.root_page_id(),
root_version: history_version,
entry_count,
next_page_id: relocated.next_page_id().max(alloc_cursor),
released_page_ids,
})
}
}