1616const Commands Module::cmds;
1717
1818std::map<std::string, Module *> ModuleBuilder::all_modules_;
19+ std::unordered_map<std::string, Node> ModuleBuilder::module_graph_;
20+ std::unordered_set<std::string> ModuleBuilder::tasks_;
21+
22+ bool ModuleBuilder::AddEdge (const std::string &from, const std::string &to) {
23+ auto from_it = module_graph_.find (from);
24+ if (from_it == module_graph_.end () || module_graph_.count (to) == 0 ) {
25+ return false ;
26+ }
27+ from_it->second .AddChild (to);
28+ return UpdateTaskGraph ();
29+ }
30+
31+ bool ModuleBuilder::RemoveEdge (const std::string &from, const std::string &to) {
32+ auto from_node = module_graph_.find (from);
33+ if (from_node == module_graph_.end () || module_graph_.count (to) == 0 ) {
34+ return false ;
35+ }
36+
37+ from_node->second .RemoveChild (to);
38+
39+ // We need to regenerate the task graph.
40+ for (auto const &task : tasks_) {
41+ auto it = all_modules_.find (task);
42+ if (it != all_modules_.end ()) {
43+ it->second ->parent_tasks_ .clear ();
44+ }
45+ }
46+ return UpdateTaskGraph ();
47+ }
48+
49+ bool ModuleBuilder::UpdateTaskGraph () {
50+ for (auto const &task : tasks_) {
51+ std::unordered_set<std::string> visited;
52+ if (!FindNextTask (task, task, &visited)) {
53+ return false ;
54+ }
55+ }
56+ return true ;
57+ }
58+
59+ bool ModuleBuilder::FindNextTask (const std::string &node_name,
60+ const std::string &parent_name,
61+ std::unordered_set<std::string> *visited) {
62+ visited->insert (node_name);
63+ // While traversing the module graph, if `node` is in the task graph and is
64+ // not `parent`, then it must be the child of `parent`.
65+ if (node_name != parent_name && tasks_.find (node_name) != tasks_.end ()) {
66+ auto parent_it = all_modules_.find (parent_name);
67+ auto node_it = all_modules_.find (node_name);
68+ if (parent_it == all_modules_.end () || node_it == all_modules_.end ()) {
69+ return false ;
70+ }
71+
72+ Module *node = node_it->second ;
73+ Module *parent = parent_it->second ;
74+ for (Module *it : node->parent_tasks_ ) {
75+ if (it == parent) {
76+ return true ;
77+ }
78+ }
79+ node->parent_tasks_ .push_back (parent);
80+ return true ;
81+ }
82+
83+ auto node_it = module_graph_.find (node_name);
84+ if (node_it == module_graph_.end ()) {
85+ return false ;
86+ }
87+
88+ for (auto &child_name : node_it->second .children ()) {
89+ if (visited->count (child_name) > 0 ) {
90+ continue ;
91+ }
92+ if (!FindNextTask (child_name, parent_name, visited)) {
93+ return false ;
94+ }
95+ }
96+ return true ;
97+ }
1998
2099Module *ModuleBuilder::CreateModule (const std::string &name,
21100 bess::metadata::Pipeline *pipeline) const {
@@ -27,7 +106,21 @@ Module *ModuleBuilder::CreateModule(const std::string &name,
27106}
28107
29108bool ModuleBuilder::AddModule (Module *m) {
30- return all_modules_.insert ({m->name (), m}).second ;
109+ if (m->is_task_ ) {
110+ if (!tasks_.insert (m->name ()).second ) {
111+ return false ;
112+ }
113+ }
114+
115+ bool module_added = all_modules_.insert ({m->name (), m}).second ;
116+ if (!module_added) {
117+ return false ;
118+ }
119+
120+ return module_graph_
121+ .emplace (std::piecewise_construct, std::forward_as_tuple (m->name ()),
122+ std::forward_as_tuple (m))
123+ .second ;
31124}
32125
33126int ModuleBuilder::DestroyModule (Module *m, bool erase) {
@@ -57,6 +150,11 @@ int ModuleBuilder::DestroyModule(Module *m, bool erase) {
57150 all_modules_.erase (m->name ());
58151 }
59152
153+ module_graph_.erase (m->name ());
154+ if (m->is_task_ ) {
155+ tasks_.erase (m->name ());
156+ }
157+
60158 delete m;
61159 return 0 ;
62160}
@@ -402,7 +500,8 @@ int Module::ConnectModules(gate_idx_t ogate_idx, Module *m_next,
402500 ogate->AddHook (new Track ());
403501 igate->PushOgate (ogate);
404502
405- return 0 ;
503+ // Update graph
504+ return !ModuleBuilder::AddEdge (name_, m_next->name_ );
406505}
407506
408507int Module::DisconnectModules (gate_idx_t ogate_idx) {
@@ -425,6 +524,11 @@ int Module::DisconnectModules(gate_idx_t ogate_idx) {
425524
426525 igate = ogate->igate ();
427526
527+ // Remove edge in module graph.
528+ if (!ModuleBuilder::RemoveEdge (name_, igate->module ()->name_ )) {
529+ return 1 ;
530+ }
531+
428532 /* Does the igate become inactive as well? */
429533 igate->RemoveOgate (ogate);
430534 if (igate->ogates_upstream ().empty ()) {
@@ -462,6 +566,12 @@ int Module::DisconnectModulesUpstream(gate_idx_t igate_idx) {
462566 Module *m_prev = ogate->module ();
463567 m_prev->ogates_ [ogate->gate_idx ()] = nullptr ;
464568 ogate->ClearHooks ();
569+
570+ // Remove edge in module graph
571+ if (!ModuleBuilder::RemoveEdge (ogate->module ()->name_ , name_)) {
572+ return 1 ;
573+ }
574+
465575 delete ogate;
466576 }
467577
0 commit comments