/*
// 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 "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "external_storer.hpp"
#include "health.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "hex_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"
#include "system_utils.hpp"

#include <boost/container/flat_map.hpp>
#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <string>
#include <sdbusplus/server/object.hpp>
#include <sdbusplus/utility/dedup_variant.hpp>

#include <algorithm>
#include <array>
#include <cstdint>
#include <limits>
#include <string_view>
#include <unordered_map>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

using resourceIdToSubtreeRespMapType =
    std::unordered_map<std::string,
                       std::pair<std::string, dbus::utility::MapperServiceMap>>;
using ManagedObjectByServiceMap =
    std::unordered_map<std::string, dbus::utility::ManagedObjectType>;

constexpr std::array<std::string_view, 2> processorInterfaces = {
    "xyz.openbmc_project.Inventory.Item.Cpu",
    "xyz.openbmc_project.Inventory.Item.Accelerator"};

constexpr std::array<std::string_view, 1> subProcessorCoreInterfaces = {
    "xyz.openbmc_project.Inventory.Item.CpuCore"};

constexpr std::array<std::string_view, 1> subProcessorThreadInterfaces = {
    "xyz.openbmc_project.Inventory.Item.CpuThread"};

inline void getSubProcessorThreadCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& coreId,
    const std::string& corePath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap);

inline void getSubProcessorCoreCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& cpuPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap);

inline void getProcessorCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap, uint8_t expandLevel,
    const std::string& systempath);

inline void handleGetCpuCoreThreadMetrics(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& cpuArg,
    const std::string& coreArg, const std::string& threadArg);

inline void
    handleGetCpuMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const nlohmann::json::json_pointer& jsonPtr,
                        const std::string& cpuArg);

inline bool
    isValidSystemServicePair(const std::string& systemName,
                                     const std::string& service);

/**
 * @brief Returns a collection of dbus interfaces applicable to SubProcessor's
 * subtree.
 *
 * @param[in] expandLevel Requested expand level.
 *
 * @return Vector of strings capturing dbus interface names.
 */
inline std::vector<std::string>
    getInterfacesForSubProcessorSubtree(uint8_t expandLevel)
{
    std::vector<std::string> subProcessorSubtreeInterfaces = {
        subProcessorCoreInterfaces.begin(), subProcessorCoreInterfaces.end()};
    if (expandLevel > 0)
    {
        subProcessorSubtreeInterfaces.insert(
            subProcessorSubtreeInterfaces.end(),
            subProcessorThreadInterfaces.begin(),
            subProcessorThreadInterfaces.end());
        return subProcessorSubtreeInterfaces;
    }
    return subProcessorSubtreeInterfaces;
}


/**
 * @brief Check if the given system name and service name are a valid pair.
 *
 * @param[in] systemName The name of the system.
 * @param[in] service The name of the service.
 *
 * @return True if the pair is valid, false otherwise.
 */
inline bool isValidSystemServicePair(const std::string& systemName,
                                     const std::string& service)
{
    static const std::unordered_map<std::string, std::string>
        validSystemServices = {
        {"system1", "xyz.openbmc_project.pldm0"},
        {"system2", "xyz.openbmc_project.pldm1"},
        {"system", "xyz.openbmc_project.pldm"}};

    auto it = validSystemServices.find(systemName);
    return (it != validSystemServices.end() && it->second == service);
}

/**
 *
 * @param[in,out] aResp   Async HTTP response.
 * @param[in] processorPath The D-Bus path of the processor.
 * @param[in] jsonPtr     json pointer to index the response fields.
 * @param[in] systemName  system name
 */
inline void getProcessorMaxTDP(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& processorPath,
                               const nlohmann::json::json_pointer& jsonPtr,
                               const std::string& systemName)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Effecter.Value"};

    managedStore::ManagedObjectStoreContext pldmContext(aResp);

    // Get all PLDM effecters using the ManagedObjectStore
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/pldm", 0, interfaces, pldmContext,
        [aResp, processorPath, jsonPtr,
         systemName](const boost::system::error_code& ec,
                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error for pldm effecters: "
                             << ec;
            // It's not a fatal error if PLDM isn't present, so just return.
            return;
        }

        // Iterate through the PLDM services (CN0, CN1, etc.)
        for (const auto& [effecterPath, serviceMap] : subtree)
        {
            if (serviceMap.empty())
            {
                continue;
            }

            // 2. Inner loop iterates over the key-value pairs in 'serviceMap'.
            for (const auto& servicePair : serviceMap)
            {
                // 3. We only use '.first' to get the service name (the key).
                const std::string& service = servicePair.first;
                BMCWEB_LOG_DEBUG << "Service Name: " << service
                                 << "Effecter Path: " << effecterPath;

                // Inverted condition to skip invalid pairs first
                if (!isValidSystemServicePair(systemName, service))
                {
                    continue;
                }

                // The effecter object path looks like:
                // /xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4.
                // This object implements the
                // xyz.openbmc_project.Effecter.Value interface, which
                // stores the configured MaxTDPWatts field. The object name
                // can be same for both pldm services on muti CN systems
                if (effecterPath.find("SOC_TDP") != std::string::npos)
                {
                    // Get the MaxTDPWatts value
                    managedStore::ManagedObjectStoreContext valueContext(aResp);
                    dbus_utils::getProperty<double>(
                        service, effecterPath,
                        "xyz.openbmc_project.Effecter.Value", "Value",
                        valueContext,
                        [aResp, jsonPtr,
                         effecterPath](const boost::system::error_code& ec3,
                                       const double& value) {
                        if (ec3)
                        {
                            BMCWEB_LOG_ERROR
                                << "DBUS response error for effecterPath: "
                                << effecterPath << " ,Error: " << ec3.message();
                            return;
                        }
                        aResp->res.jsonValue[jsonPtr]["MaxTDPWatts"] = value;
                    });
                    return;
                }
            }
        }
    });
}

/**
 * @brief Returns a collection of dbus interfaces applicable to Processor's
 * subtree.
 *
 * @param[in] expandLevel Requested expand level.
 *
 * @return Vector of strings capturing dbus interface names.
 */
inline std::vector<std::string>
    getInterfacesForProcessorSubtree(uint8_t expandLevel)
{
    if (expandLevel > 0)
    {
        std::vector<std::string> processorSubtreeInterfaces =
            getInterfacesForSubProcessorSubtree(expandLevel - 1);
        processorSubtreeInterfaces.insert(processorSubtreeInterfaces.end(),
                                          processorInterfaces.begin(),
                                          processorInterfaces.end());
        return processorSubtreeInterfaces;
    }
    return {processorInterfaces.begin(), processorInterfaces.end()};
}

/**
 * @brief Fill out uuid info of a processor by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getProcessorUUID(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const std::string& objPath, const std::string& interface,
                     const nlohmann::json::json_pointer& jsonPtr,
                     const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Processor UUID";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const std::string* property = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "UUID", property);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (property != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["UUID"] = *property;
    }
}

/**
 * @brief Populates Cpu information using given dbus properties.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] dbusProperties    DBusPropertiesMap to parse for Cpu data.
 *
 * @return void
 */
inline void getCpuDataFromDbusProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const dbus::utility::DBusPropertiesMap& dbusProperties)
{
    BMCWEB_LOG_DEBUG << "Get CPU resources from dbus properties.";

    // Set the default value of state
    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    for (const auto& property : dbusProperties)
    {
        if (property.first == "Present")
        {
            const bool* cpuPresent = std::get_if<bool>(&property.second);
            if (cpuPresent == nullptr)
            {
                // Important property not in desired type
                messages::internalError(aResp->res);
                return;
            }
            if (!*cpuPresent)
            {
                // Slot is not populated
                aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
            }
        }
        else if (property.first == "Functional")
        {
            const bool* cpuFunctional = std::get_if<bool>(&property.second);
            if (cpuFunctional == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (!*cpuFunctional)
            {
                aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
            }
        }
        else if (property.first == "CoreCount")
        {
            const uint16_t* coresCount =
                std::get_if<uint16_t>(&property.second);
            if (coresCount == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            aResp->res.jsonValue[jsonPtr]["TotalCores"] = *coresCount;
        }
        else if (property.first == "MaxSpeedInMhz")
        {
            const uint32_t* value = std::get_if<uint32_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["MaxSpeedMHz"] = *value;
            }
        }
        else if (property.first == "Socket")
        {
            const std::string* value =
                std::get_if<std::string>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["Socket"] = *value;
            }
        }
        else if (property.first == "ThreadCount")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["TotalThreads"] = *value;
            }
        }
        else if (property.first == "CoreEnable")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr)
            {
                aResp->res.jsonValue[jsonPtr]["TotalEnabledCores"] = *value;
            }
        }
        else if (property.first == "EffectiveFamily")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value != nullptr && *value != 2)
            {
                aResp->res
                    .jsonValue[jsonPtr]["ProcessorId"]["EffectiveFamily"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
        else if (property.first == "EffectiveModel")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["EffectiveModel"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
        else if (property.first == "Id")
        {
            const uint64_t* value = std::get_if<uint64_t>(&property.second);
            if (value != nullptr && *value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]
                                    ["IdentificationRegisters"] =
                    "0x" + intToHexString(*value, 16);
            }
        }
        else if (property.first == "Microcode")
        {
            const uint32_t* value = std::get_if<uint32_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != 0)
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                    "0x" + intToHexString(*value, 8);
            }
        }
        else if (property.first == "Step")
        {
            const uint16_t* value = std::get_if<uint16_t>(&property.second);
            if (value == nullptr)
            {
                messages::internalError(aResp->res);
                return;
            }
            if (*value != std::numeric_limits<uint16_t>::max())
            {
                aResp->res.jsonValue[jsonPtr]["ProcessorId"]["Step"] =
                    "0x" + intToHexString(*value, 4);
            }
        }
    }
}

/**
 * @brief Populates Cpu information using given dbus Managed Objects.
 *
 * @param[in] aResp         Async HTTP response.
 * @param[in] cpuId         Cpu identifier.
 * @param[in] objPath       Cpu dbus object path.
 * @param[in] interface     Cpu dbus interface name.
 * @param[in] jsonPtr       json pointer to index the response fields.
 * @param[in] dbusData      Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void getCpuData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& cpuId, const std::string& objPath,
                       const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& dbusData)
{
    BMCWEB_LOG_DEBUG << "Get Cpu data from managed objects for object "
                     << objPath;
    aResp->res.jsonValue[jsonPtr]["Id"] = cpuId;
    aResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "CPU";

    bool slotPresent = false;
    std::string corePath = objPath + "/core";
    size_t totalCores = 0;
    for (const auto& object : dbusData)
    {
        dbus::utility::DBusPropertiesMap properties;
        if (object.first.str == objPath)
        {
            dbus_utils::getPropertiesFromManagedObjects(dbusData, objPath,
                                                        interface, properties);
            getCpuDataFromDbusProperties(aResp, jsonPtr, properties);
        }
        else if (object.first.str.starts_with(corePath))
        {
            dbus_utils::getPropertiesFromManagedObjects(
                dbusData, object.first.str,
                "xyz.openbmc_project.Inventory.Item", properties);

            for (const auto& property : properties)
            {
                if (property.first != "Present")
                {
                    continue;
                }
                const bool* present = std::get_if<bool>(&property.second);
                if (present != nullptr && *present)
                {
                    slotPresent = true;
                    totalCores++;
                }
            }
        }
    }
    // In getCpuDataFromDbusProperties(), state and health are set based on the
    // present and functional status. If core count is zero, then it has a
    // higher precedence.
    if (slotPresent)
    {
        if (totalCores == 0)
        {
            // Slot is not populated, set status end return
            aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
            aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
        }
        aResp->res.jsonValue[jsonPtr]["TotalCores"] = totalCores;
    }
}

/**
 * @brief Populates Cpu asset information using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] objPath           Cpu dbus object path.
 * @param[in] interface         Cpu dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void
    getCpuAssetData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                    const std::string& objPath, const std::string& interface,
                    const nlohmann::json::json_pointer& jsonPtr,
                    const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
    const std::string* serialNumber = nullptr;
    const std::string* model = nullptr;
    const std::string* manufacturer = nullptr;
    const std::string* partNumber = nullptr;
    const std::string* sparePartNumber = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
        serialNumber, "Model", model, "Manufacturer", manufacturer,
        "PartNumber", partNumber, "SparePartNumber", sparePartNumber);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (serialNumber != nullptr && !serialNumber->empty())
    {
        aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *serialNumber;
    }

    if ((model != nullptr) && !model->empty())
    {
        aResp->res.jsonValue[jsonPtr]["Model"] = *model;
    }

    if (manufacturer != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *manufacturer;

        // Otherwise would be unexpected.
        if (manufacturer->find("Intel") != std::string::npos)
        {
            aResp->res.jsonValue[jsonPtr]["ProcessorArchitecture"] = "x86";
            aResp->res.jsonValue[jsonPtr]["InstructionSet"] = "x86-64";
        }
        else if (manufacturer->find("IBM") != std::string::npos)
        {
            aResp->res.jsonValue[jsonPtr]["ProcessorArchitecture"] = "Power";
            aResp->res.jsonValue[jsonPtr]["InstructionSet"] = "PowerISA";
        }
    }

    if (partNumber != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["PartNumber"] = *partNumber;
    }

    if (sparePartNumber != nullptr && !sparePartNumber->empty())
    {
        aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *sparePartNumber;
    }
}

/**
 * @brief Populates Cpu revision data using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] objPath           Cpu dbus object path.
 * @param[in] interface         Cpu dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse for Cpu data.
 *
 * @return void
 */
inline void
    getCpuRevisionData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& objPath, const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const std::string* version = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "Version", version);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (version != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["Version"] = *version;
    }
}

/**
 * @brief Populates accelerator data using given dbus Managed Objects.
 *
 * @param[in] aResp             Async HTTP response.
 * @param[in] acclrtrId         Accelerator identifier.
 * @param[in] objPath           Accelerator dbus object path.
 * @param[in] interface         Accelerator dbus interface name.
 * @param[in] jsonPtr           json pointer to index the response fields.
 * @param[in] managedObjects    Dbus Managed Objects to parse.
 *
 * @return void
 */
inline void
    getAcceleratorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& acclrtrId, const std::string& objPath,
                       const std::string& interface,
                       const nlohmann::json::json_pointer& jsonPtr,
                       const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG
        << "Get available system Accelerator resources by service.";

    const bool* functional = nullptr;
    const bool* present = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "Functional", functional,
        "Present", present);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    std::string state = "Enabled";
    std::string health = "OK";

    if (present != nullptr && !*present)
    {
        state = "Absent";
    }

    if (functional != nullptr && !*functional)
    {
        if (state == "Enabled")
        {
            health = "Critical";
        }
    }

    aResp->res.jsonValue[jsonPtr]["Id"] = acclrtrId;
    aResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = state;
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = health;
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Accelerator";
}

// OperatingConfig D-Bus Types
using TurboProfileProperty = std::vector<std::tuple<uint32_t, size_t>>;
using BaseSpeedPrioritySettingsProperty =
    std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>;
// uint32_t and size_t may or may not be the same type, requiring a dedup'd
// variant

/**
 * Fill out the HighSpeedCoreIDs in a Processor resource from the given
 * OperatingConfig D-Bus property.
 *
 * @param[in,out]   aResp               Async HTTP response.
 * @param[in]       jsonPtr     json pointer to index the response fields
 * @param[in]       baseSpeedSettings   Full list of base speed priority groups,
 *                                      to use to determine the list of high
 *                                      speed cores.
 */
inline void highSpeedCoreIdsHandler(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
{
    // The D-Bus property does not indicate which bucket is the "high
    // priority" group, so let's discern that by looking for the one with
    // highest base frequency.
    auto highPriorityGroup = baseSpeedSettings.cend();
    uint32_t highestBaseSpeed = 0;
    for (auto it = baseSpeedSettings.cbegin(); it != baseSpeedSettings.cend();
         ++it)
    {
        const uint32_t baseFreq = std::get<uint32_t>(*it);
        if (baseFreq > highestBaseSpeed)
        {
            highestBaseSpeed = baseFreq;
            highPriorityGroup = it;
        }
    }

    nlohmann::json& jsonCoreIds =
        aResp->res.jsonValue[jsonPtr]["HighSpeedCoreIDs"];
    jsonCoreIds = nlohmann::json::array();

    // There may not be any entries in the D-Bus property, so only populate
    // if there was actually something there.
    if (highPriorityGroup != baseSpeedSettings.cend())
    {
        jsonCoreIds = std::get<std::vector<uint32_t>>(*highPriorityGroup);
    }
}

/**
 * Fill out OperatingConfig related items in a Processor resource by requesting
 * data from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       cpuId           CPU D-Bus name.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const std::string& cpuId, const std::string& objPath,
                     const std::string& interface,
                     const nlohmann::json::json_pointer& jsonPtr,
                     const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId;

    nlohmann::json& json = aResp->res.jsonValue;

    const sdbusplus::message::object_path* appliedConfig = nullptr;
    const bool* baseSpeedPriorityEnabled = nullptr;
    const BaseSpeedPrioritySettingsProperty* baseSpeedList = nullptr;

    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                                interface, properties);

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
        appliedConfig, "BaseSpeedPriorityEnabled", baseSpeedPriorityEnabled);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (appliedConfig != nullptr)
    {
        const std::string& dbusPath = appliedConfig->str;
        std::string uri = "/redfish/v1/Systems/system/Processors/" + cpuId +
                          "/OperatingConfigs";
        nlohmann::json::object_t operatingConfig;
        operatingConfig["@odata.id"] = uri;
        json[jsonPtr]["OperatingConfigs"] = std::move(operatingConfig);

        // Reuse the D-Bus config object name for the Redfish
        // URI
        size_t baseNamePos = dbusPath.rfind('/');
        if (baseNamePos == std::string::npos ||
            baseNamePos == (dbusPath.size() - 1))
        {
            // If the AppliedConfig was somehow not a valid path,
            // skip adding any more properties, since everything
            // else is tied to this applied config.
            messages::internalError(aResp->res);
            return;
        }
        uri += '/';
        uri += dbusPath.substr(baseNamePos + 1);
        nlohmann::json::object_t appliedOperatingConfig;
        appliedOperatingConfig["@odata.id"] = uri;
        json[jsonPtr]["AppliedOperatingConfig"] =
            std::move(appliedOperatingConfig);

        // Once we found the current applied config, read the base freq core ids
        // out of Operating config.

        dbus::utility::DBusPropertiesMap config;
        dbus_utils::getPropertiesFromManagedObjects(
            managedObjects, dbusPath,
            "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", config);

        const bool parseConfigSuccess = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), config,
            "BaseSpeedPrioritySettings", baseSpeedList);

        if (!parseConfigSuccess)
        {
            messages::internalError(aResp->res);
            return;
        }

        if (baseSpeedList != nullptr)
        {
            highSpeedCoreIdsHandler(aResp, jsonPtr, *baseSpeedList);
        }
    }

    if (baseSpeedPriorityEnabled != nullptr)
    {
        json[jsonPtr]["BaseSpeedPriorityState"] =
            *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
    }
}

/**
 * Populate the unique identifier in a Processor resource by requesting data
 * from the given D-Bus object.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         json pointer to index the response fields
 * @param[in]       managedObjects  Dbus objects with interfaces and properties.
 */
inline void
    getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                   const std::string& objectPath, const std::string& interface,
                   const nlohmann::json::json_pointer& jsonPtr,
                   const dbus::utility::ManagedObjectType& managedObjects)
{
    BMCWEB_LOG_DEBUG << "Get CPU UniqueIdentifier";
    dbus::utility::DBusPropertiesMap properties;
    dbus_utils::getPropertiesFromManagedObjects(managedObjects, objectPath,
                                                interface, properties);

    const std::string* id = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), properties, "UniqueIdentifier", id);

    if (!success)
    {
        messages::internalError(aResp->res);
        return;
    }

    if (id != nullptr)
    {
        aResp->res.jsonValue[jsonPtr]["ProcessorId"]
                            ["ProtectedIdentificationNumber"] = *id;
    }
}

inline void getCpuChassisAssociation(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& processorId, const std::string& objectPath,
    const nlohmann::json::json_pointer& jsonPtr)
{
    BMCWEB_LOG_DEBUG << "Get CPU -- Chassis association";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", objectPath + "/chassis",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp{asyncResp}, jsonPtr,
         processorId](const boost::system::error_code ec,
                      const std::vector<std::string>& chassisList) {
        if (ec)
        {
            return;
        }
        if (chassisList.empty())
        {
            return;
        }
        if (chassisList.size() > 1)
        {
            BMCWEB_LOG_DEBUG << processorId
                             << " is associated with mutliple chassis";
            return;
        }

        sdbusplus::message::object_path chassisPath(chassisList[0]);
        std::string chassisName = chassisPath.filename();
        if (chassisName.empty())
        {
            BMCWEB_LOG_ERROR << "filename() is empty in " << chassisPath.str;
            return;
        }
        asyncResp->res.jsonValue[jsonPtr]["Links"]["Chassis"] = {
            {"@odata.id", "/redfish/v1/Chassis/" + chassisName}};
    });
}

/**
 * @brief Fill out the links to associated memory of a processor
 * by looking up its D-Bus association.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void getMemoryLinks(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& objectPath,
                           const nlohmann::json::json_pointer& jsonPtr)
{
    BMCWEB_LOG_DEBUG << "Get Processor -- Memory association";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", objectPath + "/memory",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp, jsonPtr](const boost::system::error_code ec,
                             const std::vector<std::string>& memoryList) {
        if (ec)
        {
            return;
        }
        if (memoryList.empty())
        {
            return;
        }
        nlohmann::json::array_t memoryLinks;
        for (const std::string& memory : memoryList)
        {
            sdbusplus::message::object_path memoryPath(memory);
            const std::string memoryName = memoryPath.filename();
            if (memoryName.empty())
            {
                BMCWEB_LOG_ERROR << "filename() is empty in " << memoryPath.str;
                return;
            }
            nlohmann::json::object_t memoryObject;
            memoryObject["@odata.id"] =
                "/redfish/v1/Systems/system/Memory/" + memoryName;
            memoryLinks.emplace_back(memoryObject);
        }
        asyncResp->res.jsonValue[jsonPtr]["Links"]["Memory"] =
            std::move(memoryLinks);
    });
}

/**
 * Find the D-Bus object representing the requested Processor, and call the
 * handler with the results. If matching object is not found, add 404 error to
 * response and don't call the handler.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       processorId     Redfish Processor Id.
 * @param[in]       handler         Callback to continue processing request upon
 *                                  successfully finding object.
 */
template <typename Handler>
inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                               const std::string& processorId,
                               const std::string& systemPath, Handler&& handler)
{
    BMCWEB_LOG_DEBUG << "Get available system processor resources.";

    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";
    // The subtree to query for Dimms changes if single or multi-host
    std::string subtreeRoot = "/xyz/openbmc_project/inventory";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
        subtreeRoot = systemPath;
    }

    managedStore::ManagedObjectStoreContext context(resp);
    managedStore::GetManagedObjectStore()->getSubTree(
        subtreeRoot, 0, processorInterfaces, context,
        [resp{resp}, processorId, multiHost, systemPath,
         handler = std::forward<Handler>(handler), context](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error: " << ec.value();
            messages::internalError(resp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);
        if (serviceNames.empty())
        {
            BMCWEB_LOG_ERROR << "Service list is empty";
            messages::internalError(resp->res);
            return;
        }

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [resp{std::move(resp)}, subtree, processorId, multiHost, systemPath,
             handler = std::forward<Handler>(handler)](
                const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                BMCWEB_LOG_ERROR
                    << "GetManagedObjects does not return any object.";
                messages::internalError(resp->res);
                return;
            }
            BMCWEB_LOG_DEBUG << "Looping through subtree";

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                BMCWEB_LOG_DEBUG << objectPath;
                if (multiHost && !objectPath.starts_with(systemPath))
                {
                    continue;
                }

                // Ignore any objects which don't end with our desired cpu name
                if (!objectPath.ends_with(processorId))
                {
                    continue;
                }

                // Filter out objects that don't have the CPU-specific
                // interfaces to make sure we can return 404 on non-CPUs
                // (e.g. /redfish/../Processors/dimm0)
                if (!dbus_utils::findInterfacesInServiceMap(
                        serviceMap, processorInterfaces))
                {
                    continue;
                }
                handler(objectPath, subtree, managedObjectsByService);
                return;
            }
            messages::resourceNotFound(resp->res, "Processor", processorId);
        });
    });
}

inline void
    getProcessorState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& service, const std::string& objPath,
                      const nlohmann::json::json_pointer& jsonPtr)
{

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<bool>(
        service, objPath, "xyz.openbmc_project.Inventory.Item", "Present",
        requestContext,
        [asyncResp, objPath, jsonPtr](const boost::system::error_code& ec,
                                      bool present) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "get presence failed for Processor State "
                             << objPath << " with error " << ec;

            if (ec.value() != EBADR)
            {
                messages::internalError(asyncResp->res);
            }
            return;
        }
        asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
            present ? "Enabled" : "Absent";
    });
}

inline void getProcessorStateData(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& processorId,
    const std::string& procStateId, const nlohmann::json::json_pointer& jsonPtr)
{
    BMCWEB_LOG_DEBUG << "Processor State Id: " << procStateId;
    asyncResp->res.jsonValue[jsonPtr]["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                     "Processors", processorId, "Oem", "Google",
                                     "ProcessorStates", procStateId);
    asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#GoogleProcessorState.GoogleProcessorState";
    asyncResp->res.jsonValue[jsonPtr]["Id"] = procStateId;
    asyncResp->res.jsonValue[jsonPtr]["Name"] = "Processor";
    getProcessorState(asyncResp, "xyz.openbmc_project.EntityManager",
                      absl::StrCat("/xyz/openbmc_project/inventory/",
                                   systemName, "/processorstate/", procStateId),
                      jsonPtr);
}

void handleGetProcessorState(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& processorId,
    const std::string& procStateId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    getProcessorStateData(asyncResp, systemName, processorId, procStateId,
                          ""_json_pointer);
}

using Mapper = dbus::utility::MapperGetSubTreePathsResponse;
inline void getProcessorStateLinksOrExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const nlohmann::json::json_pointer& jsonPtr,
    const std::string& systemName, uint8_t expandLevel,
    const boost::system::error_code& ec, const Mapper& procStatePaths)
{
    BMCWEB_LOG_DEBUG << "Get Processor State URL";

    if (ec)
    {
        BMCWEB_LOG_ERROR
            << "ProcessorState Collection GetSubTreePaths handler Dbus error "
            << ec;
        return;
    }
    nlohmann::json::array_t procStateLinks;
    size_t stateCount = 0;
    for (const std::string& procState : procStatePaths)
    {
        std::string procStateId =
            sdbusplus::message::object_path(procState).filename();
        nlohmann::json::json_pointer processorStatePtr =
            jsonPtr / "Oem" / "Google" / "ProcessorStates" / stateCount++;
        if (expandLevel > 0)
        {
            getProcessorStateData(aResp, systemName, processorId, procStateId,
                                  processorStatePtr);
        }
        else
        {
            nlohmann::json::object_t procStateObj;
            aResp->res.jsonValue[processorStatePtr]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             systemName, "Processors",
                                             processorId, "Oem", "Google",
                                             "ProcessorStates", procStateId);
        }
    }
}

inline void
    getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                     const nlohmann::json::json_pointer& jsonPtr,
                     uint8_t expandLevel, const std::string& processorId,
                     const std::string& systemPath,
                     const std::string& objectPath,
                     const dbus::utility::MapperGetSubTreeResponse& subtree,
                     const ManagedObjectByServiceMap& managedObjectsMap)
{
    BMCWEB_LOG_DEBUG << "Get processor data.";

    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", systemName, "Processors", processorId);

    // Get service to interface map for cpu
    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (objectPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Cpu data not available for serviceName "
                             << serviceName;
            continue;
        }

        BMCWEB_LOG_DEBUG << "Populate processor data from dbus interfaces.";
        for (const auto& interface : interfaceList)
        {
            if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
            {
                getCpuAssetData(aResp, objectPath, interface, jsonPtr,
                                iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.Revision")
            {
                getCpuRevisionData(aResp, objectPath, interface, jsonPtr,
                                   iter->second);
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item.Cpu")
            {
                getCpuData(aResp, processorId, objectPath, interface, jsonPtr,
                           iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Item.Accelerator")
            {
                getAcceleratorData(aResp, processorId, objectPath, interface,
                                   jsonPtr, iter->second);
            }
            else if (
                interface ==
                "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig")
            {
                getCpuConfigData(aResp, processorId, objectPath, interface,
                                 jsonPtr, iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.LocationCode")
            {
                location_util::getLocationCodeFromManagedObject(
                    aResp, objectPath, interface, jsonPtr / "Location",
                    iter->second);
                location_util::getPartLocationContext(
                    aResp, jsonPtr / "Location", objectPath + "/chassis");
            }
            else if (interface == "xyz.openbmc_project.Common.UUID")
            {
                getProcessorUUID(aResp, objectPath, interface, jsonPtr,
                                 iter->second);
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier")
            {
                getCpuUniqueId(aResp, objectPath, interface, jsonPtr,
                               iter->second);
            }
            else
            {
                std::optional<std::string> locationType =
                    location_util::getLocationType(interface);
                if (locationType == std::nullopt)
                {
                    BMCWEB_LOG_DEBUG
                        << "getLocationType for Processor failed for "
                        << interface;
                    continue;
                }

                aResp->res.jsonValue[jsonPtr]["Location"]["PartLocation"]
                                    ["LocationType"] = *locationType;
            }
        }
    }
    getProcessorMaxTDP(aResp, objectPath, jsonPtr, systemName);
    getCpuChassisAssociation(aResp, processorId, objectPath, jsonPtr);
    getMemoryLinks(aResp, objectPath, jsonPtr);

    managedStore::ManagedObjectStoreContext context(aResp);
    constexpr std::array<std::string_view, 1> procStateIntf = {
        "xyz.openbmc_project.Inventory.Item.ProcessorState"};
    dbus_utils::getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, procStateIntf, context,
        std::bind_front(getProcessorStateLinksOrExpand, aResp, processorId,
                        jsonPtr, systemName, expandLevel));

    // TODO(edward): Support SubProcessors and ProcessorMetrics for Multi-Host
    // as use-cases arise
    if (!multiHost)
    {
        if (expandLevel > 0)
        {
            nlohmann::json::json_pointer subProcessorPtr =
                jsonPtr / "SubProcessors";
            getSubProcessorCoreCollectionWithExpand(
                aResp, subProcessorPtr, expandLevel - 1, processorId,
                objectPath, subtree, managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[jsonPtr]["SubProcessors"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors",
                                             processorId, "SubProcessors");
        }

        if (expandLevel > 0)
        {
            nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
            handleGetCpuMetrics(aResp, metricsPtr, processorId);
        }
        else
        {
            // Inserting the "Metrics" JSON stanza
            std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
            metricsUrl += "/ProcessorMetrics";
            nlohmann::json::object_t metricsObj;
            metricsObj["@odata.id"] = std::move(metricsUrl);
            aResp->res.jsonValue[jsonPtr]["Metrics"] = std::move(metricsObj);
        }
    }
}

template <typename Handler>
inline void getProcessorPaths(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                              const std::string& processorId, Handler&& handler)
{
    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.Cpu"};

    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [processorId, aResp{aResp},
         handler{std::forward<Handler>(handler)}](
            const boost::system::error_code ec,
            const std::vector<std::string>& subTreePaths) {
        if (ec)
        {
            handler(ec, "");
            return;
        }

        for (const std::string& cpuPath : subTreePaths)
        {
            if (sdbusplus::message::object_path(cpuPath).filename() !=
                processorId)
            {
                continue;
            }

            handler(ec, cpuPath);
            return;
        }

        // Set an error code since valid cpu path is not found
        handler(boost::system::errc::make_error_code(
                    boost::system::errc::no_such_file_or_directory),
                "");
    });
}

template <typename Handler>
inline void
    getSubProcessorCorePaths(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                             const std::string& processorId,
                             const std::string& coreId, Handler&& handler)
{

    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.Cpu"};
    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [processorId, coreId, aResp{aResp},
         handler{std::forward<Handler>(handler)},
         requestContext](const boost::system::error_code ec,
                         const std::vector<std::string>& subTreeCpuPaths) {
        if (ec)
        {
            handler(ec, "");
            return;
        }

        for (const std::string& cpuPath : subTreeCpuPaths)
        {
            if (sdbusplus::message::object_path(cpuPath).filename() !=
                processorId)
            {
                continue;
            }

            std::array<std::string_view, 1> interfaces{
                "xyz.openbmc_project.Inventory.Item.CpuCore"};
            managedStore::GetManagedObjectStore()->getSubTreePaths(
                "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
                [processorId, coreId, aResp{aResp},
                 handler](const boost::system::error_code ec2,
                          const std::vector<std::string>& subTreeCorePaths) {
                if (ec2)
                {
                    handler(ec2, "");
                    return;
                }

                for (const std::string& corePath : subTreeCorePaths)
                {
                    if (sdbusplus::message::object_path(corePath).filename() !=
                        coreId)
                    {
                        continue;
                    }
                    handler(ec2, corePath);
                    return;
                }
                // Set an error code since valid processor core path is not
                // found
                handler(boost::system::errc::make_error_code(
                            boost::system::errc::no_such_file_or_directory),
                        "");
            });
            return;
        }

        // Set an error code since valid processor cpu path is not found
        handler(boost::system::errc::make_error_code(
                    boost::system::errc::no_such_file_or_directory),
                "");
    });
}

inline void
    getCoreThreadData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                      const nlohmann::json::json_pointer& jsonPtr,
                      [[maybe_unused]] const uint8_t expandLevel,
                      const std::string& processorId, const std::string& coreId,
                      const std::string& threadId,
                      const std::string& threadPath,
                      const dbus::utility::MapperGetSubTreeResponse& subtree,
                      const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors", threadId);
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Thread";
    aResp->res.jsonValue[jsonPtr]["Id"] = threadId;

    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    bool present = false;
    bool functional = false;

    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (threadPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Thread data not available for serviceName "
                             << serviceName;
            continue;
        }

        for (const auto& interface : interfaceList)
        {
            dbus::utility::DBusPropertiesMap properties;
            if (interface == "xyz.openbmc_project.State."
                             "Decorator.OperationalStatus")
            {
                const bool* propertyFunctional = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Functional",
                    propertyFunctional);
                if (!success || propertyFunctional == nullptr)
                {
                    continue;
                }
                functional = *propertyFunctional;
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item")
            {
                const bool* propertyPresent = nullptr;
                const std::string* propertyPrettyName = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Present",
                    propertyPresent, "PrettyName", propertyPrettyName);
                if (!success)
                {
                    continue;
                }

                if (propertyPresent != nullptr)
                {
                    present = *propertyPresent;
                }

                if (propertyPrettyName != nullptr)
                {
                    aResp->res.jsonValue[jsonPtr]["Name"] = *propertyPrettyName;
                }
            }
            else if (interface ==
                     "xyz.openbmc_project.Inventory.Item.CpuThread")
            {
                const uint32_t* propertyMicrocode = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, threadPath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Microcode",
                    propertyMicrocode);
                if (!success)
                {
                    continue;
                }

                if (propertyMicrocode != nullptr)
                {
                    aResp->res
                        .jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                        "0x" + intToHexString(*propertyMicrocode, 8);
                }
            }
        }
    }

    if (!present)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
    }

    if (!functional)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
    }

    if (expandLevel > 0)
    {
        nlohmann::json::json_pointer metricsPtr = jsonPtr / "Metrics";
        handleGetCpuCoreThreadMetrics(aResp, metricsPtr, processorId, coreId,
                                      threadId);
    }
    else
    {
        // Inserting the "Metrics" JSON stanza
        std::string metricsUrl = aResp->res.jsonValue[jsonPtr]["@odata.id"];
        metricsUrl += "/ProcessorMetrics";
        nlohmann::json::object_t metricsObj;
        metricsObj["@odata.id"] = std::move(metricsUrl);
        aResp->res.jsonValue[jsonPtr]["Metrics"] = std::move(metricsObj);
    }
}

inline void getSubProcessorThreadData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const std::string& threadId, const boost::system::error_code ec,
    const std::string& corePath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No sub processor thread objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");

    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        corePath, 0, subProcessorThreadInterfaces, context,
        [aResp{aResp}, processorId, coreId, threadId,
         context](const boost::system::error_code& ec2,
                  const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec2)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error, ec2: " << ec2.value();
            // No sub processor core objects found by mapper
            if (ec2.value() == boost::system::errc::io_error)
            {
                messages::resourceNotFound(
                    aResp->res, "#Processor.v1_11_0.Processor", coreId);
                return;
            }

            messages::internalError(aResp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [aResp{aResp}, subtree, processorId, coreId, threadId](
                const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                messages::internalError(aResp->res);
                return;
            }

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                if (sdbusplus::message::object_path(objectPath).filename() !=
                    threadId)
                {
                    continue;
                }

                getCoreThreadData(aResp, ""_json_pointer, 0, processorId,
                                  coreId, threadId, objectPath, subtree,
                                  managedObjectsByService);
                return;
            }

            // Object not found
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", threadId);
        });
    });
}

inline void getSubProcessorThreadMembers(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const boost::system::error_code ec, const std::string& corePath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No sub processor core objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
    aResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");
    aResp->res.jsonValue["Name"] = "SubProcessor Collection";

    const boost::urls::url& subProcessorsPath = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");

    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuThread"};

    collection_util::getCollectionMembers(aResp, subProcessorsPath, interfaces,
                                          corePath.c_str());
}

inline void
    getCpuCoreData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                   const nlohmann::json::json_pointer& jsonPtr,
                   uint8_t expandLevel, const std::string& processorId,
                   const std::string& coreId, const std::string& corePath,
                   const dbus::utility::MapperGetSubTreeResponse& subtree,
                   const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#Processor.v1_11_0.Processor";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId);

    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor";
    aResp->res.jsonValue[jsonPtr]["ProcessorType"] = "Core";
    aResp->res.jsonValue[jsonPtr]["Id"] = coreId;

    if (expandLevel > 0)
    {
        nlohmann::json::json_pointer subProcessorPtr =
            jsonPtr / "SubProcessors";
        getSubProcessorThreadCollectionWithExpand(
            aResp, subProcessorPtr, expandLevel - 1, processorId, coreId,
            corePath, subtree, managedObjectsMap);
    }
    else
    {
        aResp->res.jsonValue[jsonPtr]["SubProcessors"]["@odata.id"] =
            crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "Processors", processorId,
                "SubProcessors", coreId, "SubProcessors");
    }

    aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
    aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";

    bool present = false;
    bool functional = false;

    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (corePath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        auto iter = managedObjectsMap.find(serviceName);
        if (iter == managedObjectsMap.end())
        {
            BMCWEB_LOG_DEBUG << "Cpu data not available for serviceName "
                             << serviceName;
            continue;
        }

        for (const auto& interface : interfaceList)
        {
            dbus::utility::DBusPropertiesMap properties;
            if (interface == "xyz.openbmc_project.State."
                             "Decorator.OperationalStatus")
            {
                const bool* propertyFunctional = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Functional",
                    propertyFunctional);

                if (!success)
                {
                    continue;
                }

                if (propertyFunctional != nullptr)
                {
                    functional = *propertyFunctional;
                }
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item")
            {
                const bool* propertyPresent = nullptr;
                const std::string* propertyPrettyName = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Present",
                    propertyPresent, "PrettyName", propertyPrettyName);

                if (!success)
                {
                    continue;
                }

                if (propertyPresent != nullptr)
                {
                    present = *propertyPresent;
                }

                if (propertyPrettyName != nullptr)
                {
                    aResp->res.jsonValue[jsonPtr]["Name"] = *propertyPrettyName;
                }
            }
            else if (interface == "xyz.openbmc_project.Inventory.Item.CpuCore")
            {
                const uint32_t* propertyMicrocode = nullptr;
                dbus_utils::getPropertiesFromManagedObjects(
                    iter->second, corePath, interface, properties);
                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), properties, "Microcode",
                    propertyMicrocode);
                if (!success)
                {
                    continue;
                }

                if (propertyMicrocode != nullptr)
                {
                    aResp->res
                        .jsonValue[jsonPtr]["ProcessorId"]["MicrocodeInfo"] =
                        "0x" + intToHexString(*propertyMicrocode, 8);
                }
            }
        }
    }

    if (!present)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
    }

    if (!functional)
    {
        aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "Critical";
    }

    // The "Metrics" stanza is deliberately omitted at the Core layer
}

inline void getSubProcessorCoreData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& processorId, const std::string& coreId,
    const boost::system::error_code ec, const std::string& cpuPath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No processor objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", processorId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");

    std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuCore"};
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        cpuPath, 0, interfaces, context,
        [aResp{aResp}, processorId, coreId,
         context](const boost::system::error_code& ec2,
                  const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec2)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error, ec2: " << ec2.value();
            // No processor objects found by mapper
            if (ec2.value() == boost::system::errc::io_error)
            {
                messages::resourceNotFound(
                    aResp->res, "#Processor.v1_11_0.Processor", processorId);
                return;
            }

            messages::internalError(aResp->res);
            return;
        }

        std::vector<std::string> serviceNames =
            dbus_utils::getServiceNamesFromSubtree(subtree);

        sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
        dbus_utils::getManagedObjectsInEachService(
            std::move(serviceNames), path, context,
            [aResp{aResp}, subtree, processorId,
             coreId](const ManagedObjectByServiceMap& managedObjectsByService) {
            if (managedObjectsByService.empty())
            {
                messages::internalError(aResp->res);
                return;
            }

            for (const auto& [objectPath, serviceMap] : subtree)
            {
                if (sdbusplus::message::object_path(objectPath).filename() !=
                    coreId)
                {
                    continue;
                }
                getCpuCoreData(aResp, ""_json_pointer, 0, processorId, coreId,
                               objectPath, subtree, managedObjectsByService);
                return;
            }

            // Object not found
            messages::resourceNotFound(aResp->res,
                                       "#Processor.v1_11_0.Processor", coreId);
        });
    });
}

inline void
    getSubProcessorCoreMembers(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& processorId,
                               const boost::system::error_code ec,
                               const std::string& cpuPath)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error, ec: " << ec.value();
        // No processor objects found by mapper
        if (ec.value() == boost::system::errc::io_error)
        {
            messages::resourceNotFound(
                aResp->res, "#Processor.v1_11_0.Processor", processorId);
            return;
        }

        messages::internalError(aResp->res);
        return;
    }

    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
    aResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");
    aResp->res.jsonValue["Name"] = "SubProcessor Collection";

    const boost::urls::url& subProcessorsPath = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");

    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.CpuCore"};

    collection_util::getCollectionMembers(aResp, subProcessorsPath, interfaces,
                                          cpuPath.c_str());
}

inline void getSubProcessorThreadCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& coreId,
    const std::string& corePath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor Collection";
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors", coreId, "SubProcessors");

    // Maps thread ID to threadObjectPath
    std::map<std::string, std::string, AlphanumLess<std::string>>
        threadIdToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {
        if (!objectPath.starts_with(corePath) ||
            !dbus_utils::findInterfacesInServiceMap(
                serviceMap, subProcessorThreadInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path threadPath(objectPath);
        const std::string& threadId = threadPath.filename();
        threadIdToObjectPath.insert({threadId, threadPath});
    }

    BMCWEB_LOG_DEBUG << "Core path: " << corePath
                     << " thread count: " << threadIdToObjectPath.size();

    if (threadIdToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU thread count was somehow empty";
        aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = 0;
        aResp->res.jsonValue[jsonPtr]["Members"] = nlohmann::json::array();
        return;
    }

    size_t threadMemberCount = 0;
    for (const auto& [threadId, _] : threadIdToObjectPath)
    {
        nlohmann::json::json_pointer threadMemberPtr =
            jsonPtr / "Members" / threadMemberCount;
        if (expandLevel > 0)
        {
            getCoreThreadData(aResp, threadMemberPtr, expandLevel - 1,
                              processorId, coreId, threadId,
                              threadIdToObjectPath[threadId], subtree,
                              managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[threadMemberPtr]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors",
                                             processorId, "SubProcessors",
                                             coreId, "SubProcessors", threadId);
        }
        threadMemberCount++;
    }
    aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = threadMemberCount;
}

inline void getSubProcessorCoreCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const nlohmann::json::json_pointer& jsonPtr, uint8_t expandLevel,
    const std::string& processorId, const std::string& cpuPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap)
{
    aResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    aResp->res.jsonValue[jsonPtr]["Name"] = "SubProcessor Collection";
    aResp->res.jsonValue[jsonPtr]["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "Processors", processorId,
        "SubProcessors");

    // Maps core ID to coreObjectPath
    std::map<std::string, std::string, AlphanumLess<std::string>>
        coreIdToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {
        if (!objectPath.starts_with(cpuPath) ||
            !dbus_utils::findInterfacesInServiceMap(serviceMap,
                                                    subProcessorCoreInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path corePath(objectPath);
        const std::string& coreId = corePath.filename();
        coreIdToObjectPath.insert({coreId, objectPath});
    }

    if (coreIdToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU core count was somehow empty";
        aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = 0;
        aResp->res.jsonValue[jsonPtr]["Members"] = nlohmann::json::array();
        return;
    }

    size_t coreMemberCount = 0;
    for (const auto& [coreId, _] : coreIdToObjectPath)
    {
        nlohmann::json::json_pointer coreMemberPtr =
            jsonPtr / "Members" / coreMemberCount;
        if (expandLevel > 0)
        {
            getCpuCoreData(aResp, coreMemberPtr, expandLevel - 1, processorId,
                           coreId, coreIdToObjectPath[coreId], subtree,
                           managedObjectsMap);
        }
        else
        {
            aResp->res.jsonValue[coreMemberPtr]["@odata.id"] =
                crow::utility::urlFromPieces(
                    "redfish", "v1", "Systems", "system", "Processors",
                    processorId, "SubProcessors", coreId);
        }
        coreMemberCount++;
    }

    aResp->res.jsonValue[jsonPtr]["Members@odata.count"] = coreMemberCount;
}

inline void getProcessorCollectionWithExpand(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const ManagedObjectByServiceMap& managedObjectsMap, uint8_t expandLevel,
    const std::string& systemPath)
{
    BMCWEB_LOG_DEBUG << "Get processor collection with expand.";

    const bool multiHost = !systemPath.empty();

    // Maps cpu ID to cpuObjectPath.
    std::map<std::string, std::string, AlphanumLess<std::string>>
        cpuNameToObjectPath;

    for (const auto& [objectPath, serviceMap] : subtree)
    {

        if (!dbus_utils::findInterfacesInServiceMap(serviceMap,
                                                    processorInterfaces))
        {
            continue;
        }
        sdbusplus::message::object_path cpuPath(objectPath);

        // For multi-host systems, the object path of the cpu must be a
        // descendant of the systemPath. (e.g. if systemPath = /a/b, then
        // objectPath must be some pattern like /a/b/..)
        if (multiHost && !objectPath.starts_with(systemPath))
        {
            continue;
        }

        const std::string& cpuId = cpuPath.filename();
        cpuNameToObjectPath.insert({cpuId, cpuPath});
    }

    // If no cpus found, return
    if (cpuNameToObjectPath.empty())
    {
        BMCWEB_LOG_WARNING << "D-Bus CPU count was somehow empty";
        aResp->res.jsonValue["Members@odata.count"] = 0;
        aResp->res.jsonValue["Members"] = nlohmann::json::array();
        return;
    }

    size_t cpuMemberCount = 0;
    for (const auto& [cpu, _] : cpuNameToObjectPath)
    {
        nlohmann::json::json_pointer cpuMemberPtr =
            "/Members"_json_pointer / cpuMemberCount;
        getProcessorData(aResp, cpuMemberPtr, expandLevel - 1, cpu, systemPath,
                         cpuNameToObjectPath[cpu], subtree, managedObjectsMap);
        cpuMemberCount++;
    }

    aResp->res.jsonValue["Members@odata.count"] = cpuMemberCount;
    aResp->res.jsonValue["Name"] = "Processor Collection";
}

/**
 * Request all the properties for the given D-Bus object and fill out the
 * related entries in the Redfish OperatingConfig response.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service name to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void
    getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                           const std::string& service,
                           const std::string& objPath)
{
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig", context,
        [aResp](const boost::system::error_code& ec,
                const dbus::utility::DBusPropertiesMap& properties) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(aResp->res);
            return;
        }

        const size_t* availableCoreCount = nullptr;
        const uint32_t* baseSpeed = nullptr;
        const uint32_t* maxJunctionTemperature = nullptr;
        const uint32_t* maxSpeed = nullptr;
        const uint32_t* powerLimit = nullptr;
        const TurboProfileProperty* turboProfile = nullptr;
        const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
            nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
            availableCoreCount, "BaseSpeed", baseSpeed,
            "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
            maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
            "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        nlohmann::json& json = aResp->res.jsonValue;

        if (availableCoreCount != nullptr)
        {
            json["TotalAvailableCoreCount"] = *availableCoreCount;
        }

        if (baseSpeed != nullptr)
        {
            json["BaseSpeedMHz"] = *baseSpeed;
        }

        if (maxJunctionTemperature != nullptr)
        {
            json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
        }

        if (maxSpeed != nullptr)
        {
            json["MaxSpeedMHz"] = *maxSpeed;
        }

        if (powerLimit != nullptr)
        {
            json["TDPWatts"] = *powerLimit;
        }

        if (turboProfile != nullptr)
        {
            nlohmann::json& turboArray = json["TurboProfile"];
            turboArray = nlohmann::json::array();
            for (const auto& [turboSpeed, coreCount] : *turboProfile)
            {
                nlohmann::json::object_t turbo;
                turbo["ActiveCoreCount"] = coreCount;
                turbo["MaxSpeedMHz"] = turboSpeed;
                turboArray.emplace_back(std::move(turbo));
            }
        }

        if (baseSpeedPrioritySettings != nullptr)
        {
            nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
            baseSpeedArray = nlohmann::json::array();
            for (const auto& [baseSpeedMhz, coreList] :
                 *baseSpeedPrioritySettings)
            {
                nlohmann::json::object_t speed;
                speed["CoreCount"] = coreList.size();
                speed["CoreIDs"] = coreList;
                speed["BaseSpeedMHz"] = baseSpeedMhz;
                baseSpeedArray.emplace_back(std::move(speed));
            }
        }
    });
}

/**
 * Handle the D-Bus response from attempting to set the CPU's AppliedConfig
 * property. Main task is to translate error messages into Redfish errors.
 *
 * @param[in,out]   resp    HTTP response.
 * @param[in]       setPropVal  Value which we attempted to set.
 * @param[in]       ec      D-Bus response error code.
 * @param[in]       msg     D-Bus response message.
 */
inline void
    handleAppliedConfigResponse(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                                const std::string& setPropVal,
                                const boost::system::error_code& ec,
                                const sdbusplus::message_t& msg)
{
    if (!ec)
    {
        BMCWEB_LOG_DEBUG << "Set Property succeeded";
        return;
    }

    BMCWEB_LOG_DEBUG << "Set Property failed: " << ec;

    const sd_bus_error* dbusError = msg.get_error();
    if (dbusError == nullptr)
    {
        messages::internalError(resp->res);
        return;
    }

    // The asio error code doesn't know about our custom errors, so we have to
    // parse the error string. Some of these D-Bus -> Redfish translations are a
    // stretch, but it's good to try to communicate something vaguely useful.
    if (strcmp(dbusError->name,
               "xyz.openbmc_project.Common.Error.InvalidArgument") == 0)
    {
        // Service did not like the object_path we tried to set.
        messages::propertyValueIncorrect(
            resp->res, "AppliedOperatingConfig/@odata.id", setPropVal);
    }
    else if (strcmp(dbusError->name,
                    "xyz.openbmc_project.Common.Error.NotAllowed") == 0)
    {
        // Service indicates we can never change the config for this processor.
        messages::propertyNotWritable(resp->res, "AppliedOperatingConfig");
    }
    else if (strcmp(dbusError->name,
                    "xyz.openbmc_project.Common.Error.Unavailable") == 0)
    {
        // Service indicates the config cannot be changed right now, but maybe
        // in a different system state.
        messages::resourceInStandby(resp->res);
    }
    else
    {
        messages::internalError(resp->res);
    }
}

/**
 * Handle the PATCH operation of the AppliedOperatingConfig property. Do basic
 * validation of the input data, and then set the D-Bus property.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       processorId     Processor's Id.
 * @param[in]       appliedConfigUri    New property value to apply.
 * @param[in]       cpuObjectPath   Path of CPU object to modify.
 * @param[in]       serviceMap      Service map for CPU object.
 */
inline void patchAppliedOperatingConfig(
    const std::shared_ptr<bmcweb::AsyncResp>& resp,
    const std::string& processorId, const std::string& appliedConfigUri,
    const std::string& cpuObjectPath,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    [[maybe_unused]] const ManagedObjectByServiceMap& managedObjectsMap)
{
    // Get Service map for the object path.
    dbus::utility::MapperServiceMap serviceMap;
    for (const auto& [parsedObjectPath, parsedServiceMap] : subtree)
    {
        if (cpuObjectPath == parsedObjectPath)
        {
            serviceMap = parsedServiceMap;
            break;
        }
    }

    // Check that the property even exists by checking for the interface
    const std::string* controlService = nullptr;
    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        if (std::find(interfaceList.begin(), interfaceList.end(),
                      "xyz.openbmc_project.Control.Processor."
                      "CurrentOperatingConfig") != interfaceList.end())
        {
            controlService = &serviceName;
            break;
        }
    }

    if (controlService == nullptr)
    {
        messages::internalError(resp->res);
        return;
    }

    // Check that the config URI is a child of the cpu URI being patched.
    std::string expectedPrefix("/redfish/v1/Systems/system/Processors/");
    expectedPrefix += processorId;
    expectedPrefix += "/OperatingConfigs/";
    if (!appliedConfigUri.starts_with(expectedPrefix) ||
        expectedPrefix.size() == appliedConfigUri.size())
    {
        messages::propertyValueIncorrect(
            resp->res, "AppliedOperatingConfig/@odata.id", appliedConfigUri);
        return;
    }

    // Generate the D-Bus path of the OperatingConfig object, by assuming it's a
    // direct child of the CPU object.
    // Strip the expectedPrefix from the config URI to get the "filename", and
    // append to the CPU's path.
    std::string configBaseName = appliedConfigUri.substr(expectedPrefix.size());
    sdbusplus::message::object_path configPath(cpuObjectPath);
    configPath /= configBaseName;

    BMCWEB_LOG_INFO << "Setting config to " << configPath.str;

    // Set the property, with handler to check error responses
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        resp->strand_,
        [resp, appliedConfigUri](const boost::system::error_code& ec,
                                 const sdbusplus::message_t& msg) {
        handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg);
    },
        *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties",
        "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
        "AppliedConfig", dbus::utility::DbusVariantType(std::move(configPath)));
}

inline void handleSubProcessorThreadHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */,
    const std::string& /* coreId */, const std::string& /* threadId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleSubProcessorThreadCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */,
    const std::string& /* coreId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void
    handleSubProcessorCoreHead(crow::App& app, const crow::Request& req,
                               const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& /* systemName */,
                               const std::string& /* processorId */,
                               const std::string& /* coreId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleSubProcessorCoreCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */, const std::string& /* processorId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void handleProcessorHead(crow::App& app, const crow::Request& req,
                                const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                const std::string& /* systemName */,
                                const std::string& /* processorId */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
}

inline void handleProcessorCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& /* systemName */)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    aResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
}

inline void parseSubtreeForProcessorCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree,
    const query_param::Query& delegated, const std::string& systemPath)
{
    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
    }

    if (delegated.expandLevel == 0 ||
        delegated.expandType == query_param::ExpandType::None)
    {
        BMCWEB_LOG_DEBUG << "Use default processor expand handler";
        collection_util::getCollectionMembersFromSubtree(
            asyncResp,
            boost::urls::url("/redfish/v1/Systems/" + systemName +
                             "/Processors"),
            processorInterfaces, subtree);
        return;
    }
    BMCWEB_LOG_DEBUG << "Use efficient processor expand handler";

    std::vector<std::string> serviceNames =
        dbus_utils::getServiceNamesFromSubtree(subtree);
    if (serviceNames.empty())
    {
        BMCWEB_LOG_DEBUG << "Can't retrieve service names from subtree";
        asyncResp->res.jsonValue["Members@odata.count"] = 0;
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    // Get managed objects from each service in subtree to proactively
    // fetch all dbus data needed to serve requests for subordinate
    // resources.
    sdbusplus::message::object_path path("/xyz/openbmc_project/inventory");
    dbus_utils::getManagedObjectsInEachService(
        std::move(serviceNames), path, context,
        [asyncResp{asyncResp}, subtree, delegated,
         systemPath](const ManagedObjectByServiceMap& managedObjectsByService) {
        if (managedObjectsByService.empty())
        {
            BMCWEB_LOG_DEBUG << "Cannot get managed objects.";
            messages::internalError(asyncResp->res);
            return;
        }
        getProcessorCollectionWithExpand(asyncResp, subtree,
                                         managedObjectsByService,
                                         delegated.expandLevel, systemPath);
    });
}

inline void handleProcessorCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const query_param::Query& delegated, const std::string& systemPath)
{
    const bool multiHost = !systemPath.empty();

    // Default systemName is system and change if system is multi-host
    std::string systemName = "system";
    // The subtree to query for Dimms changes if single or multi-host
    std::string subtreeRoot = "/xyz/openbmc_project/inventory";

    if (multiHost)
    {
        systemName = sdbusplus::message::object_path(systemPath).filename();
        subtreeRoot = systemPath;
    }

    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");

    asyncResp->res.jsonValue["@odata.type"] =
        "#ProcessorCollection.ProcessorCollection";
    asyncResp->res.jsonValue["Name"] = "Processor Collection";

    asyncResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Systems/" + systemName + "/Processors";

    // Get dbus interfaces based on expand level.
    auto interfaces = getInterfacesForProcessorSubtree(delegated.expandLevel);

    if (interfaces.empty())
    {
        BMCWEB_LOG_ERROR << "Can't get interface list for expand level "
                         << delegated.expandLevel;
        messages::internalError(asyncResp->res);
        return;
    }

    // Get subtree information to serve requests for both processor
    // collection and, if expand is requested, for all requested subordinate
    // resources.
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        subtreeRoot, 0, interfaces, requestContext,
        [asyncResp{asyncResp}, delegated,
         systemPath](const boost::system::error_code& ec,
                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec == boost::system::errc::io_error)
        {
            asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
            asyncResp->res.jsonValue["Members@odata.count"] = 0;
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error " << ec.value();
            messages::internalError(asyncResp->res);
            return;
        }
        parseSubtreeForProcessorCollection(asyncResp, subtree, delegated,
                                           systemPath);
    });
}

inline void handleOperatingConfigCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& cpuName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.jsonValue["@odata.type"] =
        "#OperatingConfigCollection.OperatingConfigCollection";
    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                     "Processors", cpuName, "OperatingConfigs");
    asyncResp->res.jsonValue["Name"] = "Operating Config Collection";

    // First find the matching CPU object so we know how to
    // constrain our search for related Config objects.
    const std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp,
         cpuName](const boost::system::error_code& ec,
                  const dbus::utility::MapperGetSubTreePathsResponse& objects) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }

        for (const std::string& object : objects)
        {
            if (!object.ends_with(cpuName))
            {
                continue;
            }

            // Not expected that there will be multiple matching
            // CPU objects, but if there are just use the first
            // one.

            // Use the common search routine to construct the
            // Collection of all Config objects under this CPU.
            constexpr std::array<std::string_view, 1> interface{
                "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
            collection_util::getCollectionMembers(
                asyncResp,
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "Processors", cpuName,
                                             "OperatingConfigs"),
                interface, object.c_str());
            return;
        }
    });
}

inline void requestRoutesOperatingConfigCollection(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/")
        .privileges(redfish::privileges::getOperatingConfigCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleOperatingConfigCollectionGet, std::ref(app)));
}

inline void handleOperatingConfigGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& cpuName, const std::string& configName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    // Ask for all objects implementing OperatingConfig so we can search
    // for one with a matching name
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, cpuName,
         configName](const boost::system::error_code& ec,
                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }
        const std::string expectedEnding = cpuName + '/' + configName;
        for (const auto& [objectPath, serviceMap] : subtree)
        {
            // Ignore any configs without matching cpuX/configY
            if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
            {
                continue;
            }

            nlohmann::json& json = asyncResp->res.jsonValue;
            json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
            json["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "Processors", cpuName,
                "OperatingConfigs", configName);
            json["Name"] = "Processor Profile";
            json["Id"] = configName;

            // Just use the first implementation of the object - not
            // expected that there would be multiple matching
            // services
            getOperatingConfigData(asyncResp, serviceMap.begin()->first,
                                   objectPath);
            return;
        }
        messages::resourceNotFound(asyncResp->res, "OperatingConfig",
                                   configName);
    });
}

inline void requestRoutesOperatingConfig(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/")
        .privileges(redfish::privileges::getOperatingConfig)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleOperatingConfigGet, std::ref(app)));
}

inline int countProcessors()
{
    // TODO(): This is a STUB
    // For now, this is OK, since it is only used for syntax validation.
    // However, when and if writing (POST, PATCH, etc.) is allowed,
    // we will need to have better bounds-checking here,
    // otherwise it will be trivial for a writer to DoS all the storage.
    return 16;
}

inline int countCores(int cpuIndex)
{
    // TODO(): This is a STUB, see above comment
    (void)cpuIndex;
    return 256;
}

inline int countThreads(int cpuIndex, int coreIndex)
{
    // TODO(): This is a STUB, see above comment
    (void)cpuIndex;
    (void)coreIndex;
    return 16;
}

inline int prefixStrToInt(const std::string& prefix, const std::string& str)
{
    size_t lenPrefix = prefix.size();
    size_t lenStr = str.size();

    // Content following prefix must be within 1 to 9 characters in length
    if (lenStr < (lenPrefix + 1))
    {
        BMCWEB_LOG_ERROR << "Index number too short";
        return -1;
    }
    if (lenStr > (lenPrefix + 9))
    {
        // This length limit prevents 32-bit rollover attacks
        BMCWEB_LOG_ERROR << "Index number too long";
        return -1;
    }

    if (str.substr(0, lenPrefix) != prefix)
    {
        // Prefix does not match
        BMCWEB_LOG_ERROR << "Index number wrong prefix";
        return -1;
    }

    std::string numText = str.substr(lenPrefix);
    size_t lenText = numText.size();
    size_t lenCheck = std::strlen(numText.c_str());
    if (lenText != lenCheck)
    {
        // This comparison prevents 0x00 string truncation attacks
        BMCWEB_LOG_ERROR << "Index number wrong length";
        return -1;
    }

    // Cannot use std::stoi because stoi throws
    char* endptr = nullptr;
    int64_t value = std::strtol(numText.c_str(), &endptr, 10);
    if (*endptr != '\0')
    {
        // The number was followed by extra content
        BMCWEB_LOG_ERROR << "Index number wrong content";
        return -1;
    }

    int result = static_cast<int>(value);
    return result;
}

inline int extractIndexFromArg(const std::string& arg)
{
    const std::string index =
        arg.substr(arg.find_last_not_of("0123456789") + 1);
    if (index.empty())
    {
        BMCWEB_LOG_ERROR << "Unable to extract index from arg";
        return -1;
    }
    // use std::strtol since std::stoi can throw
    char* enptr = nullptr;
    int64_t value = std::strtol(index.c_str(), &enptr, 10);
    return static_cast<int>(value);
}

inline int cpuArgToIndex(const std::string& cpuArg)
{
    int bound = countProcessors();
    int num = extractIndexFromArg(cpuArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Processor index out of range";
        return -1;
    }
    return num;
}

inline int coreArgToIndex(const std::string& coreArg, int cpuIndex)
{

    int bound = countCores(cpuIndex);
    int num = prefixStrToInt("core", coreArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Subprocessor core index out of range";
        return -1;
    }
    return num;
}

inline int threadArgToIndex(const std::string& threadArg, int cpuIndex,
                            int coreIndex)
{

    int bound = countThreads(cpuIndex, coreIndex);
    int num = prefixStrToInt("thread", threadArg);
    if (num >= bound)
    {
        BMCWEB_LOG_ERROR << "Subprocessor thread index out of range";
        return -1;
    }
    return num;
}

inline int validateCpu(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& cpuArg)
{
    int cpuIndex = cpuArgToIndex(cpuArg);
    if (cpuIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Processor", cpuArg);
    }
    return cpuIndex;
}

inline int validateCpuCore(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& cpuArg,
                           const std::string& coreArg)
{
    int cpuIndex = validateCpu(asyncResp, cpuArg);
    if (cpuIndex < 0)
    {
        return cpuIndex;
    }
    int coreIndex = coreArgToIndex(coreArg, cpuIndex);
    if (coreIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Core", coreArg);
    }
    return coreIndex;
}

inline int
    validateCpuCoreThread(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& cpuArg, const std::string& coreArg,
                          const std::string& threadArg)
{
    int cpuIndex = validateCpu(asyncResp, cpuArg);
    if (cpuIndex < 0)
    {
        return cpuIndex;
    }
    int coreIndex = validateCpuCore(asyncResp, cpuArg, coreArg);
    if (coreIndex < 0)
    {
        return coreIndex;
    }
    int threadIndex = threadArgToIndex(threadArg, cpuIndex, coreIndex);
    if (threadIndex < 0)
    {
        messages::resourceNotFound(asyncResp->res, "Thread", threadArg);
    }
    return threadIndex;
}

// Creates a generic ExternalStorer hook, should be 2 directories above
// Each hook contains instances, each instance contains entries
// Omit the leading "/redfish/v1" from pathBase, and no trailing slash
inline external_storer::Hook makeExternalStorerHook(const std::string& pathBase)
{
    const std::string emptyString;
    const std::vector<std::string> emptyList;

    return {pathBase, emptyString, emptyList, emptyList};
}

// Creates a generic ExternalStorer instance within the given hook
// The content will be minimal, just enough to create filename on disk
// Returns true if successful
inline bool makeExternalStorerInstance(
    const std::shared_ptr<external_storer::Hook>& hook, const std::string& id)
{
    // External storer NEVER sends dbus calls, so you will never leave this thread.
    auto respGet = std::make_shared<bmcweb::AsyncResp>(nullptr);

    hook->handleGetInstance(respGet, id);
    if (respGet->res.result() == boost::beast::http::status::ok)
    {
        // Already exists, nothing more needs to be done
        return true;
    }

    boost::beast::http::request<boost::beast::http::string_body> upBody;
    std::error_code ec;

    // Create instance, with given ID, which will become filename on disk
    auto upJson = nlohmann::json::object();
    upJson["Id"] = id;

    // Must supply 4th argument to avoid throwing exceptions
    upBody.body() =
        upJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
    crow::Request reqCreate{upBody, ec};

    // External storer NEVER sends dbus calls, so you will never leave this thread.
    auto respCreate = std::make_shared<bmcweb::AsyncResp>(nullptr);

    hook->handleCreateInstance(reqCreate, respCreate);
    if (respCreate->res.result() != boost::beast::http::status::created)
    {
        BMCWEB_LOG_ERROR << "Problem creating ExternalStorer instance " << id;
        return false;
    }

    return true;
}

// Remembers toplevel Processors hook, there is only one
// Each instance in it represents a CPU and is named like cpuArg
// Each instance contains only one entry, "ProcessorMetrics"
inline std::shared_ptr<external_storer::Hook>
    rememberProcessorHook(const std::string& cpuArg)
{
    static std::shared_ptr<external_storer::Hook> hookProcessor = nullptr;

    if (!hookProcessor)
    {
        // If not already remembered by static variable, create hook
        hookProcessor = std::make_shared<external_storer::Hook>(
            makeExternalStorerHook("Systems/system/Processors"));
    }

    if (!(makeExternalStorerInstance(hookProcessor, cpuArg)))
    {
        BMCWEB_LOG_ERROR << "Problem remembering hook for " << cpuArg;
        return nullptr;
    }

    return hookProcessor;
}

// Remembers lowest-level SubProcessors hook
// There is one hook for each unique (CPU, thread) tuple
// Each instance in it represents a thread and is named like threadArg
// Each instance contains only one entry, "ProcessorMetrics"
inline std::shared_ptr<external_storer::Hook>
    rememberThreadHook(const std::string& cpuArg, const std::string& coreArg,
                       const std::string& threadArg)
{
    static std::map<
        std::string,
        std::map<std::string, std::shared_ptr<external_storer::Hook>>>
        hookMaps;

    auto findCpu = hookMaps.find(cpuArg);
    if (findCpu == hookMaps.end())
    {
        hookMaps[cpuArg] = {};
        findCpu = hookMaps.find(cpuArg);
    }

    auto findCore = findCpu->second.find(coreArg);
    if (findCore == findCpu->second.end())
    {
        (findCpu->second)[coreArg] = {};
        findCore = findCpu->second.find(coreArg);
    }

    std::shared_ptr<external_storer::Hook> hookThread = findCore->second;

    if (!hookThread)
    {
        std::string path = "Systems/system/Processors/" + cpuArg +
                           "/SubProcessors/" + coreArg + "/SubProcessors";
        hookThread = std::make_shared<external_storer::Hook>(
            makeExternalStorerHook(path));
        findCore->second = hookThread;
    }

    if (!(makeExternalStorerInstance(hookThread, threadArg)))
    {
        BMCWEB_LOG_ERROR << "Problem remembering hook for " << threadArg;
        return nullptr;
    }

    return hookThread;
}

inline nlohmann::json fakeProcessorMetrics(const std::string& cpu,
                                           const std::string& core,
                                           const std::string& thread)
{
    nlohmann::json::object_t metricsObj;

    metricsObj["Id"] = "Metrics";
    metricsObj["Name"] = "Processor Metrics";

    // The different levels have slightly different default content
    if (!thread.empty())
    {
        // Thread level
        metricsObj["CorrectableCoreErrorCount"] = 0;
        metricsObj["UncorrectableCoreErrorCount"] = 0;
    }
    metricsObj["CorrectableOtherErrorCount"] = 0;
    metricsObj["UncorrectableOtherErrorCount"] = 0;

    // ExternalStorer would normally apply this as invariant if successful
    // The caller already applies "@odata.type" as invariant no matter what
    std::string url = "/redfish/v1/Systems/system/Processors/";
    url += cpu;
    if (!core.empty())
    {
        url += "/SubProcessors/";
        url += core;
    }
    if (!thread.empty())
    {
        url += "/SubProcessors/";
        url += thread;
    }
    url += "/ProcessorMetrics";

    metricsObj["@odata.id"] = std::move(url);

    return metricsObj;
}

inline void
    handleGetCpuMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const nlohmann::json::json_pointer& jsonPtr,
                        const std::string& cpuArg)
{
    if (validateCpu(asyncResp, cpuArg) < 0)
    {
        // Error reply already composed
        return;
    }

    std::shared_ptr<external_storer::Hook> hook = rememberProcessorHook(cpuArg);
    if (!hook)
    {
        messages::resourceNotFound(asyncResp->res, "Processor", cpuArg);
        return;
    }

    std::string emptyString;
    hook->handleGetEntry(asyncResp, jsonPtr, cpuArg, emptyString,
                         "ProcessorMetrics");
    if (asyncResp->res.result() == boost::beast::http::status::not_found)
    {
        // Fake up a synthetic response to replace only the 404 error
        asyncResp->res.jsonValue[jsonPtr] =
            fakeProcessorMetrics(cpuArg, "", "");
        asyncResp->res.result(boost::beast::http::status::ok);
    }
    if (asyncResp->res.result() != boost::beast::http::status::ok)
    {
        // Error reply already composed
        return;
    }

    // Apply invariants, to override whatever might have been in the file
    asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorMetrics.v1_5_0.ProcessorMetrics";
}

inline void handleGetCpuCoreThreadMetrics(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& cpuArg,
    const std::string& coreArg, const std::string& threadArg)
{
    if (validateCpuCoreThread(asyncResp, cpuArg, coreArg, threadArg) < 0)
    {
        return;
    }

    std::shared_ptr<external_storer::Hook> hook =
        rememberThreadHook(cpuArg, coreArg, threadArg);
    if (!hook)
    {
        messages::resourceNotFound(asyncResp->res, "Thread", threadArg);
        return;
    }

    std::string emptyString;
    hook->handleGetEntry(asyncResp, jsonPtr, threadArg, emptyString,
                         "ProcessorMetrics");
    if (asyncResp->res.result() == boost::beast::http::status::not_found)
    {
        // Fake up a synthetic response to replace only the 404 error
        asyncResp->res.jsonValue[jsonPtr] =
            fakeProcessorMetrics(cpuArg, coreArg, threadArg);
        asyncResp->res.result(boost::beast::http::status::ok);
    }
    if (asyncResp->res.result() != boost::beast::http::status::ok)
    {
        // Error reply already composed
        return;
    }

    // Apply invariants, to override whatever might have been in the file
    asyncResp->res.jsonValue[jsonPtr]["@odata.type"] =
        "#ProcessorMetrics.v1_5_0.ProcessorMetrics";
}

// The glue layers are already handled by these functions elsewhere:
// Processors = requestRoutesProcessorCollection()
// Processors/cpuX = requestRoutesProcessor()
// Processors/cpuX/SubProcessors = requestRoutesSubProcessorCoreCollection()
// Processors/cpuX/SubProcessors/coreY = requestRoutesSubProcessorCore()
// Processors/cpuX/SubProcessors/coreY/SubProcessors =
// requestRoutesSubProcessorThreadCollection()
// Processors/cpuX/SubProcessors/coreY/SubProcessors/threadZ =
// requestRoutesSubProcessorThread()

// The "ProcessorMetrics" endpoints are below those glue layers:
// Processors/cpuX/ProcessorMetrics = handled here
// Processors/cpuX/SubProcessors/coreY/ProcessorMetrics = intentionally
// omitted
// Processors/cpuX/SubProcessors/coreY/SubProcessors/threadZ/ProcessorMetrics
// = handled here
inline void requestRoutesProcessorMetricsViaExternalStorer(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/system/Processors/<str>/ProcessorMetrics/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& cpuArg) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        handleGetCpuMetrics(asyncResp, ""_json_pointer, cpuArg);
    });

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/system/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/ProcessorMetrics/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& cpuArg, const std::string& coreArg,
                   const std::string& threadArg) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        handleGetCpuCoreThreadMetrics(asyncResp, ""_json_pointer, cpuArg,
                                      coreArg, threadArg);
    });

    // TODO(): Implement corresponding PATCH methods
    // The POST method is not correct to use here,
    // as the result location is already well-known name "ProcessorMetrics".
    // and from the user point of view it always exists,
    // so the creation operation is not the correct operation.
    // The PUT method also might not be correct to use here,
    // as it would fully replace all content at the result location,
    // but the expectation is to only selectively replace some content.
}

inline void requestRoutesProcessorCollection(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleProcessorCollectionHead, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName) {
        query_param::Query delegated;
        query_param::QueryCapabilities capabilities = {
#ifdef EFFICIENT_EXPAND_PROCESSORS_ENABLED
            .canDelegateExpandLevel = 6,
#else
            .canDelegateExpandLevel = 0,
#endif
        };
        if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                      delegated, capabilities))
        {
            return;
        }

        redfish::system_utils::getSystemInformation(
            asyncResp, systemName,
            [delegated](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& systemPath) {
            handleProcessorCollection(asyncResp, delegated, systemPath);
        });
    });
}

inline void getProcessorStateCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    constexpr std::array<std::string_view, 1> procStateIntf = {
        "xyz.openbmc_project.Inventory.Item.ProcessorState"};
    collection_util::getCollectionMembers(
        asyncResp,
        crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                     "Processors", processorId, "Oem", "Google",
                                     "ProcessorStates"),
        procStateIntf);
}

inline void
    handleProcessorGet(App& app, const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& systemName,
                       const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    redfish::system_utils::getSystemInformation(
        asyncResp, systemName,
        [processorId](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& systemPath) {
        getProcessorObject(asyncResp, processorId, systemPath,
                           std::bind_front(getProcessorData, asyncResp,
                                           ""_json_pointer, 0, processorId,
                                           systemPath));
    });
}

inline void
    handleProcessorPatch(App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& systemName,
                         const std::string& processorId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    if (systemName != "system")
    {
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
        return;
    }

    std::optional<nlohmann::json> appliedConfigJson;
    if (!json_util::readJsonPatch(req, asyncResp->res, "AppliedOperatingConfig",
                                  appliedConfigJson))
    {
        return;
    }

    if (appliedConfigJson)
    {
        std::string appliedConfigUri;
        if (!json_util::readJson(*appliedConfigJson, asyncResp->res,
                                 "@odata.id", appliedConfigUri))
        {
            return;
        }

        redfish::system_utils::getSystemInformation(
            asyncResp, systemName,
            [processorId, appliedConfigUri](
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& systemPath) {
            // Check for 404 and find matching D-Bus object, then run
            // property patch handlers if that all succeeds.
            getProcessorObject(asyncResp, processorId, systemPath,
                               std::bind_front(patchAppliedOperatingConfig,
                                               asyncResp, processorId,
                                               appliedConfigUri));
        });
    }
}

inline void requestRoutesProcessor(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleProcessorHead, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleProcessorGet, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
        .privileges(redfish::privileges::patchProcessor)
        .methods(boost::beast::http::verb::patch)(
            std::bind_front(handleProcessorPatch, std::ref(app)));

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/Oem/Google/ProcessorStates/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(getProcessorStateCollection, std::ref(app)));

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/Oem/Google/ProcessorStates/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetProcessorState, std::ref(app)));
}

inline void requestRoutesSubProcessorCoreCollection(App& app)
{
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(std::bind_front(
            handleSubProcessorCoreCollectionHead, std::ref(app)));

    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        BMCWEB_LOG_DEBUG << "Get available system sub processor core members.";

        getProcessorPaths(asyncResp, processorId,
                          std::bind_front(getSubProcessorCoreMembers, asyncResp,
                                          processorId));
    });
}

inline void requestRoutesSubProcessorCore(App& app)
{
    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleSubProcessorCoreHead, std::ref(app)));

    BMCWEB_ROUTE(
        app, "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        BMCWEB_LOG_DEBUG
            << "Get available system sub processor core resources.";

        getProcessorPaths(asyncResp, processorId,
                          std::bind_front(getSubProcessorCoreData, asyncResp,
                                          processorId, coreId));
    });
}

inline void requestRoutesSubProcessorThreadCollection(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/")
        .privileges(redfish::privileges::headProcessorCollection)
        .methods(boost::beast::http::verb::head)(std::bind_front(
            handleSubProcessorThreadCollectionHead, std::ref(app)));
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/")
        .privileges(redfish::privileges::getProcessorCollection)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        getSubProcessorCorePaths(asyncResp, processorId, coreId,
                                 std::bind_front(getSubProcessorThreadMembers,
                                                 asyncResp, processorId,
                                                 coreId));
    });
}

inline void requestRoutesSubProcessorThread(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::headProcessor)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleSubProcessorThreadHead, std::ref(app)));
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Processors/<str>/SubProcessors/<str>/SubProcessors/<str>/")
        .privileges(redfish::privileges::getProcessor)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName,
                   const std::string& processorId, const std::string& coreId,
                   const std::string& threadId) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        if (systemName != "system")
        {
            messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                       systemName);
            return;
        }

        getSubProcessorCorePaths(asyncResp, processorId, coreId,
                                 std::bind_front(getSubProcessorThreadData,
                                                 asyncResp, processorId, coreId,
                                                 threadId));
    });
}

} // namespace redfish
