use std::sync::atomic::Ordering as AtomicOrdering;
use crate::persistent_artrie::core::key_encoding::ByteKey;
use crate::value::DictionaryValue;
use crate::{Dictionary, MappedDictionary, MutableMappedDictionary, SyncStrategy};
use super::block_storage::BlockStorage;
use super::dict_impl::PersistentARTrie;
use super::node_impl::PersistentARTrieNode;
impl<V: DictionaryValue, S: BlockStorage> Dictionary for PersistentARTrie<V, S> {
type Node = PersistentARTrieNode<V>;
fn root(&self) -> Self::Node {
use crate::persistent_artrie::core::overlay::flip::LockFreeOverlay;
let root = <Self as LockFreeOverlay<ByteKey, V, S>>::overlay_root_node(self)
.unwrap_or_else(|| {
std::sync::Arc::new(crate::persistent_artrie::core::overlay::OverlayNode::<
ByteKey,
V,
>::new())
});
PersistentARTrieNode::from_overlay_root(root, None)
}
fn contains(&self, term: &str) -> bool {
self.contains_bytes(term.as_bytes())
}
#[inline]
fn len(&self) -> Option<usize> {
Some(self.overlay_len())
}
fn sync_strategy(&self) -> SyncStrategy {
SyncStrategy::InternalSync
}
}
impl<V: DictionaryValue, S: BlockStorage> MappedDictionary for PersistentARTrie<V, S> {
type Value = V;
fn get_value(&self, term: &str) -> Option<Self::Value> {
self.get_value_bytes(term.as_bytes())
}
}
impl<V: DictionaryValue, S: BlockStorage> MutableMappedDictionary for PersistentARTrie<V, S> {
fn insert_with_value(&self, term: &str, value: Self::Value) -> bool {
PersistentARTrie::insert_with_value(self, term, value)
}
fn union_with<F>(&self, other: &Self, merge_fn: F) -> usize
where
F: Fn(&Self::Value, &Self::Value) -> Self::Value,
Self::Value: Clone,
{
let entries = match other.iter_prefix_with_values_and_arena(b"") {
Ok(Some(terms)) => terms
.into_iter()
.map(|term| (term.term, term.value))
.collect(),
Ok(None) => return 0,
Err(error) => {
log::warn!("PersistentARTrie::union_with source iteration failed: {error}");
return 0;
}
};
self.merge_entries_overlay(entries, merge_fn)
.unwrap_or_else(|error| {
log::warn!("PersistentARTrie::union_with merge failed: {error}");
0
})
}
fn update_or_insert<F>(&self, term: &str, default_value: Self::Value, update_fn: F) -> bool
where
F: Fn(&mut Self::Value),
{
if let Some(existing) = self.get_value(term) {
let mut value = existing;
update_fn(&mut value);
PersistentARTrie::upsert(self, term, value).unwrap_or_else(|error| {
log::warn!("PersistentARTrie::update_or_insert update failed: {error}");
false
});
false
} else {
PersistentARTrie::insert_with_value(self, term, default_value)
}
}
}
impl<V: DictionaryValue, S: BlockStorage> std::fmt::Debug for PersistentARTrie<V, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PersistentARTrie")
.field("term_count", &self.term_count.load(AtomicOrdering::Relaxed))
.field("dirty", &self.dirty.load(AtomicOrdering::Relaxed))
.finish()
}
}