use std::sync::atomic::Ordering;
use crate::persistent_artrie::block_storage::BlockStorage;
use crate::persistent_artrie::error::{PersistentARTrieError, Result};
impl<S: BlockStorage> super::dict_impl::PersistentVocabARTrie<S> {
pub fn insert(&self, term: &str) -> Result<u64> {
self.insert_overlay(term)
}
fn insert_overlay(&self, term: &str) -> Result<u64> {
if let Some(id) = self.get_index_lockfree(term) {
return Ok(id);
}
let index = self.next_index.fetch_add(1, Ordering::AcqRel);
let newly =
<Self as crate::persistent_artrie_core::overlay::durable_write::DurableOverlayWrite<
crate::persistent_artrie_core::key_encoding::CharKey,
u64,
S,
>>::insert_cas_with_value_durable_default(self, term.as_bytes(), index)?;
if newly {
if let Some(ref rev) = self.reverse_term_map {
rev.insert(index, term.to_string());
}
self.entry_count.fetch_add(1, Ordering::AcqRel);
self.dirty.store(true, Ordering::Release);
Ok(index)
} else {
Ok(self.get_index_lockfree(term).unwrap_or(index))
}
}
pub fn insert_batch(&self, terms: &[&str]) -> Result<Vec<u64>> {
terms.iter().map(|&t| self.insert_overlay(t)).collect()
}
pub fn insert_with_index(&self, term: &str, index: u64) -> Result<bool> {
self.insert_with_index_overlay(term, index)
}
fn insert_with_index_overlay(&self, term: &str, index: u64) -> Result<bool> {
if index < self.start_index {
return Err(PersistentARTrieError::InvalidOperation(format!(
"vocabulary index {index} is below start index {}",
self.start_index
)));
}
if let Some(existing) = self.get_index_lockfree(term) {
if existing == index {
return Ok(false);
}
return Err(PersistentARTrieError::InvalidOperation(format!(
"term {term:?} is already assigned index {existing}, not {index}"
)));
}
if let Some(ref rev) = self.reverse_term_map {
if let Some(entry) = rev.get(&index) {
if entry.value() != term {
return Err(PersistentARTrieError::InvalidOperation(format!(
"vocabulary index {index} is already assigned to term {:?}",
entry.value()
)));
}
}
}
let newly =
<Self as crate::persistent_artrie_core::overlay::durable_write::DurableOverlayWrite<
crate::persistent_artrie_core::key_encoding::CharKey,
u64,
S,
>>::insert_cas_with_value_durable_default(self, term.as_bytes(), index)?;
if newly {
if let Some(ref rev) = self.reverse_term_map {
rev.insert(index, term.to_string());
}
self.entry_count.fetch_add(1, Ordering::AcqRel);
self.next_index.fetch_max(index + 1, Ordering::AcqRel);
self.dirty.store(true, Ordering::Release);
}
Ok(newly)
}
}