Add/Remove event timers by event name

Using the event name as the key, each timer an event adds to the list of
timers are associated to that event. This allows quick removal of those
timers when the event is removed and more efficient searching for a
timer within the smaller list of timers per event name.

Change-Id: I4624918d3a3bbe2a5224cde4bc3fc529e5b40df3
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/actions.cpp b/control/actions.cpp
index 3c3b194..029a69a 100644
--- a/control/actions.cpp
+++ b/control/actions.cpp
@@ -29,20 +29,30 @@
                 {
                     return !std::get<hasOwnerPos>(s);
                 });
-            if (setTimer &&
-                zone.findTimer(group, actions) ==
-                    std::end(zone.getTimerEvents()))
+            auto it = zone.getTimerEvents().find(__func__);
+            if (it != zone.getTimerEvents().end())
             {
-                zone.addTimer(group, actions, tConf);
-            }
-            else
-            {
-                // Stop and remove any timers for this group
-                auto timer = zone.findTimer(group, actions);
-                if (timer != std::end(zone.getTimerEvents()))
+                auto& timers = it->second;
+                auto timerIter = zone.findTimer(group, actions, timers);
+                if (setTimer && timerIter == timers.end())
                 {
-                    zone.removeTimer(timer);
+                    // No timer exists yet for action, add timer
+                    zone.addTimer(__func__, group, actions, tConf);
                 }
+                else if (!setTimer && timerIter != timers.end())
+                {
+                    // Remove any timer for this group
+                    timers.erase(timerIter);
+                    if (timers.empty())
+                    {
+                        zone.getTimerEvents().erase(it);
+                    }
+                }
+            }
+            else if (setTimer)
+            {
+                // No timer exists yet for event, add timer
+                zone.addTimer(__func__, group, actions, tConf);
             }
         }
         catch (const std::out_of_range& oore)
diff --git a/control/triggers.cpp b/control/triggers.cpp
index 706fdc1..0df2a4a 100644
--- a/control/triggers.cpp
+++ b/control/triggers.cpp
@@ -18,7 +18,8 @@
                                       const Group& group,
                                       const std::vector<Action>& actions)
     {
-        zone.addTimer(group,
+        zone.addTimer(name,
+                      group,
                       actions,
                       tConf);
     };
diff --git a/control/zone.cpp b/control/zone.cpp
index 3077f08..32a297b 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -347,23 +347,24 @@
         _signalEvents.erase(sigIter);
     }
 
-    // Remove timers of the event
-    auto it = findTimer(std::get<groupPos>(event),
-                        std::get<actionsPos>(event));
-    if (it != std::end(getTimerEvents()))
+    // Remove event timers
+    auto timIter = _timerEvents.find(std::get<sseNamePos>(event));
+    if (timIter != _timerEvents.end())
     {
-        removeTimer(it);
+        _timerEvents.erase(timIter);
     }
 }
 
 std::vector<TimerEvent>::iterator Zone::findTimer(
         const Group& eventGroup,
-        const std::vector<Action>& eventActions)
+        const std::vector<Action>& eventActions,
+        std::vector<TimerEvent>& eventTimers)
 {
-    for (auto it = _timerEvents.begin(); it != _timerEvents.end(); ++it)
+    for (auto it = eventTimers.begin(); it != eventTimers.end(); ++it)
     {
         const auto& teEventData = *std::get<timerEventDataPos>(*it);
-        if (std::get<eventActionsPos>(teEventData).size() ==
+        if (std::get<eventGroupPos>(teEventData) == eventGroup &&
+            std::get<eventActionsPos>(teEventData).size() ==
             eventActions.size())
         {
             // TODO openbmc/openbmc#2328 - Use the action function target
@@ -374,8 +375,7 @@
                         return a1.target_type().name() ==
                                a2.target_type().name();
                     };
-            if (std::get<eventGroupPos>(teEventData) == eventGroup &&
-                std::equal(eventActions.begin(),
+            if (std::equal(eventActions.begin(),
                            eventActions.end(),
                            std::get<eventActionsPos>(teEventData).begin(),
                            actsEqual))
@@ -385,10 +385,11 @@
         }
     }
 
-    return _timerEvents.end();
+    return eventTimers.end();
 }
 
-void Zone::addTimer(const Group& group,
+void Zone::addTimer(const std::string& name,
+                    const Group& group,
                     const std::vector<Action>& actions,
                     const TimerConf& tConf)
 {
@@ -416,7 +417,7 @@
     {
         throw std::invalid_argument("Invalid Timer Type");
     }
-    _timerEvents.emplace_back(std::move(eventData), std::move(timer));
+    _timerEvents[name].emplace_back(std::move(eventData), std::move(timer));
 }
 
 void Zone::timerExpired(const Group& eventGroup,
diff --git a/control/zone.hpp b/control/zone.hpp
index e28e02b..e48a981 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -440,35 +440,29 @@
          *
          * @param[in] eventGroup - Group associated with a timer
          * @param[in] eventActions - List of actions associated with a timer
+         * @param[in] eventTimers - List of timers to find the timer in
          *
          * @return - Iterator to the timer event
          */
         std::vector<TimerEvent>::iterator findTimer(
                 const Group& eventGroup,
-                const std::vector<Action>& eventActions);
+                const std::vector<Action>& eventActions,
+                std::vector<TimerEvent>& eventTimers);
 
         /**
          * @brief Add a timer to the list of timer based events
          *
+         * @param[in] name - Event name associated with timer
          * @param[in] group - Group associated with a timer
          * @param[in] actions - List of actions associated with a timer
          * @param[in] tConf - Configuration for the new timer
          */
-        void addTimer(const Group& group,
+        void addTimer(const std::string& name,
+                      const Group& group,
                       const std::vector<Action>& actions,
                       const TimerConf& tConf);
 
         /**
-         * @brief Remove the given timer event
-         *
-         * @param[in] teIter - Iterator pointing to the timer event to remove
-         */
-        inline void removeTimer(std::vector<TimerEvent>::iterator& teIter)
-        {
-            _timerEvents.erase(teIter);
-        }
-
-        /**
          * @brief Callback function for event timers that processes the given
          * actions for a group
          *
@@ -775,9 +769,9 @@
         std::map<std::string, std::vector<SignalEvent>> _signalEvents;
 
         /**
-         * @brief List of timers for events
+         * @brief List of timers per event name
          */
-        std::vector<TimerEvent> _timerEvents;
+        std::map<std::string, std::vector<TimerEvent>> _timerEvents;
 
         /**
          * @brief Save the thermal control current mode property