blob: 34609b32c9e4c46168e34284e8cb58f52dd850c3 [file] [log] [blame]
#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);
}
}