mod filtered_node_ref;
mod node_ref_filter;
mod traits;
impl_veilid_log_facility!("rtab");
use super::*;
pub(crate) use filtered_node_ref::*;
pub(crate) use node_ref_filter::*;
pub(crate) use traits::*;
pub(crate) struct NodeRef {
registry: VeilidComponentRegistry,
entry: Arc<BucketEntry>,
#[cfg(feature = "tracking")]
track_id: usize,
}
impl_veilid_component_accessors!(NodeRef);
impl NodeRef {
pub fn new(registry: VeilidComponentRegistry, entry: Arc<BucketEntry>) -> Self {
entry.ref_count.fetch_add(1u32, Ordering::AcqRel);
Self {
registry,
entry,
#[cfg(feature = "tracking")]
track_id: entry.track(),
}
}
pub fn sequencing_filtered(&self, sequencing: Sequencing) -> FilteredNodeRef {
FilteredNodeRef::new(
self.registry.clone(),
self.entry.clone(),
NodeRefFilter::new(),
sequencing,
)
}
pub fn routing_domain_filtered<R: Into<RoutingDomainSet>>(
&self,
routing_domain_set: R,
) -> FilteredNodeRef {
FilteredNodeRef::new(
self.registry.clone(),
self.entry.clone(),
NodeRefFilter::new().with_routing_domain_set(routing_domain_set.into()),
Sequencing::NoPreference,
)
}
pub fn custom_filtered(&self, filter: NodeRefFilter) -> FilteredNodeRef {
FilteredNodeRef::new(
self.registry.clone(),
self.entry.clone(),
filter,
Sequencing::NoPreference,
)
}
}
impl NodeRefAccessorsTrait for NodeRef {
fn entry(&self) -> Arc<BucketEntry> {
self.entry.clone()
}
fn sequencing(&self) -> Sequencing {
Sequencing::NoPreference
}
fn routing_domain_set(&self) -> RoutingDomainSet {
RoutingDomainSet::all()
}
fn filter(&self) -> NodeRefFilter {
NodeRefFilter::new()
}
fn take_filter(&mut self) -> NodeRefFilter {
NodeRefFilter::new()
}
fn dial_info_filter(&self) -> DialInfoFilter {
DialInfoFilter::all()
}
}
impl NodeRefOperateTrait for NodeRef {
fn operate<T, F>(&self, f: F) -> T
where
F: FnOnce(&BucketEntryInner) -> T,
{
self.entry.with(f)
}
fn operate_mut<T, F>(&self, f: F) -> T
where
F: FnOnce(&mut BucketEntryInner) -> T,
{
self.entry.with_mut(f)
}
}
impl NodeRefCommonTrait for NodeRef {}
impl Clone for NodeRef {
fn clone(&self) -> Self {
self.entry.ref_count.fetch_add(1u32, Ordering::AcqRel);
Self {
registry: self.registry.clone(),
entry: self.entry.clone(),
#[cfg(feature = "tracking")]
track_id: self.entry.write().track(),
}
}
}
impl fmt::Display for NodeRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(best_node_id) = self.entry.with(|e| e.best_node_id()) {
return write!(f, "{}", best_node_id);
} else if let Some(node_id) = self.entry.with(|e| e.node_ids().first().cloned()) {
return write!(f, "{}", node_id);
}
write!(f, "*NONE*")
}
}
impl fmt::Debug for NodeRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeRef")
.field("node_ids", &self.entry.with(|e| e.node_ids()))
.finish()
}
}
impl Drop for NodeRef {
fn drop(&mut self) {
#[cfg(feature = "tracking")]
self.entry.write().untrack(self.track_id);
let new_ref_count = self.entry.ref_count.fetch_sub(1u32, Ordering::AcqRel) - 1;
if new_ref_count == 0 {
let node_ids = self.entry.with(|e| e.node_ids());
self.routing_table().queue_bucket_kicks(node_ids);
}
}
}
impl core::hash::Hash for NodeRef {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.entry).hash(state);
}
}
impl core::cmp::PartialEq for NodeRef {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.entry, &other.entry)
}
}
impl core::cmp::Eq for NodeRef {}