17f88fe61SMatt Spinler /**
27f88fe61SMatt Spinler  * Copyright © 2017 IBM Corporation
37f88fe61SMatt Spinler  *
47f88fe61SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
57f88fe61SMatt Spinler  * you may not use this file except in compliance with the License.
67f88fe61SMatt Spinler  * You may obtain a copy of the License at
77f88fe61SMatt Spinler  *
87f88fe61SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
97f88fe61SMatt Spinler  *
107f88fe61SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
117f88fe61SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
127f88fe61SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137f88fe61SMatt Spinler  * See the License for the specific language governing permissions and
147f88fe61SMatt Spinler  * limitations under the License.
157f88fe61SMatt Spinler  */
168600d9a0SMatthew Barth #include <chrono>
17618027abSDinesh Chinari #include <phosphor-logging/log.hpp>
18df3e8d67SMatthew Barth #include <phosphor-logging/elog.hpp>
19618027abSDinesh Chinari #include <phosphor-logging/elog-errors.hpp>
20618027abSDinesh Chinari #include <xyz/openbmc_project/Common/error.hpp>
217f88fe61SMatt Spinler #include "zone.hpp"
22df3e8d67SMatthew Barth #include "utility.hpp"
23d953bb25SMatthew Barth #include "sdbusplus.hpp"
247f88fe61SMatt Spinler 
257f88fe61SMatt Spinler namespace phosphor
267f88fe61SMatt Spinler {
277f88fe61SMatt Spinler namespace fan
287f88fe61SMatt Spinler {
297f88fe61SMatt Spinler namespace control
307f88fe61SMatt Spinler {
317f88fe61SMatt Spinler 
328600d9a0SMatthew Barth using namespace std::chrono;
339014980aSMatthew Barth using namespace phosphor::fan;
34df3e8d67SMatthew Barth using namespace phosphor::logging;
35618027abSDinesh Chinari using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
36618027abSDinesh Chinari                              Error::InternalFailure;
377f88fe61SMatt Spinler 
3814184131SMatthew Barth Zone::Zone(Mode mode,
3914184131SMatthew Barth            sdbusplus::bus::bus& bus,
408600d9a0SMatthew Barth            phosphor::fan::event::EventPtr& events,
417f88fe61SMatt Spinler            const ZoneDefinition& def) :
427f88fe61SMatt Spinler     _bus(bus),
437f88fe61SMatt Spinler     _fullSpeed(std::get<fullSpeedPos>(def)),
441de66629SMatthew Barth     _zoneNum(std::get<zoneNumPos>(def)),
45e0ca13ebSMatthew Barth     _defFloorSpeed(std::get<floorSpeedPos>(def)),
468600d9a0SMatthew Barth     _defCeilingSpeed(std::get<fullSpeedPos>(def)),
47a956184bSMatthew Barth     _incDelay(std::get<incDelayPos>(def)),
48a956184bSMatthew Barth     _decInterval(std::get<decIntervalPos>(def)),
491ee48f2bSMatthew Barth     _incTimer(events, [this](){ this->incTimerExpired(); }),
509014980aSMatthew Barth     _decTimer(events, [this](){ this->decTimerExpired(); }),
519014980aSMatthew Barth     _sdEvents(events)
527f88fe61SMatt Spinler {
537f88fe61SMatt Spinler     auto& fanDefs = std::get<fanListPos>(def);
547f88fe61SMatt Spinler 
557f88fe61SMatt Spinler     for (auto& def : fanDefs)
567f88fe61SMatt Spinler     {
577f88fe61SMatt Spinler         _fans.emplace_back(std::make_unique<Fan>(bus, def));
587f88fe61SMatt Spinler     }
5938a93a8aSMatthew Barth 
6014184131SMatthew Barth     // Do not enable set speed events when in init mode
6114184131SMatthew Barth     if (mode != Mode::init)
6214184131SMatthew Barth     {
632b3db618SMatthew Barth         // Update target speed to current zone target speed
642b3db618SMatthew Barth         if (!_fans.empty())
652b3db618SMatthew Barth         {
662b3db618SMatthew Barth             _targetSpeed = _fans.front()->getTargetSpeed();
672b3db618SMatthew Barth         }
68ccc7770eSMatthew Barth         // Setup signal trigger for set speed events
69ccc7770eSMatthew Barth         for (auto& event : std::get<setSpeedEventsPos>(def))
70ccc7770eSMatthew Barth         {
71ccc7770eSMatthew Barth             initEvent(event);
72ccc7770eSMatthew Barth         }
738600d9a0SMatthew Barth         // Start timer for fan speed decreases
74a956184bSMatthew Barth         if (!_decTimer.running() && _decInterval != seconds::zero())
758600d9a0SMatthew Barth         {
76a956184bSMatthew Barth             _decTimer.start(_decInterval,
77d953bb25SMatthew Barth                             util::Timer::TimerType::repeating);
788600d9a0SMatthew Barth         }
797f88fe61SMatt Spinler     }
8014184131SMatthew Barth }
817f88fe61SMatt Spinler 
827f88fe61SMatt Spinler void Zone::setSpeed(uint64_t speed)
837f88fe61SMatt Spinler {
8460b00766SMatthew Barth     if (_isActive)
8560b00766SMatthew Barth     {
8660b00766SMatthew Barth         _targetSpeed = speed;
877f88fe61SMatt Spinler         for (auto& fan : _fans)
887f88fe61SMatt Spinler         {
8960b00766SMatthew Barth             fan->setSpeed(_targetSpeed);
9060b00766SMatthew Barth         }
9160b00766SMatthew Barth     }
9260b00766SMatthew Barth }
9360b00766SMatthew Barth 
9460b00766SMatthew Barth void Zone::setFullSpeed()
9560b00766SMatthew Barth {
9660b00766SMatthew Barth     if (_fullSpeed != 0)
9760b00766SMatthew Barth     {
9860b00766SMatthew Barth         _targetSpeed = _fullSpeed;
9960b00766SMatthew Barth         for (auto& fan : _fans)
10060b00766SMatthew Barth         {
10160b00766SMatthew Barth             fan->setSpeed(_targetSpeed);
10260b00766SMatthew Barth         }
1037f88fe61SMatt Spinler     }
1047f88fe61SMatt Spinler }
1057f88fe61SMatt Spinler 
106861d77c3SMatthew Barth void Zone::setActiveAllow(const Group* group, bool isActiveAllow)
107861d77c3SMatthew Barth {
10860b00766SMatthew Barth     _active[*(group)] = isActiveAllow;
109861d77c3SMatthew Barth     if (!isActiveAllow)
110861d77c3SMatthew Barth     {
111861d77c3SMatthew Barth         _isActive = false;
112861d77c3SMatthew Barth     }
113861d77c3SMatthew Barth     else
114861d77c3SMatthew Barth     {
115861d77c3SMatthew Barth         // Check all entries are set to allow control active
116861d77c3SMatthew Barth         auto actPred = [](auto const& entry) {return entry.second;};
117861d77c3SMatthew Barth         _isActive = std::all_of(_active.begin(),
118861d77c3SMatthew Barth                                 _active.end(),
119861d77c3SMatthew Barth                                 actPred);
120861d77c3SMatthew Barth     }
121861d77c3SMatthew Barth }
122861d77c3SMatthew Barth 
12355dea643SMatthew Barth void Zone::removeService(const Group* group,
12455dea643SMatthew Barth                          const std::string& name)
12555dea643SMatthew Barth {
12655dea643SMatthew Barth     try
12755dea643SMatthew Barth     {
12855dea643SMatthew Barth         auto& sNames = _services.at(*group);
12955dea643SMatthew Barth         auto it = std::find_if(
13055dea643SMatthew Barth             sNames.begin(),
13155dea643SMatthew Barth             sNames.end(),
13255dea643SMatthew Barth             [&name](auto const& entry)
13355dea643SMatthew Barth             {
13455dea643SMatthew Barth                 return name == std::get<namePos>(entry);
13555dea643SMatthew Barth             }
13655dea643SMatthew Barth         );
13755dea643SMatthew Barth         if (it != std::end(sNames))
13855dea643SMatthew Barth         {
13955dea643SMatthew Barth             // Remove service name from group
14055dea643SMatthew Barth             sNames.erase(it);
14155dea643SMatthew Barth         }
14255dea643SMatthew Barth     }
14355dea643SMatthew Barth     catch (const std::out_of_range& oore)
14455dea643SMatthew Barth     {
14555dea643SMatthew Barth         // No services for group found
14655dea643SMatthew Barth     }
14755dea643SMatthew Barth }
14855dea643SMatthew Barth 
149e59fdf70SMatthew Barth void Zone::setServiceOwner(const Group* group,
150e59fdf70SMatthew Barth                            const std::string& name,
151e59fdf70SMatthew Barth                            const bool hasOwner)
152e59fdf70SMatthew Barth {
153e59fdf70SMatthew Barth     try
154e59fdf70SMatthew Barth     {
155e59fdf70SMatthew Barth         auto& sNames = _services.at(*group);
156e59fdf70SMatthew Barth         auto it = std::find_if(
157e59fdf70SMatthew Barth             sNames.begin(),
158e59fdf70SMatthew Barth             sNames.end(),
159e59fdf70SMatthew Barth             [&name](auto const& entry)
160e59fdf70SMatthew Barth             {
161e59fdf70SMatthew Barth                 return name == std::get<namePos>(entry);
162e59fdf70SMatthew Barth             }
163e59fdf70SMatthew Barth         );
164e59fdf70SMatthew Barth         if (it != std::end(sNames))
165e59fdf70SMatthew Barth         {
166e59fdf70SMatthew Barth             std::get<hasOwnerPos>(*it) = hasOwner;
167e59fdf70SMatthew Barth         }
168e59fdf70SMatthew Barth         else
169e59fdf70SMatthew Barth         {
170e59fdf70SMatthew Barth             _services[*group].emplace_back(name, hasOwner);
171e59fdf70SMatthew Barth         }
172e59fdf70SMatthew Barth     }
173e59fdf70SMatthew Barth     catch (const std::out_of_range& oore)
174e59fdf70SMatthew Barth     {
175e59fdf70SMatthew Barth         _services[*group].emplace_back(name, hasOwner);
176e59fdf70SMatthew Barth     }
177e59fdf70SMatthew Barth }
178e59fdf70SMatthew Barth 
179480787c1SMatthew Barth void Zone::setServices(const Group* group)
180480787c1SMatthew Barth {
18155dea643SMatthew Barth     // Remove the empty service name if exists
18255dea643SMatthew Barth     removeService(group, "");
183480787c1SMatthew Barth     for (auto it = group->begin(); it != group->end(); ++it)
184480787c1SMatthew Barth     {
185480787c1SMatthew Barth         std::string name;
186480787c1SMatthew Barth         bool hasOwner = false;
187480787c1SMatthew Barth         try
188480787c1SMatthew Barth         {
189480787c1SMatthew Barth             name = util::SDBusPlus::getService(
190480787c1SMatthew Barth                     _bus,
191480787c1SMatthew Barth                     it->first,
192480787c1SMatthew Barth                     std::get<intfPos>(it->second));
193480787c1SMatthew Barth             hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
194480787c1SMatthew Barth                     _bus,
195480787c1SMatthew Barth                     "org.freedesktop.DBus",
196480787c1SMatthew Barth                     "/org/freedesktop/DBus",
197480787c1SMatthew Barth                     "org.freedesktop.DBus",
198480787c1SMatthew Barth                     "NameHasOwner",
199480787c1SMatthew Barth                     name);
200480787c1SMatthew Barth         }
201480787c1SMatthew Barth         catch (const InternalFailure& ife)
202480787c1SMatthew Barth         {
203480787c1SMatthew Barth             // Failed to get service name owner state
204480787c1SMatthew Barth             hasOwner = false;
205480787c1SMatthew Barth         }
206480787c1SMatthew Barth         setServiceOwner(group, name, hasOwner);
207480787c1SMatthew Barth     }
208480787c1SMatthew Barth }
209480787c1SMatthew Barth 
210b4a7cb99SMatthew Barth void Zone::setFloor(uint64_t speed)
211b4a7cb99SMatthew Barth {
21298726c45SMatthew Barth     // Check all entries are set to allow floor to be set
21398726c45SMatthew Barth     auto pred = [](auto const& entry) {return entry.second;};
21498726c45SMatthew Barth     auto setFloor = std::all_of(_floorChange.begin(),
21598726c45SMatthew Barth                                 _floorChange.end(),
21698726c45SMatthew Barth                                 pred);
21798726c45SMatthew Barth     if (setFloor)
21898726c45SMatthew Barth     {
219b4a7cb99SMatthew Barth         _floorSpeed = speed;
220b4a7cb99SMatthew Barth         // Floor speed above target, update target to floor speed
221b4a7cb99SMatthew Barth         if (_targetSpeed < _floorSpeed)
222b4a7cb99SMatthew Barth         {
223b4a7cb99SMatthew Barth             requestSpeedIncrease(_floorSpeed - _targetSpeed);
224b4a7cb99SMatthew Barth         }
225b4a7cb99SMatthew Barth     }
22698726c45SMatthew Barth }
227b4a7cb99SMatthew Barth 
228240397b9SMatthew Barth void Zone::requestSpeedIncrease(uint64_t targetDelta)
229240397b9SMatthew Barth {
230240397b9SMatthew Barth     // Only increase speed when delta is higher than
231240397b9SMatthew Barth     // the current increase delta for the zone and currently under ceiling
232240397b9SMatthew Barth     if (targetDelta > _incSpeedDelta &&
233240397b9SMatthew Barth         _targetSpeed < _ceilingSpeed)
234240397b9SMatthew Barth     {
2354e728542SMatthew Barth         auto requestTarget = getRequestSpeedBase();
23660b00766SMatthew Barth         requestTarget = (targetDelta - _incSpeedDelta) + requestTarget;
237240397b9SMatthew Barth         _incSpeedDelta = targetDelta;
238240397b9SMatthew Barth         // Target speed can not go above a defined ceiling speed
23960b00766SMatthew Barth         if (requestTarget > _ceilingSpeed)
240240397b9SMatthew Barth         {
24160b00766SMatthew Barth             requestTarget = _ceilingSpeed;
242240397b9SMatthew Barth         }
2431ee48f2bSMatthew Barth         // Cancel current timer countdown
2441ee48f2bSMatthew Barth         if (_incTimer.running())
2451ee48f2bSMatthew Barth         {
2461ee48f2bSMatthew Barth             _incTimer.stop();
247240397b9SMatthew Barth         }
24860b00766SMatthew Barth         setSpeed(requestTarget);
2491ee48f2bSMatthew Barth         // Start timer countdown for fan speed increase
250a956184bSMatthew Barth         _incTimer.start(_incDelay,
251d953bb25SMatthew Barth                         util::Timer::TimerType::oneshot);
2521ee48f2bSMatthew Barth     }
2531ee48f2bSMatthew Barth }
2541ee48f2bSMatthew Barth 
2551ee48f2bSMatthew Barth void Zone::incTimerExpired()
2561ee48f2bSMatthew Barth {
2571ee48f2bSMatthew Barth     // Clear increase delta when timer expires allowing additional speed
2581ee48f2bSMatthew Barth     // increase requests or speed decreases to occur
259240397b9SMatthew Barth     _incSpeedDelta = 0;
260240397b9SMatthew Barth }
261240397b9SMatthew Barth 
2620ce99d8bSMatthew Barth void Zone::requestSpeedDecrease(uint64_t targetDelta)
2630ce99d8bSMatthew Barth {
2640ce99d8bSMatthew Barth     // Only decrease the lowest target delta requested
2650ce99d8bSMatthew Barth     if (_decSpeedDelta == 0 || targetDelta < _decSpeedDelta)
2660ce99d8bSMatthew Barth     {
2670ce99d8bSMatthew Barth         _decSpeedDelta = targetDelta;
2680ce99d8bSMatthew Barth     }
2698600d9a0SMatthew Barth }
2700ce99d8bSMatthew Barth 
2718600d9a0SMatthew Barth void Zone::decTimerExpired()
2728600d9a0SMatthew Barth {
273*e4338cdbSMatthew Barth     // Check all entries are set to allow a decrease
274*e4338cdbSMatthew Barth     auto pred = [](auto const& entry) {return entry.second;};
275*e4338cdbSMatthew Barth     auto decAllowed = std::all_of(_decAllowed.begin(),
276*e4338cdbSMatthew Barth                                   _decAllowed.end(),
277*e4338cdbSMatthew Barth                                   pred);
278*e4338cdbSMatthew Barth 
279*e4338cdbSMatthew Barth     // Only decrease speeds when allowed,
280*e4338cdbSMatthew Barth     // where no requested increases exist and
281*e4338cdbSMatthew Barth     // the increase timer is not running
282*e4338cdbSMatthew Barth     // (i.e. not in the middle of increasing)
283*e4338cdbSMatthew Barth     if (decAllowed && _incSpeedDelta == 0 && !_incTimer.running())
2840ce99d8bSMatthew Barth     {
2854e728542SMatthew Barth         auto requestTarget = getRequestSpeedBase();
286c63973a1SMatthew Barth         // Request target speed should not start above ceiling
287c63973a1SMatthew Barth         if (requestTarget > _ceilingSpeed)
288c63973a1SMatthew Barth         {
289c63973a1SMatthew Barth             requestTarget = _ceilingSpeed;
290c63973a1SMatthew Barth         }
2910ce99d8bSMatthew Barth         // Target speed can not go below the defined floor speed
29260b00766SMatthew Barth         if ((requestTarget < _decSpeedDelta) ||
29360b00766SMatthew Barth             (requestTarget - _decSpeedDelta < _floorSpeed))
2940ce99d8bSMatthew Barth         {
29560b00766SMatthew Barth             requestTarget = _floorSpeed;
2960ce99d8bSMatthew Barth         }
2970ce99d8bSMatthew Barth         else
2980ce99d8bSMatthew Barth         {
29960b00766SMatthew Barth             requestTarget = requestTarget - _decSpeedDelta;
3000ce99d8bSMatthew Barth         }
30160b00766SMatthew Barth         setSpeed(requestTarget);
3020ce99d8bSMatthew Barth     }
3030ce99d8bSMatthew Barth     // Clear decrease delta when timer expires
3040ce99d8bSMatthew Barth     _decSpeedDelta = 0;
3058600d9a0SMatthew Barth     // Decrease timer is restarted since its repeating
3060ce99d8bSMatthew Barth }
3070ce99d8bSMatthew Barth 
308ccc7770eSMatthew Barth void Zone::initEvent(const SetSpeedEvent& event)
3091bf0ce4bSMatthew Barth {
310336f18a5SMatthew Barth     sdbusplus::message::message nullMsg{nullptr};
311336f18a5SMatthew Barth 
31267967f9aSMatthew Barth     for (auto& sig : std::get<signalsPos>(event))
3131bf0ce4bSMatthew Barth     {
314336f18a5SMatthew Barth         // Initialize the event signal using handler
315336f18a5SMatthew Barth         std::get<sigHandlerPos>(sig)(_bus, nullMsg, *this);
316336f18a5SMatthew Barth         // Setup signal matches of the property for event
317f6b76d8eSMatthew Barth         std::unique_ptr<EventData> eventData =
3181bf0ce4bSMatthew Barth             std::make_unique<EventData>(
3191bf0ce4bSMatthew Barth                     std::get<groupPos>(event),
320336f18a5SMatthew Barth                     std::get<sigMatchPos>(sig),
321336f18a5SMatthew Barth                     std::get<sigHandlerPos>(sig),
322f9201abbSMatthew Barth                     std::get<actionsPos>(event)
323f6b76d8eSMatthew Barth             );
324336f18a5SMatthew Barth         std::unique_ptr<sdbusplus::server::match::match> match = nullptr;
325336f18a5SMatthew Barth         if (!std::get<sigMatchPos>(sig).empty())
326336f18a5SMatthew Barth         {
327336f18a5SMatthew Barth             match = std::make_unique<sdbusplus::server::match::match>(
3281bf0ce4bSMatthew Barth                     _bus,
329336f18a5SMatthew Barth                     std::get<sigMatchPos>(sig).c_str(),
3301bf0ce4bSMatthew Barth                     std::bind(std::mem_fn(&Zone::handleEvent),
3311bf0ce4bSMatthew Barth                               this,
3321bf0ce4bSMatthew Barth                               std::placeholders::_1,
333f6b76d8eSMatthew Barth                               eventData.get())
334f6b76d8eSMatthew Barth                 );
335336f18a5SMatthew Barth         }
336f6b76d8eSMatthew Barth         _signalEvents.emplace_back(std::move(eventData), std::move(match));
3371bf0ce4bSMatthew Barth     }
3389014980aSMatthew Barth     // Attach a timer to run the action of an event
3399014980aSMatthew Barth     auto eventTimer = std::get<timerPos>(event);
3409014980aSMatthew Barth     if (std::get<intervalPos>(eventTimer) != seconds(0))
3419014980aSMatthew Barth     {
342bfb1a566SMatthew Barth         // Associate event data with timer
343bfb1a566SMatthew Barth         std::unique_ptr<EventData> eventData =
344bfb1a566SMatthew Barth             std::make_unique<EventData>(
345bfb1a566SMatthew Barth                     std::get<groupPos>(event),
346bfb1a566SMatthew Barth                     "",
347bfb1a566SMatthew Barth                     nullptr,
348bfb1a566SMatthew Barth                     std::get<actionsPos>(event)
349bfb1a566SMatthew Barth             );
3509014980aSMatthew Barth         std::unique_ptr<util::Timer> timer =
3519014980aSMatthew Barth             std::make_unique<util::Timer>(
3529014980aSMatthew Barth                 _sdEvents,
3539014980aSMatthew Barth                 [this,
354f9201abbSMatthew Barth                  action = &(std::get<actionsPos>(event)),
3559014980aSMatthew Barth                  group = &(std::get<groupPos>(event))]()
3569014980aSMatthew Barth                  {
3579014980aSMatthew Barth                      this->timerExpired(*group, *action);
3589014980aSMatthew Barth                  });
3599014980aSMatthew Barth         if (!timer->running())
3609014980aSMatthew Barth         {
3619014980aSMatthew Barth             timer->start(std::get<intervalPos>(eventTimer),
3627b7ceb8dSMatthew Barth                          std::get<typePos>(eventTimer));
3639014980aSMatthew Barth         }
364bfb1a566SMatthew Barth         addTimer(std::move(eventData), std::move(timer));
3659014980aSMatthew Barth     }
366f9201abbSMatthew Barth     // Run action functions for initial event state
367f9201abbSMatthew Barth     std::for_each(
368f9201abbSMatthew Barth         std::get<actionsPos>(event).begin(),
369f9201abbSMatthew Barth         std::get<actionsPos>(event).end(),
370f9201abbSMatthew Barth         [this, &event](auto const& action)
371f9201abbSMatthew Barth         {
372f9201abbSMatthew Barth             action(*this,
3731bf0ce4bSMatthew Barth                    std::get<groupPos>(event));
374f9201abbSMatthew Barth         });
3751bf0ce4bSMatthew Barth }
3761bf0ce4bSMatthew Barth 
377f6b76d8eSMatthew Barth void Zone::removeEvent(const SetSpeedEvent& event)
378f6b76d8eSMatthew Barth {
379f6b76d8eSMatthew Barth     // Find the signal event to be removed
380f6b76d8eSMatthew Barth     auto it = std::find_if(
381f6b76d8eSMatthew Barth         _signalEvents.begin(),
382f6b76d8eSMatthew Barth         _signalEvents.end(),
383f6b76d8eSMatthew Barth         [&event](auto const& se)
384f6b76d8eSMatthew Barth         {
385f6b76d8eSMatthew Barth             auto seEventData = *std::get<signalEventDataPos>(se);
386f9201abbSMatthew Barth             if (std::get<eventActionsPos>(seEventData).size() !=
387f9201abbSMatthew Barth                 std::get<actionsPos>(event).size())
388f9201abbSMatthew Barth             {
389f9201abbSMatthew Barth                 return false;
390f9201abbSMatthew Barth             }
391f9201abbSMatthew Barth             else
392f9201abbSMatthew Barth             {
393f9201abbSMatthew Barth                 // TODO openbmc/openbmc#2328 - Use the action function target
394f9201abbSMatthew Barth                 // for comparison
395f9201abbSMatthew Barth                 auto actsEqual = [](auto const& a1,
396f9201abbSMatthew Barth                                     auto const& a2)
397f9201abbSMatthew Barth                         {
398f9201abbSMatthew Barth                             return a1.target_type().name() ==
399f9201abbSMatthew Barth                                    a2.target_type().name();
400f9201abbSMatthew Barth                         };
401f6b76d8eSMatthew Barth                 return
402f6b76d8eSMatthew Barth                 (
403f6b76d8eSMatthew Barth                     std::get<eventGroupPos>(seEventData) ==
404f6b76d8eSMatthew Barth                         std::get<groupPos>(event) &&
405f9201abbSMatthew Barth                     std::equal(std::get<actionsPos>(event).begin(),
406f9201abbSMatthew Barth                                std::get<actionsPos>(event).end(),
407f9201abbSMatthew Barth                                std::get<eventActionsPos>(seEventData).begin(),
408f9201abbSMatthew Barth                                actsEqual)
409f6b76d8eSMatthew Barth                 );
410f9201abbSMatthew Barth             }
411f6b76d8eSMatthew Barth         });
412f6b76d8eSMatthew Barth     if (it != std::end(_signalEvents))
413f6b76d8eSMatthew Barth     {
414f6b76d8eSMatthew Barth         std::get<signalEventDataPos>(*it).reset();
415336f18a5SMatthew Barth         if (std::get<signalMatchPos>(*it) != nullptr)
416336f18a5SMatthew Barth         {
417f6b76d8eSMatthew Barth             std::get<signalMatchPos>(*it).reset();
418336f18a5SMatthew Barth         }
419f6b76d8eSMatthew Barth         _signalEvents.erase(it);
420f6b76d8eSMatthew Barth     }
421f6b76d8eSMatthew Barth }
422f6b76d8eSMatthew Barth 
423bfb1a566SMatthew Barth std::vector<TimerEvent>::iterator Zone::findTimer(
424bfb1a566SMatthew Barth         const Group& eventGroup,
425bfb1a566SMatthew Barth         const std::vector<Action>& eventActions)
426bfb1a566SMatthew Barth {
427bfb1a566SMatthew Barth     for (auto it = _timerEvents.begin(); it != _timerEvents.end(); ++it)
428bfb1a566SMatthew Barth     {
429bfb1a566SMatthew Barth         auto teEventData = *std::get<timerEventDataPos>(*it);
430bfb1a566SMatthew Barth         if (std::get<eventActionsPos>(teEventData).size() ==
431bfb1a566SMatthew Barth             eventActions.size())
432bfb1a566SMatthew Barth         {
433bfb1a566SMatthew Barth             // TODO openbmc/openbmc#2328 - Use the action function target
434bfb1a566SMatthew Barth             // for comparison
435bfb1a566SMatthew Barth             auto actsEqual = [](auto const& a1,
436bfb1a566SMatthew Barth                                 auto const& a2)
437bfb1a566SMatthew Barth                     {
438bfb1a566SMatthew Barth                         return a1.target_type().name() ==
439bfb1a566SMatthew Barth                                a2.target_type().name();
440bfb1a566SMatthew Barth                     };
441bfb1a566SMatthew Barth             if (std::get<eventGroupPos>(teEventData) == eventGroup &&
442bfb1a566SMatthew Barth                 std::equal(eventActions.begin(),
443bfb1a566SMatthew Barth                            eventActions.end(),
444bfb1a566SMatthew Barth                            std::get<eventActionsPos>(teEventData).begin(),
445bfb1a566SMatthew Barth                            actsEqual))
446bfb1a566SMatthew Barth             {
447bfb1a566SMatthew Barth                 return it;
448bfb1a566SMatthew Barth             }
449bfb1a566SMatthew Barth         }
450bfb1a566SMatthew Barth     }
451bfb1a566SMatthew Barth 
452bfb1a566SMatthew Barth     return _timerEvents.end();
453bfb1a566SMatthew Barth }
454bfb1a566SMatthew Barth 
455f9201abbSMatthew Barth void Zone::timerExpired(Group eventGroup, std::vector<Action> eventActions)
4569014980aSMatthew Barth {
457f9201abbSMatthew Barth     // Perform the actions
458f9201abbSMatthew Barth     std::for_each(eventActions.begin(),
459f9201abbSMatthew Barth                   eventActions.end(),
460f9201abbSMatthew Barth                   [this, &eventGroup](auto const& action)
461f9201abbSMatthew Barth                   {
462f9201abbSMatthew Barth                       action(*this, eventGroup);
463f9201abbSMatthew Barth                   });
4649014980aSMatthew Barth }
4659014980aSMatthew Barth 
46638a93a8aSMatthew Barth void Zone::handleEvent(sdbusplus::message::message& msg,
46734f1bda2SMatthew Barth                        const EventData* eventData)
46838a93a8aSMatthew Barth {
46938a93a8aSMatthew Barth     // Handle the callback
47034f1bda2SMatthew Barth     std::get<eventHandlerPos>(*eventData)(_bus, msg, *this);
471f9201abbSMatthew Barth     // Perform the actions
472f9201abbSMatthew Barth     std::for_each(
473f9201abbSMatthew Barth         std::get<eventActionsPos>(*eventData).begin(),
474f9201abbSMatthew Barth         std::get<eventActionsPos>(*eventData).end(),
475f9201abbSMatthew Barth         [this, &eventData](auto const& action)
476f9201abbSMatthew Barth         {
477f9201abbSMatthew Barth             action(*this,
47834f1bda2SMatthew Barth                    std::get<eventGroupPos>(*eventData));
479f9201abbSMatthew Barth         });
48038a93a8aSMatthew Barth }
48138a93a8aSMatthew Barth 
4827f88fe61SMatt Spinler }
4837f88fe61SMatt Spinler }
4847f88fe61SMatt Spinler }
485