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}