blob: c52e668a6f9e6d1eea9995ca4221d714dac61e6b [file] [log] [blame]
Brad Bishop3d57f502016-10-19 12:18:41 -04001#pragma once
2
3#include <utility>
4#include <memory>
5#include <sdbusplus/message.hpp>
Brad Bishop65ffffa2016-11-29 12:31:31 -05006#include "utils.hpp"
Brad Bishop3d57f502016-10-19 12:18:41 -04007
8namespace phosphor
9{
10namespace inventory
11{
12namespace manager
13{
Brad Bishopc0eae112016-10-19 21:59:47 -040014
15class Manager;
Brad Bishop65ffffa2016-11-29 12:31:31 -050016namespace details
17{
18using FilterBase = holder::CallableBase<
19 bool, sdbusplus::message::message&, Manager&>;
20using FilterBasePtr = std::shared_ptr<FilterBase>;
21template <typename T>
22using Filter = holder::CallableHolder<
23 T, bool, sdbusplus::message::message&, Manager&>;
24
Brad Bishop4f20a3e2016-11-29 15:21:46 -050025/** @struct Event
26 * @brief Event object interface.
27 */
28struct Event
29{
30 enum class Type
31 {
32 DBUS_SIGNAL,
33 };
34
35 virtual ~Event() = default;
36 Event(const Event&) = default;
37 Event& operator=(const Event&) = default;
38 Event(Event&&) = default;
39 Event& operator=(Event&&) = default;
40 explicit Event(Type t) : type(t) {}
41
42 Type type;
43};
44
45using EventBasePtr = std::shared_ptr<Event>;
46
47/** @struct DbusSignal
48 * @brief DBus signal event.
49 *
50 * DBus signal events are an association of a match signature
51 * and filtering function object.
52 */
53struct DbusSignal final :
54 public Event,
55 public std::tuple<const char *, FilterBasePtr>
56{
57 virtual ~DbusSignal() = default;
58 DbusSignal(const DbusSignal&) = default;
59 DbusSignal & operator=(const DbusSignal&) = delete;
60 DbusSignal(DbusSignal&&) = default;
61 DbusSignal& operator=(DbusSignal&&) = default;
62
63 /** @brief Import from signature and filter constructor.
64 *
65 * @param[in] sig - The DBus match signature.
66 * @param[in] filter - A DBus signal match callback filtering function.
67 */
68 DbusSignal(const char *sig, FilterBasePtr filter) :
69 Event(Type::DBUS_SIGNAL),
70 std::tuple<const char *, FilterBasePtr>(
71 sig, std::move(filter)) {}
72};
73
Brad Bishop65ffffa2016-11-29 12:31:31 -050074/** @brief make_filter
75 *
76 * Adapt a filter function object.
77 *
78 * @param[in] filter - The filter being adapted.
79 * @returns - The adapted filter.
80 *
81 * @tparam T - The type of the filter being adapted.
82 */
83template <typename T>
84auto make_filter(T&& filter)
85{
86 return Filter<T>::template make_shared<Filter<T>>(
87 std::forward<T>(filter));
88}
89} // namespace details
90
Brad Bishop3d57f502016-10-19 12:18:41 -040091namespace filters
92{
93namespace details
94{
Brad Bishopbf5aa9c2016-10-19 21:19:04 -040095namespace property_condition
96{
97
98/** @struct PropertyCondition
99 * @brief Match filter functor that tests a property value.
100 *
101 * @tparam T - The type of the property being tested.
102 * @tparam U - The type of the condition checking functor.
103 */
104template <typename T, typename U>
105struct PropertyCondition
106{
107 PropertyCondition() = delete;
108 ~PropertyCondition() = default;
109 PropertyCondition(const PropertyCondition&) = default;
110 PropertyCondition & operator=(const PropertyCondition&) = delete;
111 PropertyCondition(PropertyCondition&&) = default;
112 PropertyCondition& operator=(PropertyCondition&&) = default;
113 PropertyCondition(const char *iface, const char *property, U &&condition) :
114 _iface(iface),
115 _property(property),
116 _condition(std::forward<U>(condition)) { }
117
118 /** @brief Test a property value.
119 *
120 * Extract the property from the PropertiesChanged
121 * message and run the condition test.
122 */
Brad Bishopc0eae112016-10-19 21:59:47 -0400123 bool operator()(sdbusplus::message::message &msg, Manager &) const
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400124 {
125 std::map<
126 std::string,
127 sdbusplus::message::variant<T>> properties;
128 const char *iface = nullptr;
129
130 msg.read(iface);
131 if(strcmp(iface, _iface))
132 return false;
133
134 msg.read(properties);
135 auto it = properties.find(_property);
136 if(it == properties.cend())
137 return false;
138
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500139 return _condition(it->second.template get<T>());
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400140 }
141
142 private:
143 const char *_iface;
144 const char *_property;
145 U _condition;
146};
147
148} // namespace property_condition
Brad Bishop3d57f502016-10-19 12:18:41 -0400149} // namespace details
150
151/** @brief The default filter. */
Brad Bishopc0eae112016-10-19 21:59:47 -0400152inline bool none(sdbusplus::message::message &, Manager &) noexcept
Brad Bishop3d57f502016-10-19 12:18:41 -0400153{
154 return true;
155}
156
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400157/** @brief Implicit type deduction for constructing PropertyCondition. */
158template <typename T>
159auto propertyChangedTo(
160 const char *iface,
161 const char *property,
162 T val)
163{
Brad Bishopd1bbf3a2016-12-01 00:03:26 -0500164 auto condition = [val = std::move(val)](const std::string &arg)
165 {
166 return arg == val;
167 };
Brad Bishopbf5aa9c2016-10-19 21:19:04 -0400168 using U = decltype(condition);
169 return details::property_condition::PropertyCondition<T, U>(
170 iface, property, std::move(condition));
171}
172
Brad Bishop3d57f502016-10-19 12:18:41 -0400173} // namespace filters
174} // namespace manager
175} // namespace inventory
176} // namespace phosphor
177
178// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4