diff --git a/inc/srvcfg_manager.hpp b/inc/srvcfg_manager.hpp
index ea84c53..d0a3ae1 100644
--- a/inc/srvcfg_manager.hpp
+++ b/inc/srvcfg_manager.hpp
@@ -1,113 +1,113 @@
-/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-*/
-#pragma once
-#include "utils.hpp"
-
-#include <sdbusplus/timer.hpp>
-
-namespace phosphor
-{
-namespace service
-{
-
-static constexpr const char* serviceConfigSrvName =
-    "xyz.openbmc_project.Control.Service.Manager";
-static constexpr const char* serviceConfigIntfName =
-    "xyz.openbmc_project.Control.Service.Attributes";
-static constexpr const char* sockAttrIntfName =
-    "xyz.openbmc_project.Control.Service.SocketAttributes";
-static constexpr const char* srcCfgMgrBasePath =
-    "/xyz/openbmc_project/control/service";
-static constexpr const char* srcCfgMgrIntf =
-    "/xyz/openbmc_project.Control.Service.Manager";
-static constexpr const char* sockAttrPropPort = "Port";
-static constexpr const char* srvCfgPropMasked = "Masked";
-static constexpr const char* srvCfgPropEnabled = "Enabled";
-static constexpr const char* srvCfgPropRunning = "Running";
-
-enum class UpdatedProp
-{
-    port = 1,
-    maskedState,
-    enabledState,
-    runningState
-};
-
-using VariantType =
-    std::variant<std::string, int64_t, uint64_t, double, int32_t, uint32_t,
-                 int16_t, uint16_t, uint8_t, bool,
-                 std::vector<std::tuple<std::string, std::string>>>;
-
-class ServiceConfig
-{
-  public:
-    ServiceConfig(sdbusplus::asio::object_server& srv_,
-                  std::shared_ptr<sdbusplus::asio::connection>& conn_,
-                  const std::string& objPath_, const std::string& baseUnitName,
-                  const std::string& instanceName,
-                  const std::string& serviceObjPath,
-                  const std::string& socketObjPath);
-    ~ServiceConfig() = default;
-
-    std::shared_ptr<sdbusplus::asio::connection> conn;
-    uint8_t updatedFlag;
-
-    void stopAndApplyUnitConfig(boost::asio::yield_context yield);
-    void restartUnitConfig(boost::asio::yield_context yield);
-    void startServiceRestartTimer();
-
-  private:
-    sdbusplus::asio::object_server& server;
-    std::shared_ptr<sdbusplus::asio::dbus_interface> srvCfgIface;
-    std::shared_ptr<sdbusplus::asio::dbus_interface> sockAttrIface;
-
-    bool internalSet = false;
-    std::string objPath;
-    std::string baseUnitName;
-    std::string instanceName;
-    std::string instantiatedUnitName;
-    std::string serviceObjectPath;
-    std::string socketObjectPath;
-    std::string overrideConfDir;
-
-    // Properties
-    std::string activeState;
-    std::string subState;
-    uint16_t portNum;
-    std::vector<std::string> channelList;
-    std::string protocol;
-    std::string stateValue;
-    bool unitMaskedState = false;
-    bool unitEnabledState = false;
-    bool unitRunningState = false;
-    std::string subStateValue;
-
-    bool isMaskedOut();
-    void registerProperties();
-    void queryAndUpdateProperties();
-    void createSocketOverrideConf();
-    void updateServiceProperties(
-        const boost::container::flat_map<std::string, VariantType>&
-            propertyMap);
-    void updateSocketProperties(
-        const boost::container::flat_map<std::string, VariantType>&
-            propertyMap);
-    std::string getSocketUnitName();
-    std::string getServiceUnitName();
-};
-
-} // namespace service
-} // namespace phosphor
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+#include "utils.hpp"
+
+#include <sdbusplus/timer.hpp>
+
+namespace phosphor
+{
+namespace service
+{
+
+static constexpr const char* serviceConfigSrvName =
+    "xyz.openbmc_project.Control.Service.Manager";
+static constexpr const char* serviceConfigIntfName =
+    "xyz.openbmc_project.Control.Service.Attributes";
+static constexpr const char* sockAttrIntfName =
+    "xyz.openbmc_project.Control.Service.SocketAttributes";
+static constexpr const char* srcCfgMgrBasePath =
+    "/xyz/openbmc_project/control/service";
+static constexpr const char* srcCfgMgrIntf =
+    "/xyz/openbmc_project.Control.Service.Manager";
+static constexpr const char* sockAttrPropPort = "Port";
+static constexpr const char* srvCfgPropMasked = "Masked";
+static constexpr const char* srvCfgPropEnabled = "Enabled";
+static constexpr const char* srvCfgPropRunning = "Running";
+
+enum class UpdatedProp
+{
+    port = 1,
+    maskedState,
+    enabledState,
+    runningState
+};
+
+using VariantType =
+    std::variant<std::string, int64_t, uint64_t, double, int32_t, uint32_t,
+                 int16_t, uint16_t, uint8_t, bool,
+                 std::vector<std::tuple<std::string, std::string>>>;
+
+class ServiceConfig
+{
+  public:
+    ServiceConfig(sdbusplus::asio::object_server& srv_,
+                  std::shared_ptr<sdbusplus::asio::connection>& conn_,
+                  const std::string& objPath_, const std::string& baseUnitName,
+                  const std::string& instanceName,
+                  const std::string& serviceObjPath,
+                  const std::string& socketObjPath);
+    ~ServiceConfig() = default;
+
+    std::shared_ptr<sdbusplus::asio::connection> conn;
+    uint8_t updatedFlag;
+
+    void stopAndApplyUnitConfig(boost::asio::yield_context yield);
+    void restartUnitConfig(boost::asio::yield_context yield);
+    void startServiceRestartTimer();
+
+  private:
+    sdbusplus::asio::object_server& server;
+    std::shared_ptr<sdbusplus::asio::dbus_interface> srvCfgIface;
+    std::shared_ptr<sdbusplus::asio::dbus_interface> sockAttrIface;
+
+    bool internalSet = false;
+    std::string objPath;
+    std::string baseUnitName;
+    std::string instanceName;
+    std::string instantiatedUnitName;
+    std::string serviceObjectPath;
+    std::string socketObjectPath;
+    std::string overrideConfDir;
+
+    // Properties
+    std::string activeState;
+    std::string subState;
+    uint16_t portNum;
+    std::vector<std::string> channelList;
+    std::string protocol;
+    std::string stateValue;
+    bool unitMaskedState = false;
+    bool unitEnabledState = false;
+    bool unitRunningState = false;
+    std::string subStateValue;
+
+    bool isMaskedOut();
+    void registerProperties();
+    void queryAndUpdateProperties();
+    void createSocketOverrideConf();
+    void updateServiceProperties(
+        const boost::container::flat_map<std::string, VariantType>&
+            propertyMap);
+    void updateSocketProperties(
+        const boost::container::flat_map<std::string, VariantType>&
+            propertyMap);
+    std::string getSocketUnitName();
+    std::string getServiceUnitName();
+};
+
+} // namespace service
+} // namespace phosphor
diff --git a/inc/utils.hpp b/inc/utils.hpp
index e4a31bb..c9df6ae 100644
--- a/inc/utils.hpp
+++ b/inc/utils.hpp
@@ -1,64 +1,64 @@
-/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-*/
-#pragma once
-#include <boost/asio.hpp>
-#include <phosphor-logging/elog-errors.hpp>
-#include <sdbusplus/asio/object_server.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-
-#include <chrono>
-#include <ctime>
-#include <filesystem>
-#include <string>
-
-static constexpr const char* sysdStartUnit = "StartUnit";
-static constexpr const char* sysdStopUnit = "StopUnit";
-static constexpr const char* sysdRestartUnit = "RestartUnit";
-static constexpr const char* sysdReloadMethod = "Reload";
-static constexpr const char* sysdGetJobMethod = "GetJob";
-static constexpr const char* sysdReplaceMode = "replace";
-static constexpr const char* dBusGetAllMethod = "GetAll";
-static constexpr const char* dBusGetMethod = "Get";
-static constexpr const char* sysdService = "org.freedesktop.systemd1";
-static constexpr const char* sysdObjPath = "/org/freedesktop/systemd1";
-static constexpr const char* sysdMgrIntf = "org.freedesktop.systemd1.Manager";
-static constexpr const char* sysdUnitIntf = "org.freedesktop.systemd1.Unit";
-static constexpr const char* sysdSocketIntf = "org.freedesktop.systemd1.Socket";
-static constexpr const char* dBusPropIntf = "org.freedesktop.DBus.Properties";
-static constexpr const char* stateMasked = "masked";
-static constexpr const char* stateEnabled = "enabled";
-static constexpr const char* stateDisabled = "disabled";
-static constexpr const char* subStateRunning = "running";
-
-static inline std::string addInstanceName(const std::string& instanceName,
-                                          const std::string& suffix)
-{
-    return (instanceName.empty() ? "" : suffix + instanceName);
-}
-
-void systemdDaemonReload(
-    const std::shared_ptr<sdbusplus::asio::connection>& conn,
-    boost::asio::yield_context yield);
-
-void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn,
-                       boost::asio::yield_context yield,
-                       const std::string& unitName,
-                       const std::string& actionMethod);
-
-void systemdUnitFilesStateChange(
-    const std::shared_ptr<sdbusplus::asio::connection>& conn,
-    boost::asio::yield_context yield, const std::vector<std::string>& unitFiles,
-    const std::string& unitState, bool maskedState, bool enabledState);
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+#include <boost/asio.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+#include <chrono>
+#include <ctime>
+#include <filesystem>
+#include <string>
+
+static constexpr const char* sysdStartUnit = "StartUnit";
+static constexpr const char* sysdStopUnit = "StopUnit";
+static constexpr const char* sysdRestartUnit = "RestartUnit";
+static constexpr const char* sysdReloadMethod = "Reload";
+static constexpr const char* sysdGetJobMethod = "GetJob";
+static constexpr const char* sysdReplaceMode = "replace";
+static constexpr const char* dBusGetAllMethod = "GetAll";
+static constexpr const char* dBusGetMethod = "Get";
+static constexpr const char* sysdService = "org.freedesktop.systemd1";
+static constexpr const char* sysdObjPath = "/org/freedesktop/systemd1";
+static constexpr const char* sysdMgrIntf = "org.freedesktop.systemd1.Manager";
+static constexpr const char* sysdUnitIntf = "org.freedesktop.systemd1.Unit";
+static constexpr const char* sysdSocketIntf = "org.freedesktop.systemd1.Socket";
+static constexpr const char* dBusPropIntf = "org.freedesktop.DBus.Properties";
+static constexpr const char* stateMasked = "masked";
+static constexpr const char* stateEnabled = "enabled";
+static constexpr const char* stateDisabled = "disabled";
+static constexpr const char* subStateRunning = "running";
+
+static inline std::string addInstanceName(const std::string& instanceName,
+                                          const std::string& suffix)
+{
+    return (instanceName.empty() ? "" : suffix + instanceName);
+}
+
+void systemdDaemonReload(
+    const std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::yield_context yield);
+
+void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn,
+                       boost::asio::yield_context yield,
+                       const std::string& unitName,
+                       const std::string& actionMethod);
+
+void systemdUnitFilesStateChange(
+    const std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::yield_context yield, const std::vector<std::string>& unitFiles,
+    const std::string& unitState, bool maskedState, bool enabledState);
diff --git a/src/main.cpp b/src/main.cpp
index d15a4b9..b45cf63 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,333 +1,333 @@
-/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-*/
-#include "srvcfg_manager.hpp"
-
-#include <boost/algorithm/string/replace.hpp>
-#include <cereal/archives/json.hpp>
-#include <cereal/types/tuple.hpp>
-#include <cereal/types/unordered_map.hpp>
-#include <sdbusplus/bus/match.hpp>
-
-#include <filesystem>
-#include <fstream>
-
-std::unique_ptr<boost::asio::steady_timer> timer = nullptr;
-std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
-std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
-    srvMgrObjects;
-static bool unitQueryStarted = false;
-
-static constexpr const char* srvCfgMgrFile = "/etc/srvcfg-mgr.json";
-
-// Base service name list. All instance of these services and
-// units(service/socket) will be managed by this daemon.
-static std::array<std::string, 5> serviceNames = {
-    "phosphor-ipmi-net", "bmcweb", "phosphor-ipmi-kcs", "start-ipkvm",
-    "obmc-console"};
-
-using ListUnitsType =
-    std::tuple<std::string, std::string, std::string, std::string, std::string,
-               std::string, sdbusplus::message::object_path, uint32_t,
-               std::string, sdbusplus::message::object_path>;
-
-enum class ListUnitElements
-{
-    name,
-    descriptionString,
-    loadState,
-    activeState,
-    subState,
-    followedUnit,
-    objectPath,
-    queuedJobType,
-    jobType,
-    jobObject
-};
-
-enum class UnitType
-{
-    service,
-    socket,
-    target,
-    device,
-    invalid
-};
-
-using MonitorListMap =
-    std::unordered_map<std::string, std::tuple<std::string, std::string,
-                                               std::string, std::string>>;
-MonitorListMap unitsToMonitor;
-
-enum class monitorElement
-{
-    unitName,
-    instanceName,
-    serviceObjPath,
-    socketObjPath
-};
-
-std::tuple<std::string, UnitType, std::string>
-    getUnitNameTypeAndInstance(const std::string& fullUnitName)
-{
-    UnitType type = UnitType::invalid;
-    std::string instanceName;
-    std::string unitName;
-    // get service type
-    auto typePos = fullUnitName.rfind(".");
-    if (typePos != std::string::npos)
-    {
-        const auto& typeStr = fullUnitName.substr(typePos + 1);
-        // Ignore types other than service and socket
-        if (typeStr == "service")
-        {
-            type = UnitType::service;
-        }
-        else if (typeStr == "socket")
-        {
-            type = UnitType::socket;
-        }
-        // get instance name if available
-        auto instancePos = fullUnitName.rfind("@");
-        if (instancePos != std::string::npos)
-        {
-            instanceName =
-                fullUnitName.substr(instancePos + 1, typePos - instancePos - 1);
-            unitName = fullUnitName.substr(0, instancePos);
-        }
-        else
-        {
-            unitName = fullUnitName.substr(0, typePos);
-        }
-    }
-    return std::make_tuple(unitName, type, instanceName);
-}
-
-static inline void
-    handleListUnitsResponse(sdbusplus::asio::object_server& server,
-                            std::shared_ptr<sdbusplus::asio::connection>& conn,
-                            boost::system::error_code /*ec*/,
-                            const std::vector<ListUnitsType>& listUnits)
-{
-    // Loop through all units, and mark all units, which has to be
-    // managed, irrespective of instance name.
-    for (const auto& unit : listUnits)
-    {
-        const auto& fullUnitName =
-            std::get<static_cast<int>(ListUnitElements::name)>(unit);
-        auto [unitName, type, instanceName] =
-            getUnitNameTypeAndInstance(fullUnitName);
-        if (std::find(serviceNames.begin(), serviceNames.end(), unitName) !=
-            serviceNames.end())
-        {
-            std::string instantiatedUnitName =
-                unitName + addInstanceName(instanceName, "_40");
-            boost::replace_all(instantiatedUnitName, "-", "_2d");
-            const sdbusplus::message::object_path& objectPath =
-                std::get<static_cast<int>(ListUnitElements::objectPath)>(unit);
-            // Group the service & socket units togther.. Same services
-            // are managed together.
-            auto it = unitsToMonitor.find(instantiatedUnitName);
-            if (it != unitsToMonitor.end())
-            {
-                auto& value = it->second;
-                if (type == UnitType::service)
-                {
-                    std::get<static_cast<int>(monitorElement::unitName)>(
-                        value) = unitName;
-                    std::get<static_cast<int>(monitorElement::instanceName)>(
-                        value) = instanceName;
-                    std::get<static_cast<int>(monitorElement::serviceObjPath)>(
-                        value) = objectPath;
-                }
-                else if (type == UnitType::socket)
-                {
-                    std::get<static_cast<int>(monitorElement::socketObjPath)>(
-                        value) = objectPath;
-                }
-            }
-            if (type == UnitType::service)
-            {
-                unitsToMonitor.emplace(instantiatedUnitName,
-                                       std::make_tuple(unitName, instanceName,
-                                                       objectPath.str, ""));
-            }
-            else if (type == UnitType::socket)
-            {
-                unitsToMonitor.emplace(
-                    instantiatedUnitName,
-                    std::make_tuple("", "", "", objectPath.str));
-            }
-        }
-    }
-
-    bool updateRequired = false;
-    bool jsonExist = std::filesystem::exists(srvCfgMgrFile);
-    if (jsonExist)
-    {
-        std::ifstream file(srvCfgMgrFile);
-        cereal::JSONInputArchive archive(file);
-        MonitorListMap savedMonitorList;
-        archive(savedMonitorList);
-
-        // compare the unit list read from systemd1 and the save list.
-        MonitorListMap diffMap;
-        std::set_difference(begin(unitsToMonitor), end(unitsToMonitor),
-                            begin(savedMonitorList), end(savedMonitorList),
-                            std::inserter(diffMap, begin(diffMap)));
-        for (auto& unitIt : diffMap)
-        {
-            auto it = savedMonitorList.find(unitIt.first);
-            if (it == savedMonitorList.end())
-            {
-                savedMonitorList.insert(unitIt);
-                updateRequired = true;
-            }
-        }
-        unitsToMonitor = savedMonitorList;
-    }
-    if (!jsonExist || updateRequired)
-    {
-        std::ofstream file(srvCfgMgrFile);
-        cereal::JSONOutputArchive archive(file);
-        archive(CEREAL_NVP(unitsToMonitor));
-    }
-
-    // create objects for needed services
-    for (auto& it : unitsToMonitor)
-    {
-        std::string objPath(std::string(phosphor::service::srcCfgMgrBasePath) +
-                            "/" + it.first);
-        std::string instanciatedUnitName =
-            std::get<static_cast<int>(monitorElement::unitName)>(it.second) +
-            addInstanceName(
-                std::get<static_cast<int>(monitorElement::instanceName)>(
-                    it.second),
-                "@");
-        auto srvCfgObj = std::make_unique<phosphor::service::ServiceConfig>(
-            server, conn, objPath,
-            std::get<static_cast<int>(monitorElement::unitName)>(it.second),
-            std::get<static_cast<int>(monitorElement::instanceName)>(it.second),
-            std::get<static_cast<int>(monitorElement::serviceObjPath)>(
-                it.second),
-            std::get<static_cast<int>(monitorElement::socketObjPath)>(
-                it.second));
-        srvMgrObjects.emplace(
-            std::make_pair(std::move(objPath), std::move(srvCfgObj)));
-    }
-}
-
-void init(sdbusplus::asio::object_server& server,
-          std::shared_ptr<sdbusplus::asio::connection>& conn)
-{
-    // Go through all systemd units, and dynamically detect and manage
-    // the service daemons
-    conn->async_method_call(
-        [&server, &conn](boost::system::error_code ec,
-                         const std::vector<ListUnitsType>& listUnits) {
-            if (ec)
-            {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "async_method_call error: ListUnits failed");
-                return;
-            }
-            handleListUnitsResponse(server, conn, ec, listUnits);
-        },
-        sysdService, sysdObjPath, sysdMgrIntf, "ListUnits");
-}
-
-void checkAndInit(sdbusplus::asio::object_server& server,
-                  std::shared_ptr<sdbusplus::asio::connection>& conn)
-{
-    // Check whether systemd completed all the loading before initializing
-    conn->async_method_call(
-        [&server, &conn](boost::system::error_code ec,
-                         const std::variant<uint64_t>& value) {
-            if (ec)
-            {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "async_method_call error: ListUnits failed");
-                return;
-            }
-            if (std::get<uint64_t>(value))
-            {
-                if (!unitQueryStarted)
-                {
-                    unitQueryStarted = true;
-                    init(server, conn);
-                }
-            }
-            else
-            {
-                // FIX-ME: Latest up-stream sync caused issue in receiving
-                // StartupFinished signal. Unable to get StartupFinished signal
-                // from systemd1 hence using poll method too, to trigger it
-                // properly.
-                constexpr size_t pollTimeout = 10; // seconds
-                initTimer->expires_after(std::chrono::seconds(pollTimeout));
-                initTimer->async_wait([&server, &conn](
-                                          const boost::system::error_code& ec) {
-                    if (ec == boost::asio::error::operation_aborted)
-                    {
-                        // Timer reset.
-                        return;
-                    }
-                    if (ec)
-                    {
-                        phosphor::logging::log<phosphor::logging::level::ERR>(
-                            "service config mgr - init - async wait error.");
-                        return;
-                    }
-                    checkAndInit(server, conn);
-                });
-            }
-        },
-        sysdService, sysdObjPath, dBusPropIntf, dBusGetMethod, sysdMgrIntf,
-        "FinishTimestamp");
-}
-
-int main()
-{
-    boost::asio::io_service io;
-    auto conn = std::make_shared<sdbusplus::asio::connection>(io);
-    timer = std::make_unique<boost::asio::steady_timer>(io);
-    initTimer = std::make_unique<boost::asio::steady_timer>(io);
-    conn->request_name(phosphor::service::serviceConfigSrvName);
-    auto server = sdbusplus::asio::object_server(conn, true);
-    auto mgrIntf = server.add_interface(phosphor::service::srcCfgMgrBasePath,
-                                        phosphor::service::srcCfgMgrIntf);
-    mgrIntf->initialize();
-    server.add_manager(phosphor::service::srcCfgMgrBasePath);
-    // Initialize the objects after systemd indicated startup finished.
-    auto userUpdatedSignal = std::make_unique<sdbusplus::bus::match::match>(
-        static_cast<sdbusplus::bus::bus&>(*conn),
-        "type='signal',"
-        "member='StartupFinished',path='/org/freedesktop/systemd1',"
-        "interface='org.freedesktop.systemd1.Manager'",
-        [&server, &conn](sdbusplus::message::message& /*msg*/) {
-            if (!unitQueryStarted)
-            {
-                unitQueryStarted = true;
-                init(server, conn);
-            }
-        });
-    // this will make sure to initialize the objects, when daemon is
-    // restarted.
-    checkAndInit(server, conn);
-
-    io.run();
-
-    return 0;
-}
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include "srvcfg_manager.hpp"
+
+#include <boost/algorithm/string/replace.hpp>
+#include <cereal/archives/json.hpp>
+#include <cereal/types/tuple.hpp>
+#include <cereal/types/unordered_map.hpp>
+#include <sdbusplus/bus/match.hpp>
+
+#include <filesystem>
+#include <fstream>
+
+std::unique_ptr<boost::asio::steady_timer> timer = nullptr;
+std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
+std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
+    srvMgrObjects;
+static bool unitQueryStarted = false;
+
+static constexpr const char* srvCfgMgrFile = "/etc/srvcfg-mgr.json";
+
+// Base service name list. All instance of these services and
+// units(service/socket) will be managed by this daemon.
+static std::array<std::string, 5> serviceNames = {
+    "phosphor-ipmi-net", "bmcweb", "phosphor-ipmi-kcs", "start-ipkvm",
+    "obmc-console"};
+
+using ListUnitsType =
+    std::tuple<std::string, std::string, std::string, std::string, std::string,
+               std::string, sdbusplus::message::object_path, uint32_t,
+               std::string, sdbusplus::message::object_path>;
+
+enum class ListUnitElements
+{
+    name,
+    descriptionString,
+    loadState,
+    activeState,
+    subState,
+    followedUnit,
+    objectPath,
+    queuedJobType,
+    jobType,
+    jobObject
+};
+
+enum class UnitType
+{
+    service,
+    socket,
+    target,
+    device,
+    invalid
+};
+
+using MonitorListMap =
+    std::unordered_map<std::string, std::tuple<std::string, std::string,
+                                               std::string, std::string>>;
+MonitorListMap unitsToMonitor;
+
+enum class monitorElement
+{
+    unitName,
+    instanceName,
+    serviceObjPath,
+    socketObjPath
+};
+
+std::tuple<std::string, UnitType, std::string>
+    getUnitNameTypeAndInstance(const std::string& fullUnitName)
+{
+    UnitType type = UnitType::invalid;
+    std::string instanceName;
+    std::string unitName;
+    // get service type
+    auto typePos = fullUnitName.rfind(".");
+    if (typePos != std::string::npos)
+    {
+        const auto& typeStr = fullUnitName.substr(typePos + 1);
+        // Ignore types other than service and socket
+        if (typeStr == "service")
+        {
+            type = UnitType::service;
+        }
+        else if (typeStr == "socket")
+        {
+            type = UnitType::socket;
+        }
+        // get instance name if available
+        auto instancePos = fullUnitName.rfind("@");
+        if (instancePos != std::string::npos)
+        {
+            instanceName =
+                fullUnitName.substr(instancePos + 1, typePos - instancePos - 1);
+            unitName = fullUnitName.substr(0, instancePos);
+        }
+        else
+        {
+            unitName = fullUnitName.substr(0, typePos);
+        }
+    }
+    return std::make_tuple(unitName, type, instanceName);
+}
+
+static inline void
+    handleListUnitsResponse(sdbusplus::asio::object_server& server,
+                            std::shared_ptr<sdbusplus::asio::connection>& conn,
+                            boost::system::error_code /*ec*/,
+                            const std::vector<ListUnitsType>& listUnits)
+{
+    // Loop through all units, and mark all units, which has to be
+    // managed, irrespective of instance name.
+    for (const auto& unit : listUnits)
+    {
+        const auto& fullUnitName =
+            std::get<static_cast<int>(ListUnitElements::name)>(unit);
+        auto [unitName, type, instanceName] =
+            getUnitNameTypeAndInstance(fullUnitName);
+        if (std::find(serviceNames.begin(), serviceNames.end(), unitName) !=
+            serviceNames.end())
+        {
+            std::string instantiatedUnitName =
+                unitName + addInstanceName(instanceName, "_40");
+            boost::replace_all(instantiatedUnitName, "-", "_2d");
+            const sdbusplus::message::object_path& objectPath =
+                std::get<static_cast<int>(ListUnitElements::objectPath)>(unit);
+            // Group the service & socket units togther.. Same services
+            // are managed together.
+            auto it = unitsToMonitor.find(instantiatedUnitName);
+            if (it != unitsToMonitor.end())
+            {
+                auto& value = it->second;
+                if (type == UnitType::service)
+                {
+                    std::get<static_cast<int>(monitorElement::unitName)>(
+                        value) = unitName;
+                    std::get<static_cast<int>(monitorElement::instanceName)>(
+                        value) = instanceName;
+                    std::get<static_cast<int>(monitorElement::serviceObjPath)>(
+                        value) = objectPath;
+                }
+                else if (type == UnitType::socket)
+                {
+                    std::get<static_cast<int>(monitorElement::socketObjPath)>(
+                        value) = objectPath;
+                }
+            }
+            if (type == UnitType::service)
+            {
+                unitsToMonitor.emplace(instantiatedUnitName,
+                                       std::make_tuple(unitName, instanceName,
+                                                       objectPath.str, ""));
+            }
+            else if (type == UnitType::socket)
+            {
+                unitsToMonitor.emplace(
+                    instantiatedUnitName,
+                    std::make_tuple("", "", "", objectPath.str));
+            }
+        }
+    }
+
+    bool updateRequired = false;
+    bool jsonExist = std::filesystem::exists(srvCfgMgrFile);
+    if (jsonExist)
+    {
+        std::ifstream file(srvCfgMgrFile);
+        cereal::JSONInputArchive archive(file);
+        MonitorListMap savedMonitorList;
+        archive(savedMonitorList);
+
+        // compare the unit list read from systemd1 and the save list.
+        MonitorListMap diffMap;
+        std::set_difference(begin(unitsToMonitor), end(unitsToMonitor),
+                            begin(savedMonitorList), end(savedMonitorList),
+                            std::inserter(diffMap, begin(diffMap)));
+        for (auto& unitIt : diffMap)
+        {
+            auto it = savedMonitorList.find(unitIt.first);
+            if (it == savedMonitorList.end())
+            {
+                savedMonitorList.insert(unitIt);
+                updateRequired = true;
+            }
+        }
+        unitsToMonitor = savedMonitorList;
+    }
+    if (!jsonExist || updateRequired)
+    {
+        std::ofstream file(srvCfgMgrFile);
+        cereal::JSONOutputArchive archive(file);
+        archive(CEREAL_NVP(unitsToMonitor));
+    }
+
+    // create objects for needed services
+    for (auto& it : unitsToMonitor)
+    {
+        std::string objPath(std::string(phosphor::service::srcCfgMgrBasePath) +
+                            "/" + it.first);
+        std::string instanciatedUnitName =
+            std::get<static_cast<int>(monitorElement::unitName)>(it.second) +
+            addInstanceName(
+                std::get<static_cast<int>(monitorElement::instanceName)>(
+                    it.second),
+                "@");
+        auto srvCfgObj = std::make_unique<phosphor::service::ServiceConfig>(
+            server, conn, objPath,
+            std::get<static_cast<int>(monitorElement::unitName)>(it.second),
+            std::get<static_cast<int>(monitorElement::instanceName)>(it.second),
+            std::get<static_cast<int>(monitorElement::serviceObjPath)>(
+                it.second),
+            std::get<static_cast<int>(monitorElement::socketObjPath)>(
+                it.second));
+        srvMgrObjects.emplace(
+            std::make_pair(std::move(objPath), std::move(srvCfgObj)));
+    }
+}
+
+void init(sdbusplus::asio::object_server& server,
+          std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+    // Go through all systemd units, and dynamically detect and manage
+    // the service daemons
+    conn->async_method_call(
+        [&server, &conn](boost::system::error_code ec,
+                         const std::vector<ListUnitsType>& listUnits) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "async_method_call error: ListUnits failed");
+                return;
+            }
+            handleListUnitsResponse(server, conn, ec, listUnits);
+        },
+        sysdService, sysdObjPath, sysdMgrIntf, "ListUnits");
+}
+
+void checkAndInit(sdbusplus::asio::object_server& server,
+                  std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+    // Check whether systemd completed all the loading before initializing
+    conn->async_method_call(
+        [&server, &conn](boost::system::error_code ec,
+                         const std::variant<uint64_t>& value) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "async_method_call error: ListUnits failed");
+                return;
+            }
+            if (std::get<uint64_t>(value))
+            {
+                if (!unitQueryStarted)
+                {
+                    unitQueryStarted = true;
+                    init(server, conn);
+                }
+            }
+            else
+            {
+                // FIX-ME: Latest up-stream sync caused issue in receiving
+                // StartupFinished signal. Unable to get StartupFinished signal
+                // from systemd1 hence using poll method too, to trigger it
+                // properly.
+                constexpr size_t pollTimeout = 10; // seconds
+                initTimer->expires_after(std::chrono::seconds(pollTimeout));
+                initTimer->async_wait([&server, &conn](
+                                          const boost::system::error_code& ec) {
+                    if (ec == boost::asio::error::operation_aborted)
+                    {
+                        // Timer reset.
+                        return;
+                    }
+                    if (ec)
+                    {
+                        phosphor::logging::log<phosphor::logging::level::ERR>(
+                            "service config mgr - init - async wait error.");
+                        return;
+                    }
+                    checkAndInit(server, conn);
+                });
+            }
+        },
+        sysdService, sysdObjPath, dBusPropIntf, dBusGetMethod, sysdMgrIntf,
+        "FinishTimestamp");
+}
+
+int main()
+{
+    boost::asio::io_service io;
+    auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+    timer = std::make_unique<boost::asio::steady_timer>(io);
+    initTimer = std::make_unique<boost::asio::steady_timer>(io);
+    conn->request_name(phosphor::service::serviceConfigSrvName);
+    auto server = sdbusplus::asio::object_server(conn, true);
+    auto mgrIntf = server.add_interface(phosphor::service::srcCfgMgrBasePath,
+                                        phosphor::service::srcCfgMgrIntf);
+    mgrIntf->initialize();
+    server.add_manager(phosphor::service::srcCfgMgrBasePath);
+    // Initialize the objects after systemd indicated startup finished.
+    auto userUpdatedSignal = std::make_unique<sdbusplus::bus::match::match>(
+        static_cast<sdbusplus::bus::bus&>(*conn),
+        "type='signal',"
+        "member='StartupFinished',path='/org/freedesktop/systemd1',"
+        "interface='org.freedesktop.systemd1.Manager'",
+        [&server, &conn](sdbusplus::message::message& /*msg*/) {
+            if (!unitQueryStarted)
+            {
+                unitQueryStarted = true;
+                init(server, conn);
+            }
+        });
+    // this will make sure to initialize the objects, when daemon is
+    // restarted.
+    checkAndInit(server, conn);
+
+    io.run();
+
+    return 0;
+}
diff --git a/src/srvcfg_manager.cpp b/src/srvcfg_manager.cpp
index 2d346c2..038d11a 100644
--- a/src/srvcfg_manager.cpp
+++ b/src/srvcfg_manager.cpp
@@ -1,505 +1,505 @@
-/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-*/
-#include "srvcfg_manager.hpp"
-
-#include <boost/asio/spawn.hpp>
-
-#include <fstream>
-#include <regex>
-
-extern std::unique_ptr<boost::asio::steady_timer> timer;
-extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
-    srvMgrObjects;
-static bool updateInProgress = false;
-
-namespace phosphor
-{
-namespace service
-{
-
-static constexpr const char* overrideConfFileName = "override.conf";
-static constexpr const size_t restartTimeout = 15; // seconds
-
-static constexpr const char* systemd1UnitBasePath =
-    "/org/freedesktop/systemd1/unit/";
-static constexpr const char* systemdOverrideUnitBasePath =
-    "/etc/systemd/system/";
-
-void ServiceConfig::updateSocketProperties(
-    const boost::container::flat_map<std::string, VariantType>& propertyMap)
-{
-    auto listenIt = propertyMap.find("Listen");
-    if (listenIt != propertyMap.end())
-    {
-        auto listenVal =
-            std::get<std::vector<std::tuple<std::string, std::string>>>(
-                listenIt->second);
-        if (listenVal.size())
-        {
-            protocol = std::get<0>(listenVal[0]);
-            std::string port = std::get<1>(listenVal[0]);
-            auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
-                                  nullptr, 10);
-            if (tmp > std::numeric_limits<uint16_t>::max())
-            {
-                throw std::out_of_range("Out of range");
-            }
-            portNum = tmp;
-            if (sockAttrIface && sockAttrIface->is_initialized())
-            {
-                internalSet = true;
-                sockAttrIface->set_property(sockAttrPropPort, portNum);
-                internalSet = false;
-            }
-        }
-    }
-}
-
-void ServiceConfig::updateServiceProperties(
-    const boost::container::flat_map<std::string, VariantType>& propertyMap)
-{
-    auto stateIt = propertyMap.find("UnitFileState");
-    if (stateIt != propertyMap.end())
-    {
-        stateValue = std::get<std::string>(stateIt->second);
-        unitEnabledState = unitMaskedState = false;
-        if (stateValue == stateMasked)
-        {
-            unitMaskedState = true;
-        }
-        else if (stateValue == stateEnabled)
-        {
-            unitEnabledState = true;
-        }
-        if (srvCfgIface && srvCfgIface->is_initialized())
-        {
-            internalSet = true;
-            srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
-            srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
-            internalSet = false;
-        }
-    }
-    auto subStateIt = propertyMap.find("SubState");
-    if (subStateIt != propertyMap.end())
-    {
-        subStateValue = std::get<std::string>(subStateIt->second);
-        if (subStateValue == subStateRunning)
-        {
-            unitRunningState = true;
-        }
-        if (srvCfgIface && srvCfgIface->is_initialized())
-        {
-            internalSet = true;
-            srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
-            internalSet = false;
-        }
-    }
-}
-
-void ServiceConfig::queryAndUpdateProperties()
-{
-    conn->async_method_call(
-        [this](boost::system::error_code ec,
-               const boost::container::flat_map<std::string, VariantType>&
-                   propertyMap) {
-            if (ec)
-            {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "async_method_call error: Failed to service unit "
-                    "properties");
-                return;
-            }
-            try
-            {
-                updateServiceProperties(propertyMap);
-                if (!socketObjectPath.empty())
-                {
-                    conn->async_method_call(
-                        [this](boost::system::error_code ec,
-                               const boost::container::flat_map<
-                                   std::string, VariantType>& propertyMap) {
-                            if (ec)
-                            {
-                                phosphor::logging::log<
-                                    phosphor::logging::level::ERR>(
-                                    "async_method_call error: Failed to get "
-                                    "all property");
-                                return;
-                            }
-                            try
-                            {
-                                updateSocketProperties(propertyMap);
-                                if (!srvCfgIface)
-                                {
-                                    registerProperties();
-                                }
-                            }
-                            catch (const std::exception& e)
-                            {
-                                phosphor::logging::log<
-                                    phosphor::logging::level::ERR>(
-                                    "Exception in getting socket properties",
-                                    phosphor::logging::entry("WHAT=%s",
-                                                             e.what()));
-                                return;
-                            }
-                        },
-                        sysdService, socketObjectPath, dBusPropIntf,
-                        dBusGetAllMethod, sysdSocketIntf);
-                }
-                else if (!srvCfgIface)
-                {
-                    registerProperties();
-                }
-            }
-            catch (const std::exception& e)
-            {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "Exception in getting socket properties",
-                    phosphor::logging::entry("WHAT=%s", e.what()));
-                return;
-            }
-        },
-        sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod,
-        sysdUnitIntf);
-    return;
-}
-
-void ServiceConfig::createSocketOverrideConf()
-{
-    if (!socketObjectPath.empty())
-    {
-        std::string socketUnitName(instantiatedUnitName + ".socket");
-        /// Check override socket directory exist, if not create it.
-        std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
-        ovrUnitFileDir += socketUnitName;
-        ovrUnitFileDir += ".d";
-        if (!std::filesystem::exists(ovrUnitFileDir))
-        {
-            if (!std::filesystem::create_directories(ovrUnitFileDir))
-            {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "Unable to create the directory.",
-                    phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
-                phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
-                                            Common::Error::InternalFailure>();
-            }
-        }
-        overrideConfDir = std::string(ovrUnitFileDir);
-    }
-}
-
-ServiceConfig::ServiceConfig(
-    sdbusplus::asio::object_server& srv_,
-    std::shared_ptr<sdbusplus::asio::connection>& conn_,
-    const std::string& objPath_, const std::string& baseUnitName_,
-    const std::string& instanceName_, const std::string& serviceObjPath_,
-    const std::string& socketObjPath_) :
-    conn(conn_),
-    server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
-    instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
-    socketObjectPath(socketObjPath_)
-{
-    instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
-    updatedFlag = 0;
-    queryAndUpdateProperties();
-    return;
-}
-
-std::string ServiceConfig::getSocketUnitName()
-{
-    return instantiatedUnitName + ".socket";
-}
-
-std::string ServiceConfig::getServiceUnitName()
-{
-    return instantiatedUnitName + ".service";
-}
-
-bool ServiceConfig::isMaskedOut()
-{
-    // return true  if state is masked & no request to update the maskedState
-    return (
-        stateValue == "masked" &&
-        !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
-}
-
-void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
-{
-    if (!updatedFlag || isMaskedOut())
-    {
-        // No updates / masked - Just return.
-        return;
-    }
-    phosphor::logging::log<phosphor::logging::level::INFO>(
-        "Applying new settings.",
-        phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
-    if (subStateValue == "running")
-    {
-        if (!socketObjectPath.empty())
-        {
-            systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
-        }
-        systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
-    }
-
-    if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
-    {
-        createSocketOverrideConf();
-        // Create override config file and write data.
-        std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
-        std::string tmpFile{ovrCfgFile + "_tmp"};
-        std::ofstream cfgFile(tmpFile, std::ios::out);
-        if (!cfgFile.good())
-        {
-            phosphor::logging::log<phosphor::logging::level::ERR>(
-                "Failed to open override.conf_tmp file");
-            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
-                                        Error::InternalFailure>();
-        }
-
-        // Write the socket header
-        cfgFile << "[Socket]\n";
-        // Listen
-        cfgFile << "Listen" << protocol << "="
-                << "\n";
-        cfgFile << "Listen" << protocol << "=" << portNum << "\n";
-        cfgFile.close();
-
-        if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
-        {
-            phosphor::logging::log<phosphor::logging::level::ERR>(
-                "Failed to rename tmp file as override.conf");
-            std::remove(tmpFile.c_str());
-            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
-                                        Error::InternalFailure>();
-        }
-    }
-
-    if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
-                       (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
-    {
-        std::vector<std::string> unitFiles;
-        if (socketObjectPath.empty())
-        {
-            unitFiles = {getServiceUnitName()};
-        }
-        else
-        {
-            unitFiles = {getSocketUnitName(), getServiceUnitName()};
-        }
-        systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
-                                    unitMaskedState, unitEnabledState);
-    }
-    return;
-}
-void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
-{
-    if (!updatedFlag || isMaskedOut())
-    {
-        // No updates. Just return.
-        return;
-    }
-
-    if (unitRunningState)
-    {
-        if (!socketObjectPath.empty())
-        {
-            systemdUnitAction(conn, yield, getSocketUnitName(),
-                              sysdRestartUnit);
-        }
-        systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit);
-    }
-
-    // Reset the flag
-    updatedFlag = 0;
-
-    phosphor::logging::log<phosphor::logging::level::INFO>(
-        "Applied new settings",
-        phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
-
-    queryAndUpdateProperties();
-    return;
-}
-
-void ServiceConfig::startServiceRestartTimer()
-{
-    timer->expires_after(std::chrono::seconds(restartTimeout));
-    timer->async_wait([this](const boost::system::error_code& ec) {
-        if (ec == boost::asio::error::operation_aborted)
-        {
-            // Timer reset.
-            return;
-        }
-        else if (ec)
-        {
-            phosphor::logging::log<phosphor::logging::level::ERR>(
-                "async wait error.");
-            return;
-        }
-        updateInProgress = true;
-        boost::asio::spawn(conn->get_io_context(),
-                           [this](boost::asio::yield_context yield) {
-                               // Stop and apply configuration for all objects
-                               for (auto& srvMgrObj : srvMgrObjects)
-                               {
-                                   auto& srvObj = srvMgrObj.second;
-                                   if (srvObj->updatedFlag)
-                                   {
-                                       srvObj->stopAndApplyUnitConfig(yield);
-                                   }
-                               }
-                               // Do system reload
-                               systemdDaemonReload(conn, yield);
-                               // restart unit config.
-                               for (auto& srvMgrObj : srvMgrObjects)
-                               {
-                                   auto& srvObj = srvMgrObj.second;
-                                   if (srvObj->updatedFlag)
-                                   {
-                                       srvObj->restartUnitConfig(yield);
-                                   }
-                               }
-                               updateInProgress = false;
-                           });
-    });
-}
-
-void ServiceConfig::registerProperties()
-{
-    srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
-
-    if (!socketObjectPath.empty())
-    {
-        sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
-        sockAttrIface->register_property(
-            sockAttrPropPort, portNum,
-            [this](const uint16_t& req, uint16_t& res) {
-                if (!internalSet)
-                {
-                    if (req == res)
-                    {
-                        return 1;
-                    }
-                    if (updateInProgress)
-                    {
-                        return 0;
-                    }
-                    portNum = req;
-                    updatedFlag |=
-                        (1 << static_cast<uint8_t>(UpdatedProp::port));
-                    startServiceRestartTimer();
-                }
-                res = req;
-                return 1;
-            });
-    }
-
-    srvCfgIface->register_property(
-        srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
-            if (!internalSet)
-            {
-                if (req == res)
-                {
-                    return 1;
-                }
-                if (updateInProgress)
-                {
-                    return 0;
-                }
-                unitMaskedState = req;
-                unitEnabledState = !unitMaskedState;
-                unitRunningState = !unitMaskedState;
-                updatedFlag |=
-                    (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
-                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
-                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
-                internalSet = true;
-                srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
-                srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
-                internalSet = false;
-                startServiceRestartTimer();
-            }
-            res = req;
-            return 1;
-        });
-
-    srvCfgIface->register_property(
-        srvCfgPropEnabled, unitEnabledState,
-        [this](const bool& req, bool& res) {
-            if (!internalSet)
-            {
-                if (req == res)
-                {
-                    return 1;
-                }
-                if (updateInProgress)
-                {
-                    return 0;
-                }
-                if (unitMaskedState)
-                { // block updating if masked
-                    phosphor::logging::log<phosphor::logging::level::ERR>(
-                        "Invalid value specified");
-                    return -EINVAL;
-                }
-                unitEnabledState = req;
-                updatedFlag |=
-                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
-                startServiceRestartTimer();
-            }
-            res = req;
-            return 1;
-        });
-
-    srvCfgIface->register_property(
-        srvCfgPropRunning, unitRunningState,
-        [this](const bool& req, bool& res) {
-            if (!internalSet)
-            {
-                if (req == res)
-                {
-                    return 1;
-                }
-                if (updateInProgress)
-                {
-                    return 0;
-                }
-                if (unitMaskedState)
-                { // block updating if masked
-                    phosphor::logging::log<phosphor::logging::level::ERR>(
-                        "Invalid value specified");
-                    return -EINVAL;
-                }
-                unitRunningState = req;
-                updatedFlag |=
-                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
-                startServiceRestartTimer();
-            }
-            res = req;
-            return 1;
-        });
-
-    srvCfgIface->initialize();
-    if (!socketObjectPath.empty())
-    {
-        sockAttrIface->initialize();
-    }
-    return;
-}
-
-} // namespace service
-} // namespace phosphor
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include "srvcfg_manager.hpp"
+
+#include <boost/asio/spawn.hpp>
+
+#include <fstream>
+#include <regex>
+
+extern std::unique_ptr<boost::asio::steady_timer> timer;
+extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
+    srvMgrObjects;
+static bool updateInProgress = false;
+
+namespace phosphor
+{
+namespace service
+{
+
+static constexpr const char* overrideConfFileName = "override.conf";
+static constexpr const size_t restartTimeout = 15; // seconds
+
+static constexpr const char* systemd1UnitBasePath =
+    "/org/freedesktop/systemd1/unit/";
+static constexpr const char* systemdOverrideUnitBasePath =
+    "/etc/systemd/system/";
+
+void ServiceConfig::updateSocketProperties(
+    const boost::container::flat_map<std::string, VariantType>& propertyMap)
+{
+    auto listenIt = propertyMap.find("Listen");
+    if (listenIt != propertyMap.end())
+    {
+        auto listenVal =
+            std::get<std::vector<std::tuple<std::string, std::string>>>(
+                listenIt->second);
+        if (listenVal.size())
+        {
+            protocol = std::get<0>(listenVal[0]);
+            std::string port = std::get<1>(listenVal[0]);
+            auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
+                                  nullptr, 10);
+            if (tmp > std::numeric_limits<uint16_t>::max())
+            {
+                throw std::out_of_range("Out of range");
+            }
+            portNum = tmp;
+            if (sockAttrIface && sockAttrIface->is_initialized())
+            {
+                internalSet = true;
+                sockAttrIface->set_property(sockAttrPropPort, portNum);
+                internalSet = false;
+            }
+        }
+    }
+}
+
+void ServiceConfig::updateServiceProperties(
+    const boost::container::flat_map<std::string, VariantType>& propertyMap)
+{
+    auto stateIt = propertyMap.find("UnitFileState");
+    if (stateIt != propertyMap.end())
+    {
+        stateValue = std::get<std::string>(stateIt->second);
+        unitEnabledState = unitMaskedState = false;
+        if (stateValue == stateMasked)
+        {
+            unitMaskedState = true;
+        }
+        else if (stateValue == stateEnabled)
+        {
+            unitEnabledState = true;
+        }
+        if (srvCfgIface && srvCfgIface->is_initialized())
+        {
+            internalSet = true;
+            srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
+            srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
+            internalSet = false;
+        }
+    }
+    auto subStateIt = propertyMap.find("SubState");
+    if (subStateIt != propertyMap.end())
+    {
+        subStateValue = std::get<std::string>(subStateIt->second);
+        if (subStateValue == subStateRunning)
+        {
+            unitRunningState = true;
+        }
+        if (srvCfgIface && srvCfgIface->is_initialized())
+        {
+            internalSet = true;
+            srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
+            internalSet = false;
+        }
+    }
+}
+
+void ServiceConfig::queryAndUpdateProperties()
+{
+    conn->async_method_call(
+        [this](boost::system::error_code ec,
+               const boost::container::flat_map<std::string, VariantType>&
+                   propertyMap) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "async_method_call error: Failed to service unit "
+                    "properties");
+                return;
+            }
+            try
+            {
+                updateServiceProperties(propertyMap);
+                if (!socketObjectPath.empty())
+                {
+                    conn->async_method_call(
+                        [this](boost::system::error_code ec,
+                               const boost::container::flat_map<
+                                   std::string, VariantType>& propertyMap) {
+                            if (ec)
+                            {
+                                phosphor::logging::log<
+                                    phosphor::logging::level::ERR>(
+                                    "async_method_call error: Failed to get "
+                                    "all property");
+                                return;
+                            }
+                            try
+                            {
+                                updateSocketProperties(propertyMap);
+                                if (!srvCfgIface)
+                                {
+                                    registerProperties();
+                                }
+                            }
+                            catch (const std::exception& e)
+                            {
+                                phosphor::logging::log<
+                                    phosphor::logging::level::ERR>(
+                                    "Exception in getting socket properties",
+                                    phosphor::logging::entry("WHAT=%s",
+                                                             e.what()));
+                                return;
+                            }
+                        },
+                        sysdService, socketObjectPath, dBusPropIntf,
+                        dBusGetAllMethod, sysdSocketIntf);
+                }
+                else if (!srvCfgIface)
+                {
+                    registerProperties();
+                }
+            }
+            catch (const std::exception& e)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Exception in getting socket properties",
+                    phosphor::logging::entry("WHAT=%s", e.what()));
+                return;
+            }
+        },
+        sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod,
+        sysdUnitIntf);
+    return;
+}
+
+void ServiceConfig::createSocketOverrideConf()
+{
+    if (!socketObjectPath.empty())
+    {
+        std::string socketUnitName(instantiatedUnitName + ".socket");
+        /// Check override socket directory exist, if not create it.
+        std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
+        ovrUnitFileDir += socketUnitName;
+        ovrUnitFileDir += ".d";
+        if (!std::filesystem::exists(ovrUnitFileDir))
+        {
+            if (!std::filesystem::create_directories(ovrUnitFileDir))
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Unable to create the directory.",
+                    phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
+                phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
+                                            Common::Error::InternalFailure>();
+            }
+        }
+        overrideConfDir = std::string(ovrUnitFileDir);
+    }
+}
+
+ServiceConfig::ServiceConfig(
+    sdbusplus::asio::object_server& srv_,
+    std::shared_ptr<sdbusplus::asio::connection>& conn_,
+    const std::string& objPath_, const std::string& baseUnitName_,
+    const std::string& instanceName_, const std::string& serviceObjPath_,
+    const std::string& socketObjPath_) :
+    conn(conn_),
+    server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
+    instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
+    socketObjectPath(socketObjPath_)
+{
+    instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
+    updatedFlag = 0;
+    queryAndUpdateProperties();
+    return;
+}
+
+std::string ServiceConfig::getSocketUnitName()
+{
+    return instantiatedUnitName + ".socket";
+}
+
+std::string ServiceConfig::getServiceUnitName()
+{
+    return instantiatedUnitName + ".service";
+}
+
+bool ServiceConfig::isMaskedOut()
+{
+    // return true  if state is masked & no request to update the maskedState
+    return (
+        stateValue == "masked" &&
+        !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
+}
+
+void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
+{
+    if (!updatedFlag || isMaskedOut())
+    {
+        // No updates / masked - Just return.
+        return;
+    }
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "Applying new settings.",
+        phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
+    if (subStateValue == "running")
+    {
+        if (!socketObjectPath.empty())
+        {
+            systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
+        }
+        systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
+    }
+
+    if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
+    {
+        createSocketOverrideConf();
+        // Create override config file and write data.
+        std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
+        std::string tmpFile{ovrCfgFile + "_tmp"};
+        std::ofstream cfgFile(tmpFile, std::ios::out);
+        if (!cfgFile.good())
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Failed to open override.conf_tmp file");
+            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
+                                        Error::InternalFailure>();
+        }
+
+        // Write the socket header
+        cfgFile << "[Socket]\n";
+        // Listen
+        cfgFile << "Listen" << protocol << "="
+                << "\n";
+        cfgFile << "Listen" << protocol << "=" << portNum << "\n";
+        cfgFile.close();
+
+        if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Failed to rename tmp file as override.conf");
+            std::remove(tmpFile.c_str());
+            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
+                                        Error::InternalFailure>();
+        }
+    }
+
+    if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
+                       (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
+    {
+        std::vector<std::string> unitFiles;
+        if (socketObjectPath.empty())
+        {
+            unitFiles = {getServiceUnitName()};
+        }
+        else
+        {
+            unitFiles = {getSocketUnitName(), getServiceUnitName()};
+        }
+        systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
+                                    unitMaskedState, unitEnabledState);
+    }
+    return;
+}
+void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
+{
+    if (!updatedFlag || isMaskedOut())
+    {
+        // No updates. Just return.
+        return;
+    }
+
+    if (unitRunningState)
+    {
+        if (!socketObjectPath.empty())
+        {
+            systemdUnitAction(conn, yield, getSocketUnitName(),
+                              sysdRestartUnit);
+        }
+        systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit);
+    }
+
+    // Reset the flag
+    updatedFlag = 0;
+
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "Applied new settings",
+        phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
+
+    queryAndUpdateProperties();
+    return;
+}
+
+void ServiceConfig::startServiceRestartTimer()
+{
+    timer->expires_after(std::chrono::seconds(restartTimeout));
+    timer->async_wait([this](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            // Timer reset.
+            return;
+        }
+        else if (ec)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "async wait error.");
+            return;
+        }
+        updateInProgress = true;
+        boost::asio::spawn(conn->get_io_context(),
+                           [this](boost::asio::yield_context yield) {
+                               // Stop and apply configuration for all objects
+                               for (auto& srvMgrObj : srvMgrObjects)
+                               {
+                                   auto& srvObj = srvMgrObj.second;
+                                   if (srvObj->updatedFlag)
+                                   {
+                                       srvObj->stopAndApplyUnitConfig(yield);
+                                   }
+                               }
+                               // Do system reload
+                               systemdDaemonReload(conn, yield);
+                               // restart unit config.
+                               for (auto& srvMgrObj : srvMgrObjects)
+                               {
+                                   auto& srvObj = srvMgrObj.second;
+                                   if (srvObj->updatedFlag)
+                                   {
+                                       srvObj->restartUnitConfig(yield);
+                                   }
+                               }
+                               updateInProgress = false;
+                           });
+    });
+}
+
+void ServiceConfig::registerProperties()
+{
+    srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
+
+    if (!socketObjectPath.empty())
+    {
+        sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
+        sockAttrIface->register_property(
+            sockAttrPropPort, portNum,
+            [this](const uint16_t& req, uint16_t& res) {
+                if (!internalSet)
+                {
+                    if (req == res)
+                    {
+                        return 1;
+                    }
+                    if (updateInProgress)
+                    {
+                        return 0;
+                    }
+                    portNum = req;
+                    updatedFlag |=
+                        (1 << static_cast<uint8_t>(UpdatedProp::port));
+                    startServiceRestartTimer();
+                }
+                res = req;
+                return 1;
+            });
+    }
+
+    srvCfgIface->register_property(
+        srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
+            if (!internalSet)
+            {
+                if (req == res)
+                {
+                    return 1;
+                }
+                if (updateInProgress)
+                {
+                    return 0;
+                }
+                unitMaskedState = req;
+                unitEnabledState = !unitMaskedState;
+                unitRunningState = !unitMaskedState;
+                updatedFlag |=
+                    (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
+                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
+                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
+                internalSet = true;
+                srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
+                srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
+                internalSet = false;
+                startServiceRestartTimer();
+            }
+            res = req;
+            return 1;
+        });
+
+    srvCfgIface->register_property(
+        srvCfgPropEnabled, unitEnabledState,
+        [this](const bool& req, bool& res) {
+            if (!internalSet)
+            {
+                if (req == res)
+                {
+                    return 1;
+                }
+                if (updateInProgress)
+                {
+                    return 0;
+                }
+                if (unitMaskedState)
+                { // block updating if masked
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        "Invalid value specified");
+                    return -EINVAL;
+                }
+                unitEnabledState = req;
+                updatedFlag |=
+                    (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
+                startServiceRestartTimer();
+            }
+            res = req;
+            return 1;
+        });
+
+    srvCfgIface->register_property(
+        srvCfgPropRunning, unitRunningState,
+        [this](const bool& req, bool& res) {
+            if (!internalSet)
+            {
+                if (req == res)
+                {
+                    return 1;
+                }
+                if (updateInProgress)
+                {
+                    return 0;
+                }
+                if (unitMaskedState)
+                { // block updating if masked
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        "Invalid value specified");
+                    return -EINVAL;
+                }
+                unitRunningState = req;
+                updatedFlag |=
+                    (1 << static_cast<uint8_t>(UpdatedProp::runningState));
+                startServiceRestartTimer();
+            }
+            res = req;
+            return 1;
+        });
+
+    srvCfgIface->initialize();
+    if (!socketObjectPath.empty())
+    {
+        sockAttrIface->initialize();
+    }
+    return;
+}
+
+} // namespace service
+} // namespace phosphor
diff --git a/src/utils.cpp b/src/utils.cpp
index 775c39e..b4ed9f7 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -1,134 +1,134 @@
-/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-*/
-#include "utils.hpp"
-
-static inline void checkAndThrowInternalFailure(boost::system::error_code& ec,
-                                                const std::string& msg)
-{
-    if (ec)
-    {
-        std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg);
-        phosphor::logging::log<phosphor::logging::level::ERR>(msgToLog.c_str());
-        phosphor::logging::elog<
-            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
-    }
-    return;
-}
-
-void systemdDaemonReload(
-    const std::shared_ptr<sdbusplus::asio::connection>& conn,
-    boost::asio::yield_context yield)
-{
-    boost::system::error_code ec;
-    conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
-                              sysdReloadMethod);
-    checkAndThrowInternalFailure(ec, "daemon-reload operation failed");
-    return;
-}
-
-static inline uint32_t getJobId(const std::string& path)
-{
-    auto pos = path.rfind("/");
-    if (pos == std::string::npos)
-    {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Unable to get job id from job path");
-        phosphor::logging::elog<
-            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
-    }
-    return static_cast<uint32_t>(std::stoul(path.substr(pos + 1)));
-}
-
-void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn,
-                       boost::asio::yield_context yield,
-                       const std::string& unitName,
-                       const std::string& actionMethod)
-{
-    boost::system::error_code ec;
-    auto jobPath = conn->yield_method_call<sdbusplus::message::object_path>(
-        yield, ec, sysdService, sysdObjPath, sysdMgrIntf, actionMethod,
-        unitName, sysdReplaceMode);
-    checkAndThrowInternalFailure(ec,
-                                 "Systemd operation failed, " + actionMethod);
-    // Query the job till it doesn't exist anymore.
-    // this way we guarantee that queued job id is done.
-    // this is needed to make sure dependency list on units are
-    // properly handled.
-    while (1)
-    {
-        ec.clear();
-        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
-                                  sysdMgrIntf, sysdGetJobMethod,
-                                  getJobId(jobPath.str));
-        if (ec)
-        {
-            if (ec.value() == boost::system::errc::no_such_file_or_directory)
-            {
-                // Queued job is done, return now
-                return;
-            }
-            phosphor::logging::log<phosphor::logging::level::ERR>(
-                "Systemd operation failed for job query");
-            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
-                                        Error::InternalFailure>();
-        }
-        boost::asio::steady_timer sleepTimer(conn->get_io_context());
-        sleepTimer.expires_after(std::chrono::milliseconds(20));
-        ec.clear();
-        sleepTimer.async_wait(yield[ec]);
-        checkAndThrowInternalFailure(ec, "Systemd operation timer error");
-    }
-    return;
-}
-
-void systemdUnitFilesStateChange(
-    const std::shared_ptr<sdbusplus::asio::connection>& conn,
-    boost::asio::yield_context yield, const std::vector<std::string>& unitFiles,
-    const std::string& unitState, bool maskedState, bool enabledState)
-{
-    boost::system::error_code ec;
-
-    if (unitState == stateMasked && !maskedState)
-    {
-        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
-                                  sysdMgrIntf, "UnmaskUnitFiles", unitFiles,
-                                  false);
-        checkAndThrowInternalFailure(ec, "Systemd UnmaskUnitFiles() failed.");
-    }
-    else if (unitState != stateMasked && maskedState)
-    {
-        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
-                                  sysdMgrIntf, "MaskUnitFiles", unitFiles,
-                                  false, false);
-        checkAndThrowInternalFailure(ec, "Systemd MaskUnitFiles() failed.");
-    }
-    ec.clear();
-    if (unitState != stateEnabled && enabledState)
-    {
-        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
-                                  sysdMgrIntf, "EnableUnitFiles", unitFiles,
-                                  false, false);
-        checkAndThrowInternalFailure(ec, "Systemd EnableUnitFiles() failed.");
-    }
-    else if (unitState != stateDisabled && !enabledState)
-    {
-        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
-                                  sysdMgrIntf, "DisableUnitFiles", unitFiles,
-                                  false);
-        checkAndThrowInternalFailure(ec, "Systemd DisableUnitFiles() failed.");
-    }
-    return;
-}
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include "utils.hpp"
+
+static inline void checkAndThrowInternalFailure(boost::system::error_code& ec,
+                                                const std::string& msg)
+{
+    if (ec)
+    {
+        std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg);
+        phosphor::logging::log<phosphor::logging::level::ERR>(msgToLog.c_str());
+        phosphor::logging::elog<
+            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
+    }
+    return;
+}
+
+void systemdDaemonReload(
+    const std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::yield_context yield)
+{
+    boost::system::error_code ec;
+    conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
+                              sysdReloadMethod);
+    checkAndThrowInternalFailure(ec, "daemon-reload operation failed");
+    return;
+}
+
+static inline uint32_t getJobId(const std::string& path)
+{
+    auto pos = path.rfind("/");
+    if (pos == std::string::npos)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Unable to get job id from job path");
+        phosphor::logging::elog<
+            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
+    }
+    return static_cast<uint32_t>(std::stoul(path.substr(pos + 1)));
+}
+
+void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn,
+                       boost::asio::yield_context yield,
+                       const std::string& unitName,
+                       const std::string& actionMethod)
+{
+    boost::system::error_code ec;
+    auto jobPath = conn->yield_method_call<sdbusplus::message::object_path>(
+        yield, ec, sysdService, sysdObjPath, sysdMgrIntf, actionMethod,
+        unitName, sysdReplaceMode);
+    checkAndThrowInternalFailure(ec,
+                                 "Systemd operation failed, " + actionMethod);
+    // Query the job till it doesn't exist anymore.
+    // this way we guarantee that queued job id is done.
+    // this is needed to make sure dependency list on units are
+    // properly handled.
+    while (1)
+    {
+        ec.clear();
+        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
+                                  sysdMgrIntf, sysdGetJobMethod,
+                                  getJobId(jobPath.str));
+        if (ec)
+        {
+            if (ec.value() == boost::system::errc::no_such_file_or_directory)
+            {
+                // Queued job is done, return now
+                return;
+            }
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Systemd operation failed for job query");
+            phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
+                                        Error::InternalFailure>();
+        }
+        boost::asio::steady_timer sleepTimer(conn->get_io_context());
+        sleepTimer.expires_after(std::chrono::milliseconds(20));
+        ec.clear();
+        sleepTimer.async_wait(yield[ec]);
+        checkAndThrowInternalFailure(ec, "Systemd operation timer error");
+    }
+    return;
+}
+
+void systemdUnitFilesStateChange(
+    const std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::yield_context yield, const std::vector<std::string>& unitFiles,
+    const std::string& unitState, bool maskedState, bool enabledState)
+{
+    boost::system::error_code ec;
+
+    if (unitState == stateMasked && !maskedState)
+    {
+        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
+                                  sysdMgrIntf, "UnmaskUnitFiles", unitFiles,
+                                  false);
+        checkAndThrowInternalFailure(ec, "Systemd UnmaskUnitFiles() failed.");
+    }
+    else if (unitState != stateMasked && maskedState)
+    {
+        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
+                                  sysdMgrIntf, "MaskUnitFiles", unitFiles,
+                                  false, false);
+        checkAndThrowInternalFailure(ec, "Systemd MaskUnitFiles() failed.");
+    }
+    ec.clear();
+    if (unitState != stateEnabled && enabledState)
+    {
+        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
+                                  sysdMgrIntf, "EnableUnitFiles", unitFiles,
+                                  false, false);
+        checkAndThrowInternalFailure(ec, "Systemd EnableUnitFiles() failed.");
+    }
+    else if (unitState != stateDisabled && !enabledState)
+    {
+        conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
+                                  sysdMgrIntf, "DisableUnitFiles", unitFiles,
+                                  false);
+        checkAndThrowInternalFailure(ec, "Systemd DisableUnitFiles() failed.");
+    }
+    return;
+}
