Throw DBusPropertyError for all property accesses

On all get/set property functions, when an error occurs performing the
access of a property, throw a DBusPropertyError exception containing the
identifying parameters of the property.

Tested:
    DBusPropertyError exception occurs on failing to set a property
    DBusPropertyError exception occurs on failing to get a property

Change-Id: I9882d62d75153b4320a8d4a21ba7a52efbdd0af2
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/main.cpp b/control/main.cpp
index dd9330d..80a7df6 100644
--- a/control/main.cpp
+++ b/control/main.cpp
@@ -101,6 +101,14 @@
                 entry("INTERFACE=%s", e.interface.c_str()),
                 entry("METHOD=%s", e.method.c_str()));
     }
+    catch (phosphor::fan::util::DBusPropertyError& e)
+    {
+        log<level::ERR>("Uncaught DBus property access failure exception",
+                entry("BUSNAME=%s", e.busName.c_str()),
+                entry("PATH=%s", e.path.c_str()),
+                entry("INTERFACE=%s", e.interface.c_str()),
+                entry("PROPERTY=%s", e.property.c_str()));
+    }
 
     return -1;
 }
diff --git a/sdbusplus.hpp b/sdbusplus.hpp
index 5842133..3a6cd65 100644
--- a/sdbusplus.hpp
+++ b/sdbusplus.hpp
@@ -87,6 +87,34 @@
         const std::string interface;
 };
 
+/**
+ * @class DBusPropertyError
+ *
+ * Thrown when a set/get property fails.
+ */
+class DBusPropertyError : public DBusError
+{
+    public:
+        DBusPropertyError(
+                const char* msg,
+                const std::string& busName,
+                const std::string& path,
+                const std::string& interface,
+                const std::string& property) :
+            DBusError(msg),
+            busName(busName),
+            path(path),
+            interface(interface),
+            property(property)
+            {
+            }
+
+        const std::string busName;
+        const std::string path;
+        const std::string interface;
+        const std::string property;
+};
+
 /** @brief Alias for PropertiesChanged signal callbacks. */
 template <typename ...T>
 using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;
@@ -286,14 +314,24 @@
         {
             using namespace std::literals::string_literals;
 
+            auto service = getService(bus, path, interface);
             auto msg = callMethod(
                     bus,
-                    getService(bus, path, interface),
+                    service,
                     path,
                     "org.freedesktop.DBus.Properties"s,
                     "Get"s,
                     interface,
                     property);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus get property failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
             sdbusplus::message::variant<Property> value;
             msg.read(value);
             return value.template get<Property>();
@@ -323,14 +361,24 @@
         {
             using namespace std::literals::string_literals;
 
+            auto service = getService(bus, path, interface);
             auto msg = callMethod(
                     bus,
-                    getService(bus, path, interface),
+                    service,
                     path,
                     "org.freedesktop.DBus.Properties"s,
                     "Get"s,
                     interface,
                     property);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus get property variant failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
             Variant value;
             msg.read(value);
             return value;
@@ -361,7 +409,7 @@
         {
             using namespace std::literals::string_literals;
 
-            auto msg = callMethod(
+            auto msg = callMethodAndReturn(
                     bus,
                     service,
                     path,
@@ -369,6 +417,15 @@
                     "Get"s,
                     interface,
                     property);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus get property failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
             sdbusplus::message::variant<Property> value;
             msg.read(value);
             return value.template get<Property>();
@@ -401,7 +458,7 @@
         {
             using namespace std::literals::string_literals;
 
-            auto msg = callMethod(
+            auto msg = callMethodAndReturn(
                     bus,
                     service,
                     path,
@@ -409,6 +466,15 @@
                     "Get"s,
                     interface,
                     property);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus get property variant failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
             Variant value;
             msg.read(value);
             return value;
@@ -444,15 +510,25 @@
             sdbusplus::message::variant<Property> varValue(
                     std::forward<Property>(value));
 
-            callMethod(
+            auto service = getService(bus, path, interface);
+            auto msg = callMethodAndReturn(
                     bus,
-                    getService(bus, path, interface),
+                    service,
                     path,
                     "org.freedesktop.DBus.Properties"s,
                     "Set"s,
                     interface,
                     property,
                     varValue);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus set property failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
         }
 
         /** @brief Set a property with mapper lookup. */
@@ -486,7 +562,7 @@
             sdbusplus::message::variant<Property> varValue(
                     std::forward<Property>(value));
 
-            callMethod(
+            auto msg = callMethodAndReturn(
                     bus,
                     service,
                     path,
@@ -495,6 +571,15 @@
                     interface,
                     property,
                     varValue);
+            if (msg.is_method_error())
+            {
+                throw DBusPropertyError{
+                        "DBus set property failed",
+                        service,
+                        path,
+                        interface,
+                        property};
+            }
         }
 
         /** @brief Set a property without mapper lookup. */