#include "managed_store.hpp"

#include <sys/types.h>

#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <fstream>
#include <functional>
#include <ios>
#include <list>
#include <memory>
#include <optional>
#include <queue>
#include <span>
#include <string>
#include <string_view>
#include <thread>
#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/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 "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"

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

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

using ::ecclesia::EventSourceId;

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...);
}

}  // namespace

// 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) {
  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 ManagedStore instance(
      *cfg, *io_main_thread, std::this_thread::get_id(),
      io_context_worker_threads, subscription_service, systemBus);
  return &instance;
}

ManagedStore* GetManagedObjectStore() {
  return InitializeManagedStore(nullptr, nullptr, nullptr, nullptr, nullptr);
}

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::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 {
              std::function<void()> callback_wrapper = internal::CallAtMostOnce(
                  [callback(std::move(callback)), value]() mutable {
                    std::move(callback)(value);
                  });
              strand->post(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([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
