1 #include "trigger.hpp" 2 3 #include "trigger_manager.hpp" 4 #include "types/report_types.hpp" 5 #include "types/trigger_types.hpp" 6 #include "utils/conversion_trigger.hpp" 7 #include "utils/transform.hpp" 8 9 #include <phosphor-logging/log.hpp> 10 11 Trigger::Trigger( 12 boost::asio::io_context& ioc, 13 const std::shared_ptr<sdbusplus::asio::object_server>& objServer, 14 const std::string& idIn, const std::string& nameIn, 15 const std::vector<TriggerAction>& triggerActionsIn, 16 const std::shared_ptr<std::vector<std::string>> reportIdsIn, 17 std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, 18 interfaces::TriggerManager& triggerManager, 19 interfaces::JsonStorage& triggerStorageIn, 20 const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn, 21 interfaces::ReportManager& reportManagerIn) : 22 id(idIn), 23 name(nameIn), triggerActions(std::move(triggerActionsIn)), 24 path(triggerDir + id), reportIds(std::move(reportIdsIn)), 25 thresholds(std::move(thresholdsIn)), 26 fileName(std::to_string(std::hash<std::string>{}(id))), 27 triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), 28 reportManager(reportManagerIn) 29 { 30 deleteIface = objServer->add_unique_interface( 31 path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { 32 dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { 33 if (persistent) 34 { 35 triggerStorage.remove(fileName); 36 } 37 for (const auto& reportId : *reportIds) 38 { 39 reportManager.updateTriggerIds(reportId, id, 40 TriggerIdUpdate::Remove); 41 } 42 boost::asio::post(ioc, [this, &triggerManager] { 43 triggerManager.removeTrigger(this); 44 }); 45 }); 46 }); 47 48 triggerIface = objServer->add_unique_interface( 49 path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { 50 persistent = storeConfiguration(); 51 dbusIface.register_property_rw( 52 "Persistent", persistent, 53 sdbusplus::vtable::property_::emits_change, 54 [this](bool newVal, const auto&) { 55 if (newVal == persistent) 56 { 57 return 1; 58 } 59 if (newVal) 60 { 61 persistent = storeConfiguration(); 62 } 63 else 64 { 65 triggerStorage.remove(fileName); 66 persistent = false; 67 } 68 return 1; 69 }, 70 [this](const auto&) { return persistent; }); 71 72 dbusIface.register_property_rw( 73 "Thresholds", TriggerThresholdParams{}, 74 sdbusplus::vtable::property_::emits_change, 75 [this, &triggerFactory](auto newVal, auto& oldVal) { 76 auto newThresholdParams = std::visit( 77 utils::ToLabeledThresholdParamConversion(), newVal); 78 triggerFactory.updateThresholds(thresholds, triggerActions, 79 reportIds, sensors, 80 newThresholdParams); 81 oldVal = std::move(newVal); 82 return 1; 83 }, 84 [this](const auto&) { 85 return fromLabeledThresholdParam( 86 utils::transform(thresholds, [](const auto& threshold) { 87 return threshold->getThresholdParam(); 88 })); 89 }); 90 91 dbusIface.register_property_rw( 92 "Sensors", SensorsInfo{}, 93 sdbusplus::vtable::property_::emits_change, 94 [this, &triggerFactory](auto newVal, auto& oldVal) { 95 auto labeledSensorInfo = 96 triggerFactory.getLabeledSensorsInfo(newVal); 97 triggerFactory.updateSensors(sensors, labeledSensorInfo); 98 for (const auto& threshold : thresholds) 99 { 100 threshold->updateSensors(sensors); 101 } 102 oldVal = std::move(newVal); 103 return 1; 104 }, 105 [this](const auto&) { 106 return utils::fromLabeledSensorsInfo( 107 utils::transform(sensors, [](const auto& sensor) { 108 return sensor->getLabeledSensorInfo(); 109 })); 110 }); 111 112 dbusIface.register_property_rw( 113 "ReportNames", std::vector<std::string>{}, 114 sdbusplus::vtable::property_::emits_change, 115 [this](auto newVal, auto& oldVal) { 116 TriggerManager::verifyReportIds(newVal); 117 updateTriggerIdsInReports(newVal); 118 reportIds->clear(); 119 std::copy(newVal.begin(), newVal.end(), 120 std::back_inserter(*reportIds)); 121 oldVal = std::move(newVal); 122 return 1; 123 }, 124 [this](const auto&) { return *reportIds; }); 125 126 dbusIface.register_property_r( 127 "Discrete", false, sdbusplus::vtable::property_::const_, 128 [this](const auto& x) { 129 return !std::holds_alternative< 130 numeric::LabeledThresholdParam>( 131 thresholds.back()->getThresholdParam()); 132 }); 133 134 dbusIface.register_property_rw( 135 "Name", std::string(), 136 sdbusplus::vtable::property_::emits_change, 137 [this](auto newVal, auto& oldVal) { 138 name = oldVal = newVal; 139 return 1; 140 }, 141 [this](const auto&) { return name; }); 142 143 dbusIface.register_property_r( 144 "TriggerActions", std::vector<std::string>(), 145 sdbusplus::vtable::property_::const_, [this](const auto&) { 146 return utils::transform(triggerActions, 147 [](const auto& action) { 148 return actionToString(action); 149 }); 150 }); 151 }); 152 153 for (const auto& threshold : thresholds) 154 { 155 threshold->initialize(); 156 } 157 158 for (const auto& reportId : *reportIds) 159 { 160 reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add); 161 } 162 } 163 164 bool Trigger::storeConfiguration() const 165 { 166 try 167 { 168 nlohmann::json data; 169 170 auto labeledThresholdParams = 171 std::visit(utils::ToLabeledThresholdParamConversion(), 172 fromLabeledThresholdParam(utils::transform( 173 thresholds, [](const auto& threshold) { 174 return threshold->getThresholdParam(); 175 }))); 176 177 data["Version"] = triggerVersion; 178 data["Id"] = id; 179 data["Name"] = name; 180 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 181 data["TriggerActions"] = 182 utils::transform(triggerActions, [](const auto& action) { 183 return actionToString(action); 184 }); 185 data["ThresholdParams"] = 186 utils::labeledThresholdParamsToJson(labeledThresholdParams); 187 data["ReportIds"] = *reportIds; 188 data["Sensors"] = utils::transform(sensors, [](const auto& sensor) { 189 return sensor->getLabeledSensorInfo(); 190 }); 191 192 triggerStorage.store(fileName, data); 193 } 194 catch (const std::exception& e) 195 { 196 phosphor::logging::log<phosphor::logging::level::ERR>( 197 "Failed to store a trigger in storage", 198 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 199 return false; 200 } 201 return true; 202 } 203 204 void Trigger::updateTriggerIdsInReports( 205 const std::vector<std::string>& newReportIds) 206 { 207 std::vector<std::string> toBeRemoved, toBeAdded; 208 size_t maxSize = std::max(reportIds->size(), newReportIds.size()); 209 toBeRemoved.reserve(maxSize); 210 toBeAdded.reserve(maxSize); 211 std::set_difference(reportIds->begin(), reportIds->end(), 212 newReportIds.begin(), newReportIds.end(), 213 std::back_inserter(toBeRemoved)); 214 std::set_difference(newReportIds.begin(), newReportIds.end(), 215 reportIds->begin(), reportIds->end(), 216 std::back_inserter(toBeAdded)); 217 for (auto& reportId : toBeRemoved) 218 { 219 reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Remove); 220 } 221 for (auto& reportId : toBeAdded) 222 { 223 reportManager.updateTriggerIds(reportId, id, TriggerIdUpdate::Add); 224 } 225 } 226