EventService: Add enable/disable support

Add EventService enable/disable support.
When EventService is enabled
 - Check for no of event log subscribers and then
   only process events async sending.
 - Check for no of metric report subscribers
   and register for metric report signal.
When EventService is disabled
 - Discard the inotify event for redfish logs.
 - Unregister the metric report signal.

Tested:
 - Modified ServieEnabled, DeliveryRetryAttempts,
   DeliveryRetryInterval values using patch and
   it reflects on subsequent gets.
 - Above mentioned functionality tested with Service
   enabled & disabled modifications.
 - Ran redfish validator successfully.

Change-Id: Id049860a89d3040d859ac8907e7bad5b4209b73d
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 2c0f189..b9779b6 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -35,6 +35,7 @@
 
 using ReadingsObjType =
     std::vector<std::tuple<std::string, std::string, double, std::string>>;
+using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>;
 
 static constexpr const char* eventFormatType = "Event";
 static constexpr const char* metricReportFormatType = "MetricReport";
@@ -449,31 +450,33 @@
 class EventServiceManager
 {
   private:
+    bool serviceEnabled;
+    uint32_t retryAttempts;
+    uint32_t retryTimeoutInterval;
+
     EventServiceManager(const EventServiceManager&) = delete;
     EventServiceManager& operator=(const EventServiceManager&) = delete;
     EventServiceManager(EventServiceManager&&) = delete;
     EventServiceManager& operator=(EventServiceManager&&) = delete;
 
-    EventServiceManager() : noOfMetricReportSubscribers(0)
+    EventServiceManager() :
+        noOfEventLogSubscribers(0), noOfMetricReportSubscribers(0)
     {
         // TODO: Read the persistent data from store and populate.
         // Populating with default.
-        enabled = true;
+        serviceEnabled = true;
         retryAttempts = 3;
         retryTimeoutInterval = 30; // seconds
     }
 
     std::string lastEventTStr;
+    size_t noOfEventLogSubscribers;
     size_t noOfMetricReportSubscribers;
     std::shared_ptr<sdbusplus::bus::match::match> matchTelemetryMonitor;
     boost::container::flat_map<std::string, std::shared_ptr<Subscription>>
         subscriptionsMap;
 
   public:
-    bool enabled;
-    uint32_t retryAttempts;
-    uint32_t retryTimeoutInterval;
-
     static EventServiceManager& getInstance()
     {
         static EventServiceManager handler;
@@ -488,6 +491,79 @@
         return;
     }
 
+    EventServiceConfig getEventServiceConfig()
+    {
+        return {serviceEnabled, retryAttempts, retryTimeoutInterval};
+    }
+
+    void setEventServiceConfig(const EventServiceConfig& cfg)
+    {
+        bool updateConfig = false;
+
+        if (serviceEnabled != std::get<0>(cfg))
+        {
+            serviceEnabled = std::get<0>(cfg);
+            if (serviceEnabled && noOfMetricReportSubscribers)
+            {
+                registerMetricReportSignal();
+            }
+            else
+            {
+                unregisterMetricReportSignal();
+            }
+            updateConfig = true;
+        }
+
+        if (retryAttempts != std::get<1>(cfg))
+        {
+            retryAttempts = std::get<1>(cfg);
+            updateConfig = true;
+        }
+
+        if (retryTimeoutInterval != std::get<2>(cfg))
+        {
+            retryTimeoutInterval = std::get<2>(cfg);
+            updateConfig = true;
+        }
+
+        if (updateConfig)
+        {
+            updateSubscriptionData();
+        }
+    }
+
+    void updateNoOfSubscribersCount()
+    {
+        size_t eventLogSubCount = 0;
+        size_t metricReportSubCount = 0;
+        for (const auto& it : subscriptionsMap)
+        {
+            std::shared_ptr<Subscription> entry = it.second;
+            if (entry->eventFormatType == eventFormatType)
+            {
+                eventLogSubCount++;
+            }
+            else if (entry->eventFormatType == metricReportFormatType)
+            {
+                metricReportSubCount++;
+            }
+        }
+
+        noOfEventLogSubscribers = eventLogSubCount;
+        if (noOfMetricReportSubscribers != metricReportSubCount)
+        {
+            noOfMetricReportSubscribers = metricReportSubCount;
+            if (noOfMetricReportSubscribers)
+            {
+                registerMetricReportSignal();
+            }
+            else
+            {
+                unregisterMetricReportSignal();
+            }
+        }
+    }
+
     std::shared_ptr<Subscription> getSubscription(const std::string& id)
     {
         auto obj = subscriptionsMap.find(id);
@@ -523,15 +599,7 @@
             return std::string("");
         }
 
-        if (subValue->eventFormatType == metricReportFormatType)
-        {
-            // If it is first entry,  Register Metrics report signal.
-            if ((++noOfMetricReportSubscribers == 1))
-            {
-                registerMetricReportSignal();
-            }
-        }
-
+        updateNoOfSubscribersCount();
         updateSubscriptionData();
 
 #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
@@ -558,16 +626,8 @@
         auto obj = subscriptionsMap.find(id);
         if (obj != subscriptionsMap.end())
         {
-            std::shared_ptr<Subscription> entry = obj->second;
-            if (entry->eventFormatType == metricReportFormatType)
-            {
-                if ((--noOfMetricReportSubscribers == 0))
-                {
-                    unregisterMetricReportSignal();
-                }
-            }
-
             subscriptionsMap.erase(obj);
+            updateNoOfSubscribersCount();
             updateSubscriptionData();
         }
     }
@@ -636,10 +696,9 @@
 
     void readEventLogsFromFile()
     {
-        if (!getNumberOfSubscriptions())
+        if (!serviceEnabled || !noOfEventLogSubscribers)
         {
-            // no subscriptions. Just return.
-            BMCWEB_LOG_DEBUG << "No Subscriptions\n";
+            BMCWEB_LOG_DEBUG << "EventService disabled or no Subscriptions.";
             return;
         }
         std::ifstream logStream(redfishEventLogFile);
@@ -839,16 +898,19 @@
 
     void unregisterMetricReportSignal()
     {
-        BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister";
-        matchTelemetryMonitor.reset();
-        matchTelemetryMonitor = nullptr;
+        if (matchTelemetryMonitor)
+        {
+            BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister";
+            matchTelemetryMonitor.reset();
+            matchTelemetryMonitor = nullptr;
+        }
     }
 
     void registerMetricReportSignal()
     {
-        if (matchTelemetryMonitor)
+        if (!serviceEnabled || matchTelemetryMonitor)
         {
-            BMCWEB_LOG_DEBUG << "Metrics report signal - Already registered.";
+            BMCWEB_LOG_DEBUG << "Not registering metric report signal.";
             return;
         }
 
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index 63302d6..b88cb43 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -61,13 +61,15 @@
                            "EventService.SubmitTestEvent"}}}}},
             {"@odata.id", "/redfish/v1/EventService"}};
 
-        asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
-        asyncResp->res.jsonValue["ServiceEnabled"] =
-            EventServiceManager::getInstance().enabled;
-        asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
-            EventServiceManager::getInstance().retryAttempts;
+        const auto& [enabled, retryAttempts, retryTimeoutInterval] =
+            EventServiceManager::getInstance().getEventServiceConfig();
+
+        asyncResp->res.jsonValue["Status"]["State"] =
+            (enabled ? "Enabled" : "Disabled");
+        asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
+        asyncResp->res.jsonValue["DeliveryRetryAttempts"] = retryAttempts;
         asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
-            EventServiceManager::getInstance().retryTimeoutInterval;
+            retryTimeoutInterval;
         asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
         asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
     }
@@ -88,9 +90,12 @@
             return;
         }
 
+        auto [enabled, retryCount, retryTimeoutInterval] =
+            EventServiceManager::getInstance().getEventServiceConfig();
+
         if (serviceEnabled)
         {
-            EventServiceManager::getInstance().enabled = *serviceEnabled;
+            enabled = *serviceEnabled;
         }
 
         if (retryAttemps)
@@ -104,8 +109,7 @@
             }
             else
             {
-                EventServiceManager::getInstance().retryAttempts =
-                    *retryAttemps;
+                retryCount = *retryAttemps;
             }
         }
 
@@ -120,12 +124,12 @@
             }
             else
             {
-                EventServiceManager::getInstance().retryTimeoutInterval =
-                    *retryInterval;
+                retryTimeoutInterval = *retryInterval;
             }
         }
 
-        EventServiceManager::getInstance().updateSubscriptionData();
+        EventServiceManager::getInstance().setEventServiceConfig(
+            std::make_tuple(enabled, retryCount, retryTimeoutInterval));
     }
 };