diff options
Diffstat (limited to 'entity_map_json.cpp')
-rw-r--r-- | entity_map_json.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/entity_map_json.cpp b/entity_map_json.cpp new file mode 100644 index 0000000..7b4e0bf --- /dev/null +++ b/entity_map_json.cpp @@ -0,0 +1,119 @@ +#include "entity_map_json.hpp" + +#include <exception> +#include <fstream> +#include <ipmid/types.hpp> +#include <memory> +#include <nlohmann/json.hpp> +#include <string> +#include <utility> + +namespace ipmi +{ +namespace sensor +{ + +EntityInfoMapContainer* EntityInfoMapContainer::getContainer() +{ + static std::unique_ptr<EntityInfoMapContainer> 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<EntityInfoMapContainer>( + 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<Id>(); + obj.containerEntityId = + entry.at("containerEntityId").get<uint8_t>(); + obj.containerEntityInstance = + entry.at("containerEntityInstance").get<uint8_t>(); + obj.isList = entry.at("isList").get<bool>(); + obj.isLinked = entry.at("isLinked").get<bool>(); + + 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<uint8_t>(), + jsonEntities[i].at("instance").get<uint8_t>()); + } + + 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 |