1 #pragma once
2 
3 #include <map>
4 #include <memory>
5 #include <string>
6 #include <vector>
7 #include <sdbusplus/server.hpp>
8 #include "xyz/openbmc_project/Inventory/Manager/server.hpp"
9 #include "filters.hpp"
10 #include "actions.hpp"
11 
12 namespace phosphor
13 {
14 namespace inventory
15 {
16 namespace manager
17 {
18 namespace details
19 {
20 namespace interface
21 {
22 namespace holder
23 {
24 
25 /** @struct Base
26  *  @brief sdbusplus server interface holder base.
27  *
28  *  Provides a common type for assembling containers of sdbusplus server
29  *  interfaces.  Typically a multiple inheritance scheme (sdbusplus::object)
30  *  would be used for this; however, for objects created by PIM the interfaces
31  *  are not known at build time.
32  */
33 struct Base
34 {
35     Base() = default;
36     virtual ~Base() = default;
37     Base(const Base&) = delete;
38     Base& operator=(const Base&) = delete;
39     Base(Base&&) = default;
40     Base& operator=(Base&&) = default;
41 };
42 
43 /** @struct Holder
44  *  @brief sdbusplus server interface holder.
45  *
46  *  Holds a pointer to an sdbusplus server interface instance.
47  *
48  *  @tparam T - The sdbusplus server interface type to hold.
49  */
50 template <typename T>
51 struct Holder final : public Base
52 {
53     Holder() = delete;
54     ~Holder() = default;
55     Holder(const Holder&) = delete;
56     Holder& operator=(const Holder&) = delete;
57     Holder(Holder&&) = default;
58     Holder& operator=(Holder&&) = default;
59     explicit Holder(auto &&ptr) noexcept : _ptr(std::move(ptr)) {}
60 
61     /** @brief sdbusplus server interface holder factory method.
62      *
63      *  @param bus[in] - An sdbusplus bus connection
64      *  @param bus[in] - The path of the object for which
65      *          an interface is to be held.
66      *  @returns A held interface.
67      */
68     static auto make(sdbusplus::bus::bus &bus, const char *path)
69     {
70         return static_cast<std::unique_ptr<Base>>(
71                 std::make_unique<Holder<T>>(
72                     std::make_unique<T>(bus, path)));
73     }
74 
75     private:
76     std::unique_ptr<T> _ptr;
77 };
78 
79 } // namespace holder
80 } // namespace interface
81 
82 template <typename T>
83 using ServerObject = typename sdbusplus::server::object::object<T>;
84 
85 using ManagerIface =
86     sdbusplus::server::xyz::openbmc_project::Inventory::Manager;
87 
88 } // namespace details
89 
90 /** @class Manager
91  *  @brief OpenBMC inventory manager implementation.
92  *
93  *  A concrete implementation for the xyz.openbmc_project.Inventory.Manager
94  *  DBus API.
95  */
96 class Manager final :
97     public details::ServerObject<details::ManagerIface>
98 {
99     public:
100     Manager() = delete;
101     Manager(const Manager&) = delete;
102     Manager& operator=(const Manager&) = delete;
103     Manager(Manager&&) = default;
104     Manager& operator=(Manager&&) = default;
105     ~Manager() = default;
106 
107     /** @brief Construct an inventory manager.
108      *
109      *  @param[in] bus - An sdbusplus bus connection.
110      *  @param[in] busname - The DBus busname to own.
111      *  @param[in] root - The DBus path on which to implement
112      *      an inventory manager.
113      *  @param[in] iface - The DBus inventory interface to implement.
114      */
115     Manager(sdbusplus::bus::bus &&, const char *, const char*, const char*);
116 
117     using Object = std::map<
118         std::string, std::map<
119             std::string, sdbusplus::message::variant<std::string>>>;
120 
121     /** @brief Start processing DBus messages. */
122     void run() noexcept;
123 
124     /** @brief Provided for testing only. */
125     void shutdown() noexcept;
126 
127     /** @brief sd_bus Notify method implementation callback. */
128     void notify(std::string path, Object) override;
129 
130     /** @brief sd_bus signal callback. */
131     void signal(sdbusplus::message::message &, auto &);
132 
133     /** @brief Drop an object from DBus. */
134     void destroyObject(const char *);
135 
136     using Event = std::tuple<
137         const char *,
138         filters::details::Wrapper,
139         actions::details::Wrapper>;
140     using SigArgs = std::vector<
141         std::unique_ptr<
142             std::tuple<
143                 Manager *,
144                 const Event *>>>;
145     using SigArg = SigArgs::value_type::element_type;
146 
147     private:
148     using Holder = details::interface::holder::Base;
149     using HolderPtr = std::unique_ptr<Holder>;
150     using InterfaceComposite = std::map<std::string, HolderPtr>;
151     using ObjectReferences = std::map<std::string, InterfaceComposite>;
152     using Events = std::map<const char *, Event>;
153     using MakerType = HolderPtr(*)(
154             sdbusplus::bus::bus &, const char *);
155     using Makers = std::map<std::string, MakerType>;
156 
157     /** @brief Provided for testing only. */
158     bool _shutdown;
159 
160     /** @brief Path prefix applied to any relative paths. */
161     const char * _root;
162 
163     /** @brief A container of sdbusplus server interface references. */
164     ObjectReferences _refs;
165 
166     /** @brief A container contexts for signal callbacks. */
167     SigArgs _sigargs;
168 
169     /** @brief A container of sdbusplus signal matches.  */
170     std::vector<sdbusplus::server::match::match> _matches;
171 
172     /** @brief Persistent sdbusplus DBus bus connection. */
173     sdbusplus::bus::bus _bus;
174 
175     /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
176     sdbusplus::server::manager::manager _manager;
177 
178     /** @brief A container of pimgen generated events and responses.  */
179     static const Events _events;
180 
181     /** @brief A container of pimgen generated factory methods.  */
182     static const Makers _makers;
183 };
184 
185 } // namespace manager
186 } // namespace inventory
187 } // namespace phosphor
188 
189 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
190