use crate::{
db::{
data::StorageKey,
index::{entry::RawIndexEntry, key::RawIndexKey},
},
error::InternalError,
};
use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
pub struct IndexStore {
pub(super) map: BTreeMap<RawIndexKey, RawIndexEntry, VirtualMemory<DefaultMemoryImpl>>,
generation: u64,
secondary_covering_authoritative: bool,
secondary_existence_witness_authoritative: bool,
}
impl IndexStore {
#[must_use]
pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
Self {
map: BTreeMap::init(memory),
generation: 0,
secondary_covering_authoritative: false,
secondary_existence_witness_authoritative: false,
}
}
#[allow(clippy::redundant_closure_for_method_calls)]
pub(crate) fn entries(&self) -> Vec<(RawIndexKey, RawIndexEntry)> {
self.map.iter().map(|entry| entry.into_pair()).collect()
}
pub(in crate::db) fn get(&self, key: &RawIndexKey) -> Option<RawIndexEntry> {
self.map.get(key)
}
pub fn len(&self) -> u64 {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
#[must_use]
pub(in crate::db) const fn generation(&self) -> u64 {
self.generation
}
pub(crate) fn insert(
&mut self,
key: RawIndexKey,
entry: RawIndexEntry,
) -> Option<RawIndexEntry> {
let previous = self.map.insert(key, entry);
self.bump_generation();
self.invalidate_secondary_covering_authority();
self.invalidate_secondary_existence_witness_authority();
previous
}
pub(crate) fn remove(&mut self, key: &RawIndexKey) -> Option<RawIndexEntry> {
let previous = self.map.remove(key);
self.bump_generation();
self.invalidate_secondary_covering_authority();
self.invalidate_secondary_existence_witness_authority();
previous
}
pub fn clear(&mut self) {
self.map.clear();
self.bump_generation();
self.invalidate_secondary_covering_authority();
self.invalidate_secondary_existence_witness_authority();
}
#[must_use]
pub(in crate::db) const fn secondary_covering_authoritative(&self) -> bool {
self.secondary_covering_authoritative
}
pub(in crate::db) const fn mark_secondary_covering_authoritative(&mut self) {
self.secondary_covering_authoritative = true;
}
#[must_use]
pub(in crate::db) const fn secondary_existence_witness_authoritative(&self) -> bool {
self.secondary_existence_witness_authoritative
}
pub(in crate::db) const fn mark_secondary_existence_witness_authoritative(&mut self) {
self.secondary_existence_witness_authoritative = true;
}
pub(in crate::db) fn mark_memberships_missing_for_storage_key(
&mut self,
storage_key: StorageKey,
) -> Result<usize, InternalError> {
let mut entries = Vec::new();
for entry in self.map.iter() {
entries.push(entry.into_pair());
}
let mut marked = 0usize;
for (raw_key, mut raw_entry) in entries {
if raw_entry
.mark_key_missing(storage_key)
.map_err(InternalError::index_entry_decode_failed)?
{
self.map.insert(raw_key, raw_entry);
marked = marked.saturating_add(1);
}
}
if marked > 0 {
self.bump_generation();
self.invalidate_secondary_covering_authority();
self.invalidate_secondary_existence_witness_authority();
}
Ok(marked)
}
pub fn memory_bytes(&self) -> u64 {
self.map
.iter()
.map(|entry| entry.key().as_bytes().len() as u64 + entry.value().len() as u64)
.sum()
}
const fn bump_generation(&mut self) {
self.generation = self.generation.saturating_add(1);
}
const fn invalidate_secondary_covering_authority(&mut self) {
self.secondary_covering_authoritative = false;
}
const fn invalidate_secondary_existence_witness_authority(&mut self) {
self.secondary_existence_witness_authoritative = false;
}
}