use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use uuid::Uuid;
use crate::registry::{self, OwnedNamespaceSignature, WriteAccess};
use crate::{ContextString, NamespaceString, UuidPoolError};
struct OwnedNamespaceInner {
namespace: parking_lot::Mutex<NamespaceString>,
signature: OwnedNamespaceSignature,
invalidated: AtomicBool,
}
impl Drop for OwnedNamespaceInner {
fn drop(&mut self) {
if self.invalidated.load(Ordering::Acquire) {
return;
}
let namespace = self.namespace.get_mut().clone();
let _ = registry::release_owned_namespace(&namespace, &self.signature);
}
}
pub struct OwnedNamespace {
inner: Arc<OwnedNamespaceInner>,
}
impl Clone for OwnedNamespace {
fn clone(&self) -> Self {
Self { inner: self.inner.clone() }
}
}
impl OwnedNamespace {
pub(crate) fn new(namespace: NamespaceString, signature: OwnedNamespaceSignature) -> Self {
Self {
inner: Arc::new(OwnedNamespaceInner {
namespace: parking_lot::Mutex::new(namespace),
signature,
invalidated: AtomicBool::new(false),
}),
}
}
fn access(&self) -> WriteAccess<'_> {
WriteAccess::owned(&self.inner.signature)
}
fn current_namespace(&self) -> NamespaceString {
self.inner.namespace.lock().clone()
}
fn ensure_active(&self) -> Result<(), UuidPoolError> {
if self.inner.invalidated.load(Ordering::Acquire) {
return Err(UuidPoolError::UnauthorizedNamespaceWriteAccessError(format!(
"Namespace '{}' ownership has already been released",
self.current_namespace()
)));
}
Ok(())
}
pub fn namespace(&self) -> NamespaceString {
self.current_namespace()
}
pub fn reserve_id(&self, context: &str) -> Result<Uuid, UuidPoolError> {
self.reserve_id_with(context, crate::interface::DEFAULT_UUID_BASE, crate::interface::DEFAULT_MAX_RETRIES)
}
pub fn reserve_id_with_base(&self, context: &str, base: u32) -> Result<Uuid, UuidPoolError> {
self.reserve_id_with(context, base, crate::interface::DEFAULT_MAX_RETRIES)
}
pub fn reserve_id_with(&self, context: &str, base: u32, max_retries: usize) -> Result<Uuid, UuidPoolError> {
self.ensure_active()?;
registry::random_uuid(&self.current_namespace(), context, base, max_retries, 0, self.access())
}
pub fn add_id(&self, context: &str, uuid: Uuid) -> Result<(), UuidPoolError> {
self.ensure_active()?;
registry::add_uuid_to_pool(&self.current_namespace(), context, &uuid, self.access())
}
pub fn remove_id(&self, context: &str, uuid: Uuid) -> Result<(), UuidPoolError> {
self.ensure_active()?;
registry::remove_uuid_from_pool(&self.current_namespace(), context, &uuid, self.access())
}
pub fn replace_id(&self, context: &str, old_uuid: Uuid, new_uuid: Uuid) -> Result<(), UuidPoolError> {
self.ensure_active()?;
registry::replace_uuid_in_pool(&self.current_namespace(), context, &old_uuid, &new_uuid, self.access())
}
pub fn clear_context(&self, context: &str) -> Result<(), UuidPoolError> {
self.ensure_active()?;
registry::clear_context(&self.current_namespace(), context, self.access())
}
pub fn clear_all_contexts(&self) -> Result<(), UuidPoolError> {
self.ensure_active()?;
registry::clear_all_contexts(&self.current_namespace(), self.access())
}
pub fn drain_context(&self, context: &str) -> Result<Vec<(ContextString, Uuid)>, UuidPoolError> {
self.ensure_active()?;
registry::drain_context(&self.current_namespace(), context, self.access())
}
pub fn drain_all_contexts(&self) -> Result<Vec<(NamespaceString, ContextString, Uuid)>, UuidPoolError> {
self.ensure_active()?;
registry::drain_all_contexts(&self.current_namespace(), self.access())
}
pub fn rename(&self, new_namespace: &str) -> Result<(), UuidPoolError> {
self.ensure_active()?;
let mut guard = self.inner.namespace.lock();
registry::replace_namespace(&guard, new_namespace, self.access())?;
*guard = new_namespace.to_string();
Ok(())
}
pub fn remove(self) -> Result<(), UuidPoolError> {
self.ensure_active()?;
let namespace = self.current_namespace();
registry::release_owned_namespace(&namespace, &self.inner.signature)?;
self.inner.invalidated.store(true, Ordering::Release);
Ok(())
}
}