fuchsia_inspect_contrib/graph/
edge.rs
1use super::events::GraphObjectEventTracker;
6use super::types::{EdgeMarker, VertexId};
7use super::{EdgeGraphMetadata, Metadata, Vertex};
8use fuchsia_inspect as inspect;
9use fuchsia_sync::{RwLock, RwLockWriteGuard};
10use std::ops::{Deref, DerefMut};
11use std::sync::atomic::{AtomicU64, Ordering};
12use std::sync::{Arc, Weak};
13
14#[derive(Debug)]
16pub struct Edge {
17 state: Arc<RwLock<EdgeState>>,
18}
19
20static NEXT_ID: AtomicU64 = AtomicU64::new(0);
21
22impl Edge {
23 pub(crate) fn new<'a, I, M>(
24 from: &Vertex<I>,
25 to: &mut Vertex<I>,
26 initial_metadata: M,
27 events_tracker: Option<GraphObjectEventTracker<EdgeMarker>>,
28 ) -> Self
29 where
30 I: VertexId,
31 M: IntoIterator<Item = Metadata<'a>>,
32 {
33 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
34 let to_id = to.id().get_id();
35 let metadata_iterator = initial_metadata.into_iter();
36 let (node, metadata) = from.outgoing_edges_node.atomic_update(|parent| {
37 let node = parent.create_child(to_id.as_ref());
38 node.record_uint("edge_id", id);
39 let metadata = EdgeGraphMetadata::new(
40 &node,
41 id,
42 metadata_iterator,
43 events_tracker,
44 from.id().get_id().as_ref(),
45 to_id.as_ref(),
46 );
47 (node, metadata)
48 });
49 let state = Arc::new(RwLock::new(EdgeState::Active { metadata, _node: node }));
50 Self { state }
51 }
52
53 pub fn meta(&mut self) -> EdgeGraphMetadataRef<'_> {
55 let lock = self.state.write();
56 EdgeGraphMetadataRef { lock }
57 }
58
59 pub(crate) fn id(&self) -> u64 {
60 self.state.read().metadata().id()
61 }
62
63 pub(crate) fn weak_ref(&self) -> WeakEdgeRef {
64 WeakEdgeRef(Arc::downgrade(&self.state))
65 }
66}
67
68pub struct EdgeGraphMetadataRef<'a> {
69 lock: RwLockWriteGuard<'a, EdgeState>,
70}
71
72impl Deref for EdgeGraphMetadataRef<'_> {
73 type Target = EdgeGraphMetadata;
74
75 fn deref(&self) -> &Self::Target {
76 self.lock.metadata()
77 }
78}
79
80impl DerefMut for EdgeGraphMetadataRef<'_> {
81 fn deref_mut(&mut self) -> &mut Self::Target {
82 self.lock.metadata_mut()
83 }
84}
85
86#[derive(Debug)]
87enum EdgeState {
88 Active { metadata: EdgeGraphMetadata, _node: inspect::Node },
89 Gone { metadata: EdgeGraphMetadata },
90}
91
92impl EdgeState {
93 pub fn mark_as_gone(&mut self) {
94 match self {
95 Self::Active { metadata, .. } => {
96 let id = metadata.id();
97 *self = Self::Gone { metadata: EdgeGraphMetadata::noop(id) };
98 }
99 Self::Gone { .. } => {}
100 }
101 }
102
103 fn metadata_mut(&mut self) -> &mut EdgeGraphMetadata {
104 match self {
105 EdgeState::Active { metadata, .. } | EdgeState::Gone { metadata, .. } => metadata,
106 }
107 }
108
109 fn metadata(&self) -> &EdgeGraphMetadata {
110 match self {
111 EdgeState::Active { metadata, .. } | EdgeState::Gone { metadata, .. } => metadata,
112 }
113 }
114}
115
116#[derive(Debug, Clone)]
117pub(crate) struct WeakEdgeRef(Weak<RwLock<EdgeState>>);
118
119impl WeakEdgeRef {
120 pub fn mark_as_gone(&self) {
121 if let Some(value) = self.0.upgrade() {
122 value.write().mark_as_gone();
123 }
124 }
125
126 pub fn is_valid(&self) -> bool {
127 self.0.upgrade().map(|v| matches!(*v.read(), EdgeState::Active { .. })).unwrap_or(false)
128 }
129}
130
131impl Drop for Edge {
132 fn drop(&mut self) {
133 if let Some(events_tracker) = self.state.read().metadata().events_tracker() {
134 events_tracker.record_removed(self.id());
135 }
136 }
137}