blob: 1399531f0df74dbee964a2b9c4c5f530b7a7b0f3 [file] [log] [blame]
Brad Bishop0df00be2017-05-25 23:38:37 -04001#pragma once
2
Brad Bishop0df00be2017-05-25 23:38:37 -04003#include "callback.hpp"
4
Patrick Venture3d6d3182018-08-31 09:33:09 -07005#include <experimental/tuple>
Alexander Soldatov12789e62018-11-23 10:40:40 +03006#include <phosphor-logging/log.hpp>
Andrew Geisslerae4c95c2020-05-16 13:58:53 -05007#include <string>
Patrick Venture3d6d3182018-08-31 09:33:09 -07008
Brad Bishop0df00be2017-05-25 23:38:37 -04009namespace phosphor
10{
11namespace dbus
12{
13namespace monitoring
14{
15namespace detail
16{
17
Alexander Soldatov12789e62018-11-23 10:40:40 +030018using namespace phosphor::logging;
19
Brad Bishop0df00be2017-05-25 23:38:37 -040020/** @class CallDBusMethod
21 * @brief Provide explicit call forwarding to
22 * DBusInterface::callMethodNoReply.
23 *
24 * @tparam DBusInterface - The DBus interface to use.
25 * @tparam MethodArgs - DBus method argument types.
26 */
Patrick Venture3d6d3182018-08-31 09:33:09 -070027template <typename DBusInterface, typename... MethodArgs>
28struct CallDBusMethod
Brad Bishop0df00be2017-05-25 23:38:37 -040029{
Brad Bishopd1eac882018-03-29 10:34:05 -040030 static void op(const std::string& bus, const std::string& path,
31 const std::string& iface, const std::string& method,
32 MethodArgs&&... args)
Brad Bishop0df00be2017-05-25 23:38:37 -040033 {
Alexander Soldatov12789e62018-11-23 10:40:40 +030034 try
35 {
36 DBusInterface::callMethodNoReply(bus, path, iface, method,
37 std::forward<MethodArgs>(args)...);
38 }
39 catch (const sdbusplus::exception::SdBusError& e)
40 {
41 // clang-format off
42 log<level::ERR>("Unable to call DBus method",
43 entry("BUS=%s", bus.c_str(),
44 "PATH=%s", path.c_str(),
45 "IFACE=%s", iface.c_str(),
46 "METHOD=%s", method.c_str(),
47 "ERROR=%s", e.what()));
48 // clang-format on
49 }
Brad Bishop0df00be2017-05-25 23:38:37 -040050 }
51};
52} // namespace detail
53
54/** @class MethodBase
55 * @brief Invoke DBus method callback implementation.
56 *
57 * The method callback invokes the client supplied DBus method.
58 */
59class MethodBase : public Callback
60{
Brad Bishopd1eac882018-03-29 10:34:05 -040061 public:
62 MethodBase() = delete;
63 MethodBase(const MethodBase&) = delete;
64 MethodBase(MethodBase&&) = default;
65 MethodBase& operator=(const MethodBase&) = delete;
66 MethodBase& operator=(MethodBase&&) = default;
67 virtual ~MethodBase() = default;
68 MethodBase(const std::string& b, const std::string& p, const std::string& i,
69 const std::string& m) :
70 Callback(),
71 bus(b), path(p), interface(i), method(m)
72 {
73 }
Brad Bishop0df00be2017-05-25 23:38:37 -040074
Brad Bishopd1eac882018-03-29 10:34:05 -040075 /** @brief Callback interface implementation. */
76 void operator()(Context ctx) override = 0;
Brad Bishop0df00be2017-05-25 23:38:37 -040077
Brad Bishopd1eac882018-03-29 10:34:05 -040078 protected:
79 const std::string& bus;
80 const std::string& path;
81 const std::string& interface;
82 const std::string& method;
Brad Bishop0df00be2017-05-25 23:38:37 -040083};
84
85/** @class Method
86 * @brief C++ type specific logic for the method callback.
87 *
88 * @tparam DBusInterface - The DBus interface to use to call the method.
89 * @tparam MethodArgs - DBus method argument types.
90 */
Brad Bishopd1eac882018-03-29 10:34:05 -040091template <typename DBusInterface, typename... MethodArgs>
Brad Bishop0df00be2017-05-25 23:38:37 -040092class Method : public MethodBase
93{
Brad Bishopd1eac882018-03-29 10:34:05 -040094 public:
95 Method() = delete;
96 Method(const Method&) = default;
97 Method(Method&&) = default;
98 Method& operator=(const Method&) = default;
99 Method& operator=(Method&&) = default;
100 ~Method() = default;
101 Method(const std::string& bus, const std::string& path,
102 const std::string& iface, const std::string& method,
103 MethodArgs&&... arguments) :
104 MethodBase(bus, path, iface, method),
105 args(std::forward<MethodArgs>(arguments)...)
106 {
107 }
Brad Bishop0df00be2017-05-25 23:38:37 -0400108
Brad Bishopd1eac882018-03-29 10:34:05 -0400109 /** @brief Callback interface implementation. */
110 void operator()(Context ctx) override
111 {
112 std::experimental::apply(
113 detail::CallDBusMethod<DBusInterface, MethodArgs...>::op,
114 std::tuple_cat(std::make_tuple(bus), std::make_tuple(path),
115 std::make_tuple(interface), std::make_tuple(method),
116 args));
117 }
Brad Bishop0df00be2017-05-25 23:38:37 -0400118
Brad Bishopd1eac882018-03-29 10:34:05 -0400119 private:
120 std::tuple<MethodArgs...> args;
Brad Bishop0df00be2017-05-25 23:38:37 -0400121};
122
123/** @brief Argument type deduction for constructing Method instances. */
Brad Bishopd1eac882018-03-29 10:34:05 -0400124template <typename DBusInterface, typename... MethodArgs>
125auto makeMethod(const std::string& bus, const std::string& path,
126 const std::string& iface, const std::string& method,
127 MethodArgs&&... arguments)
Brad Bishop0df00be2017-05-25 23:38:37 -0400128{
129 return std::make_unique<Method<DBusInterface, MethodArgs...>>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400130 bus, path, iface, method, std::forward<MethodArgs>(arguments)...);
Brad Bishop0df00be2017-05-25 23:38:37 -0400131}
132
133} // namespace monitoring
134} // namespace dbus
135} // namespace phosphor