use crate::Result;
use crate::btree::BTree;
use crate::catalog::codec::Catalog;
use crate::errors::PagedbError;
use crate::vfs::Vfs;
pub struct CounterRef<'a, V: Vfs + Clone> {
pub(super) catalog_tree: &'a mut BTree<V>,
pub(super) main_tree: &'a mut BTree<V>,
pub(super) key: Vec<u8>,
}
impl<V: Vfs + Clone> CounterRef<'_, V> {
pub async fn get(&self) -> Result<u64> {
match self.catalog_tree.get(&self.key).await? {
Some(v) => Catalog::decode_counter(&v),
None => Ok(0),
}
}
pub async fn set(&mut self, value: u64) -> Result<()> {
let current = self.get().await?;
if value < current {
return Err(PagedbError::Aborted);
}
Self::sync_to(self.main_tree, self.catalog_tree);
let bytes = Catalog::encode_counter(value);
self.catalog_tree.put(&self.key, &bytes).await?;
Self::sync_from(self.catalog_tree, self.main_tree);
Ok(())
}
pub async fn increment_by(&mut self, delta: u64) -> Result<u64> {
let current = self.get().await?;
let next = current
.checked_add(delta)
.ok_or(PagedbError::NonceCounterExhausted)?;
Self::sync_to(self.main_tree, self.catalog_tree);
let bytes = Catalog::encode_counter(next);
self.catalog_tree.put(&self.key, &bytes).await?;
Self::sync_from(self.catalog_tree, self.main_tree);
Ok(next)
}
fn sync_to(main: &BTree<V>, catalog: &mut BTree<V>) {
let shared = main.next_page_id().max(catalog.next_page_id());
catalog.set_next_page_id(shared);
}
fn sync_from(catalog: &BTree<V>, main: &mut BTree<V>) {
let c = catalog.next_page_id();
if main.next_page_id() < c {
main.set_next_page_id(c);
}
}
}