2323#include " appmodel/TriggerApplication.hpp"
2424#include " appmodel/appmodelIssues.hpp"
2525
26+ #include " appmodel/DataHandlerModule.hpp"
27+ #include " appmodel/DataReaderModule.hpp"
28+ #include " appmodel/DataMoveCallbackConf.hpp"
29+ #include " appmodel/SocketDataWriterModule.hpp"
30+
2631#include " conffwk/Configuration.hpp"
2732#include " conffwk/Schema.hpp"
2833#include " confmodel/Connection.hpp"
34+ #include " confmodel/NetworkConnection.hpp"
2935#include " confmodel/DaqModule.hpp"
3036#include " confmodel/Session.hpp"
3137#include " ers/ers.hpp"
@@ -425,7 +431,7 @@ GraphBuilder::find_objects_and_connections(const ConfigObject& object)
425431 if (m_root_object_kind == ObjectKind::kSession || m_root_object_kind == ObjectKind::kSegment ) {
426432 allowed_conns = { " NetworkConnection" };
427433 } else if (m_root_object_kind == ObjectKind::kApplication || m_root_object_kind == ObjectKind::kModule ) {
428- allowed_conns = { " NetworkConnection" , " Queue" , " QueueWithSourceId" };
434+ allowed_conns = { " NetworkConnection" , " Queue" , " QueueWithSourceId" , " DataMoveCallbackConf " };
429435 }
430436
431437 for (const auto & module : modules) {
@@ -436,7 +442,12 @@ GraphBuilder::find_objects_and_connections(const ConfigObject& object)
436442 // connection is a network or a queue, so include the
437443 // class name in the std::string key
438444
439- const std::string key = in->config_object ().UID () + " @" + in->config_object ().class_name ();
445+ std::string key = in->config_object ().UID () + " @" + in->config_object ().class_name ();
446+
447+ if (in->config_object ().class_name () == " NetworkConnection" ) {
448+ auto innc = in->cast <dunedaq::confmodel::NetworkConnection>();
449+ key += " @" + innc->get_connection_type ();
450+ }
440451
441452 if (std::ranges::find (allowed_conns, in->config_object ().class_name ()) != allowed_conns.end ()) {
442453 m_incoming_connections[key].push_back (object.UID ());
@@ -446,14 +457,56 @@ GraphBuilder::find_objects_and_connections(const ConfigObject& object)
446457
447458 for (auto out : module ->get_outputs ()) {
448459
449- const std::string key = out->config_object ().UID () + " @" + out->config_object ().class_name ();
460+ std::string key = out->config_object ().UID () + " @" + out->config_object ().class_name ();
461+
462+ if (out->config_object ().class_name () == " NetworkConnection" ) {
463+ auto outnc = out->cast <dunedaq::confmodel::NetworkConnection>();
464+ key += " @" + outnc->get_connection_type ();
465+ }
450466
451467 if (std::ranges::find (allowed_conns, out->config_object ().class_name ()) != allowed_conns.end ()) {
452468 m_outgoing_connections[key].push_back (object.UID ());
453469 m_outgoing_connections[key].push_back (module ->UID ());
454470 }
455471 }
456472
473+ // Look for DataMoveCallbackConfs
474+ auto datareader = module ->cast <dunedaq::appmodel::DataReaderModule>();
475+ auto datahandler = module ->cast <dunedaq::appmodel::DataHandlerModule>();
476+ auto socketwriter = module ->cast <dunedaq::appmodel::SocketDataWriterModule>();
477+
478+ if (datareader != nullptr ) {
479+ for (auto & out : datareader->get_raw_data_callbacks ()) {
480+ const std::string key = out->config_object ().UID () + " @" + out->config_object ().class_name ();
481+ if (std::ranges::find (allowed_conns, out->config_object ().class_name ()) != allowed_conns.end ()) {
482+ m_outgoing_connections[key].push_back (object.UID ());
483+ m_outgoing_connections[key].push_back (module ->UID ());
484+ }
485+ }
486+ }
487+ if (datahandler != nullptr ) {
488+ auto in = datahandler->get_raw_data_callback ();
489+ if (in != nullptr ) {
490+ const std::string key = in->config_object ().UID () + " @" + in->config_object ().class_name ();
491+
492+ if (std::ranges::find (allowed_conns, in->config_object ().class_name ()) != allowed_conns.end ()) {
493+ m_incoming_connections[key].push_back (object.UID ());
494+ m_incoming_connections[key].push_back (module ->UID ());
495+ }
496+ }
497+ }
498+ if (socketwriter != nullptr ) {
499+ auto in = socketwriter->get_raw_data_callback ();
500+ if (in != nullptr ) {
501+ const std::string key = in->config_object ().UID () + " @" + in->config_object ().class_name ();
502+
503+ if (std::ranges::find (allowed_conns, in->config_object ().class_name ()) != allowed_conns.end ()) {
504+ m_incoming_connections[key].push_back (object.UID ());
505+ m_incoming_connections[key].push_back (module ->UID ());
506+ }
507+ }
508+ }
509+
457510 if (std::ranges::find (m_included_classes.at (m_root_object_kind), " Module" ) !=
458511 m_included_classes.at (m_root_object_kind).end ()) {
459512 find_objects_and_connections (module ->config_object ());
@@ -518,9 +571,6 @@ GraphBuilder::construct_graph(std::string root_obj_uid)
518571 for (auto & possible_sender_object : m_objects_for_graph | std::views::values) {
519572 for (auto & receiver_info : possible_sender_object.receiving_object_infos ) {
520573
521- auto at_pos = receiver_info.connection_name .find (" @" );
522- const std::string connection_label = receiver_info.connection_name .substr (0 , at_pos);
523-
524574 // If we're plotting at the level of a session or segment,
525575 // show the connections as between applications; if we're
526576 // doing this for a single application, show them entering and
@@ -540,7 +590,7 @@ GraphBuilder::construct_graph(std::string root_obj_uid)
540590
541591 boost::add_edge (possible_sender_object.vertex_in_graph ,
542592 m_objects_for_graph.at (receiver_info.receiver_label ).vertex_in_graph ,
543- { connection_label },
593+ { receiver_info. connection_name },
544594 m_graph)
545595 .first ;
546596 }
@@ -608,7 +658,16 @@ GraphBuilder::write_graph(const std::string& outputfilename) const
608658 { ObjectKind::kModule , { " rectangle" , " red" } } };
609659
610660 std::string dotfile_slurped = outputstream.str ();
611- std::vector<std::string> legend_entries{};
661+ std::vector<std::string> legend_entries{
662+ " legendGA [label=<<font color=\" black\" ><b><i>⟶ Network Connection</i></b></font>>, shape=plaintext];" ,
663+ " legendGB [label=<<font color=\" blue\" ><b><i>⟶ Pub/Sub Network</i></b></font>>, shape=plaintext];"
664+ };
665+ std::vector<std::string> internal_legend_entries{
666+ " legendGC [label=<<font color=\" green\" ><b><i>⟶ Data Move Callback</i></b></font>>, shape=plaintext];" ,
667+ " legendGD [label=<<font color=\" red\" ><b><i>⟶ Queue</i></b></font>>, shape=plaintext];" ,
668+ " legendGE [label=<<font color=\" orange\" ><b><i>⟶ Queue w/ Source ID</i></b></font>>, shape=plaintext];"
669+ };
670+ bool internal_legend_added = false ;
612671 std::vector<std::string> legend_ordering_code{};
613672
614673 for (auto & eo : m_objects_for_graph | std::views::values) {
@@ -665,6 +724,12 @@ GraphBuilder::write_graph(const std::string& outputfilename) const
665724 case ObjectKind::kModule :
666725 add_vertex_info ();
667726 add_legend_entry (' D' , " DAQModule" );
727+ if (!internal_legend_added) {
728+ legend_entries.insert (legend_entries.end (),
729+ internal_legend_entries.begin (),
730+ internal_legend_entries.end ());
731+ internal_legend_added = true ;
732+ }
668733 break ;
669734 case ObjectKind::kIncomingExternal :
670735 legendstr
@@ -741,6 +806,23 @@ GraphBuilder::write_graph(const std::string& outputfilename) const
741806 pos += (unlabeled_edge + edge_modifier).length ();
742807 }
743808
809+ // Replace the connection types with color information
810+ std::vector<std::pair<std::string, std::string>> connection_colors = { { " @NetworkConnection@kSendRecv\" " , " \" , color=black" },
811+ { " @NetworkConnection@kPubSub\" " , " \" , color=blue" },
812+ { " @QueueWithSourceId\" " , " \" , color=orange" },
813+ { " @Queue\" " , " \" , color=red" },
814+ { " @DataMoveCallbackConf\" " ,
815+ " \" , color=green" } };
816+ for (auto & color_pair : connection_colors) {
817+ auto conn_type = color_pair.first ;
818+ auto color_info = color_pair.second ;
819+ pos = 0 ;
820+ while ((pos = dotfile_slurped.find (conn_type, pos)) != std::string::npos) {
821+ dotfile_slurped.replace (pos, conn_type.length (), color_info);
822+ pos += color_info.length ();
823+ }
824+ }
825+
744826 // And now with all the edits made to the contents of the DOT code, write it to file
745827
746828 std::ofstream outputfile;
0 commit comments