summaryrefslogtreecommitdiffstats
path: root/elog_meta.hpp
blob: 6783a325e4f47fd336e3918662b144b74174749a (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#pragma once

#include "callouts-gen.hpp"
#include "elog_entry.hpp"

#include <algorithm>
#include <cstring>
#include <phosphor-logging/elog-errors.hpp>
#include <string>
#include <tuple>
#include <vector>

namespace phosphor
{
namespace logging
{
namespace metadata
{

using Metadata = std::string;

namespace associations
{

using Type = void(const std::string&, const std::vector<std::string>&,
                  AssociationList& list);

/** @brief Pull out metadata name and value from the string
 *         <metadata name>=<metadata value>
 *  @param [in] data - metadata key=value entries
 *  @param [out] metadata - map of metadata name:value
 */
inline void parse(const std::vector<std::string>& data,
                  std::map<std::string, std::string>& metadata)
{
    constexpr auto separator = '=';
    for (const auto& entryItem : data)
    {
        auto pos = entryItem.find(separator);
        if (std::string::npos != pos)
        {
            auto key = entryItem.substr(0, entryItem.find(separator));
            auto value = entryItem.substr(entryItem.find(separator) + 1);
            metadata.emplace(std::move(key), std::move(value));
        }
    }
};

/** @brief Combine the metadata keys and values from the map
 *         into a vector of strings that look like:
 *            "<metadata name>=<metadata value>"
 *  @param [in] data - metadata key:value map
 *  @param [out] metadata - vector of "key=value" strings
 */
inline void combine(const std::map<std::string, std::string>& data,
                    std::vector<std::string>& metadata)
{
    for (const auto& [key, value] : data)
    {
        std::string line{key};
        line += "=" + value;
        metadata.push_back(std::move(line));
    }
}

/** @brief Build error associations specific to metadata. Specialize this
 *         template for handling a specific type of metadata.
 *  @tparam M - type of metadata
 *  @param [in] match - metadata to be handled
 *  @param [in] data - metadata key=value entries
 *  @param [out] list - list of error association objects
 */
template <typename M>
void build(const std::string& match, const std::vector<std::string>& data,
           AssociationList& list) = delete;

// Example template specialization - we don't want to do anything
// for this metadata.
using namespace example::xyz::openbmc_project::Example::Elog;
template <>
inline void build<TestErrorTwo::DEV_ID>(const std::string& match,
                                        const std::vector<std::string>& data,
                                        AssociationList& list)
{
}

template <>
inline void
    build<example::xyz::openbmc_project::Example::Device::Callout::
              CALLOUT_DEVICE_PATH_TEST>(const std::string& match,
                                        const std::vector<std::string>& data,
                                        AssociationList& list)
{
    std::map<std::string, std::string> metadata;
    parse(data, metadata);
    auto iter = metadata.find(match);
    if (metadata.end() != iter)
    {
        auto comp = [](const auto& first, const auto& second) {
            return (std::strcmp(std::get<0>(first), second) < 0);
        };
        auto callout = std::lower_bound(callouts.begin(), callouts.end(),
                                        (iter->second).c_str(), comp);
        if ((callouts.end() != callout) &&
            !std::strcmp((iter->second).c_str(), std::get<0>(*callout)))
        {
            constexpr auto ROOT = "/xyz/openbmc_project/inventory";

            list.push_back(std::make_tuple(
                "callout", "fault", std::string(ROOT) + std::get<1>(*callout)));
        }
    }
}

// The PROCESS_META flag is needed to get out of tree builds working. Such
// builds will have access only to internal error interfaces, hence handlers
// for out dbus error interfaces won't compile. This flag is not set by default,
// the phosphor-logging recipe enabled it.
#if defined PROCESS_META

template <>
void build<xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH>(
    const std::string& match, const std::vector<std::string>& data,
    AssociationList& list);

template <>
void build<
    xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH>(
    const std::string& match, const std::vector<std::string>& data,
    AssociationList& list);

#endif // PROCESS_META

} // namespace associations
} // namespace metadata
} // namespace logging
} // namespace phosphor
OpenPOWER on IntegriCloud