Add propertyIs filter
The existing property match filter tests a property
in the PropertiesChanged signal payload.
Add a match filter that tests any arbitrary property on
any object.
Change-Id: I1c238c03a3ccbf45f7b338693a4342fbd4f670c2
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/events.hpp b/events.hpp
index 80fcdae..45122a0 100644
--- a/events.hpp
+++ b/events.hpp
@@ -154,6 +154,120 @@
U _condition;
};
+/** @struct PropertyConditionBase
+ * @brief Match filter functor that tests a property value.
+ *
+ * Base class for PropertyCondition - factored out code that
+ * doesn't need to be templated.
+ */
+struct PropertyConditionBase
+{
+ PropertyConditionBase() = delete;
+ virtual ~PropertyConditionBase() = default;
+ PropertyConditionBase(const PropertyConditionBase&) = delete;
+ PropertyConditionBase& operator=(const PropertyConditionBase&) = delete;
+ PropertyConditionBase(PropertyConditionBase&&) = default;
+ PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
+
+ /** @brief Constructor
+ *
+ * The service argument can be nullptr. If something
+ * else is provided the function will call the the
+ * service directly. If omitted, the function will
+ * look up the service in the ObjectMapper.
+ *
+ * @param path - The path of the object containing
+ * the property to be tested.
+ * @param iface - The interface hosting the property
+ * to be tested.
+ * @param property - The property to be tested.
+ * @param service - The DBus service hosting the object.
+ */
+ PropertyConditionBase(
+ const char* path,
+ const char* iface,
+ const char* property,
+ const char* service) :
+ _path(path),
+ _iface(iface),
+ _property(property),
+ _service(service) {}
+
+ /** @brief Forward comparison to type specific implementation. */
+ virtual bool eval(sdbusplus::message::message&) const = 0;
+
+ /** @brief Test a property value.
+ *
+ * Make a DBus call and test the value of any property.
+ */
+ bool operator()(
+ sdbusplus::bus::bus&,
+ sdbusplus::message::message&,
+ Manager&) const;
+
+ private:
+ std::string _path;
+ std::string _iface;
+ std::string _property;
+ const char* _service;
+};
+
+/** @struct PropertyCondition
+ * @brief Match filter functor that tests a property value.
+ *
+ * @tparam T - The type of the property being tested.
+ * @tparam U - The type of the condition checking functor.
+ */
+template <typename T, typename U>
+struct PropertyCondition final : public PropertyConditionBase
+{
+ PropertyCondition() = delete;
+ ~PropertyCondition() = default;
+ PropertyCondition(const PropertyCondition&) = delete;
+ PropertyCondition& operator=(const PropertyCondition&) = delete;
+ PropertyCondition(PropertyCondition&&) = default;
+ PropertyCondition& operator=(PropertyCondition&&) = default;
+
+ /** @brief Constructor
+ *
+ * The service argument can be nullptr. If something
+ * else is provided the function will call the the
+ * service directly. If omitted, the function will
+ * look up the service in the ObjectMapper.
+ *
+ * @param path - The path of the object containing
+ * the property to be tested.
+ * @param iface - The interface hosting the property
+ * to be tested.
+ * @param property - The property to be tested.
+ * @param condition - The test to run on the property.
+ * @param service - The DBus service hosting the object.
+ */
+ PropertyCondition(
+ const char* path,
+ const char* iface,
+ const char* property,
+ U&& condition,
+ const char* service) :
+ PropertyConditionBase(path, iface, property, service),
+ _condition(std::forward<decltype(condition)>(condition)) {}
+
+ /** @brief Test a property value.
+ *
+ * Make a DBus call and test the value of any property.
+ */
+ bool eval(sdbusplus::message::message& msg) const override
+ {
+ sdbusplus::message::variant<T> value;
+ msg.read(value);
+ return _condition(
+ std::forward<T>(value.template get<T>()));
+ }
+
+ private:
+ U _condition;
+};
+
} // namespace property_condition
} // namespace details
@@ -173,6 +287,24 @@
iface, property, std::move(condition));
}
+/** @brief Implicit type deduction for constructing PropertyCondition. */
+template <typename T>
+auto propertyIs(
+ const char* path,
+ const char* iface,
+ const char* property,
+ T&& val,
+ const char* service = nullptr)
+{
+ auto condition = [val = std::forward<T>(val)](T && arg)
+ {
+ return arg == val;
+ };
+ using U = decltype(condition);
+ return details::property_condition::PropertyCondition<T, U>(
+ path, iface, property, std::move(condition), service);
+}
+
} // namespace filters
} // namespace manager
} // namespace inventory