#include "managed_store.hpp"

#include "dbus_utility.hpp"
#include "managed_store_clock.hpp"
#include "managed_store_types.hpp"
#include "str_utility.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>

// TODO:: move these to a separate file (future CL when we have more stores):
namespace managedStore
{

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
ManagedObjectStore* managedObjectStore = nullptr;

// TODO:: can ^ be a std::shared_ptr on `static ManagedObjectStore::instance()`
// when we implement graceful shutdowns

void ManagedObjectStore::processDbusResponse(KeyType keyType,
                                             const ValueType& managedValue,
                                             bool isReadThroughRequest)
{
    ValueType value(managedValue);
    std::string keyTypeStr = keyType.toString();

    BMCWEB_LOG_STATEFUL_DEBUG << "Updating store with fresh "
                              << " Object: " << keyTypeStr
                              << " Value: " << value.toString()
                              << " ec: " << value.errorCode.message();

    // Initialize numTimesUsed:
    value.numTimesUsed = 1;
    auto currentObjectIter = managedObjects.find(keyTypeStr);
    if (currentObjectIter != managedObjects.end())
    {
        // preserve the lastUsed:
        value.lastUsed = currentObjectIter->second.lastUsed;
        // preserve the lastUsedAges:
        value.lastUsedAges = currentObjectIter->second.lastUsedAges;
        // preserve the numTimesUsed:
        value.numTimesUsed = currentObjectIter->second.numTimesUsed;
        // an shared / unique pointer) count refreshes:
        value.numRefreshesDone = currentObjectIter->second.numRefreshesDone + 1;
        // count the scheduled refreshes:
        value.numRefreshesScheduled =
            currentObjectIter->second.numRefreshesScheduled;

        BMCWEB_LOG_STATEFUL_DEBUG << "Updating Current Object:"
                                  << " Key: " << keyTypeStr
                                  << " Value: " << value.toString();
    }

    // Avoid queuing a refresh if a Pq entry exists for the key.
    if (!pqEntrySet.contains(keyTypeStr))
    {
        // Queue refresh operation
        pq.push(PriorityQueueEntry(keyType, value.nextRefreshAt));
        // Track pq entry
        pqEntrySet.insert(keyTypeStr);
    }

    // upsert the key:
    managedObjects.insert_or_assign(keyTypeStr, value);

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Updated Object:"
        << " Object: " << keyTypeStr
        << " New: " << managedObjects.find(keyTypeStr)->second.toString();

    // Update pending dbus response count on receiving response.
    this->managedStoreTracker.decrementPendingDbusResponses(
        isReadThroughRequest);

    auto cbMapIter = requestCbMap.find(keyTypeStr);
    if (cbMapIter != requestCbMap.end())
    {
        std::queue<ManagedStoreCb>& cbQueue = cbMapIter->second;
        while (!cbQueue.empty())
        {
            auto callback = cbQueue.front();
            callback(value);
            cbQueue.pop();
        }
        requestCbMap.erase(cbMapIter->first);
    }

    // Finally, call scheduler to queue up next refresh operations.
    scheduleRefresh();
}

void ManagedObjectStore::refreshObject(const KeyType& key,
                                       bool isReadThroughRequest)
{
    auto managedObjectIter = this->managedObjects.find(key.toString());
    if (managedObjectIter != this->managedObjects.end())
    {
        managedObjectIter->second.numRefreshesScheduled += 1;

        BMCWEB_LOG_STATEFUL_DEBUG
            << "refreshObject:"
            << " Key: " << managedObjectIter->first
            << " value: " << managedObjectIter->second.toString();
    }

    switch (key.getManagedType())
    {
        case ManagedType::kManagedObject:
        {
            getManagedObjectsFromDbusService(
                key.serviceName, key.objectPath,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedPropertyMap:
        {
            getManagedPropertiesMapFromDbusService(
                key.serviceName, key.objectPath, key.interface,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedProperty:
        {
            getManagedPropertiesFromDbusService(
                key.serviceName, key.objectPath, key.interface, key.property,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedSubtree:
        {
            getManagedSubtreeFromDbusService(
                key.objectPath, key.treeDepth, key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedSubtreePaths:
        {
            getManagedSubtreePathsFromDbusService(
                key.objectPath, key.treeDepth, key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedAssociatedSubtree:
        {
            getManagedAssociatedSubtreeFromDbusService(
                key.associatedPath, key.objectPath, key.treeDepth,
                key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedAssociatedSubtreePaths:
        {
            getManagedAssociatedSubtreePathsFromDbusService(
                key.associatedPath, key.objectPath, key.treeDepth,
                key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
    }

    // Record a pending refresh operation.
    this->managedStoreTracker.incrementPendingDbusResponses(
        isReadThroughRequest);
}

bool ManagedObjectStore::canScheduleRefresh()
{
    // The timer callback will schedule the next refresh if the scheduler is
    // active.
    if (this->isSchedulerActive)
    {
        return false;
    }

    // Cannot schedule refresh if pending dbus responses reach threshold.
    if (this->managedStoreTracker.countPendingDbusResponses >=
        this->config.pendingDbusResponsesMax)
    {
        BMCWEB_LOG_STATEFUL_DEBUG << "scheduleRefresh: Pending io "
                                  << "threshold reached.";
        return false;
    }

    // Scan the priority queue to pop the entries that are no longer used
    // or can be refreshed instantly to get to a schedulable entry.
    std::chrono::steady_clock::time_point timeNow = clockNow();
    bool canSchedule = false;
    while (!canSchedule && !this->pq.empty())
    {
        const PriorityQueueEntry& pqEntry = pq.top();

        // Get managedStore key to queue refresh of corresponding object in
        // the managedStore.
        const KeyType& managedStoreKey = pqEntry.managedStoreKey;
        const std::string managedStoreKeyStr = managedStoreKey.toString();
        auto managedObjectIter = managedObjects.find(managedStoreKeyStr);

        // the object is no longer tracked:
        if (managedObjectIter == managedObjects.end())
        {
            pq.pop();
            pqEntrySet.erase(managedStoreKeyStr);
            continue;
        }

        ValueType& keyValue = managedObjectIter->second;
        const auto durationSinceUsed = clockSince(keyValue.lastUsed, timeNow);
        bool isRecentlyUsed = durationSinceUsed < this->config.tLRUThreshold;

        BMCWEB_LOG_STATEFUL_DEBUG
            << "SinceUsed:"
            << " Key: " << managedStoreKeyStr << " durationSinceUsed: "
            << clockSinceMilliseconds(keyValue.lastUsed, timeNow)
            << " isRecentlyUsed: " << isRecentlyUsed;
        // LRU Eviction:
        if (!isRecentlyUsed)
        {
            BMCWEB_LOG_STATEFUL_DEBUG << "Since Used: Evict:"
                                      << " Key: " << managedStoreKeyStr;
            managedObjects.erase(managedObjectIter->first);
            pq.pop();
            pqEntrySet.erase(managedStoreKeyStr);
            continue;
        }

        // If the object corresponding to pqEntry was recently refreshed,
        // re-queue the entry to schedule refresh for later point in time.
        if (keyValue.nextRefreshAt > pqEntry.nextRefreshAt)
        {
            BMCWEB_LOG_STATEFUL_DEBUG << "PQ entry recently refreshed: "
                                      << "Re-queue Key: " << managedStoreKeyStr;
            // Remember associated managedStore key before we pop the pq entry.
            const KeyType key = managedStoreKey;
            pq.pop();
            pq.push(PriorityQueueEntry(key, keyValue.nextRefreshAt));
            continue;
        }
        canSchedule = true;
    }
    return canSchedule;
}

void ManagedObjectStore::scheduleRefresh()
{
    if (!this->canScheduleRefresh())
    {
        return;
    }

    BMCWEB_LOG_STATEFUL_DEBUG
        << "scheduleRefresh: " << pq.size() << " Pending dbus responses: "
        << this->managedStoreTracker.countPendingDbusResponses;

    PriorityQueueEntry pqEntry = pq.top();
    pq.pop();

    std::chrono::steady_clock::time_point timeNow = clockNow();

    // Get service name and object path to schedule refresh of the corresponding
    // object in store.
    const KeyType& managedStoreKey = pqEntry.managedStoreKey;
    std::string managedStoreKeyStr = managedStoreKey.toString();

    // Stop tracking the pq entry once it is pop'd from the queue.
    pqEntrySet.erase(managedStoreKeyStr);

    // Set scheduler status to active before scheduling the refresh op to ensure
    // an immediate callback keeps the system in the correct state.
    isSchedulerActive = true;

    // If the refresh needs to be scheduled later in time, we set the timeout
    // based on the time difference between the expected refresh time and
    // current time.
    // NOTE: the expected refresh time is set based on t_ttl.
    const auto timerTimeout =
        std::chrono::duration_cast<std::chrono::milliseconds>(
            pqEntry.nextRefreshAt - timeNow);
    timer.expires_after(timerTimeout);

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Scheduling Refresh after " << timerTimeout.count()
        << " milliseconds. "
        << "ServiceName: " << managedStoreKey.serviceName
        << " ObjectPath: " << managedStoreKey.objectPath.str
        << " Interface: " << managedStoreKey.interface << " Property: "
        << managedStoreKey.property;

    timer.async_wait([this, self = shared_from_this(),
                      managedStoreKey](boost::system::error_code ec) {
        isSchedulerActive = false;
        if (ec == boost::asio::error::operation_aborted)
        {
            BMCWEB_LOG_STATEFUL_ERROR << "Timer operation aborted" << ec;
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_STATEFUL_ERROR << "Async_wait failed" << ec;
            return;
        }
        BMCWEB_LOG_STATEFUL_DEBUG
            << "Refreshing managed object. "
            << "ServiceName: " << managedStoreKey.serviceName
            << " ObjectPath: " << managedStoreKey.objectPath.str
            << " Interface: " << managedStoreKey.interface << " Property: "
            << managedStoreKey.property;
        refreshObject(managedStoreKey);
        scheduleRefresh();
    });
}

void ManagedObjectStore::getProperty(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    GetManagedPropertyCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        dbus::utility::getProperty(keyType.serviceName, keyType.objectPath,
                                   keyType.interface, keyType.property,
                                   std::move(callback));
        return;
    }

    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedProperty.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedProperty.value());
    });
}

void ManagedObjectStore::getAllProperties(
    const std::string& service, const std::string& objectPath,
    const std::string& interface,
    const ManagedObjectStoreContext& requestContext,
    GetManagedPropertyMapCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        sdbusplus::asio::getAllProperties(*crow::connections::systemBus,
                                          service, objectPath, interface,
                                          std::move(callback));
        return;
    }

    KeyType keyType(ManagedType::kManagedPropertyMap, service, objectPath,
                    interface);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedPropertyMap.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedPropertyMap.value());
    });
}

void ManagedObjectStore::getSubTree(
    const std::string& path, int32_t depth,
    const std::vector<std::string>& interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreeResponse& subtree) {
            callback(ec, subtree);
        },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
            interfaces);
        return;
    }

    KeyType keyType(ManagedType::kManagedSubtree, path, depth, interfaces);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtree.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtree.value());
    });
}

void ManagedObjectStore::getSubTree(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    this->getSubTree(path, depth, interfaces2, requestContext,
                     std::move(callback));
}

void ManagedObjectStore::getSubTreePaths(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreePathsCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreePathsResponse&
                    subtreePaths) { callback(ec, subtreePaths); },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
            interfaces2);
        return;
    }

    KeyType keyType(ManagedType::kManagedSubtreePaths, path, depth,
                    interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtreePaths.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtreePaths.value());
    });
}

void ManagedObjectStore::getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }
    this->getAssociatedSubTree(associatedPath, path, depth, interfaces2,
                               requestContext, std::move(callback));
}

void ManagedObjectStore::getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreeResponse& subtree) {
            callback(ec, subtree);
        },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
            associatedPath, path, depth, interfaces2);
        return;
    }

    KeyType keyType(ManagedType::kManagedAssociatedSubtree, associatedPath.str,
                    path.str, depth, interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtree.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtree.value());
    });
}

void ManagedObjectStore::getAssociatedSubTreePaths(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreePathsCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreePathsResponse&
                    subtreePaths) { callback(ec, subtreePaths); },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
            associatedPath, path, depth, interfaces);
        return;
    }

    KeyType keyType(ManagedType::kManagedAssociatedSubtreePaths,
                    associatedPath.str, path.str, depth, interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtreePaths.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtreePaths.value());
    });
}

void ManagedObjectStore::getManagedObjects(
    const std::string& service, const sdbusplus::message::object_path& path,
    GetManagedObjectsCb&& callback)
{
    BMCWEB_LOG_STATEFUL_DEBUG << "getManagedObjects:"
                              << " service: " << service
                              << " path: " << path.str;
    // std::shared_ptr<bmcweb::AsyncResp> resp;
    ManagedObjectStoreContext context(nullptr);
    getManagedObjectsWithContext(service, path, context, std::move(callback));
}

void ManagedObjectStore::getManagedObjectsWithContext(
    const std::string& service, const sdbusplus::message::object_path& path,
    const ManagedObjectStoreContext& requestContext,
    GetManagedObjectsCb&& callback)
{
    // total counter of calls:
    this->managedStoreTracker.countGetManagedObjects += 1;

    BMCWEB_LOG_STATEFUL_DEBUG
        << "getManagedObjectsWithContext:"
        << " service: " << service << " path: " << path.str
        << " requestContext: " << requestContext.toString()
        << " count: " << this->managedStoreTracker.countGetManagedObjects;

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        // TODO:: do we want to count that (if the cache is actually disabled)
        // i think we should since we want to use that as validation for the
        // store being enabled?
        this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;
        dbus::utility::getManagedObjects(service, path, std::move(callback));
        return;
    }

    KeyType keyType(ManagedType::kManagedObject, service, path.str);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (valueType.managedObject.has_value())
        {
            callback(valueType.errorCode, valueType.managedObject.value());
            return;
        }
        callback(valueType.errorCode, {});
    });
}

void ManagedObjectStore::getManagedObjectsInStore(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    ManagedStoreCb&& callback)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "getManagedObjectsInStore:"
        << " service: " << keyType.serviceName
        << " path: " << keyType.objectPath.str << " interface: "
        << keyType.interface << " property: " << keyType.property
        << " requestContext: " << requestContext.toString();

    // Execute callback immidiately if object is cached in store.
    std::string keyTypeStr = keyType.toString();
    auto managedObjectIter = managedObjects.find(keyTypeStr);
    if (managedObjectIter != managedObjects.end())
    {
        ValueType& mappedValueInStore = managedObjectIter->second;
        const std::chrono::steady_clock::time_point timeNow = clockNow();
        const auto currentAge =
            clockSince(mappedValueInStore.lastRefreshAt, timeNow);

        // update lastUsed:
        mappedValueInStore.lastUsed = timeNow;
        // count number of times used:
        mappedValueInStore.numTimesUsed += 1;
        // update lastUsedAges:
        if (!mappedValueInStore.lastUsedAges)
        {
            mappedValueInStore.lastUsedAges = std::make_shared<
                std::list<std::chrono::steady_clock::duration>>();
        }
        mappedValueInStore.lastUsedAges->push_back(currentAge);
        while (mappedValueInStore.lastUsedAges->size() >=
               mappedValueInStore.kLastUsedAgesMaxSize)
        {
            mappedValueInStore.lastUsedAges->pop_front();
        }

        BMCWEB_LOG_STATEFUL_DEBUG
            << "ManagedObject found in store. "
            << " service: " << keyType.serviceName
            << " path: " << keyType.objectPath.str << " interface: "
            << keyType.interface << " property: " << keyType.property
            << " CurrentAge: " << clockDurationMilliseconds(currentAge)
            << " Context: " << requestContext.toString()
            << " Value: " << mappedValueInStore.toString();

        // check if the current object is stale:
        const bool isObjectStale = currentAge >= (this->config.tfixedThreshold +
                                                  this->config.tgraceThreshold);

        // can we use it as is:
        bool isUseCurrentObject = !isObjectStale;

        if (requestContext.hintMaxAge > std::chrono::seconds(0))
        {
            // we have to refresh it because of hintMaxAge
            isUseCurrentObject = (currentAge <= requestContext.hintMaxAge);
            this->managedStoreTracker.countGetManagedObjectsCacheMissMaxAge +=
                1;
            BMCWEB_LOG_STATEFUL_DEBUG
                << "apply:"
                << " hintMaxAgeMS: "
                << clockDurationMilliseconds(requestContext.hintMaxAge);
        }

        // Return if the object is still fresh.
        if (isUseCurrentObject)
        {
            this->managedStoreTracker.countGetManagedObjectsCacheHit += 1;
            callback(mappedValueInStore);
            return;
        }

        // Evict the object from store as it has became stale.
        if (isObjectStale)
        {
            BMCWEB_LOG_ALWAYS
                << "Object has become stale! "
                << " service: " << keyType.serviceName
                << " path: " << keyType.objectPath.str << " interface: "
                << keyType.interface << " property: " << keyType.property
                << " CurrentAge: " << clockDurationMilliseconds(currentAge)
                << " Context: " << requestContext.toString()
                << " Value: " << mappedValueInStore.toString();
            managedObjects.erase(managedObjectIter->first);
        }
    }

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Fetching fresh object over dbus. "
        << " Key: " << keyType.toString()
        << " requestContext: " << requestContext.toString();

    // Handle concurrent requests for the same object by storing callback
    // for the request.
    auto cbMapIter = requestCbMap.find(keyTypeStr);
    if (cbMapIter != requestCbMap.end())
    {
        // Since a request has already read through, any subsequent request
        // will not read through. The callback for these duplicate requests
        // will be stored and invoked when the first request gets a response
        // from dbus.
        cbMapIter->second.push(std::move(callback));
        return;
    }
    requestCbMap[keyTypeStr].push(std::move(callback));

    this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;

    // Note: This refresh operation is not rate limited i.e all incoming
    // requests with cache-miss will continue to read through without a cap on
    // pending i/o since we don't want to block on scheduler or send a failure
    // response.
    refreshObject(keyType, true);
}

void ManagedObjectStore::clearAllObjects()
{
    this->managedObjects.clear();
    // looks like it's the only way to do this:
    this->pq = ManagedStorePriorityQueue();
}

void ManagedObjectStore::getManagedObjectsFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    ManagedStoreCb&& callback)
{
    dbus::utility::getManagedObjects(
        service, path,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& objects) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(objects, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    });
}

void ManagedObjectStore::getManagedPropertiesFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, const std::string& property,
    ManagedStoreCb&& callback)
{
    dbus::utility::getProperty(
        service, path, interface, property,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DbusVariantType& propertyValue) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(propertyValue, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    });
}

void ManagedObjectStore::getManagedPropertiesMapFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, ManagedStoreCb&& callback)
{
    sdbusplus::asio::getAllProperties(
        *crow::connections::systemBus, service, path.str, interface,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DBusPropertiesMap& propertyMap) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(propertyMap, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    });
}

// Calls into dbus service to get subtree.
void ManagedObjectStore::getManagedSubtreeFromDbusService(
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtree, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree", path.str, depth,
        interfaces);
}

// Calls into dbus service to get subtree paths.
void ManagedObjectStore::getManagedSubtreePathsFromDbusService(
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtreePaths, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path.str, depth,
        interfaces);
}

// Calls into dbus service to get subtree.
void ManagedObjectStore::getManagedAssociatedSubtreeFromDbusService(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtree, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
        associatedPath, path, depth, interfaces);
}

// Calls into dbus service to get subtree paths.
void ManagedObjectStore::getManagedAssociatedSubtreePathsFromDbusService(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtreePaths, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
        associatedPath, path, depth, interfaces);
}

std::string ManagedObjectStoreConfig::toString() const
{
    return this->toJson().dump();
}

nlohmann::json ManagedObjectStoreConfig::toJson() const
{
    nlohmann::json obj;
    obj["is_enabled"] = this->isEnabled;
    obj["pendingDbusResponsesMax"] = this->pendingDbusResponsesMax;
    obj["tfixedThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tfixedThreshold);
    obj["tgraceThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tgraceThreshold);
    obj["tLRUThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tLRUThreshold);
    return obj;
}

std::string KeyType::toString() const
{
    std::string ret;
    bmcweb::append_with_sep(ret, kSep, std::to_string(managedElementType));

    switch (managedElementType)
    {
        case ManagedType::kManagedObject:
        {
            bmcweb::append_with_sep(ret, kSep, serviceName, objectPath.str);
            break;
        }
        case ManagedType::kManagedPropertyMap:
        {
            bmcweb::append_with_sep(ret, kSep, serviceName, objectPath.str,
                                    interface);
            break;
        }
        case ManagedType::kManagedProperty:
        {
            bmcweb::append_with_sep(ret, kSep, serviceName, objectPath.str,
                                    interface, property);
            break;
        }
        case ManagedType::kManagedSubtree:
        case ManagedType::kManagedSubtreePaths:
        case ManagedType::kManagedAssociatedSubtree:
        case ManagedType::kManagedAssociatedSubtreePaths:
        {
            std::string interfaceListStr;
            for (const std::string& interfaceStr : interfaceList)
            {
                bmcweb::append_with_sep(interfaceListStr, ',', interfaceStr);
            }
            bmcweb::append_with_sep(ret, kSep, objectPath.str,
                                    std::to_string(treeDepth), interfaceListStr,
                                    associatedPath.str);
            break;
        }
    }
    return ret;
}

} // namespace managedStore
