#include "trigger.hpp" #include "messages/collect_trigger_id.hpp" #include "messages/trigger_presence_changed_ind.hpp" #include "trigger_manager.hpp" #include "types/report_types.hpp" #include "types/trigger_types.hpp" #include "utils/contains.hpp" #include "utils/conversion_trigger.hpp" #include "utils/dbus_path_utils.hpp" #include "utils/transform.hpp" #include Trigger::Trigger( boost::asio::io_context& ioc, const std::shared_ptr& objServer, TriggerId&& idIn, const std::string& nameIn, const std::vector& triggerActionsIn, const std::shared_ptr> reportIdsIn, std::vector>&& thresholdsIn, interfaces::TriggerManager& triggerManager, interfaces::JsonStorage& triggerStorageIn, const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) : id(std::move(idIn)), path(utils::pathAppend(utils::constants::triggerDirPath, *id)), name(nameIn), triggerActions(std::move(triggerActionsIn)), reportIds(std::move(reportIdsIn)), thresholds(std::move(thresholdsIn)), fileName(std::to_string(std::hash{}(*id))), triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), messanger(ioc) { deleteIface = objServer->add_unique_interface( path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { if (persistent) { triggerStorage.remove(fileName); } messanger.send(messages::TriggerPresenceChangedInd{ messages::Presence::Removed, *id, {}}); 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); TriggerManager::verifyThresholdParams(newThresholdParams); triggerFactory.updateThresholds( thresholds, *id, triggerActions, reportIds, sensors, newThresholdParams); oldVal = std::move(newVal); return 1; }, [this](const auto&) { return fromLabeledThresholdParam(getLabeledThresholds()); }); 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( getLabeledSensorInfo()); }); dbusIface.register_property_rw( "Reports", std::vector(), sdbusplus::vtable::property_::emits_change, [this](auto newVal, auto& oldVal) { auto newReportIds = utils::transform( newVal, [](const auto& path) { return utils::reportPathToId(path); }); TriggerManager::verifyReportIds(newReportIds); *reportIds = newReportIds; messanger.send(messages::TriggerPresenceChangedInd{ messages::Presence::Exist, *id, *reportIds}); oldVal = std::move(newVal); return 1; }, [this](const auto&) { return utils::transform( *reportIds, [](const auto& id) { return utils::pathAppend( utils::constants::reportDirPath, id); }); }); dbusIface.register_property_r( "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_, [this](const auto& x) { return isDiscreate(); }); dbusIface.register_property_rw( "Name", name, sdbusplus::vtable::property_::emits_change, [this](auto newVal, auto& oldVal) { if (newVal.length() > utils::constants::maxIdNameLength) { throw errors::InvalidArgument("Name", "Name is too long."); } name = oldVal = newVal; return 1; }, [this](const auto&) { return name; }); dbusIface.register_property_r( "TriggerActions", std::vector(), sdbusplus::vtable::property_::const_, [this](const auto&) { return utils::transform(triggerActions, [](const auto& action) { return actionToString(action); }); }); }); for (const auto& threshold : thresholds) { threshold->initialize(); } messanger.on_receive( [this](const auto& msg) { if (utils::contains(*reportIds, msg.reportId)) { messanger.send(messages::CollectTriggerIdResp{*id}); } }); messanger.send(messages::TriggerPresenceChangedInd{ messages::Presence::Exist, *id, *reportIds}); } bool Trigger::storeConfiguration() const { try { nlohmann::json data; auto labeledThresholdParams = std::visit(utils::ToLabeledThresholdParamConversion(), fromLabeledThresholdParam(getLabeledThresholds())); 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"] = getLabeledSensorInfo(); triggerStorage.store(fileName, data); } catch (const std::exception& e) { phosphor::logging::log( "Failed to store a trigger in storage", phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); return false; } return true; } std::vector Trigger::getLabeledSensorInfo() const { return utils::transform(sensors, [](const auto& sensor) { return sensor->getLabeledSensorInfo(); }); } std::vector Trigger::getLabeledThresholds() const { return utils::transform(thresholds, [](const auto& threshold) { return threshold->getThresholdParam(); }); } bool Trigger::isDiscreate() const { const auto labeledThresholds = getLabeledThresholds(); return utils::isFirstElementOfType(labeledThresholds) || utils::isFirstElementOfType( labeledThresholds); }