summaryrefslogtreecommitdiff
path: root/agent/data/table/item.hpp
blob: 7c4c0ebac1fd2316c0eb9354fadec7222744ff4a (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
 * @brief MIB tables item definition.
 *
 * This file is part of sila-snmp project.
 *
 * Copyright (c) 2022 SILA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#pragma once

#include "sdbusplus/helper.hpp"

namespace phosphor
{
namespace snmp
{
namespace data
{
namespace table
{

/**
 * @brief MIB Table row implementation.
 */
template <typename... T> struct Item
{
    /*
     * The `std::variant` allows to keep duplicates of types,
     * but `std::get<>()` and `std::holds_alternative<>()` is ill-formed
     * in this case.
     *
     * So we can't use here:
     *   using variant_t = std::variant<T...>;
     * and we should specify all possible types.
     */
    using variant_t = std::variant<int64_t, std::string, bool, uint8_t, double>;

    using values_t = std::tuple<T...>;
    using fields_map_t = std::map<std::string, variant_t>;

    /* Define all of the basic class operations:
     *     Not allowed:
     *         - Default constructor to avoid nullptrs.
     *         - Copy operations due to internal unique_ptr.
     *     Allowed:
     *         - Move operations.
     *         - Destructor.
     */
    Item() = delete;
    Item(const Item&) = delete;
    Item& operator=(const Item&) = delete;
    Item(Item&&) = default;
    Item& operator=(Item&&) = default;
    ~Item() = default;

    /**
     * @brief Object constructor
     *
     * @param folder - Base folder for DBus object path
     * @param name - DBus object path relative by folder
     * @param args - Default values for each fields
     */
    Item(const std::string& folder, const std::string& name, T&&... args) :
        name(name), data(std::forward<T>(args)...),
        changedMatch(sdbusplus::helper::helper::getBus(),
                     sdbusplus::bus::match::rules::propertiesChanged(
                         folder + "/" + name),
                     std::bind(&Item<T...>::onPropertiesChanged, this,
                               std::placeholders::_1))
    {
    }

    /**
     * @brief PropertiesChanged signal handler
     */
    virtual void onPropertiesChanged(sdbusplus::message::message& m)
    {
        std::string iface;
        fields_map_t data;
        std::vector<std::string> v;
        m.read(iface, data, v);

        setFields(data);
    }

    /**
     * @brief Store fields values recieved from DBus
     */
    virtual void setFields(const fields_map_t& fields) = 0;

    /**
     * @brief Called after object has been created.
     */
    virtual void onCreate()
    {
    }

    /**
     * @brief Called before object will be destroyed.
     */
    virtual void onDestroy()
    {
    }

    /**
     * @brief String fields vlaues helper
     */
    template <size_t Index>
    void setField(const fields_map_t& fieldsMap, const char* propertyName)
    {
        using FieldType = typename std::tuple_element<Index, values_t>::type;
        if (fieldsMap.find(propertyName) != fieldsMap.end() &&
            std::holds_alternative<FieldType>(fieldsMap.at(propertyName)))
        {
            std::get<Index>(data) =
                std::get<FieldType>(fieldsMap.at(propertyName));
        }
    }

    /**
     * @brief Fill snmp reply with fields values
     */
    virtual void get_snmp_reply(netsnmp_agent_request_info* reqinfo,
                                netsnmp_request_info* request) const = 0;

    std::string name;
    values_t data;

  private:
    sdbusplus::bus::match::match changedMatch;
};

/**
 * @brief Used for std::lower_bound throw vector of smartpointers.
 */
template <typename ItemType>
inline bool operator<(const std::unique_ptr<ItemType>& o, const std::string& s)
{
    return o->name < s;
}

} // namespace table
} // namespace data
} // namespace snmp
} // namespace phosphor