blob: 003ee37cd81e7d63243cb13a110419deade0613f [file] [log] [blame]
Brad Bishop4b916f12017-05-23 18:06:38 -04001#pragma once
2
3#include <sdbusplus/message.hpp>
4#include <sdbusplus/bus/match.hpp>
5#include <vector>
Brad Bishopfccdc392017-05-22 21:11:09 -04006#include "callback.hpp"
Brad Bishop4b916f12017-05-23 18:06:38 -04007#include "data_types.hpp"
8#include "propertywatch.hpp"
9
10namespace phosphor
11{
12namespace dbus
13{
14namespace monitoring
15{
16
Brad Bishop4b916f12017-05-23 18:06:38 -040017using MappedPropertyIndex =
18 RefKeyMap<const std::string,
Brad Bishopd1eac882018-03-29 10:34:05 -040019 RefKeyMap<const std::string, RefVector<const std::string>>>;
Brad Bishop4b916f12017-05-23 18:06:38 -040020
21MappedPropertyIndex convert(const PropertyIndex& index);
22
23template <typename DBusInterfaceType>
24void PropertyWatch<DBusInterfaceType>::start()
25{
26 if (alreadyRan)
27 {
28 return;
29 }
Brad Bishop4b916f12017-05-23 18:06:38 -040030
31 // The index has a flat layout which is not optimal here. Nest
32 // properties in a map of interface names in a map of object paths.
33 auto mapped = convert(index);
34
35 for (const auto& m : mapped)
36 {
37 const auto& path = m.first.get();
38 const auto& interfaces = m.second;
39
40 // Watch for new interfaces on this path.
41 DBusInterfaceType::addMatch(
42 sdbusplus::bus::match::rules::interfacesAdded(path),
Brad Bishopd1eac882018-03-29 10:34:05 -040043 [this](auto& msg)
44 // *INDENT-OFF*
45 { this->interfacesAdded(msg); });
Brad Bishop4b916f12017-05-23 18:06:38 -040046 // *INDENT-ON*
47
48 // Do a query to populate the cache. Start with a mapper query.
49 // The specific services are queried below.
50 const std::vector<std::string> queryInterfaces; // all interfaces
51 auto mapperResp =
52 DBusInterfaceType::template callMethodAndRead<GetObject>(
Brad Bishopd1eac882018-03-29 10:34:05 -040053 MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject",
54 path, queryInterfaces);
Brad Bishop4b916f12017-05-23 18:06:38 -040055
56 for (const auto& i : interfaces)
57 {
58 const auto& interface = i.first.get();
59
60 // Watch for property changes on this interface.
61 DBusInterfaceType::addMatch(
Brad Bishopd1eac882018-03-29 10:34:05 -040062 sdbusplus::bus::match::rules::propertiesChanged(path,
63 interface),
64 [this](auto& msg)
Brad Bishop4b916f12017-05-23 18:06:38 -040065 // *INDENT-OFF*
66 {
67 std::string interface;
68 msg.read(interface);
69 auto path = msg.get_path();
70 this->propertiesChanged(msg, path, interface);
71 });
Brad Bishopd1eac882018-03-29 10:34:05 -040072 // *INDENT-ON*
Brad Bishop4b916f12017-05-23 18:06:38 -040073
74 // The mapper response is a busname:[interfaces] map. Look for
75 // each interface in the index and if found, query the service and
76 // populate the cache entries for the interface.
77 for (const auto& mr : mapperResp)
78 {
79 const auto& busName = mr.first;
80 const auto& mapperInterfaces = mr.second;
Brad Bishopd1eac882018-03-29 10:34:05 -040081 if (mapperInterfaces.end() ==
82 std::find(mapperInterfaces.begin(), mapperInterfaces.end(),
83 interface))
Brad Bishop4b916f12017-05-23 18:06:38 -040084 {
85 // This interface isn't being watched.
86 continue;
87 }
88
89 // Delegate type specific property updates to subclasses.
90 updateProperties(busName, path, interface);
91 }
92 }
93 }
Brad Bishopc1283ae2017-05-20 21:42:38 -040094
95 alreadyRan = true;
Brad Bishop4b916f12017-05-23 18:06:38 -040096}
97
Brad Bishopce4fbe12017-06-06 23:58:09 -040098template <typename DBusInterfaceType>
Ratan Guptaa45e0862018-02-21 19:03:13 +053099void PropertyWatch<DBusInterfaceType>::callback(Context ctx)
Brad Bishopce4fbe12017-06-06 23:58:09 -0400100{
101 // Invoke callback if present.
102 if (this->alreadyRan && this->cb)
103 {
Ratan Guptaa45e0862018-02-21 19:03:13 +0530104 (*this->cb)(ctx);
Brad Bishopce4fbe12017-06-06 23:58:09 -0400105 }
106}
107
Brad Bishop4b916f12017-05-23 18:06:38 -0400108template <typename T, typename DBusInterfaceType>
109void PropertyWatchOfType<T, DBusInterfaceType>::updateProperties(
Brad Bishopd1eac882018-03-29 10:34:05 -0400110 const std::string& busName, const std::string& path,
Brad Bishop4b916f12017-05-23 18:06:38 -0400111 const std::string& interface)
112{
113 auto properties =
114 DBusInterfaceType::template callMethodAndRead<PropertiesChanged<T>>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400115 busName.c_str(), path.c_str(), "org.freedesktop.DBus.Properties",
116 "GetAll", interface);
Brad Bishop4b916f12017-05-23 18:06:38 -0400117 propertiesChanged(path, interface, properties);
118}
119
120template <typename T, typename DBusInterfaceType>
121void PropertyWatchOfType<T, DBusInterfaceType>::propertiesChanged(
Brad Bishopd1eac882018-03-29 10:34:05 -0400122 const std::string& path, const std::string& interface,
Brad Bishop4b916f12017-05-23 18:06:38 -0400123 const PropertiesChanged<T>& properties)
124{
125 // Update the cache for any watched properties.
126 for (const auto& p : properties)
127 {
128 auto key = std::make_tuple(path, interface, p.first);
129 auto item = this->index.find(key);
130 if (item == this->index.end())
131 {
132 // This property isn't being watched.
133 continue;
134 }
135
Matt Spinler1abcb062018-02-26 09:14:31 -0600136 std::get<valueIndex>(std::get<storageIndex>(item->second).get()) =
Brad Bishopd1eac882018-03-29 10:34:05 -0400137 p.second.template get<T>();
Brad Bishopfccdc392017-05-22 21:11:09 -0400138
139 // Invoke callback if present.
Ratan Guptaa45e0862018-02-21 19:03:13 +0530140 this->callback(Context::SIGNAL);
Brad Bishop4b916f12017-05-23 18:06:38 -0400141 }
142}
143
144template <typename T, typename DBusInterfaceType>
145void PropertyWatchOfType<T, DBusInterfaceType>::propertiesChanged(
Brad Bishopd1eac882018-03-29 10:34:05 -0400146 sdbusplus::message::message& msg, const std::string& path,
Brad Bishop4b916f12017-05-23 18:06:38 -0400147 const std::string& interface)
148{
149 PropertiesChanged<T> properties;
150 msg.read(properties);
151 propertiesChanged(path, interface, properties);
152}
153
154template <typename T, typename DBusInterfaceType>
155void PropertyWatchOfType<T, DBusInterfaceType>::interfacesAdded(
Brad Bishopd1eac882018-03-29 10:34:05 -0400156 const std::string& path, const InterfacesAdded<T>& interfaces)
Brad Bishop4b916f12017-05-23 18:06:38 -0400157{
158 for (const auto& i : interfaces)
159 {
160 propertiesChanged(path, i.first, i.second);
161 }
162}
163
164template <typename T, typename DBusInterfaceType>
165void PropertyWatchOfType<T, DBusInterfaceType>::interfacesAdded(
166 sdbusplus::message::message& msg)
167{
168 sdbusplus::message::object_path path;
169 InterfacesAdded<T> interfaces;
170 msg.read(path, interfaces);
171 interfacesAdded(path, interfaces);
172}
173
174} // namespace monitoring
175} // namespace dbus
176} // namespace phosphor