| #include "trigger.hpp" |
| |
| #include "trigger_manager.hpp" |
| #include "types/report_types.hpp" |
| #include "types/trigger_types.hpp" |
| #include "utils/conversion_trigger.hpp" |
| #include "utils/transform.hpp" |
| |
| #include <phosphor-logging/log.hpp> |
| |
| Trigger::Trigger( |
| boost::asio::io_context& ioc, |
| const std::shared_ptr<sdbusplus::asio::object_server>& objServer, |
| const std::string& idIn, const std::string& nameIn, |
| const std::vector<TriggerAction>& triggerActionsIn, |
| const std::shared_ptr<std::vector<std::string>> reportIdsIn, |
| std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, |
| interfaces::TriggerManager& triggerManager, |
| interfaces::JsonStorage& triggerStorageIn, |
| const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn, |
| interfaces::ReportManager& reportManagerIn) : |
| id(idIn), |
| name(nameIn), triggerActions(std::move(triggerActionsIn)), |
| path(triggerDir + id), reportIds(std::move(reportIdsIn)), |
| thresholds(std::move(thresholdsIn)), |
| fileName(std::to_string(std::hash<std::string>{}(id))), |
| triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), |
| reportManager(reportManagerIn) |
| { |
| deleteIface = objServer->add_unique_interface( |
| path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { |
| dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { |
| if (persistent) |
| { |
| triggerStorage.remove(fileName); |
| } |
| for (const auto& reportId : *reportIds) |
| { |
| reportManager.updateTriggerIds(reportId, id, |
| TriggerIdUpdate::Remove); |
| } |
| boost::asio::post(ioc, [this, &triggerManager] { |
| triggerManager.removeTrigger(this); |
| }); |
| }); |
| }); |
| |
| triggerIface = objServer->add_unique_interface( |
| path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { |
| persistent = storeConfiguration(); |
| dbusIface.register_property_rw( |
| "Persistent", persistent, |
| sdbusplus::vtable::property_::emits_change, |
| [this](bool newVal, const auto&) { |
| if (newVal == persistent) |
| { |
| return 1; |
| } |
| if (newVal) |
| { |
| persistent = storeConfiguration(); |
| } |
| else |
| { |
| triggerStorage.remove(fileName); |
| persistent = false; |
| } |
| return 1; |
| }, |
| [this](const auto&) { return persistent; }); |
| |
| dbusIface.register_property_rw( |
| "Thresholds", TriggerThresholdParams{}, |
| sdbusplus::vtable::property_::emits_change, |
| [this, &triggerFactory](auto newVal, auto& oldVal) { |
| auto newThresholdParams = std::visit( |
| utils::ToLabeledThresholdParamConversion(), newVal); |
| triggerFactory.updateThresholds(thresholds, triggerActions, |
| reportIds, sensors, |
| newThresholdParams); |
| oldVal = std::move(newVal); |
| return 1; |
| }, |
| [this](const auto&) { |
| return fromLabeledThresholdParam( |
| utils::transform(thresholds, [](const auto& threshold) { |
| return threshold->getThresholdParam(); |
| })); |
| }); |
| |
| dbusIface.register_property_rw( |
| "Sensors", SensorsInfo{}, |
| sdbusplus::vtable::property_::emits_change, |
| [this, &triggerFactory](auto newVal, auto& oldVal) { |
| auto labeledSensorInfo = |
| triggerFactory.getLabeledSensorsInfo(newVal); |
| triggerFactory.updateSensors(sensors, labeledSensorInfo); |
| for (const auto& threshold : thresholds) |
| { |
| threshold->updateSensors(sensors); |
| } |
| oldVal = std::move(newVal); |
| return 1; |
| }, |
| [this](const auto&) { |
| return utils::fromLabeledSensorsInfo( |
| utils::transform(sensors, [](const auto& sensor) { |
| return sensor->getLabeledSensorInfo(); |
| })); |
| }); |
| |
| dbusIface.register_property_rw( |
| "ReportNames", std::vector<std::string>{}, |
| sdbusplus::vtable::property_::emits_change, |
| [this](auto newVal, auto& oldVal) { |
| TriggerManager::verifyReportIds(newVal); |
| updateTriggerIdsInReports(newVal); |
| reportIds->clear(); |
| std::copy(newVal.begin(), newVal.end(), |
| std::back_inserter(*reportIds)); |
| oldVal = std::move(newVal); |
| return 1; |
| }, |
| [this](const auto&) { return *reportIds; }); |
| |
| dbusIface.register_property_r( |
| "Discrete", false, sdbusplus::vtable::property_::const_, |
| [this](const auto& x) { |
| return !std::holds_alternative< |
| numeric::LabeledThresholdParam>( |
| thresholds.back()->getThresholdParam()); |
| }); |
| |
| dbusIface.register_property_rw( |
| "Name", std::string(), |
| sdbusplus::vtable::property_::emits_change, |
| [this](auto newVal, auto& oldVal) { |
| name = oldVal = newVal; |
| return 1; |
| }, |
| [this](const auto&) { return name; }); |
| |
| dbusIface.register_property_r( |
| "TriggerActions", std::vector<std::string>(), |
| sdbusplus::vtable::property_::const_, [this](const auto&) { |
| return utils::transform(triggerActions, |
| [](const auto& action) { |
| return actionToString(action); |
| }); |
| }); |
| }); |
| |
| for (const auto& threshold : thresholds) |
| { |
| threshold->initialize(); |
| } |
| |
| for (const auto& reportId : *reportIds) |
| { |
| reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add); |
| } |
| } |
| |
| bool Trigger::storeConfiguration() const |
| { |
| try |
| { |
| nlohmann::json data; |
| |
| auto labeledThresholdParams = |
| std::visit(utils::ToLabeledThresholdParamConversion(), |
| fromLabeledThresholdParam(utils::transform( |
| thresholds, [](const auto& threshold) { |
| return threshold->getThresholdParam(); |
| }))); |
| |
| data["Version"] = triggerVersion; |
| data["Id"] = id; |
| data["Name"] = name; |
| data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); |
| data["TriggerActions"] = |
| utils::transform(triggerActions, [](const auto& action) { |
| return actionToString(action); |
| }); |
| data["ThresholdParams"] = |
| utils::labeledThresholdParamsToJson(labeledThresholdParams); |
| data["ReportIds"] = *reportIds; |
| data["Sensors"] = utils::transform(sensors, [](const auto& sensor) { |
| return sensor->getLabeledSensorInfo(); |
| }); |
| |
| triggerStorage.store(fileName, data); |
| } |
| catch (const std::exception& e) |
| { |
| phosphor::logging::log<phosphor::logging::level::ERR>( |
| "Failed to store a trigger in storage", |
| phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); |
| return false; |
| } |
| return true; |
| } |
| |
| void Trigger::updateTriggerIdsInReports( |
| const std::vector<std::string>& newReportIds) |
| { |
| std::vector<std::string> toBeRemoved, toBeAdded; |
| size_t maxSize = std::max(reportIds->size(), newReportIds.size()); |
| toBeRemoved.reserve(maxSize); |
| toBeAdded.reserve(maxSize); |
| std::set_difference(reportIds->begin(), reportIds->end(), |
| newReportIds.begin(), newReportIds.end(), |
| std::back_inserter(toBeRemoved)); |
| std::set_difference(newReportIds.begin(), newReportIds.end(), |
| reportIds->begin(), reportIds->end(), |
| std::back_inserter(toBeAdded)); |
| for (auto& reportId : toBeRemoved) |
| { |
| reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Remove); |
| } |
| for (auto& reportId : toBeAdded) |
| { |
| reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add); |
| } |
| } |