#include "managed_store.hpp"

#include <sys/types.h>

#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <fstream>
#include <ios>
#include <list>
#include <memory>
#include <optional>
#include <queue>
#include <span>
#include <string>
#include <string_view>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/synchronization/mutex.h"
#include "boost/asio/io_context.hpp"
#include "boost/asio/post.hpp"  // NOLINT
#include "boost/asio/steady_timer.hpp"
#include "boost/callable_traits/return_type.hpp"
#include "boost/system/detail/errc.hpp"
#include "boost/system/detail/error_code.hpp"
#include "boost/system/error_code.hpp"
#include "subscription.h"
#include "logging.hpp"
#include "dbus_utility.hpp"
#include <nlohmann/json.hpp>
#include "tlbmc/hal/system_registry.h"
#include "managed_store_clock.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/asio/connection.hpp"
#include "sdbusplus/bus/match.hpp"
#include "sdbusplus/message.hpp"
#include "sdbusplus/message/native_types.hpp"

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

void AppendWithSep(std::string& out, const char sep, const std::string& arg) {
  if (!out.empty()) out += sep;
  out += arg;
}

// join 'args' strings with a separator without creating any intermediate
// objects, append to 'out'
template <typename... Args>
void AppendWithSep(std::string& out, const char sep, const std::string& arg,
                   const Args&... args) {
  AppendWithSep(out, sep, arg);
  AppendWithSep(out, sep, args...);
}

ManagedObjectStore* managedObjectStoreInstance = nullptr;

}  // namespace

void SetManagedStoreInstanceForTesting(ManagedObjectStore* instance) {
  managedObjectStoreInstance = instance;
}

// TODO:: can ^ be a std::shared_ptr on `static ManagedObjectStore::instance()`
// when we implement graceful shutdowns
ManagedStore* InitializeManagedStore(
    const ManagedObjectStoreConfig* cfg,
    boost::asio::io_context* io_main_thread,
    const std::shared_ptr<boost::asio::io_context>& io_context_worker_threads,
    ecclesia::SubscriptionService* subscription_service,
    sdbusplus::asio::connection* systemBus,
    std::shared_ptr<milotic_tlbmc::SystemRegistry> system_registry) {
  if (managedObjectStoreInstance != nullptr) {
    return managedObjectStoreInstance;
  }

  LOG(INFO) << "InitializeManagedStore with systembus";

  static bool initialize = false;

  // First initialization should only happen if cfg, io, and systemBus are not
  // null
  if (cfg != nullptr && io_main_thread != nullptr && systemBus != nullptr) {
    // Once this is set to true, every future call will always return the
    // managed store instance
    initialize = true;
  }

  if (!initialize) {
    return nullptr;
  }

  // NOLINTNEXTLINE(google3-runtime-global-variables)
  static ManagedObjectStore instance(
      *cfg, *io_main_thread, std::this_thread::get_id(),
      io_context_worker_threads, subscription_service, systemBus,
      system_registry);
  managedObjectStoreInstance = &instance;
  return managedObjectStoreInstance;
}

ManagedStore* InitializeManagedStore(
    const ManagedObjectStoreConfig* cfg,
    boost::asio::io_context* io_main_thread,
    const std::shared_ptr<boost::asio::io_context>& io_context_worker_threads,
    ecclesia::SubscriptionService* subscription_service,
    sdbusplus::asio::connection* systemBus) {
  return InitializeManagedStore(cfg, io_main_thread, io_context_worker_threads,
                                subscription_service, systemBus, nullptr);
}

ManagedStore* GetManagedObjectStore() { return managedObjectStoreInstance; }

void ManagedObjectStore::UpdateOrInsertManagedObjects(
    const std::string& key_id, const std::shared_ptr<ValueType>& value) {
  absl::MutexLock lock(managed_objects_mutex_);
  // Initialize numTimesUsed:
  value->numTimesUsed = 1;
  auto current_object_iter = managedObjects.find(key_id);
  // Update managed object if being tracked already.
  if (current_object_iter != managedObjects.end()) {
    // preserve the lastUsed:
    value->lastUsed = current_object_iter->second->lastUsed;
    // preserve the lastUsedAges:
    value->lastUsedAges = current_object_iter->second->lastUsedAges;
    // preserve the numTimesUsed:
    value->numTimesUsed = current_object_iter->second->numTimesUsed;
    // an shared / unique pointer count refreshes:
    value->numRefreshesDone = current_object_iter->second->numRefreshesDone + 1;
    // count the scheduled refreshes:
    value->numRefreshesScheduled =
        current_object_iter->second->numRefreshesScheduled;

    BMCWEB_LOG_STATEFUL_DEBUG << "Update existing entry:" << " Key: " << key_id
                              << " Value: " << value->toString();
  }
  // upsert the key:
  managedObjects.insert_or_assign(key_id, value);

  BMCWEB_LOG_STATEFUL_DEBUG
      << "Updated Object! Key: " << key_id
      << " New: " << managedObjects.find(key_id)->second->toString();
}

void ManagedObjectStore::processDbusResponse(
    const KeyType& key, const std::shared_ptr<ValueType>& value,
    bool isReadThroughRequest, std::optional<uint64_t> refresh_interval) {
  std::string key_id = key.GetId();

  BMCWEB_LOG_STATEFUL_DEBUG << "Updating store with fresh dbus response "
                            << " Key: " << key_id
                            << " Value: " << value->toString()
                            << " ec: " << value->errorCode.message();

  UpdateOrInsertManagedObjects(key_id, value);

  // Callbacks to invoke after processing dbus response.
  std::queue<ManagedStoreCb> cb_queue = GetCallbacksFromRequestCbMap(key_id);

  // Update pending dbus response count on receiving response.
  {
    absl::MutexLock lock(managed_store_tracker_mutex_);
    this->managedStoreTracker.decrementPendingDbusResponses(
        isReadThroughRequest);
  }

  while (!cb_queue.empty()) {
    auto& callback = cb_queue.front();
    std::move(callback)(value);
    cb_queue.pop();
  }

  bool has_refresh_interval = refresh_interval.has_value();

  // A refresh operation is queued into the priority queue if the object has
  // no previous queued refresh operation or if there is a
  // custom refresh interval that needs to be prioritized over previously queued
  // refresh operation.
  size_t& pq_entry_count = key_to_pq_entry_[key_id];
  if (pq_entry_count == 0 || has_refresh_interval) {
    pq_entry_count++;
    // Queue refresh operation.
    pq.push(
        PriorityQueueEntry(key, value->nextRefreshAt, value->lastRefreshAt));

    // Cancel current scheduled refresh operation if refresh interval of the key
    // is less than the timer wait duration.
    auto timer_wait_duration = timer.expiry() - clockNow();
    if (isSchedulerActive && has_refresh_interval &&
        timer_wait_duration > std::chrono::milliseconds(*refresh_interval)) {
      timer.cancel();
      return;
    }
  }

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

bool ManagedObjectStore::DetectChange(const ValueType& valueA,
                                      const ValueType& valueB) {
  return (valueA != valueB);
}

void ManagedObjectStore::UpdateNumRefreshesScheduled(std::string& key_id) {
  absl::MutexLock lock(managed_objects_mutex_);
  auto managed_object_iter = this->managedObjects.find(key_id);
  if (managed_object_iter != this->managedObjects.end()) {
    managed_object_iter->second->numRefreshesScheduled += 1;

    BMCWEB_LOG_STATEFUL_DEBUG
        << "refreshObject: Key: " << managed_object_iter->first
        << " Value before refresh: " << managed_object_iter->second->toString();
  }
}

void ManagedObjectStore::refreshObject(
    const KeyType& key, bool isReadThroughRequest,
    const std::shared_ptr<boost::asio::io_context::strand>& strand) {
  std::string key_id = key.GetId();

  UpdateNumRefreshesScheduled(key_id);

  std::optional<uint64_t> refresh_interval = GetRefreshInterval(key_id);

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

  // Record a pending refresh operation.
  absl::MutexLock lock(managed_store_tracker_mutex_);
  managedStoreTracker.incrementPendingDbusResponses(isReadThroughRequest);
}

void ManagedObjectStore::scheduleRefresh() {
  if (this->isSchedulerActive || this->config.snap_shot_mode) {
    // The timer callback will schedule the next refresh if the scheduler is
    // active.
    return;
  }

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

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

    // Get managedStore key to queue refresh of corresponding object in
    // the managedStore.
    const KeyType& key = pqEntry.managedStoreKey;
    const std::string key_id = key.GetId();

    // The object is no longer tracked:
    if (!IsManagedObjectTracked(key_id)) {
      pq.pop();
      key_to_pq_entry_.erase(key_id);
      continue;
    }

    std::chrono::steady_clock::time_point managed_store_entry_last_used;
    std::chrono::steady_clock::time_point managed_store_entry_next_refresh_at;
    std::chrono::steady_clock::time_point managed_store_entry_last_refresh_at;
    {
      absl::MutexLock lock(managed_objects_mutex_);
      auto managed_object_iter = managedObjects.find(key_id);
      if (managed_object_iter == managedObjects.end()) continue;

      // Copy managed_store_entry timepoints so that we don't need locks later.
      // Note, time here might be invalid after the following line
      // because of an immediate object insertion or usage. This is ok because
      // even if the priority queue entry is removed, when we find the object
      // becomes stale, it will enqueued again.
      // Invalid `last_refresh_at` or `next_refresh_at` will not cause fatal
      // issues, as well, because freshness is strictly checked.
      managed_store_entry_last_used = managed_object_iter->second->lastUsed;
      managed_store_entry_next_refresh_at =
          managed_object_iter->second->nextRefreshAt;
      managed_store_entry_last_refresh_at =
          managed_object_iter->second->lastRefreshAt;
    }

    const auto duration_since_used =
        clockSince(managed_store_entry_last_used, timeNow);
    bool is_recently_used = duration_since_used < this->config.tLRUThreshold;

    BMCWEB_LOG_STATEFUL_DEBUG
        << "SinceUsed:" << " Key: " << key.toString()
        << " duration_since_used: "
        << clockSinceMilliseconds(managed_store_entry_last_used, timeNow)
        << " is_recently_used: " << is_recently_used;

    // LRU Eviction:
    if (!is_recently_used) {
      BMCWEB_LOG_STATEFUL_DEBUG << "Since Used: Evict:" << " Key: " << key_id;
      EvictManagedObject(key_id);
      pq.pop();
      key_to_pq_entry_.erase(key_id);
      continue;
    }

    // Handle recently refreshed object.
    if (managed_store_entry_last_refresh_at > pqEntry.lastRefreshAt) {
      BMCWEB_LOG_STATEFUL_DEBUG << "PQ entry recently refreshed: " << key_id;

      // Get current refresh interval from the managedStore entry.
      auto current_refresh_interval = managed_store_entry_next_refresh_at -
                                      managed_store_entry_last_refresh_at;

      // Get refresh interval from the priority queue entry.
      auto pq_entry_refresh_interval =
          pqEntry.nextRefreshAt - pqEntry.lastRefreshAt;
      size_t* pq_entry_count = nullptr;
      if (auto find_key_count = key_to_pq_entry_.find(key_id);
          find_key_count != key_to_pq_entry_.end()) {
        pq_entry_count = &find_key_count->second;
      }

      // The pqEntry is redundant and needs to be removed if corresponding
      // managed store entry is refreshed recently and refresh interval
      // configured in managedStore entry is less than the refresh interval
      // configured in pqEntry.
      if (pq_entry_count != nullptr &&
          (current_refresh_interval < pq_entry_refresh_interval ||
           (current_refresh_interval == pq_entry_refresh_interval &&
            *pq_entry_count > 1))) {
        BMCWEB_LOG_STATEFUL_DEBUG << "Removing redundant pqEntry: "
                                  << pqEntry.managedStoreKey.toString();
        pq.pop();
        if (--(*pq_entry_count) == 0) {
          key_to_pq_entry_.erase(key_id);
        }
        continue;
      }

      // Re-queue the entry because the last object was refreshed due to a
      // forced cache read through.
      BMCWEB_LOG_STATEFUL_DEBUG << "Re-queue pqEntry: "
                                << pqEntry.managedStoreKey.toString();
      const KeyType key_local = key;
      pq.pop();
      pq.push(PriorityQueueEntry(key_local, managed_store_entry_next_refresh_at,
                                 managed_store_entry_last_refresh_at));
      continue;
    }
    can_schedule = true;
  }

  if (!can_schedule) {
    return;
  }

  BMCWEB_LOG_STATEFUL_DEBUG
      << "scheduleRefresh: " << pq.size()
      << " Pending dbus responses: " << count_pending_dbus_responses;

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

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

  // Stop tracking the pq entry once it is pop'd from the queue.
  if (auto iter = key_to_pq_entry_.find(key_id);
      iter != key_to_pq_entry_.end()) {
    if (--iter->second == 0) {
      key_to_pq_entry_.erase(iter);
    }
  }

  // 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. "
                            << "Key: " << managedStoreKey.GetId();

  timer.async_wait(
      [this, managedStoreKey, pqEntry](boost::system::error_code ec) {
        isSchedulerActive = false;
        if (ec == boost::asio::error::operation_aborted) {
          BMCWEB_LOG_STATEFUL_INFO << "Timer operation aborted for key: "
                                   << managedStoreKey.GetId();
          // There is an object needs to be refreshed earlier than currently
          // scheduled object. Push the key for current object back into the PQ
          // to be scheduled later point in time.
          pq.push(PriorityQueueEntry(managedStoreKey, pqEntry.nextRefreshAt,
                                     pqEntry.lastRefreshAt));
          scheduleRefresh();
          return;
        }

        if (ec) {
          BMCWEB_LOG_STATEFUL_ERROR << "Async_wait failed" << ec;
          return;
        }
        BMCWEB_LOG_STATEFUL_DEBUG << "Refreshing managed store entry. "
                                  << "Key: " << managedStoreKey.GetId();
        refreshObject(managedStoreKey);
        scheduleRefresh();
      });
}

// TODO - testing
void ManagedObjectStore::listUnits(
    const ManagedObjectStoreContext& requestContext,
    GetManagedSystemdListUnitsCb callback) {
  // When Object Store is disabled, the requests read through.
  if (!this->isEnabled()) {
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::SystemdListUnits& listUnits) mutable {
          std::move(callback)(ec, listUnits);
        },
        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager", "ListUnits");
    return;
  }

  KeyType key_type(ManagedType::kManagedSystemdListUnits);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->SystemdListUnits.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(callback)(valueType->errorCode,
                            valueType->SystemdListUnits.value());
      });
}

void ManagedObjectStore::getProperty(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    GetManagedPropertyCb callback) {
  // When Object Store is disabled, the requests read through.
  if (!this->isEnabled()) {
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DbusVariantType& value) mutable {
          std::move(callback)(ec, value, 0);
        },
        keyType.serviceName, keyType.objectPath.str,
        "org.freedesktop.DBus.Properties", "Get", keyType.interface,
        keyType.property);
    return;
  }

  getStoredOrReadThrough(
      keyType, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedProperty.has_value()) {
          callback(valueType->errorCode, {}, 0);
          return;
        }
        uint64_t age_in_ms = static_cast<uint64_t>(
            std::chrono::duration_cast<std::chrono::milliseconds>(
                clockNow() - valueType->lastRefreshAt)
                .count());
        LOG(INFO) << "MAX AGE AT THIS POINT: " << age_in_ms;
        std::move(callback)(valueType->errorCode,
                            valueType->managedProperty.value(), age_in_ms);
      });
}

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()) {
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const ::dbus::utility::DBusPropertiesMap& properties) mutable {
          std::move(callback)(ec, properties);
        },
        service, objectPath, "org.freedesktop.DBus.Properties", "GetAll",
        interface);
    return;
  }

  KeyType key_type(ManagedType::kManagedPropertyMap, service, objectPath,
                   interface);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedPropertyMap.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(callback)(valueType->errorCode,
                            valueType->managedPropertyMap.value());
      });
}

void ManagedObjectStore::subscribe(
    const ManagedObjectStoreContext& requestContext,
    const std::string& match_expression,
    ecclesia::EventSourceId event_source_id) {
  if (match_expression.empty()) {
    LOG(WARNING)
        << "D-Bus match expression is empty. Invalid call to subscribe!";
    return;
  }

  if (requestContext.eventSourceIds == nullptr ||
      requestContext.request_type ==
          ManagedObjectStoreContext::RequestType::kQuery) {
    LOG(WARNING) << "eventSourceIds is null. Invalid call to subscribe!";
    return;
  }

  // Check if monitor already exists.
  {
    absl::MutexLock lock(signal_monitor_mutex_);
    if (auto find_monitor = signal_monitors_.find(event_source_id);
        find_monitor != signal_monitors_.end()) {
      if (requestContext.request_type ==
          ManagedObjectStoreContext::RequestType::kCancelSubscription) {
        // Erase the monitor
        signal_monitors_.erase(find_monitor);
        LOG(WARNING) << "Erased D-Bus monitor for id: "
                     << event_source_id.ToString();
        return;
      }

      LOG(WARNING) << "D-Bus monitor already created for id: "
                   << event_source_id.ToString();

      // Record monitor id regardless of an existing subscription since
      // multiple Redfish resources can have dependency on a dbus signal.
      requestContext.eventSourceIds->push_back(std::move(event_source_id));
      return;
    }
  }

  boost::asio::post(io_context_main_thread_, [this, event_source_id,
                                              match_expression] {
    absl::MutexLock lock(signal_monitor_mutex_);
    signal_monitors_[event_source_id] = std::make_unique<
        sdbusplus::bus::match_t>(
        *system_bus_, match_expression,
        [event_source_id, this](sdbusplus::message_t&) {
          LOG(INFO)
              << "Received dbus signal. Notifying Subscription service now!";
          auto status =
              subscription_service_->Notify(event_source_id, absl::OkStatus());
          if (status.ok()) {
            LOG(INFO) << "Notified successfully!";
            return;
          }
          LOG(WARNING) << "Error while sending notification: " << status;
          if (status.code() == absl::StatusCode::kNotFound) {
            absl::MutexLock lock(signal_monitor_mutex_);
            signal_monitors_.erase(event_source_id);
            LOG(INFO) << "Erased D-Bus monitor for id: "
                      << event_source_id.ToString();
          }
        });
    LOG(INFO) << "D-Bus monitor created. Event Source id: "
              << event_source_id.ToString();
  });

  // Record event source ids.
  requestContext.eventSourceIds->push_back(std::move(event_source_id));
}

void ManagedObjectStore::subscribeToInterfacesAdded(
    const std::string& object_path,
    const ManagedObjectStoreContext& request_context) {
  std::string match_expression = absl::Substitute(
      "type='signal',interface='org.freedesktop.DBus.ObjectManager',path_"
      "namespace='$0',"
      "member='InterfacesAdded'",
      object_path);

  std::string monitor_id;
  AppendWithSep(monitor_id, '|', object_path, "InterfacesAdded", "EVENT");

  ecclesia::EventSourceId event_source_id(
      monitor_id, ecclesia::EventSourceId::Type::kDbusObjects);

  subscribe(request_context, match_expression, std::move(event_source_id));
}

void ManagedObjectStore::subscribeToHealthMonitor(
    const std::string& object_path, HealthChangeCallback callback) {
  std::string match_expression = absl::Substitute(
      "type='signal'"
      ",interface='xyz.openbmc_project.HealthMonitor.GetStatus',path_"
      "namespace='$0',"
      "member='healthyPropertyChanged'",
      object_path);

  std::string monitor_id;
  AppendWithSep(monitor_id, '|', object_path, "healthyPropertyChanged",
                "EVENT");

  boost::asio::post(
      io_context_main_thread_, [this, match_expression, object_path,
                                callback = std::move(callback)]() mutable {
        if (health_monitors_.contains(object_path)) {
          return;
        }
        health_monitors_[object_path] =
            std::make_unique<sdbusplus::bus::match_t>(
                *system_bus_, match_expression,
                [callback = std::make_shared<HealthChangeCallback>(
                     std::move(callback))](sdbusplus::message_t& msg) {
                  std::string dbusPath;
                  try {
                    msg.read(dbusPath);
                  } catch (const std::exception& e) {
                    LOG(WARNING) << "Failed to read dbus path: " << e.what();
                    return;
                  }
                  (*callback)(dbusPath);
                });
      });
}

void ManagedObjectStore::subscribeToEntityManagerChange(
    EntityManagerChangeCallback callback) {
  std::string match_expression =
      "type='signal',member='PropertiesChanged',"
      "path_namespace='/xyz/openbmc_project/inventory',"
      "arg0namespace='xyz.openbmc_project.Configuration.HealthMonitor'";

  std::string monitor_id;
  AppendWithSep(monitor_id, '|', "/xyz/openbmc_project/inventory",
                "PropertiesChanged", "EVENT");

  boost::asio::post(
      io_context_main_thread_,
      [this, match_expression, callback = std::move(callback)]() mutable {
        entity_manager_monitor_ = std::make_unique<sdbusplus::bus::match_t>(
            *system_bus_, match_expression,
            [callback = std::make_shared<EntityManagerChangeCallback>(
                 std::move(callback))](sdbusplus::message_t& message) {
              // TODO: b/433598433 -
              // Add unit test for this callback.
              (*callback)(message.get_path());
            });
      });
}

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()) {
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
          std::move(callback)(ec, subtree);
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
        interfaces);
    return;
  }

  KeyType key_type(ManagedType::kManagedSubtree, path, depth, interfaces);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedSubtree.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(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 (const 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 (const auto& s : interfaces) {
    interfaces2.emplace_back(s);
  }

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

  KeyType key_type(ManagedType::kManagedSubtreePaths, path, depth, interfaces2);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedSubtreePaths.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(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 (const 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;
  interfaces2.reserve(interfaces.size());
  for (const auto& s : interfaces) {
    interfaces2.emplace_back(s);
  }

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

  KeyType key_type(ManagedType::kManagedAssociatedSubtree, associatedPath.str,
                   path.str, depth, interfaces2);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedSubtree.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(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 (const auto& s : interfaces) {
    interfaces2.emplace_back(s);
  }

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

  KeyType key_type(ManagedType::kManagedAssociatedSubtreePaths,
                   associatedPath.str, path.str, depth, interfaces2);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (!valueType->managedSubtreePaths.has_value()) {
          std::move(callback)(valueType->errorCode, {});
          return;
        }
        std::move(callback)(valueType->errorCode,
                            valueType->managedSubtreePaths.value());
      });
}

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

  // When Object Store is disabled, the requests read through.
  if (!this->isEnabled()) {
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetObject& object) mutable {
          std::move(callback)(ec, object);
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces2);
    return;
  }

  KeyType key_type(ManagedType::kManagedMapperObject, path, interfaces2);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (valueType->mapperGetObject.has_value()) {
          std::move(callback)(valueType->errorCode,
                              valueType->mapperGetObject.value());
          return;
        }
        std::move(callback)(valueType->errorCode, {});
      });
}

void ManagedObjectStore::getManagedObjectsWithContext(
    const std::string& service, const sdbusplus::message::object_path& path,
    const ManagedObjectStoreContext& requestContext,
    GetManagedObjectsCb callback) {
  {
    uint64_t count_get_managed_objects = 0;
    // total counter of calls:
    absl::MutexLock lock(managed_store_tracker_mutex_);
    count_get_managed_objects =
        ++this->managedStoreTracker.countGetManagedObjects;
    BMCWEB_LOG_STATEFUL_DEBUG
        << "getManagedObjectsWithContext:" << " service: " << service
        << " path: " << path.str
        << " requestContext: " << requestContext.toString()
        << " count: " << count_get_managed_objects;
  }

  // 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?
    {
      absl::MutexLock lock(managed_store_tracker_mutex_);
      this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;
    }
    PostDbusCallToIoContextThreadSafe(
        requestContext.GetStrand(),
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& objects) mutable {
          std::move(callback)(ec, objects);
        },
        service, path, "org.freedesktop.DBus.ObjectManager",
        "GetManagedObjects");
    return;
  }

  KeyType key_type(ManagedType::kManagedObject, service, path.str);
  getStoredOrReadThrough(
      key_type, requestContext,
      [callback = std::move(callback)](
          const std::shared_ptr<ValueType>& valueType) mutable {
        if (valueType->managedObject.has_value()) {
          std::move(callback)(valueType->errorCode,
                              valueType->managedObject.value());
          return;
        }
        std::move(callback)(valueType->errorCode, {});
      });
}

std::shared_ptr<ValueType> ManagedObjectStore::IsManagedObjectCurrentAndTracked(
    const std::string& key_id, const KeyType& keyType,
    const ManagedObjectStoreContext& requestContext) {
  absl::MutexLock lock(managed_objects_mutex_);

  std::shared_ptr<ValueType> cached_object = nullptr;
  bool is_object_current = false;

  auto managed_object_iter = managedObjects.find(key_id);
  // Execute callback immediately if object is cached in store.
  if (managed_object_iter != managedObjects.end()) {
    cached_object = managed_object_iter->second;
    const std::chrono::steady_clock::time_point timeNow = clockNow();
    std::chrono::steady_clock::duration current_age =
        clockSince(cached_object->lastRefreshAt, timeNow);

    // update lastUsed:
    // NOMUTANTS -- TODO later
    cached_object->lastUsed = timeNow;
    // count number of times used:
    cached_object->numTimesUsed += 1;
    // update lastUsedAges:
    if (!cached_object->lastUsedAges) {
      cached_object->lastUsedAges =
          std::make_shared<std::list<std::chrono::steady_clock::duration>>();
    }
    cached_object->lastUsedAges->push_back(current_age);
    while (cached_object->lastUsedAges->size() >=
           managedStore::ValueType::kLastUsedAgesMaxSize) {
      cached_object->lastUsedAges->pop_front();
    }

    LOG(INFO) << "Object found in store. " << " Key: " << key_id
              << " CurrentAge: " << clockDurationMilliseconds(current_age)
              << " Context: " << requestContext.toString()
              << " Value: " << cached_object->toString();

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

    // Always use the cache if snapshot mode is enabled.
    if (config.snap_shot_mode) {
      is_object_stale = false;
    }

    // Evict the object from store as it has become stale.
    if (is_object_stale) {
      LOG(INFO) << "Object has become stale! "
                << " service: " << keyType.serviceName
                << " path: " << keyType.objectPath.str << " interface: "
                << keyType.interface << " property: " << keyType.property
                << " current_age: " << clockDurationMilliseconds(current_age)
                << " Context: " << requestContext.toString()
                << " Value: " << cached_object->toString();
      managedObjects.erase(managed_object_iter->first);
    }

    // can we use it as is:
    is_object_current = !is_object_stale;

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

    // Force a refresh if the request is associated with subscription.
    if (requestContext.request_type ==
        ManagedObjectStoreContext::RequestType::kOnEvent) {
      // TODO(rahulkpr): Need to log how many read throughs were due to
      // events.
      is_object_current = false;
    }
  }

  if (requestContext.HasCustomRefreshInterval()) {
    std::optional<uint64_t> current_refresh_interval =
        GetRefreshInterval(key_id);
    // NO_CDC: HasCustomRefreshInterval checks for optional.
    const uint64_t& refresh_interval_ms = *requestContext.refresh_interval_ms;
    if (std::chrono::milliseconds(refresh_interval_ms) >=
        this->config.tfixedThreshold) {
      // Requested interval is greater than global refresh interval. This
      // is a no-op. Just read from cache without changing intervals.
      BMCWEB_LOG_STATEFUL_DEBUG
          << "Ignoring custom refresh interval.\nRequested "
             "refresh_interval_ms: "
          << refresh_interval_ms << " is greater than global refresh interval: "
          << config.tfixedThreshold << " for key: " << key_id;
    } else if (!current_refresh_interval.has_value() ||
               (current_refresh_interval.has_value() &&
                refresh_interval_ms < *current_refresh_interval)) {
      // Requested interval is less than global refresh interval and there
      // isn't any custom interval set.
      // We need to do a cache read through and update refresh interval.
      SetRefreshInterval(key_id, refresh_interval_ms);
      // Read through is required to set custom interval.
      is_object_current = false;
    }
  }

  if (!is_object_current) {
    return nullptr;
  }

  return cached_object;
}

void ManagedObjectStore::getStoredOrReadThrough(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    ManagedStoreCb callback) {
  std::string key_id = keyType.GetId();

  BMCWEB_LOG_DEBUG << __func__ << " Key: " << key_id
                   << " requestContext: " << requestContext.toString();

  // Object is served from cache except in following scenarios:
  //  1. Cache is cold.
  //  2. Cached object is stale.
  //  3. Custom refresh interval needs to be configured.
  //  4. Request is associated with redfish event which requires a read
  //     through to create origin of condition.

  std::shared_ptr<ValueType> cached_object =
      IsManagedObjectCurrentAndTracked(key_id, keyType, requestContext);

  bool is_object_current = cached_object != nullptr;

  // Evict the object from store as it has become stale.
  if (is_object_current) {
    // Return if the object is still fresh
    {
      absl::MutexLock lock(managed_store_tracker_mutex_);
      this->managedStoreTracker.countGetManagedObjectsCacheHit += 1;
    }
    BMCWEB_LOG_STATEFUL_DEBUG << "Cache hit: calling the user callback for "
                              << key_id;
    // If we are in snapshot mode, we want to simulate asynchronous callback
    // behavior to catch dangling references into the callback.
    if (config.snap_shot_mode) {
      boost::asio::post(io_context_main_thread_,
                        [callback{std::move(callback)},
                         cached_object{std::move(cached_object)}]() mutable {
                          // already in the strand
                          std::move(callback)(cached_object);
                        });
      return;
    }
    callback(cached_object);
    return;
  }

  {
    absl::MutexLock lock(managed_store_tracker_mutex_);
    this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;
  }

  // If snapshot mode is enabled, we will fail the request and send error code
  if (this->config.snap_shot_mode) {
    LOG(WARNING) << key_id << " not found in cache.";
    LOG(WARNING) << "Cache miss in snapshot mode; no way to update the cache.";
    callback(std::make_shared<ValueType>(boost::system::errc::make_error_code(
        boost::system::errc::no_such_file_or_directory)));
    return;
  }

  bool need_refresh = true;
  if (requestContext.GetStrand()) {
    // from now on we need to make callback only happen in the strand
    absl::AnyInvocable<void(const std::shared_ptr<ValueType>&)>
        callback_in_strand =
            [callback = std::move(callback),
             strand = requestContext.GetStrand()](
                const std::shared_ptr<ValueType>& value) mutable {
              auto callback_wrapper = internal::CallAtMostOnce(
                  [callback(std::move(callback)), value]() mutable {
                    std::move(callback)(value);
                  });
              boost::asio::post(*strand, std::move(callback_wrapper));
            };

    // Handle concurrent requests for the same object by storing callback
    // for the request.
    // There might be cases where a callback is enqueued but dequeued shortly
    // after, which makes the `need_refresh` invalid, however, this is totally
    // fine as the follow `refreshObject` will just do a refresh earlier.
    need_refresh = InsertCallbackIntoRequestCbMapAndReturnTrueIfNew(
        key_id, std::move(callback_in_strand));
  } else {
    need_refresh = InsertCallbackIntoRequestCbMapAndReturnTrueIfNew(
        key_id, std::move(callback));
  }

  if (!need_refresh) {
    return;
  }

  BMCWEB_LOG_DEBUG << "Fetching fresh object over dbus. " << " Key: " << key_id
                   << " requestContext: " << requestContext.toString();

  // 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.
  BMCWEB_LOG_DEBUG << "strand is "
                   << (requestContext.GetStrand() ? "set" : "null");
  refreshObject(keyType, true, requestContext.GetStrand());
}

void ManagedObjectStore::clearAllObjects() {
  {
    absl::MutexLock lock(managed_objects_mutex_);
    this->managedObjects.clear();
  }
  clearTimeTrace();
  // looks like it's the only way to do this:
  boost::asio::post(io_context_main_thread_,
                    [this]() { pq = ManagedStorePriorityQueue(); });
}

void ManagedObjectStore::getManagedObjectsFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    const std::string& service, const sdbusplus::message::object_path& path,
    ManagedStoreCb callback, std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback{std::move(callback)}, refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& objects) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(objects, ec, timeNow,
                                                 timeNow + interval);
        std::move(callback)(value);
      },
      service, path.str, "org.freedesktop.DBus.ObjectManager",
      "GetManagedObjects");
}

void ManagedObjectStore::getManagedMapperObjectFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    const sdbusplus::message::object_path& path,
    const std::vector<std::string>& interfaces, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback{std::move(callback)}, refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetObject& object) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(object, ec, timeNow,
                                                 timeNow + interval);
        std::move(callback)(value);
      },
      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
      "xyz.openbmc_project.ObjectMapper", "GetObject", path.str, interfaces);
}

void ManagedObjectStore::getSystemdUnitsFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    ManagedStoreCb callback, std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback{std::move(callback)}, refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::SystemdListUnits& listUnits) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(listUnits, ec, timeNow,
                                                 timeNow + interval);
        std::move(callback)(value);
      },
      "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
      "org.freedesktop.systemd1.Manager", "ListUnits");
}

void ManagedObjectStore::getManagedPropertiesFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, const std::string& property,
    ManagedStoreCb callback, std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback{std::move(callback)}, refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::DbusVariantType& propertyValue) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(propertyValue, ec, timeNow,
                                                 timeNow + interval);
        std::move(callback)(value);
      },
      service, path.str, "org.freedesktop.DBus.Properties", "Get", interface,
      property);
}

void ManagedObjectStore::getManagedPropertiesMapFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback{std::move(callback)}, refresh_interval](
          const boost::system::error_code ec,
          const ::dbus::utility::DBusPropertiesMap& properties) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(properties, ec, timeNow,
                                                 timeNow + interval);
        std::move(callback)(value);
      },
      service, path, "org.freedesktop.DBus.Properties", "GetAll", interface);
}

// Calls into dbus service to get subtree.
void ManagedObjectStore::getManagedSubtreeFromDbusService(
    const std::shared_ptr<boost::asio::io_context::strand>& strand,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback(std::move(callback)), refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(subtree, ec, timeNow,
                                                 timeNow + interval);
        std::move(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 std::shared_ptr<boost::asio::io_context::strand>& strand,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback(std::move(callback)), refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse&
              subtreePaths) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(subtreePaths, ec, timeNow,
                                                 timeNow + interval);
        std::move(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 std::shared_ptr<boost::asio::io_context::strand>& strand,
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback(std::move(callback)), refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(subtree, ec, timeNow,
                                                 timeNow + interval);
        std::move(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 std::shared_ptr<boost::asio::io_context::strand>& strand,
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb callback,
    std::optional<uint64_t> refresh_interval) {
  PostDbusCallToIoContextThreadSafe(
      strand,
      [this, callback(std::move(callback)), refresh_interval](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse&
              subtreePaths) mutable {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        std::chrono::steady_clock::duration interval =
            refresh_interval.has_value()
                ? std::chrono::milliseconds(*refresh_interval)
                : this->config.tfixedThreshold;
        auto value = std::make_shared<ValueType>(subtreePaths, ec, timeNow,
                                                 timeNow + interval);
        std::move(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();
}

void ManagedObjectStore::storeTimeTrace(const nlohmann::json& tTrace) {
  absl::MutexLock lock(time_trace_array_mutex_);
  if (time_trace_array_.size() >= this->config.timetrace_size_max) {
    time_trace_array_.erase(0);
  }
  time_trace_array_.push_back(tTrace);
}

void ManagedObjectStore::clearTimeTrace() {
  absl::MutexLock lock(time_trace_array_mutex_);
  time_trace_array_.clear();
}

bool ManagedObjectStore::serialize(std::string_view filePath) {
  BMCWEB_LOG_STATEFUL_DEBUG << "starting Serialized";
  nlohmann::json obj;
  if (!toJson(obj)) {
    BMCWEB_LOG_STATEFUL_DEBUG << "unable to serialize data ManagedObjectStore";
    return false;
  }
  try {
    std::ofstream serializeFile(filePath.data(), std::ios::out);
    serializeFile << obj.dump();
  } catch (const std::exception& e) {
    BMCWEB_LOG_STATEFUL_DEBUG << "unable write serialzed data to file";
    BMCWEB_LOG_STATEFUL_DEBUG << "error message:  " << e.what();
    return false;
  }
  return true;
}

bool ManagedObjectStore::deserialize(std::string_view filePath) {
  BMCWEB_LOG_STATEFUL_DEBUG << "starting Deserialized";
  nlohmann::json obj;
  std::optional<std::string> file_string =
      serialize::ReadBinaryFileToString(filePath);
  if (!file_string.has_value()) {
    BMCWEB_LOG_STATEFUL_DEBUG << "unable read the deserialzed file";
    return false;
  }
  obj = nlohmann::json::parse(file_string.value());
  BMCWEB_LOG_STATEFUL_DEBUG << "json file parsed";
  if (!fromJson(obj)) {
    BMCWEB_LOG_STATEFUL_DEBUG
        << "unable to deserialize ManagedObjectStore from json";
    return false;
  }
  BMCWEB_LOG_STATEFUL_DEBUG << "ManagedObjectStore deserialized from json";
  return true;
}

bool ManagedObjectStore::toJson(nlohmann::json& obj) {
  // turn data from ManagedObjectsMap to json
  nlohmann::json jsonManagedObjects = nlohmann::json::array();
  absl::MutexLock lock(managed_objects_mutex_);
  for (ManagedObjectsMap::iterator itor = managedObjects.begin();
       itor != managedObjects.end(); itor++) {
    nlohmann::json managedObject;
    managedObject["key"] = itor->first;
    managedObject["value"] = itor->second->serialize();
    jsonManagedObjects.push_back(managedObject);
  }
  obj["managedObject"] = jsonManagedObjects;

  return true;
}

bool ManagedObjectStore::fromJson(const nlohmann::json& obj) {
  nlohmann::json jsonManagedObjects = obj["managedObject"];
  for (nlohmann::json::iterator jmanagedObject = jsonManagedObjects.begin();
       jmanagedObject != jsonManagedObjects.end(); jmanagedObject++) {
    try {
      nlohmann::json::reference ref = jmanagedObject->at("value");
      std::shared_ptr<ValueType> val = std::make_shared<ValueType>(ref);
      std::string key = jmanagedObject->at("key");
      absl::MutexLock lock(managed_objects_mutex_);
      managedObjects.insert({key, val});
    } catch (const std::exception& e) {
      BMCWEB_LOG_STATEFUL_DEBUG
          << "unable deserialize, error building managedObjects";
      BMCWEB_LOG_STATEFUL_DEBUG << "error message:  " << e.what();
      return false;
    }
  }
  return true;
}

nlohmann::json ManagedObjectStore::GetSubscriptionsToJSON() {
  nlohmann::json json;
  if (subscription_service_ == nullptr) {
    json["Error"] = "SubscriptionService is null";
    return json;
  }
  return subscription_service_->GetSubscriptionsToJSON();
}

nlohmann::json ManagedObjectStore::GetEventsToJSON() {
  nlohmann::json json;
  if (subscription_service_ == nullptr) {
    json["Error"] = "SubscriptionService is null";
    return json;
  }
  return subscription_service_->GetEventsToJSON();
}

nlohmann::json ManagedObjectStore::GetDBusMonitorsToJSON() {
  nlohmann::json json;
  nlohmann::json& monitors_json = json["DBusMonitors"];
  monitors_json = nlohmann::json::array();
  absl::MutexLock lock(signal_monitor_mutex_);
  for (const auto& [event_source_id, match] : signal_monitors_) {
    nlohmann::json m_json;
    m_json["EventSourceId"] = event_source_id.ToJSON();
    monitors_json.push_back(m_json);
  }
  return json;
}

nlohmann::json ManagedObjectStore::GetEventsBySubscriptionIdToJSON(
    size_t subscription_id) {
  nlohmann::json json;
  if (subscription_service_ == nullptr) {
    json["Error"] = "SubscriptionService is null";
    return json;
  }
  return subscription_service_->GetEventsBySubscriptionIdToJSON(
      subscription_id);
}

nlohmann::json ManagedObjectStore::ClearEventStore() {
  nlohmann::json json;
  if (subscription_service_ == nullptr) {
    json["Error"] = "SubscriptionService is null";
    return json;
  }
  subscription_service_->ClearEventStore();
  return subscription_service_->GetEventsToJSON();
}

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);
  obj["is_timetrace_enabled"] = this->timetrace;
  obj["timetrace_size_max"] = this->timetrace_size_max;
  return obj;
}

std::string KeyType::GetId() const {
  // Convert interface list to string
  std::string interface_list_to_str;
  for (const std::string& interface_str : interfaceList) {
    AppendWithSep(interface_list_to_str, ',', interface_str);
  }

  std::string ret;
  switch (managedElementType) {
    case ManagedType::kManagedObject: {
      AppendWithSep(ret, kSep, "kManagedObject", serviceName, objectPath.str);
      break;
    }
    case ManagedType::kManagedPropertyMap: {
      AppendWithSep(ret, kSep, "kManagedPropertyMap", serviceName,
                    objectPath.str, interface);
      break;
    }
    case ManagedType::kManagedProperty: {
      AppendWithSep(ret, kSep, "kManagedProperty", serviceName, objectPath.str,
                    interface, property);
      break;
    }
    case ManagedType::kManagedMapperObject: {
      AppendWithSep(ret, kSep, "kManagedMapperObject", objectPath.str,
                    interface_list_to_str);
      break;
    }
    case ManagedType::kManagedSystemdListUnits: {
      AppendWithSep(ret, kSep, "kManagedSystemdListUnits");
      break;
    }
    case ManagedType::kManagedSubtree: {
      AppendWithSep(ret, kSep, "kManagedSubtree", objectPath.str,
                    std::to_string(treeDepth), interface_list_to_str);
      break;
    }
    case ManagedType::kManagedSubtreePaths: {
      AppendWithSep(ret, kSep, "kManagedSubtreePaths", objectPath.str,
                    std::to_string(treeDepth), interface_list_to_str);
      break;
    }
    case ManagedType::kManagedAssociatedSubtree: {
      AppendWithSep(ret, kSep, "kManagedAssociatedSubtree", objectPath.str,
                    std::to_string(treeDepth), interface_list_to_str,
                    associatedPath.str);
      break;
    }
    case ManagedType::kManagedAssociatedSubtreePaths: {
      AppendWithSep(ret, kSep, "kManagedAssociatedSubtreePaths", objectPath.str,
                    std::to_string(treeDepth), interface_list_to_str,
                    associatedPath.str);
      break;
    }
  }
  return ret;
}

inline std::size_t GetEstimatedJsonSize(const nlohmann::json& root) {
  if (root.is_null()) {
    return 0;
  }
  if (root.is_number()) {
    return 8;
  }
  if (root.is_boolean()) {
    return 1;
  }
  if (root.is_string()) {
    return root.get<std::string>().size();
  }
  if (root.is_binary()) {
    return root.get_binary().size();
  }
  const nlohmann::json::array_t* arr =
      root.get_ptr<const nlohmann::json::array_t*>();
  if (arr != nullptr) {
    std::size_t sum = 0;
    for (const auto& element : *arr) {
      sum += GetEstimatedJsonSize(element);
    }
    return sum;
  }
  const nlohmann::json::object_t* object =
      root.get_ptr<const nlohmann::json::object_t*>();
  if (object != nullptr) {
    std::size_t sum = 0;
    for (const auto& [k, v] : *object) {
      sum += k.size() + GetEstimatedJsonSize(v);
    }
    return sum;
  }
  return 0;
}

std::size_t ManagedObjectStore::GetSnapshotSizeInBytes() const {
  std::size_t bytes = 0;
  absl::MutexLock lock(managed_objects_mutex_);
  for (const auto& iter : managedObjects) {
    const std::string& key = iter.first;
    bytes += key.size();  // Not using capacity here for simplicity

    const ValueType& value = *iter.second;
    bytes += GetEstimatedJsonSize(
        value.serialize());  // This might be over-estimate but it is the
                             // simpliest way to give us a quick number without
                             // developing complicated code that visit all types
  }
  return bytes;
}

// Returns a json object with metrics about the managed objects.
nlohmann::json ManagedObjectStore::GetManagedObjectsMetrics(
    std::chrono::steady_clock::time_point now) const {
  constexpr int64_t kNumBuckets = 20;
  constexpr int64_t kBucketSize = 1000;
  nlohmann::json managed_objects_age_histograms = nlohmann::json::array();
  for (size_t i = 0; i < kNumBuckets; i++) {
    nlohmann::json bucket;
    bucket["Start"] = i * kBucketSize;
    bucket["Count"] = 0;
    managed_objects_age_histograms.push_back(bucket);
  }

  nlohmann::json managed_objects = nlohmann::json::array();
  int64_t max_object_age_ms = 0;
  int64_t max_last_served_age_ms = 0;
  int64_t count_last_served = 0;
  uint64_t sum_sotal_object_refreshes = 0;
  uint64_t sum_total_object_refresh_scheduled = 0;
  uint64_t sum_total_object_used = 0;

  int key_index = 0;

  {
    absl::MutexLock lock(managed_objects_mutex_);
    for (const auto& iter : managedObjects) {
      const std::string& key = iter.first;
      const ValueType& value = *iter.second;

      nlohmann::json obj;
      obj["@odata.id"] =
          "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/"
          "GoogleManagedObjectStoreMetrics#/ManagedObjects/" +
          std::to_string(key_index);
      obj["@odata.type"] =
          "#GoogleManagedObjectMetrics.v1_0_0.GoogleManagedObjectMetrics";

      // Split the key:
      std::string service_name;
      std::string object_path;
      std::string interface;
      std::string property;
      KeyType::fromKey(key, service_name, object_path, interface, property);

      obj["Id"] = key_index;
      obj["ServiceName"] = service_name;
      obj["ObjectPath"] = object_path;
      obj["Interface"] = interface;
      obj["Property"] = property;
      obj["Age"] = clockSinceMilliseconds(value.lastRefreshAt, now);
      obj["RefreshCountDone"] = value.numRefreshesDone;
      obj["RefreshCountScheduled"] = value.numRefreshesScheduled;
      obj["NumTimesUsed"] = value.numTimesUsed;

      key_index++;

      // sum up the counts:
      sum_sotal_object_refreshes += value.numRefreshesDone;
      sum_total_object_refresh_scheduled += value.numRefreshesScheduled;
      sum_total_object_used += value.numTimesUsed;

      nlohmann::json last_used_ages_obj = nlohmann::json::array();
      if (value.lastUsedAges) {
        std::for_each(
            value.lastUsedAges->begin(), value.lastUsedAges->end(),
            [&last_used_ages_obj, &count_last_served, &max_last_served_age_ms](
                const std::chrono::steady_clock::duration& dur) {
              const int64_t lastUsedDurationMs = clockDurationMilliseconds(dur);
              // report the last served ages:
              last_used_ages_obj.push_back(lastUsedDurationMs);
              // total count:
              count_last_served += 1;
              // track the max:
              max_last_served_age_ms =
                  std::max(max_last_served_age_ms, lastUsedDurationMs);
            });
      }
      obj["AgeLastServed"] = last_used_ages_obj;

      // object age histogram:
      const int64_t object_age_ms =
          clockSinceMilliseconds(value.lastRefreshAt, now);
      if (object_age_ms >= 0) {
        int64_t bucket_index =
            std::min(object_age_ms / kBucketSize, kNumBuckets);
        if (bucket_index >= 0) {
          // last buckets catches all:
          if (bucket_index >= kNumBuckets) {
            bucket_index = (kNumBuckets - 1);
          }
          const auto i = static_cast<size_t>(bucket_index);
          auto count = managed_objects_age_histograms[i]["Count"]
                           .get_ref<nlohmann::json::number_integer_t&>();
          managed_objects_age_histograms[i]["Count"] = count + 1;
        }
        // max age:
        max_object_age_ms = std::max(max_object_age_ms, object_age_ms);
      }
      managed_objects.push_back(obj);
    }
  }

  nlohmann::json google;
  google["@odata.id"] =
      "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/"
      "GoogleManagedObjectStoreMetrics";
  google["@odata.type"] =
      "#GoogleManagedObjectStoreMetrics.v1_0_0."
      "GoogleManagedObjectStoreMetrics";

  // Age Buckets:
  google["ManagedObjectsAgeHistograms"]["AgeBuckets"] =
      managed_objects_age_histograms;
  // Age Max:
  google["ManagedObjectsAgeHistograms"]["AgeMax"] = max_object_age_ms;

  // Last Served Count:
  google["ManagedObjectsAgeHistograms"]["LastServedCount"] = count_last_served;
  google["ManagedObjectsAgeHistograms"]["LastServedMax"] =
      max_last_served_age_ms;

  // Total num of refreshes:
  google["NumRefreshesDone"] = sum_sotal_object_refreshes;
  google["NumRefreshesScheduled"] = sum_total_object_refresh_scheduled;

  // Total num used:
  google["NumTimesUsed"] = sum_total_object_used;

  // ManagedStore counters from managedStoreTracker
  const ManagedStoreTracker store_tracker = getStoreTracker();
  google["NumGetManagedObjects"] = store_tracker.countGetManagedObjects;
  google["NumGetManagedObjectsCacheMiss"] =
      store_tracker.countGetManagedObjectsCacheMiss;
  google["NumGetManagedObjectsCacheHit"] =
      store_tracker.countGetManagedObjectsCacheHit;
  google["NumGetManagedObjectsCacheMissMaxAge"] =
      store_tracker.countGetManagedObjectsCacheMissMaxAge;

  // Export max pending and the threshold:
  google["PendingResponsesMax"] = store_tracker.countMaxPendingDbusResponses;
  google["PendingResponsesThreshold"] =
      store_tracker.countThresholdPendingResponses;

  // objects: (will probably remove from none debug builds)
  google["ManagedObjects"] = managed_objects;
  google["ManagedObjectsSize"] = managed_objects.size();
  // final object:
  return google;
}

}  // namespace managedStore
