#include "report_manager.hpp" #include "report.hpp" #include #include #include #include ReportManager::ReportManager( std::unique_ptr reportFactoryIn, std::unique_ptr reportStorageIn, const std::shared_ptr& objServerIn) : reportFactory(std::move(reportFactoryIn)), reportStorage(std::move(reportStorageIn)), objServer(objServerIn) { reports.reserve(maxReports); loadFromPersistent(); reportManagerIface = objServer->add_unique_interface( reportManagerPath, reportManagerIfaceName, [this](auto& dbusIface) { dbusIface.register_property_r( "MaxReports", uint32_t{}, sdbusplus::vtable::property_::const_, [](const auto&) { return maxReports; }); dbusIface.register_property_r( "MinInterval", uint64_t{}, sdbusplus::vtable::property_::const_, [](const auto&) -> uint64_t { return minInterval.count(); }); dbusIface.register_method( "AddReport", [this](boost::asio::yield_context& yield, const std::string& reportName, const std::string& reportingType, const bool emitsReadingsUpdate, const bool logToMetricReportsCollection, const uint64_t interval, const ReadingParameters& metricParams) { return addReport(yield, reportName, reportingType, emitsReadingsUpdate, logToMetricReportsCollection, std::chrono::milliseconds(interval), metricParams) ->getPath(); }); }); } void ReportManager::removeReport(const interfaces::Report* report) { reports.erase( std::remove_if(reports.begin(), reports.end(), [report](const auto& x) { return report == x.get(); }), reports.end()); } std::unique_ptr& ReportManager::addReport( std::optional> yield, const std::string& reportName, const std::string& reportingType, const bool emitsReadingsUpdate, const bool logToMetricReportsCollection, std::chrono::milliseconds interval, const ReadingParameters& metricParams) { if (reports.size() >= maxReports) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::too_many_files_open), "Reached maximal report count"); } for (const auto& report : reports) { if (report->getName() == reportName) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::file_exists), "Duplicate report"); } } if (interval < minInterval) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::invalid_argument), "Invalid interval"); } reports.emplace_back( reportFactory->make(yield, reportName, reportingType, emitsReadingsUpdate, logToMetricReportsCollection, interval, metricParams, *this, *reportStorage)); return reports.back(); } void ReportManager::loadFromPersistent() { std::vector paths = reportStorage->list(); for (const auto& path : paths) { std::optional data = reportStorage->load(path); try { size_t version = data->at("Version").get(); if (version != Report::reportVersion) { throw std::logic_error("Invalid version"); } std::string& name = data->at("Name").get_ref(); std::string& reportingType = data->at("ReportingType").get_ref(); bool emitsReadingsSignal = data->at("EmitsReadingsUpdate").get(); bool logToMetricReportsCollection = data->at("LogToMetricReportsCollection").get(); uint64_t interval = data->at("Interval").get(); ReadingParameters readingParameters; for (auto& item : data->at("ReadingParameters")) { readingParameters.emplace_back( LabeledReadingParameter::from_json(item)); } addReport(std::nullopt, name, reportingType, emitsReadingsSignal, logToMetricReportsCollection, std::chrono::milliseconds(interval), readingParameters); } catch (const std::exception& e) { phosphor::logging::log( "Failed to load report from storage", phosphor::logging::entry( "filename=", static_cast(path).c_str()), phosphor::logging::entry("msg=", e.what())); reportStorage->remove(path); } } }