1 #pragma once
2 
3 #include <cstring>
4 #include <vector>
5 #include <experimental/filesystem>
6 #include <functional>
7 #include <sdbusplus/bus.hpp>
8 #include <powercap.hpp>
9 #include "occ_pass_through.hpp"
10 #include "occ_status.hpp"
11 #include "occ_finder.hpp"
12 #include "config.h"
13 
14 namespace sdbusRule = sdbusplus::bus::match::rules;
15 
16 namespace open_power
17 {
18 namespace occ
19 {
20 
21 /** @class Manager
22  *  @brief Builds and manages OCC objects
23  */
24 struct Manager
25 {
26     public:
27         Manager() = delete;
28         Manager(const Manager&) = delete;
29         Manager& operator=(const Manager&) = delete;
30         Manager(Manager&&) = default;
31         Manager& operator=(Manager&&) = default;
32         ~Manager() = default;
33 
34         /** @brief Adds OCC pass-through and status objects on the bus
35          *         when corresponding CPU inventory is created.
36          *
37          *  @param[in] bus   - handle to the bus
38          *  @param[in] event - Unique ptr reference to sd_event
39          */
40         Manager(sdbusplus::bus::bus& bus,
41                 EventPtr& event) :
42             bus(bus),
43             event(event)
44         {
45             // Check if CPU inventory exists already.
46             auto occs = open_power::occ::finder::get();
47             if (occs.empty())
48             {
49                 // Need to watch for CPU inventory creation.
50                 for (auto id = 0; id < MAX_CPUS; ++id)
51                 {
52                     auto path = std::string(CPU_PATH) + std::to_string(id);
53                     cpuMatches.emplace_back(
54                         bus,
55                         sdbusRule::interfacesAdded() +
56                         sdbusRule::argNpath(0, path),
57                         std::bind(std::mem_fn(&Manager::cpuCreated),
58                                   this, std::placeholders::_1));
59                 }
60             }
61             else
62             {
63                 for (const auto& occ : occs)
64                 {
65                     // CPU inventory exists already, OCC objects can be created.
66                     createObjects(occ);
67                 }
68             }
69         }
70 
71         /** @brief Callback that responds to cpu creation in the inventory -
72          *         by creating the needed objects.
73          *
74          *  @param[in] msg - bus message
75          *
76          *  @returns 0 to indicate success
77          */
78         int cpuCreated(sdbusplus::message::message& msg)
79         {
80             namespace fs = std::experimental::filesystem;
81 
82             sdbusplus::message::object_path o;
83             msg.read(o);
84             fs::path cpuPath(std::string(std::move(o)));
85 
86             auto name = cpuPath.filename().string();
87             auto index = name.find(CPU_NAME);
88             name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
89 
90             createObjects(name);
91 
92             return 0;
93         }
94 
95     private:
96         /** @brief Create child OCC objects.
97          *
98          *  @param[in] occ - the occ name, such as occ0.
99          */
100         void createObjects(const std::string& occ)
101         {
102             auto path = fs::path(OCC_CONTROL_ROOT) / occ;
103 
104             passThroughObjects.emplace_back(
105                 std::make_unique<PassThrough>(
106                     bus,
107                     path.c_str()));
108 
109             statusObjects.emplace_back(
110                 std::make_unique<Status>(
111                     bus,
112                     event,
113                     path.c_str()));
114 
115             // Create the power cap monitor object for master occ (0)
116             if (!pcap)
117             {
118                 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
119                                                         bus,
120                                                         *statusObjects.front());
121             }
122         }
123 
124         /** @brief reference to the bus */
125         sdbusplus::bus::bus& bus;
126 
127         /** @brief reference to sd_event wrapped in unique_ptr */
128         EventPtr& event;
129 
130         /** @brief OCC pass-through objects */
131         std::vector<std::unique_ptr<PassThrough>> passThroughObjects;
132 
133         /** @brief OCC Status objects */
134         std::vector<std::unique_ptr<Status>> statusObjects;
135 
136         /** @brief Power cap monitor and occ notification object */
137         std::unique_ptr<open_power::occ::powercap::PowerCap> pcap;
138 
139         /** @brief sbdbusplus match objects */
140         std::vector<sdbusplus::bus::match_t> cpuMatches;
141 };
142 
143 } // namespace occ
144 } // namespace open_power
145