#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 "health.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 {

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::subscribeToHealthMonitor(
    const std::string& object_path) {
  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] {
    health_monitor_ = std::make_unique<sdbusplus::bus::match_t>(
        *system_bus_, match_expression, [](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;
          }
          redfish::HealthStatusCache::getInstance().processHealthStatusChange(
              dbusPath);
        });
  });
}

void ManagedObjectStore::subscribeToEntityManagerChange() {
  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] {
    entity_manager_monitor_ =
        std::make_unique<sdbusplus::bus::match_t>(
            *system_bus_, match_expression,
            [](sdbusplus::message_t& message) {
              // TODO: b/433598433 -
              // Add unit test for this callback.
              redfish::HealthStatusCache::getInstance()
                  .getHealthAttributes(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 {
              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
