Skip to main content

rings_core/
inspect.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use crate::dht::entry::Entry;
5use crate::dht::EntryStorage;
6use crate::dht::PeerRing;
7use crate::dht::SuccessorReader;
8use crate::swarm::Swarm;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct SwarmInspect {
12    pub peers: Vec<ConnectionInspect>,
13    pub dht: DHTInspect,
14    pub persistence_storage: StorageInspect,
15    pub cache_storage: StorageInspect,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ConnectionInspect {
20    pub did: String,
21    pub state: String,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub struct DHTInspect {
26    pub did: String,
27    pub successors: Vec<String>,
28    #[serde(default)]
29    pub predecessor: Option<String>,
30    pub finger_table: Vec<(Option<String>, u64, u64)>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct StorageInspect {
35    pub items: Vec<(String, Entry)>,
36}
37
38impl SwarmInspect {
39    pub async fn inspect(swarm: &Swarm) -> Self {
40        let dht = DHTInspect::inspect(&swarm.dht());
41        let peers = swarm.peers();
42        let persistence_storage = StorageInspect::inspect_kv_storage(&swarm.dht().storage).await;
43        let cache_storage = StorageInspect::inspect_kv_storage(&swarm.dht().cache).await;
44
45        Self {
46            peers,
47            dht,
48            persistence_storage,
49            cache_storage,
50        }
51    }
52}
53
54impl DHTInspect {
55    pub fn inspect(dht: &PeerRing) -> Self {
56        let did = dht.did.to_string();
57        let successors = {
58            dht.successors()
59                .list()
60                .unwrap_or_default()
61                .into_iter()
62                .map(|s| s.to_string())
63                .collect()
64        };
65
66        let predecessor = {
67            dht.lock_predecessor()
68                .map(|x| *x)
69                .ok()
70                .flatten()
71                .map(|x| x.to_string())
72        };
73
74        let finger_table = {
75            dht.lock_finger()
76                .map(|ft| {
77                    let finger = ft.list().iter().map(|x| x.map(|did| did.to_string()));
78                    compress_iter(finger)
79                })
80                .unwrap_or_default()
81        };
82
83        Self {
84            did,
85            successors,
86            predecessor,
87            finger_table,
88        }
89    }
90}
91
92impl StorageInspect {
93    pub async fn inspect_kv_storage(storage: &EntryStorage) -> Self {
94        Self {
95            items: storage
96                .get_all()
97                .await
98                .unwrap_or_default()
99                .into_iter()
100                .collect(),
101        }
102    }
103}
104
105pub fn compress_iter<T>(iter: impl Iterator<Item = T>) -> Vec<(T, u64, u64)>
106where T: PartialEq {
107    let mut result = vec![];
108    let mut start = 0u64;
109    let mut count = 0u64;
110    let mut prev: Option<T> = None;
111
112    for (i, x) in iter.enumerate() {
113        match prev {
114            Some(p) if p == x => {
115                count += 1;
116            }
117            _ => {
118                if let Some(p) = prev {
119                    result.push((p, start, start + count - 1));
120                }
121                start = i as u64;
122                count = 1;
123            }
124        }
125        prev = Some(x);
126    }
127
128    if let Some(p) = prev {
129        result.push((p, start, start + count - 1));
130    }
131
132    result
133}
134
135#[cfg(test)]
136mod tests {
137    use super::*;
138
139    #[test]
140    fn test_compress_iter() {
141        let v = vec!['a', 'a', 'f', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e'];
142        assert_eq!(
143            vec![
144                ('a', 0, 1),
145                ('f', 2, 2),
146                ('a', 3, 3),
147                ('b', 4, 5),
148                ('c', 6, 8),
149                ('d', 9, 9),
150                ('e', 10, 10),
151            ],
152            compress_iter(v.into_iter())
153        );
154    }
155}