blob: f8f8f513a0cdeed5a4b824cc73560a034e112473 [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>
Patrick Venture3d6d3182018-08-31 09:33:09 -07007
Brad Bishop0df00be2017-05-25 23:38:37 -04008namespace phosphor
9{
10namespace dbus
11{
12namespace monitoring
13{
14namespace detail
15{
16
Alexander Soldatov12789e62018-11-23 10:40:40 +030017using namespace phosphor::logging;
18
Brad Bishop0df00be2017-05-25 23:38:37 -040019/** @class CallDBusMethod
20 * @brief Provide explicit call forwarding to
21 * DBusInterface::callMethodNoReply.
22 *
23 * @tparam DBusInterface - The DBus interface to use.
24 * @tparam MethodArgs - DBus method argument types.
25 */
Patrick Venture3d6d3182018-08-31 09:33:09 -070026template <typename DBusInterface, typename... MethodArgs>
27struct CallDBusMethod
Brad Bishop0df00be2017-05-25 23:38:37 -040028{
Brad Bishopd1eac882018-03-29 10:34:05 -040029 static void op(const std::string& bus, const std::string& path,
30 const std::string& iface, const std::string& method,
31 MethodArgs&&... args)
Brad Bishop0df00be2017-05-25 23:38:37 -040032 {
Alexander Soldatov12789e62018-11-23 10:40:40 +030033 try
34 {
35 DBusInterface::callMethodNoReply(bus, path, iface, method,
36 std::forward<MethodArgs>(args)...);
37 }
38 catch (const sdbusplus::exception::SdBusError& e)
39 {
40 // clang-format off
41 log<level::ERR>("Unable to call DBus method",
42 entry("BUS=%s", bus.c_str(),
43 "PATH=%s", path.c_str(),
44 "IFACE=%s", iface.c_str(),
45 "METHOD=%s", method.c_str(),
46 "ERROR=%s", e.what()));
47 // clang-format on
48 }
Brad Bishop0df00be2017-05-25 23:38:37 -040049 }
50};
51} // namespace detail
52
53/** @class MethodBase
54 * @brief Invoke DBus method callback implementation.
55 *
56 * The method callback invokes the client supplied DBus method.
57 */
58class MethodBase : public Callback
59{
Brad Bishopd1eac882018-03-29 10:34:05 -040060 public:
61 MethodBase() = delete;
62 MethodBase(const MethodBase&) = delete;
63 MethodBase(MethodBase&&) = default;
64 MethodBase& operator=(const MethodBase&) = delete;
65 MethodBase& operator=(MethodBase&&) = default;
66 virtual ~MethodBase() = default;
67 MethodBase(const std::string& b, const std::string& p, const std::string& i,
68 const std::string& m) :
69 Callback(),
70 bus(b), path(p), interface(i), method(m)
71 {
72 }
Brad Bishop0df00be2017-05-25 23:38:37 -040073
Brad Bishopd1eac882018-03-29 10:34:05 -040074 /** @brief Callback interface implementation. */
75 void operator()(Context ctx) override = 0;
Brad Bishop0df00be2017-05-25 23:38:37 -040076
Brad Bishopd1eac882018-03-29 10:34:05 -040077 protected:
78 const std::string& bus;
79 const std::string& path;
80 const std::string& interface;
81 const std::string& method;
Brad Bishop0df00be2017-05-25 23:38:37 -040082};
83
84/** @class Method
85 * @brief C++ type specific logic for the method callback.
86 *
87 * @tparam DBusInterface - The DBus interface to use to call the method.
88 * @tparam MethodArgs - DBus method argument types.
89 */
Brad Bishopd1eac882018-03-29 10:34:05 -040090template <typename DBusInterface, typename... MethodArgs>
Brad Bishop0df00be2017-05-25 23:38:37 -040091class Method : public MethodBase
92{
Brad Bishopd1eac882018-03-29 10:34:05 -040093 public:
94 Method() = delete;
95 Method(const Method&) = default;
96 Method(Method&&) = default;
97 Method& operator=(const Method&) = default;
98 Method& operator=(Method&&) = default;
99 ~Method() = default;
100 Method(const std::string& bus, const std::string& path,
101 const std::string& iface, const std::string& method,
102 MethodArgs&&... arguments) :
103 MethodBase(bus, path, iface, method),
104 args(std::forward<MethodArgs>(arguments)...)
105 {
106 }
Brad Bishop0df00be2017-05-25 23:38:37 -0400107
Brad Bishopd1eac882018-03-29 10:34:05 -0400108 /** @brief Callback interface implementation. */
109 void operator()(Context ctx) override
110 {
111 std::experimental::apply(
112 detail::CallDBusMethod<DBusInterface, MethodArgs...>::op,
113 std::tuple_cat(std::make_tuple(bus), std::make_tuple(path),
114 std::make_tuple(interface), std::make_tuple(method),
115 args));
116 }
Brad Bishop0df00be2017-05-25 23:38:37 -0400117
Brad Bishopd1eac882018-03-29 10:34:05 -0400118 private:
119 std::tuple<MethodArgs...> args;
Brad Bishop0df00be2017-05-25 23:38:37 -0400120};
121
122/** @brief Argument type deduction for constructing Method instances. */
Brad Bishopd1eac882018-03-29 10:34:05 -0400123template <typename DBusInterface, typename... MethodArgs>
124auto makeMethod(const std::string& bus, const std::string& path,
125 const std::string& iface, const std::string& method,
126 MethodArgs&&... arguments)
Brad Bishop0df00be2017-05-25 23:38:37 -0400127{
128 return std::make_unique<Method<DBusInterface, MethodArgs...>>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400129 bus, path, iface, method, std::forward<MethodArgs>(arguments)...);
Brad Bishop0df00be2017-05-25 23:38:37 -0400130}
131
132} // namespace monitoring
133} // namespace dbus
134} // namespace phosphor