#include "entity_map_json.hpp" #include #include #include #include #include #include #include namespace ipmi { namespace sensor { EntityInfoMapContainer* EntityInfoMapContainer::getContainer() { static std::unique_ptr instance; if (!instance) { /* TODO: With multi-threading this would all need to be locked so * the first thread to hit it would set it up. */ EntityInfoMap builtEntityMap = buildEntityMapFromFile(); instance = std::unique_ptr( new EntityInfoMapContainer(builtEntityMap)); } return instance.get(); } const EntityInfoMap& EntityInfoMapContainer::getIpmiEntityRecords() { return entityRecords; } EntityInfoMap buildEntityMapFromFile() { const char* entityMapJsonFilename = "/usr/share/ipmi-providers/entity-map.json"; EntityInfoMap builtMap; std::ifstream mapFile(entityMapJsonFilename); if (!mapFile.is_open()) { return builtMap; } auto data = nlohmann::json::parse(mapFile, nullptr, false); if (data.is_discarded()) { return builtMap; } return buildJsonEntityMap(data); } EntityInfoMap buildJsonEntityMap(const nlohmann::json& data) { EntityInfoMap builtMap; if (data.type() != nlohmann::json::value_t::array) { return builtMap; } try { for (const auto& entry : data) { /* It's an array entry with the following fields: id, * containerEntityId, containerEntityInstance, isList, isLinked, * entities[4] */ EntityInfo obj; Id recordId = entry.at("id").get(); obj.containerEntityId = entry.at("containerEntityId").get(); obj.containerEntityInstance = entry.at("containerEntityInstance").get(); obj.isList = entry.at("isList").get(); obj.isLinked = entry.at("isLinked").get(); auto jsonEntities = entry.at("entities"); if (jsonEntities.type() != nlohmann::json::value_t::array) { throw std::runtime_error( "Invalid type for entities entry, must be array"); } if (jsonEntities.size() != obj.containedEntities.size()) { throw std::runtime_error( "Entities must be in pairs of " + std::to_string(obj.containedEntities.size())); } for (std::size_t i = 0; i < obj.containedEntities.size(); i++) { obj.containedEntities[i] = std::make_pair( jsonEntities[i].at("id").get(), jsonEntities[i].at("instance").get()); } builtMap.insert({recordId, obj}); } } catch (const std::exception& e) { /* If any entry is invalid, the entire file cannot be trusted. */ builtMap.clear(); } return builtMap; } } // namespace sensor } // namespace ipmi