|  | #include "topology.hpp" | 
|  |  | 
|  | #include <iostream> | 
|  |  | 
|  | void Topology::addBoard(const std::string& path, const std::string& boardType, | 
|  | const std::string& boardName, | 
|  | const nlohmann::json& exposesItem) | 
|  | { | 
|  | auto findType = exposesItem.find("Type"); | 
|  | if (findType == exposesItem.end()) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | boardNames.try_emplace(boardName, path); | 
|  |  | 
|  | PortType exposesType = findType->get<std::string>(); | 
|  |  | 
|  | if (exposesType == "DownstreamPort") | 
|  | { | 
|  | auto findConnectsTo = exposesItem.find("ConnectsToType"); | 
|  | if (findConnectsTo == exposesItem.end()) | 
|  | { | 
|  | std::cerr << "Board at path " << path | 
|  | << " is missing ConnectsToType" << std::endl; | 
|  | return; | 
|  | } | 
|  | PortType connectsTo = findConnectsTo->get<std::string>(); | 
|  |  | 
|  | downstreamPorts[connectsTo].emplace_back(path); | 
|  | boardTypes[path] = boardType; | 
|  | auto findPoweredBy = exposesItem.find("PowerPort"); | 
|  | if (findPoweredBy != exposesItem.end()) | 
|  | { | 
|  | powerPaths.insert(path); | 
|  | } | 
|  | } | 
|  | else if (exposesType.ends_with("Port")) | 
|  | { | 
|  | upstreamPorts[exposesType].emplace_back(path); | 
|  | boardTypes[path] = boardType; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::unordered_map<std::string, std::vector<Association>> | 
|  | Topology::getAssocs(const std::map<Path, BoardName>& boards) | 
|  | { | 
|  | std::unordered_map<std::string, std::vector<Association>> result; | 
|  |  | 
|  | // look at each upstream port type | 
|  | for (const auto& upstreamPortPair : upstreamPorts) | 
|  | { | 
|  | auto downstreamMatch = downstreamPorts.find(upstreamPortPair.first); | 
|  |  | 
|  | if (downstreamMatch == downstreamPorts.end()) | 
|  | { | 
|  | // no match | 
|  | continue; | 
|  | } | 
|  |  | 
|  | for (const Path& upstream : upstreamPortPair.second) | 
|  | { | 
|  | if (boardTypes[upstream] == "Chassis" || | 
|  | boardTypes[upstream] == "Board") | 
|  | { | 
|  | for (const Path& downstream : downstreamMatch->second) | 
|  | { | 
|  | // The downstream path must be one we care about. | 
|  | if (boards.find(downstream) != boards.end()) | 
|  | { | 
|  | result[downstream].emplace_back("contained_by", | 
|  | "containing", upstream); | 
|  | if (powerPaths.find(downstream) != powerPaths.end()) | 
|  | { | 
|  | result[upstream].emplace_back( | 
|  | "powered_by", "powering", downstream); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void Topology::remove(const std::string& boardName) | 
|  | { | 
|  | // Remove the board from boardNames, and then using the path | 
|  | // found in boardNames remove it from upstreamPorts and | 
|  | // downstreamPorts. | 
|  | auto boardFind = boardNames.find(boardName); | 
|  | if (boardFind == boardNames.end()) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | std::string boardPath = boardFind->second; | 
|  |  | 
|  | boardNames.erase(boardFind); | 
|  |  | 
|  | for (auto it = upstreamPorts.begin(); it != upstreamPorts.end();) | 
|  | { | 
|  | auto pathIt = std::find(it->second.begin(), it->second.end(), | 
|  | boardPath); | 
|  | if (pathIt != it->second.end()) | 
|  | { | 
|  | it->second.erase(pathIt); | 
|  | } | 
|  |  | 
|  | if (it->second.empty()) | 
|  | { | 
|  | it = upstreamPorts.erase(it); | 
|  | } | 
|  | else | 
|  | { | 
|  | ++it; | 
|  | } | 
|  | } | 
|  |  | 
|  | for (auto it = downstreamPorts.begin(); it != downstreamPorts.end();) | 
|  | { | 
|  | auto pathIt = std::find(it->second.begin(), it->second.end(), | 
|  | boardPath); | 
|  | if (pathIt != it->second.end()) | 
|  | { | 
|  | it->second.erase(pathIt); | 
|  | } | 
|  |  | 
|  | if (it->second.empty()) | 
|  | { | 
|  | it = downstreamPorts.erase(it); | 
|  | } | 
|  | else | 
|  | { | 
|  | ++it; | 
|  | } | 
|  | } | 
|  | } |