Remove all signals when an event is removed
Each event could have multiple signals associated and when the event is
removed, all of those signals should also be removed. This ensures no
dangling signals remain after an event is removed from be processed by
fan control
Tested:
The total number of signals subscribed are reduced by the same
number of signals of a removed event
Change-Id: I651f70dbe6aed9c7eef06aff4eac9eae7ad89d77
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/zone.cpp b/control/zone.cpp
index 17ec5fc..d37701e 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -353,48 +353,64 @@
void Zone::removeEvent(const SetSpeedEvent& event)
{
- // Find the signal event to be removed
- auto it = std::find_if(
- _signalEvents.begin(),
- _signalEvents.end(),
- [&event](auto const& se)
- {
- auto seEventData = *std::get<signalEventDataPos>(se);
- if (std::get<eventActionsPos>(seEventData).size() !=
- std::get<actionsPos>(event).size())
- {
- return false;
- }
- else
- {
- // TODO openbmc/openbmc#2328 - Use the action function target
- // for comparison
- auto actsEqual = [](auto const& a1,
- auto const& a2)
- {
- return a1.target_type().name() ==
- a2.target_type().name();
- };
- return
- (
- std::get<eventGroupPos>(seEventData) ==
- std::get<groupPos>(event) &&
- std::equal(std::get<actionsPos>(event).begin(),
- std::get<actionsPos>(event).end(),
- std::get<eventActionsPos>(seEventData).begin(),
- actsEqual)
- );
- }
- });
- if (it != std::end(_signalEvents))
+ // Remove signals of the event
+ for (auto& sig : std::get<signalsPos>(event))
{
- std::get<signalEventDataPos>(*it).reset();
- if (std::get<signalMatchPos>(*it) != nullptr)
+ auto it = findSignal(sig,
+ std::get<groupPos>(event),
+ std::get<actionsPos>(event));
+ if (it != std::end(getSignalEvents()))
{
- std::get<signalMatchPos>(*it).reset();
+ removeSignal(it);
}
- _signalEvents.erase(it);
}
+ // Remove timers of the event
+ if (std::get<intervalPos>(std::get<timerPos>(event)) != seconds(0))
+ {
+ auto it = findTimer(std::get<groupPos>(event),
+ std::get<actionsPos>(event));
+ if (it != std::end(getTimerEvents()))
+ {
+ removeTimer(it);
+ }
+ }
+}
+
+std::vector<SignalEvent>::iterator Zone::findSignal(
+ const Signal& signal,
+ const Group& eGroup,
+ const std::vector<Action>& eActions)
+{
+ // Find the signal in the event to be removed
+ for (auto it = _signalEvents.begin(); it != _signalEvents.end(); ++ it)
+ {
+ const auto& seEventData = *std::get<signalEventDataPos>(*it);
+ if (eGroup == std::get<eventGroupPos>(seEventData) &&
+ std::get<sigMatchPos>(signal) ==
+ std::get<eventMatchPos>(seEventData) &&
+ std::get<sigHandlerPos>(signal).target_type().name() ==
+ std::get<eventHandlerPos>(seEventData).target_type().name() &&
+ eActions.size() == std::get<eventActionsPos>(seEventData).size())
+ {
+ // TODO openbmc/openbmc#2328 - Use the function target
+ // for comparison
+ auto actsEqual = [](auto const& a1,
+ auto const& a2)
+ {
+ return a1.target_type().name() ==
+ a2.target_type().name();
+ };
+ if (std::equal(eActions.begin(),
+ eActions.end(),
+ std::get<eventActionsPos>(seEventData).begin(),
+ actsEqual))
+ {
+ return it;
+ }
+ }
+ }
+
+ return _signalEvents.end();
}
std::vector<TimerEvent>::iterator Zone::findTimer(
diff --git a/control/zone.hpp b/control/zone.hpp
index 002feb4..11cfc65 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -343,6 +343,46 @@
}
/**
+ * @brief Get the list of signal events
+ *
+ * @return - List of signal events
+ */
+ inline auto& getSignalEvents()
+ {
+ return _signalEvents;
+ }
+
+ /**
+ * @brief Find the first instance of a signal event
+ *
+ * @param[in] signal - Event signal to find
+ * @param[in] eGroup - Group associated with the signal
+ * @param[in] eActions - List of actions associated with the signal
+ *
+ * @return - Iterator to the stored signal event
+ */
+ std::vector<SignalEvent>::iterator findSignal(
+ const Signal& signal,
+ const Group& eGroup,
+ const std::vector<Action>& eActions);
+
+ /**
+ * @brief Remove the given signal event
+ *
+ * @param[in] seIter - Iterator pointing to the signal event to remove
+ */
+ inline void removeSignal(std::vector<SignalEvent>::iterator& seIter)
+ {
+ assert(seIter != std::end(_signalEvents));
+ std::get<signalEventDataPos>(*seIter).reset();
+ if (std::get<signalMatchPos>(*seIter) != nullptr)
+ {
+ std::get<signalMatchPos>(*seIter).reset();
+ }
+ _signalEvents.erase(seIter);
+ }
+
+ /**
* @brief Get the list of timer events
*
* @return - List of timer events