176833cb5SWludzik, Jozef #include "trigger_manager.hpp" 276833cb5SWludzik, Jozef 34416fce6SCezary Zwolak #include "trigger.hpp" 4dcc4e193SKrzysztof Grobelny #include "types/trigger_types.hpp" 54416fce6SCezary Zwolak #include "utils/conversion_trigger.hpp" 6b8cc78ddSKrzysztof Grobelny #include "utils/generate_id.hpp" 74416fce6SCezary Zwolak #include "utils/transform.hpp" 84416fce6SCezary Zwolak 94416fce6SCezary Zwolak #include <phosphor-logging/log.hpp> 104416fce6SCezary Zwolak 11*b4ef22e4SSzymon Dompke #include <unordered_set> 12*b4ef22e4SSzymon Dompke 1376833cb5SWludzik, Jozef TriggerManager::TriggerManager( 1476833cb5SWludzik, Jozef std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn, 15a4e67616SCezary Zwolak std::unique_ptr<interfaces::JsonStorage> triggerStorageIn, 1676833cb5SWludzik, Jozef const std::shared_ptr<sdbusplus::asio::object_server>& objServer) : 17a4e67616SCezary Zwolak triggerFactory(std::move(triggerFactoryIn)), 18a4e67616SCezary Zwolak triggerStorage(std::move(triggerStorageIn)) 1976833cb5SWludzik, Jozef { 204416fce6SCezary Zwolak loadFromPersistent(); 214416fce6SCezary Zwolak 2276833cb5SWludzik, Jozef managerIface = objServer->add_unique_interface( 2376833cb5SWludzik, Jozef triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) { 2476833cb5SWludzik, Jozef iface.register_method( 2576833cb5SWludzik, Jozef "AddTrigger", 26e28aa53dSSzymon Dompke [this](boost::asio::yield_context& yield, const std::string& id, 272001301aSSzymon Dompke const std::string& name, 282001301aSSzymon Dompke const std::vector<std::string>& triggerActions, 294416fce6SCezary Zwolak const SensorsInfo& sensors, 30b8cc78ddSKrzysztof Grobelny const std::vector<std::string>& reportIds, 314416fce6SCezary Zwolak const TriggerThresholdParamsExt& thresholds) { 324416fce6SCezary Zwolak LabeledTriggerThresholdParams 334416fce6SCezary Zwolak labeledTriggerThresholdParams = std::visit( 344416fce6SCezary Zwolak utils::ToLabeledThresholdParamConversion(), 354416fce6SCezary Zwolak thresholds); 3676833cb5SWludzik, Jozef 374416fce6SCezary Zwolak std::vector<LabeledSensorInfo> labeledSensorsInfo = 384416fce6SCezary Zwolak triggerFactory->getLabeledSensorsInfo(yield, sensors); 3976833cb5SWludzik, Jozef 40e28aa53dSSzymon Dompke return addTrigger(id, name, triggerActions, 41b8cc78ddSKrzysztof Grobelny labeledSensorsInfo, reportIds, 424416fce6SCezary Zwolak labeledTriggerThresholdParams) 434416fce6SCezary Zwolak .getPath(); 4476833cb5SWludzik, Jozef }); 4576833cb5SWludzik, Jozef }); 4676833cb5SWludzik, Jozef } 4776833cb5SWludzik, Jozef 4876833cb5SWludzik, Jozef void TriggerManager::removeTrigger(const interfaces::Trigger* trigger) 4976833cb5SWludzik, Jozef { 5076833cb5SWludzik, Jozef triggers.erase( 5176833cb5SWludzik, Jozef std::remove_if(triggers.begin(), triggers.end(), 5276833cb5SWludzik, Jozef [trigger](const auto& x) { return trigger == x.get(); }), 5376833cb5SWludzik, Jozef triggers.end()); 5476833cb5SWludzik, Jozef } 554416fce6SCezary Zwolak 56*b4ef22e4SSzymon Dompke void TriggerManager::verifyReportIds( 57*b4ef22e4SSzymon Dompke const std::vector<std::string>& newReportIds) 58*b4ef22e4SSzymon Dompke { 59*b4ef22e4SSzymon Dompke if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() != 60*b4ef22e4SSzymon Dompke newReportIds.size()) 61*b4ef22e4SSzymon Dompke { 62*b4ef22e4SSzymon Dompke throw sdbusplus::exception::SdBusError( 63*b4ef22e4SSzymon Dompke static_cast<int>(std::errc::invalid_argument), 64*b4ef22e4SSzymon Dompke "Duplicate element in ReportIds"); 65*b4ef22e4SSzymon Dompke } 66*b4ef22e4SSzymon Dompke } 67*b4ef22e4SSzymon Dompke 68*b4ef22e4SSzymon Dompke void TriggerManager::verifyAddTrigger( 69*b4ef22e4SSzymon Dompke const std::string& triggerId, const std::string& triggerName, 70*b4ef22e4SSzymon Dompke const std::vector<std::string>& newReportIds) const 714416fce6SCezary Zwolak { 724416fce6SCezary Zwolak if (triggers.size() >= maxTriggers) 734416fce6SCezary Zwolak { 744416fce6SCezary Zwolak throw sdbusplus::exception::SdBusError( 754416fce6SCezary Zwolak static_cast<int>(std::errc::too_many_files_open), 764416fce6SCezary Zwolak "Reached maximal trigger count"); 774416fce6SCezary Zwolak } 784416fce6SCezary Zwolak 79b8cc78ddSKrzysztof Grobelny utils::verifyIdCharacters(triggerId); 80e28aa53dSSzymon Dompke 814416fce6SCezary Zwolak for (const auto& trigger : triggers) 824416fce6SCezary Zwolak { 83e28aa53dSSzymon Dompke if (trigger->getId() == triggerId) 844416fce6SCezary Zwolak { 854416fce6SCezary Zwolak throw sdbusplus::exception::SdBusError( 864416fce6SCezary Zwolak static_cast<int>(std::errc::file_exists), "Duplicate trigger"); 874416fce6SCezary Zwolak } 884416fce6SCezary Zwolak } 89*b4ef22e4SSzymon Dompke 90*b4ef22e4SSzymon Dompke verifyReportIds(newReportIds); 914416fce6SCezary Zwolak } 924416fce6SCezary Zwolak 934416fce6SCezary Zwolak interfaces::Trigger& TriggerManager::addTrigger( 94e28aa53dSSzymon Dompke const std::string& triggerIdIn, const std::string& triggerNameIn, 952001301aSSzymon Dompke const std::vector<std::string>& triggerActions, 964416fce6SCezary Zwolak const std::vector<LabeledSensorInfo>& labeledSensorsInfo, 97b8cc78ddSKrzysztof Grobelny const std::vector<std::string>& reportIds, 984416fce6SCezary Zwolak const LabeledTriggerThresholdParams& labeledThresholdParams) 994416fce6SCezary Zwolak { 100a950e42bSKrzysztof Grobelny const auto existingTriggerIds = utils::transform( 101a950e42bSKrzysztof Grobelny triggers, [](const auto& trigger) { return trigger->getId(); }); 102e28aa53dSSzymon Dompke 103a950e42bSKrzysztof Grobelny auto [id, name] = 104a950e42bSKrzysztof Grobelny utils::generateId(triggerIdIn, triggerNameIn, triggerNameDefault, 105a950e42bSKrzysztof Grobelny existingTriggerIds, maxTriggerIdLength); 106e28aa53dSSzymon Dompke 107*b4ef22e4SSzymon Dompke verifyAddTrigger(id, name, reportIds); 1084416fce6SCezary Zwolak 1094416fce6SCezary Zwolak triggers.emplace_back(triggerFactory->make( 110a950e42bSKrzysztof Grobelny id, name, triggerActions, reportIds, *this, *triggerStorage, 111a950e42bSKrzysztof Grobelny labeledThresholdParams, labeledSensorsInfo)); 1124416fce6SCezary Zwolak 1134416fce6SCezary Zwolak return *triggers.back(); 1144416fce6SCezary Zwolak } 1154416fce6SCezary Zwolak 1164416fce6SCezary Zwolak void TriggerManager::loadFromPersistent() 1174416fce6SCezary Zwolak { 1184416fce6SCezary Zwolak std::vector<interfaces::JsonStorage::FilePath> paths = 1194416fce6SCezary Zwolak triggerStorage->list(); 1204416fce6SCezary Zwolak 1214416fce6SCezary Zwolak for (const auto& path : paths) 1224416fce6SCezary Zwolak { 1234416fce6SCezary Zwolak std::optional<nlohmann::json> data = triggerStorage->load(path); 1244416fce6SCezary Zwolak try 1254416fce6SCezary Zwolak { 1264416fce6SCezary Zwolak if (!data.has_value()) 1274416fce6SCezary Zwolak { 1284416fce6SCezary Zwolak throw std::runtime_error("Empty storage"); 1294416fce6SCezary Zwolak } 1304416fce6SCezary Zwolak size_t version = data->at("Version").get<size_t>(); 1314416fce6SCezary Zwolak if (version != Trigger::triggerVersion) 1324416fce6SCezary Zwolak { 1334416fce6SCezary Zwolak throw std::runtime_error("Invalid version"); 1344416fce6SCezary Zwolak } 135e28aa53dSSzymon Dompke const std::string& id = data->at("Id").get_ref<std::string&>(); 1364416fce6SCezary Zwolak const std::string& name = data->at("Name").get_ref<std::string&>(); 1374416fce6SCezary Zwolak int thresholdParamsDiscriminator = 1384416fce6SCezary Zwolak data->at("ThresholdParamsDiscriminator").get<int>(); 1392001301aSSzymon Dompke const std::vector<std::string> triggerActions = 1402001301aSSzymon Dompke data->at("TriggerActions").get<std::vector<std::string>>(); 1414416fce6SCezary Zwolak 1424416fce6SCezary Zwolak LabeledTriggerThresholdParams labeledThresholdParams; 1434416fce6SCezary Zwolak if (0 == thresholdParamsDiscriminator) 1444416fce6SCezary Zwolak { 1454416fce6SCezary Zwolak labeledThresholdParams = 1464416fce6SCezary Zwolak data->at("ThresholdParams") 1474416fce6SCezary Zwolak .get<std::vector<numeric::LabeledThresholdParam>>(); 1484416fce6SCezary Zwolak } 1494416fce6SCezary Zwolak else 1504416fce6SCezary Zwolak { 1514416fce6SCezary Zwolak labeledThresholdParams = 1524416fce6SCezary Zwolak data->at("ThresholdParams") 1534416fce6SCezary Zwolak .get<std::vector<discrete::LabeledThresholdParam>>(); 1544416fce6SCezary Zwolak } 1554416fce6SCezary Zwolak 156b8cc78ddSKrzysztof Grobelny auto reportIds = 157b8cc78ddSKrzysztof Grobelny data->at("ReportIds").get<std::vector<std::string>>(); 1584416fce6SCezary Zwolak 1594416fce6SCezary Zwolak auto labeledSensorsInfo = 1604416fce6SCezary Zwolak data->at("Sensors").get<std::vector<LabeledSensorInfo>>(); 1614416fce6SCezary Zwolak 162b8cc78ddSKrzysztof Grobelny addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds, 163b8cc78ddSKrzysztof Grobelny labeledThresholdParams); 1644416fce6SCezary Zwolak } 1654416fce6SCezary Zwolak catch (const std::exception& e) 1664416fce6SCezary Zwolak { 1674416fce6SCezary Zwolak phosphor::logging::log<phosphor::logging::level::ERR>( 1684416fce6SCezary Zwolak "Failed to load trigger from storage", 1694416fce6SCezary Zwolak phosphor::logging::entry( 1704416fce6SCezary Zwolak "FILENAME=%s", 1714416fce6SCezary Zwolak static_cast<std::filesystem::path>(path).c_str()), 1724416fce6SCezary Zwolak phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 1734416fce6SCezary Zwolak triggerStorage->remove(path); 1744416fce6SCezary Zwolak } 1754416fce6SCezary Zwolak } 1764416fce6SCezary Zwolak } 177*b4ef22e4SSzymon Dompke 178*b4ef22e4SSzymon Dompke std::vector<std::string> 179*b4ef22e4SSzymon Dompke TriggerManager::getTriggerIdsForReport(const std::string& reportId) const 180*b4ef22e4SSzymon Dompke { 181*b4ef22e4SSzymon Dompke std::vector<std::string> result; 182*b4ef22e4SSzymon Dompke for (const auto& trigger : triggers) 183*b4ef22e4SSzymon Dompke { 184*b4ef22e4SSzymon Dompke const auto& reportIds = trigger->getReportIds(); 185*b4ef22e4SSzymon Dompke if (std::find(reportIds.begin(), reportIds.end(), reportId) != 186*b4ef22e4SSzymon Dompke reportIds.end()) 187*b4ef22e4SSzymon Dompke { 188*b4ef22e4SSzymon Dompke result.emplace_back(trigger->getId()); 189*b4ef22e4SSzymon Dompke } 190*b4ef22e4SSzymon Dompke } 191*b4ef22e4SSzymon Dompke return result; 192*b4ef22e4SSzymon Dompke } 193