1 #include "topology.hpp"
2
3 #include <iostream>
4
addBoard(const std::string & path,const std::string & boardType,const std::string & boardName,const nlohmann::json & exposesItem)5 void Topology::addBoard(const std::string& path, const std::string& boardType,
6 const std::string& boardName,
7 const nlohmann::json& exposesItem)
8 {
9 auto findType = exposesItem.find("Type");
10 if (findType == exposesItem.end())
11 {
12 return;
13 }
14
15 boardNames.try_emplace(boardName, path);
16
17 PortType exposesType = findType->get<std::string>();
18
19 if (exposesType == "DownstreamPort")
20 {
21 auto findConnectsTo = exposesItem.find("ConnectsToType");
22 if (findConnectsTo == exposesItem.end())
23 {
24 std::cerr << "Board at path " << path
25 << " is missing ConnectsToType" << std::endl;
26 return;
27 }
28 PortType connectsTo = findConnectsTo->get<std::string>();
29
30 downstreamPorts[connectsTo].emplace_back(path);
31 boardTypes[path] = boardType;
32 auto findPoweredBy = exposesItem.find("PowerPort");
33 if (findPoweredBy != exposesItem.end())
34 {
35 powerPaths.insert(path);
36 }
37 }
38 else if (exposesType.ends_with("Port"))
39 {
40 upstreamPorts[exposesType].emplace_back(path);
41 boardTypes[path] = boardType;
42 }
43 }
44
45 std::unordered_map<std::string, std::vector<Association>>
getAssocs(const std::map<Path,BoardName> & boards)46 Topology::getAssocs(const std::map<Path, BoardName>& boards)
47 {
48 std::unordered_map<std::string, std::vector<Association>> result;
49
50 // look at each upstream port type
51 for (const auto& upstreamPortPair : upstreamPorts)
52 {
53 auto downstreamMatch = downstreamPorts.find(upstreamPortPair.first);
54
55 if (downstreamMatch == downstreamPorts.end())
56 {
57 // no match
58 continue;
59 }
60
61 for (const Path& upstream : upstreamPortPair.second)
62 {
63 if (boardTypes[upstream] == "Chassis" ||
64 boardTypes[upstream] == "Board")
65 {
66 for (const Path& downstream : downstreamMatch->second)
67 {
68 // The downstream path must be one we care about.
69 if (boards.find(downstream) != boards.end())
70 {
71 result[downstream].emplace_back("contained_by",
72 "containing", upstream);
73 if (powerPaths.find(downstream) != powerPaths.end())
74 {
75 result[upstream].emplace_back(
76 "powered_by", "powering", downstream);
77 }
78 }
79 }
80 }
81 }
82 }
83
84 return result;
85 }
86
remove(const std::string & boardName)87 void Topology::remove(const std::string& boardName)
88 {
89 // Remove the board from boardNames, and then using the path
90 // found in boardNames remove it from upstreamPorts and
91 // downstreamPorts.
92 auto boardFind = boardNames.find(boardName);
93 if (boardFind == boardNames.end())
94 {
95 return;
96 }
97
98 std::string boardPath = boardFind->second;
99
100 boardNames.erase(boardFind);
101
102 for (auto it = upstreamPorts.begin(); it != upstreamPorts.end();)
103 {
104 auto pathIt =
105 std::find(it->second.begin(), it->second.end(), boardPath);
106 if (pathIt != it->second.end())
107 {
108 it->second.erase(pathIt);
109 }
110
111 if (it->second.empty())
112 {
113 it = upstreamPorts.erase(it);
114 }
115 else
116 {
117 ++it;
118 }
119 }
120
121 for (auto it = downstreamPorts.begin(); it != downstreamPorts.end();)
122 {
123 auto pathIt =
124 std::find(it->second.begin(), it->second.end(), boardPath);
125 if (pathIt != it->second.end())
126 {
127 it->second.erase(pathIt);
128 }
129
130 if (it->second.empty())
131 {
132 it = downstreamPorts.erase(it);
133 }
134 else
135 {
136 ++it;
137 }
138 }
139 }
140