summaryrefslogtreecommitdiffstats
path: root/entity_map_json.cpp
blob: 7b4e0bf49267cf0eaa4a876d7eb83b61eef7efff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
OpenPOWER on IntegriCloud