use std::sync::atomic::Ordering;
use std::sync::Arc;
use dashmap::DashMap;
use crate::persistent_artrie_char::nodes::persistent_node::Child as ChildGeneric;
use crate::persistent_artrie_char::nodes::{
AtomicNodePtr as AtomicNodePtrGeneric, PersistentCharNode as PersistentCharNodeGeneric,
};
type Child = ChildGeneric<u64>;
type AtomicNodePtr = AtomicNodePtrGeneric<u64>;
type PersistentCharNode = PersistentCharNodeGeneric<u64>;
impl<S: crate::persistent_artrie::block_storage::BlockStorage>
super::dict_impl::PersistentVocabARTrie<S>
{
pub(crate) fn install_overlay(&mut self) -> bool {
if self.lockfree_root.is_some() {
return false;
}
let root = Arc::new(PersistentCharNode::new());
self.lockfree_root = Some(AtomicNodePtr::new(root));
self.lockfree_cache = Some(DashMap::new());
self.reverse_term_map = Some(DashMap::new());
true
}
pub(super) fn try_insert_lockfree_path(
&self,
root: &Arc<PersistentCharNode>,
chars: &[u32],
index: u64,
) -> std::result::Result<Arc<PersistentCharNode>, u64> {
if chars.is_empty() {
if root.is_final() {
return Err(root.get_value().unwrap_or(0));
}
let new_root = root.as_final().with_value(index);
return Ok(Arc::new(new_root));
}
self.insert_lockfree_recursive(root, chars, 0, index)
}
fn insert_lockfree_recursive(
&self,
node: &Arc<PersistentCharNode>,
chars: &[u32],
depth: usize,
index: u64,
) -> std::result::Result<Arc<PersistentCharNode>, u64> {
if depth == chars.len() {
if node.is_final() {
return Err(node.get_value().unwrap_or(0));
}
let new_node = node.as_final().with_value(index);
return Ok(Arc::new(new_node));
}
let c = chars[depth];
match node.find_child(c) {
Some(child) => {
if child.is_null() {
return Err(0); }
match child.as_in_mem() {
Some(child_arc) => {
let child_arc = Arc::clone(child_arc);
let new_child =
self.insert_lockfree_recursive(&child_arc, chars, depth + 1, index)?;
let new_node = node.with_child(c, Child::InMem(new_child));
Ok(Arc::new(new_node))
}
None => {
Err(0)
}
}
}
None => {
let new_child = self.create_lockfree_path(&chars[depth + 1..], index);
let new_node = node.with_child(c, Child::InMem(new_child));
Ok(Arc::new(new_node))
}
}
}
fn create_lockfree_path(&self, chars: &[u32], index: u64) -> Arc<PersistentCharNode> {
if chars.is_empty() {
let node = PersistentCharNode::new().as_final().with_value(index);
return Arc::new(node);
}
let mut current = Arc::new(PersistentCharNode::new().as_final().with_value(index));
for &c in chars.iter().rev() {
let parent = PersistentCharNode::new().with_child(c, Child::InMem(current));
current = Arc::new(parent);
}
current
}
pub(super) fn find_in_lockfree_trie(
&self,
root: &Arc<PersistentCharNode>,
chars: &[u32],
) -> Option<u64> {
let mut current = root.clone();
for &c in chars {
match current.find_child(c) {
Some(child) => {
if child.is_null() {
return None;
}
match child.as_in_mem() {
Some(child_arc) => current = Arc::clone(child_arc),
None => return None,
}
}
None => return None,
}
}
current.get_value()
}
#[inline]
pub fn cas_retries(&self) -> u64 {
self.cas_retries.load(Ordering::Relaxed)
}
}