#include "report_manager.hpp" #include "interfaces/types.hpp" #include "report.hpp" #include "utils/transform.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, ReadingParameters metricParams) { return addReport(yield, reportName, reportingType, emitsReadingsUpdate, logToMetricReportsCollection, std::chrono::milliseconds(interval), std::move(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()); } void ReportManager::verifyAddReport(const std::string& reportName, std::chrono::milliseconds interval) { 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"); } } interfaces::Report& ReportManager::addReport( boost::asio::yield_context& yield, const std::string& reportName, const std::string& reportingType, const bool emitsReadingsUpdate, const bool logToMetricReportsCollection, std::chrono::milliseconds interval, ReadingParameters metricParams) { verifyAddReport(reportName, interval); reports.emplace_back(reportFactory->make( yield, reportName, reportingType, emitsReadingsUpdate, logToMetricReportsCollection, interval, std::move(metricParams), *this, *reportStorage)); return *reports.back(); } interfaces::Report& ReportManager::addReport( const std::string& reportName, const std::string& reportingType, const bool emitsReadingsUpdate, const bool logToMetricReportsCollection, std::chrono::milliseconds interval, std::vector labeledMetricParams) { verifyAddReport(reportName, interval); auto metricParams = utils::transform( labeledMetricParams, [](const LabeledMetricParameters& param) { using namespace utils::tstring; return ReadingParameters::value_type( utils::transform(param.at_index<0>(), [](const LabeledSensorParameters& p) { return sdbusplus::message::object_path( p.at_label()); }), param.at_index<1>(), param.at_index<2>(), param.at_index<3>()); }); reports.emplace_back(reportFactory->make( reportName, reportingType, emitsReadingsUpdate, logToMetricReportsCollection, interval, std::move(metricParams), *this, *reportStorage, labeledMetricParams)); 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(); auto readingParameters = data->at("ReadingParameters") .get>(); addReport(name, reportingType, emitsReadingsSignal, logToMetricReportsCollection, std::chrono::milliseconds(interval), std::move(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); } } }