Просмотр исходного кода

dnetview: create new msg log HashMap and render it

messages are perodically cleared on the p2p side so dnetview must keep
track of messages.

because View has no permanence, we create a HashMap<String, Vec<(String,
String)> in Model to store the message log.

this allows us to keep track of the message log for every connection.
the values are copied into View before each render.
lunar-mining 4 лет назад
Родитель
Сommit
2148c094b5
3 измененных файлов с 115 добавлено и 38 удалено
  1. 53 19
      bin/dnetview/src/main.rs
  2. 8 5
      bin/dnetview/src/model.rs
  3. 54 14
      bin/dnetview/src/view.rs

+ 53 - 19
bin/dnetview/src/main.rs

@@ -1,5 +1,5 @@
 use async_std::sync::{Arc, Mutex};
-use std::{fs::File, io, io::Read, path::PathBuf};
+use std::{collections::hash_map::Entry, fs::File, io, io::Read, path::PathBuf};
 
 use easy_parallel::Parallel;
 use fxhash::{FxHashMap, FxHashSet};
@@ -107,10 +107,10 @@ async fn main() -> Result<()> {
     terminal.clear()?;
 
     let ids = Mutex::new(FxHashSet::default());
-    let node_info = Mutex::new(FxHashMap::default());
-    let select_info = Mutex::new(FxHashMap::default());
-
-    let model = Arc::new(Model::new(ids, node_info, select_info));
+    let nodes = Mutex::new(FxHashMap::default());
+    let selectables = Mutex::new(FxHashMap::default());
+    let msg_log = Mutex::new(FxHashMap::default());
+    let model = Arc::new(Model::new(ids, nodes, selectables, msg_log));
 
     let nthreads = num_cpus::get();
     let (signal, shutdown) = async_channel::unbounded::<()>();
@@ -123,6 +123,7 @@ async fn main() -> Result<()> {
         .finish(|| {
             smol::future::block_on(async move {
                 run_rpc(&config, ex2.clone(), model.clone()).await?;
+                // msg_log
                 render(&mut terminal, model.clone()).await?;
                 drop(signal);
                 Ok::<(), darkfi::Error>(())
@@ -177,10 +178,11 @@ async fn parse_data(
     sessions.push(out_session.clone());
     sessions.push(man_session.clone());
 
-    let node_info = NodeInfo::new(node_id.clone(), node_name.to_string(), sessions.clone());
+    let nodes = NodeInfo::new(node_id.clone(), node_name.to_string(), sessions.clone());
 
-    update_node_info(model.clone(), node_info.clone(), node_id.clone()).await;
-    update_selectable_and_ids(model.clone(), sessions.clone(), node_info.clone()).await?;
+    update_nodes(model.clone(), nodes.clone(), node_id.clone()).await;
+    update_selectable_and_ids(model.clone(), sessions.clone(), nodes.clone()).await?;
+    update_msgs(model.clone(), sessions.clone()).await?;
 
     //debug!("IDS: {:?}", model.ids.lock().await);
     //debug!("INFOS: {:?}", model.infos.lock().await);
@@ -188,29 +190,52 @@ async fn parse_data(
     Ok(())
 }
 
+async fn update_msgs(model: Arc<Model>, sessions: Vec<SessionInfo>) -> Result<()> {
+    for session in sessions {
+        for connection in session.children {
+            if !model.msg_log.lock().await.contains_key(&connection.connect_id) {
+                model.msg_log.lock().await.insert(connection.connect_id, connection.msg_log);
+            } else {
+                match model.msg_log.lock().await.entry(connection.connect_id) {
+                    Entry::Vacant(e) => {
+                        e.insert(connection.msg_log);
+                    }
+                    Entry::Occupied(mut e) => {
+                        for msg in connection.msg_log {
+                            e.get_mut().push(msg);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    //debug!("MSGS: {:?}", model.msg_log.lock().await);
+    Ok(())
+}
+
 async fn update_ids(model: Arc<Model>, id: String) {
     model.ids.lock().await.insert(id);
 }
 
-async fn update_node_info(model: Arc<Model>, node: NodeInfo, id: String) {
-    model.node_info.lock().await.insert(id, node);
+async fn update_nodes(model: Arc<Model>, node: NodeInfo, id: String) {
+    model.nodes.lock().await.insert(id, node);
 }
 
 async fn update_selectable_and_ids(
     model: Arc<Model>,
     sessions: Vec<SessionInfo>,
-    node_info: NodeInfo,
+    nodes: NodeInfo,
 ) -> Result<()> {
-    let node_obj = SelectableObject::Node(node_info.clone());
-    model.select_info.lock().await.insert(node_info.node_id.clone(), node_obj);
-    update_ids(model.clone(), node_info.node_id.clone()).await;
+    let node_obj = SelectableObject::Node(nodes.clone());
+    model.selectables.lock().await.insert(nodes.node_id.clone(), node_obj);
+    update_ids(model.clone(), nodes.node_id.clone()).await;
     for session in sessions.clone() {
         let session_obj = SelectableObject::Session(session.clone());
-        model.select_info.lock().await.insert(session.clone().session_id, session_obj);
+        model.selectables.lock().await.insert(session.clone().session_id, session_obj);
         update_ids(model.clone(), session.clone().session_id).await;
         for connect in session.children {
             let connect_obj = SelectableObject::Connect(connect.clone());
-            model.select_info.lock().await.insert(connect.clone().connect_id, connect_obj);
+            model.selectables.lock().await.insert(connect.clone().connect_id, connect_obj);
             update_ids(model.clone(), connect.clone().connect_id).await;
         }
     }
@@ -261,6 +286,9 @@ async fn parse_inbound(inbound: &Value, node_id: String) -> Result<SessionInfo>
                         let is_empty = false;
                         let parent = session_id.clone();
                         let msg_values = node.unwrap().get("log").unwrap().as_array().unwrap();
+                        // append to existing values
+                        //let mut writer = msg_log.write().unwrap();
+                        //writer.insert(connect_id, connect.clone());
                         let mut msgs: Vec<(String, String)> = Vec::new();
                         for msg in msg_values {
                             let msg: (String, String) = serde_json::from_value(msg.clone())?;
@@ -364,6 +392,7 @@ async fn parse_outbound(outbound: &Value, node_id: String) -> Result<SessionInfo
                         let addr = &slot["addr"];
                         let state = &slot["state"];
                         let parent = session_id.clone();
+                        // append to existing values
                         let mut msgs: Vec<(String, String)> = Vec::new();
                         for msg in msg_values {
                             let msg: (String, String) = serde_json::from_value(msg.clone())?;
@@ -402,15 +431,20 @@ async fn render<B: Backend>(terminal: &mut Terminal<B>, model: Arc<Model>) -> Re
     let active_ids = IdListView::new(FxHashSet::default());
     let info_list = NodeInfoView::new(FxHashMap::default());
     let selectable = FxHashMap::default();
+    let msg_log = FxHashMap::default();
 
-    let mut view = View::new(active_ids.clone(), info_list.clone(), selectable);
+    let mut view = View::new(active_ids.clone(), info_list.clone(), selectable, msg_log);
     view.active_ids.state.select(Some(0));
 
     loop {
-        view.update(model.node_info.lock().await.clone(), model.select_info.lock().await.clone());
+        view.update(
+            model.nodes.lock().await.clone(),
+            model.selectables.lock().await.clone(),
+            model.msg_log.lock().await.clone(),
+        );
 
         terminal.draw(|f| {
-            view.clone().render(f);
+            view.render(f);
         })?;
         for k in asi.by_ref().keys() {
             match k.unwrap() {

+ 8 - 5
bin/dnetview/src/model.rs

@@ -19,20 +19,23 @@ pub enum SelectableObject {
 
 pub struct Model {
     pub ids: Mutex<FxHashSet<String>>,
-    pub node_info: Mutex<FxHashMap<String, NodeInfo>>,
-    pub select_info: Mutex<FxHashMap<String, SelectableObject>>,
+    pub nodes: Mutex<FxHashMap<String, NodeInfo>>,
+    pub selectables: Mutex<FxHashMap<String, SelectableObject>>,
+    pub msg_log: Mutex<FxHashMap<String, Vec<(String, String)>>>,
 }
 
 impl Model {
     pub fn new(
         ids: Mutex<FxHashSet<String>>,
-        node_info: Mutex<FxHashMap<String, NodeInfo>>,
-        select_info: Mutex<FxHashMap<String, SelectableObject>>,
+        nodes: Mutex<FxHashMap<String, NodeInfo>>,
+        selectables: Mutex<FxHashMap<String, SelectableObject>>,
+        msg_log: Mutex<FxHashMap<String, Vec<(String, String)>>>,
     ) -> Model {
-        Model { ids, node_info, select_info }
+        Model { ids, nodes, selectables, msg_log }
     }
 }
 
+// TODO: tidy variable names to avoid redudancies like NodeInfo.node_id
 #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Hash)]
 pub struct NodeInfo {
     pub node_id: String,

+ 54 - 14
bin/dnetview/src/view.rs

@@ -12,36 +12,41 @@ use tui::{
 };
 
 use crate::model::{NodeInfo, SelectableObject};
+//use log::debug;
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub struct View {
     pub active_ids: IdListView,
-    pub node_info: NodeInfoView,
+    pub nodes: NodeInfoView,
     pub selectables: FxHashMap<String, SelectableObject>,
+    pub msg_log: FxHashMap<String, Vec<(String, String)>>,
 }
 
 impl View {
     pub fn new(
         active_ids: IdListView,
-        node_info: NodeInfoView,
+        nodes: NodeInfoView,
         selectables: FxHashMap<String, SelectableObject>,
+        msg_log: FxHashMap<String, Vec<(String, String)>>,
     ) -> View {
-        View { active_ids, node_info, selectables }
+        View { active_ids, nodes, selectables, msg_log }
     }
 
     pub fn update(
         &mut self,
         nodes: FxHashMap<String, NodeInfo>,
         selectables: FxHashMap<String, SelectableObject>,
+        msg_log: FxHashMap<String, Vec<(String, String)>>,
     ) {
-        self.update_node_info(nodes);
+        self.update_nodes(nodes);
         self.update_selectable(selectables);
         self.update_active_ids();
+        self.update_msg_log(msg_log);
     }
 
-    fn update_node_info(&mut self, nodes: FxHashMap<String, NodeInfo>) {
+    fn update_nodes(&mut self, nodes: FxHashMap<String, NodeInfo>) {
         for (id, node) in nodes {
-            self.node_info.infos.insert(id, node);
+            self.nodes.infos.insert(id, node);
         }
     }
 
@@ -52,7 +57,7 @@ impl View {
     }
 
     fn update_active_ids(&mut self) {
-        for info in self.node_info.infos.values() {
+        for info in self.nodes.infos.values() {
             self.active_ids.ids.insert(info.node_id.to_string());
             for child in &info.children {
                 if !child.is_empty == true {
@@ -65,7 +70,13 @@ impl View {
         }
     }
 
-    pub fn render<B: Backend>(mut self, f: &mut Frame<'_, B>) {
+    fn update_msg_log(&mut self, msg_log: FxHashMap<String, Vec<(String, String)>>) {
+        for (id, msg) in msg_log {
+            self.msg_log.insert(id, msg);
+        }
+    }
+
+    pub fn render<B: Backend>(&mut self, f: &mut Frame<'_, B>) {
         let mut nodes = Vec::new();
         let mut ids = Vec::new();
         let style = Style::default();
@@ -73,7 +84,7 @@ impl View {
         let list_direction = Direction::Horizontal;
         let list_cnstrnts = vec![Constraint::Percentage(50), Constraint::Percentage(50)];
 
-        for info in self.node_info.infos.values() {
+        for info in self.nodes.infos.values() {
             let name_span = Span::raw(&info.node_name);
             let lines = vec![Spans::from(name_span)];
             let names = ListItem::new(lines);
@@ -136,7 +147,7 @@ impl View {
             Some(i) => {
                 match ids.get(i) {
                     Some(i) => {
-                        self.clone().render_info(f, slice.clone(), i.to_string());
+                        self.render_info(f, slice.clone(), i.to_string());
                         // found id
                     }
                     None => {
@@ -150,10 +161,16 @@ impl View {
         }
     }
 
-    fn render_info<B: Backend>(mut self, f: &mut Frame<'_, B>, slice: Vec<Rect>, selected: String) {
+    fn render_info<B: Backend>(
+        &mut self,
+        f: &mut Frame<'_, B>,
+        slice: Vec<Rect>,
+        selected: String,
+    ) {
         let style = Style::default();
         //let mut infos = Vec::new();
         let mut spans = Vec::new();
+        //let mut msgs = Vec::new();
 
         let info = self.selectables.get(&selected);
 
@@ -167,8 +184,31 @@ impl View {
                 spans.push(name_span);
             }
             Some(SelectableObject::Connect(connect)) => {
-                let name_span = Spans::from("Connect Info");
-                spans.push(name_span);
+                let log = self.msg_log.get(&connect.connect_id);
+                match log {
+                    Some(values) => {
+                        for (k, v) in values {
+                            match k.as_str() {
+                                "send" => {
+                                    let msg_log =
+                                        Spans::from(Span::styled(format!("S: {}", v), style));
+                                    spans.push(msg_log);
+                                }
+                                "recv" => {
+                                    let msg_log =
+                                        Spans::from(Span::styled(format!("R: {}", v), style));
+                                    spans.push(msg_log);
+                                }
+                                _ => {
+                                    // TODO
+                                }
+                            }
+                        }
+                    }
+                    None => {
+                        // TODO
+                    }
+                }
             }
             None => {
                 // TODO