[systemd-devel] [RFC 03/12] bus: add two new bus_*_map_*_properties() helpers

David Herrmann dh.herrmann at gmail.com
Wed Nov 27 10:48:38 PST 2013


This splits the core of bus_map_all_properties() out into a new helper
called bus_message_map_all_properties(). Instead of sending a blocking
dbus call, this helper takes the response message as argument and parses
it. So the normal use-case is to send an async GetAll() request and once
you get the response, pass it to the helper to map the properties.

The existing bus_map_all_properties() helper is now just a small wrapper
around sd_bus_call_method() and the new helper.

Furthermore, a second helper is added which parses "PropertiesChanged"
dbus signals. Whenever you get such a signal, you can pass the message to
a new helper called bus_message_map_properties_changed(). It parses the
PropertiesChanged payload for changed properties and maps them. In case
the payload only contains invalidation-requests and no new values, this
functions returns the number of successfully mapped properties that were
invalidated. Thus, if it returns >0, you should send a GetAll() or Get()
request.

Both helpers allow very convenient handling of dbus-properties in a
non-blocking fashion. This is required for graphics-applications and other
programs that need low-latency responses. In all other cases, the existing
blocking bus_map_all_properties() helper should be enough.
---
 src/libsystemd-bus/bus-util.c | 87 ++++++++++++++++++++++++++++++-------------
 src/libsystemd-bus/bus-util.h |  6 +++
 2 files changed, 68 insertions(+), 25 deletions(-)

diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c
index 2daf8c1..0e520c1 100644
--- a/src/libsystemd-bus/bus-util.c
+++ b/src/libsystemd-bus/bus-util.c
@@ -838,31 +838,12 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
         return r;
 }
 
-int bus_map_all_properties(sd_bus *bus,
-                           const char *destination,
-                           const char *path,
-                           const struct bus_properties_map *map,
-                           void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+int bus_message_map_all_properties(sd_bus_message *m,
+                                   const struct bus_properties_map *map,
+                                   void *userdata) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
-        assert(bus);
-        assert(destination);
-        assert(path);
-        assert(map);
-
-        r = sd_bus_call_method( bus,
-                        destination,
-                        path,
-                        "org.freedesktop.DBus.Properties",
-                        "GetAll",
-                        &error,
-                        &m,
-                        "s", "");
-        if (r < 0)
-                return r;
-
         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
         if (r < 0)
                 return r;
@@ -895,9 +876,9 @@ int bus_map_all_properties(sd_bus *bus,
 
                         v = (uint8_t *)userdata + prop->offset;
                         if (map[i].set)
-                                r = prop->set(bus, member, m, &error, v);
+                                r = prop->set(m->bus, member, m, &error, v);
                         else
-                                r = map_basic(bus, member, m, &error, v);
+                                r = map_basic(m->bus, member, m, &error, v);
 
                         r = sd_bus_message_exit_container(m);
                         if (r < 0)
@@ -913,7 +894,63 @@ int bus_map_all_properties(sd_bus *bus,
                         return r;
         }
 
-        return r;
+        return sd_bus_message_exit_container(m);
+}
+
+int bus_map_all_properties(sd_bus *bus,
+                           const char *destination,
+                           const char *path,
+                           const struct bus_properties_map *map,
+                           void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
+
+        assert(bus);
+        assert(destination);
+        assert(path);
+        assert(map);
+
+        r = sd_bus_call_method( bus,
+                        destination,
+                        path,
+                        "org.freedesktop.DBus.Properties",
+                        "GetAll",
+                        &error,
+                        &m,
+                        "s", "");
+        if (r < 0)
+                return r;
+
+        return bus_message_map_all_properties(m, map, userdata);
+}
+
+int bus_message_map_properties_changed(sd_bus_message *m,
+                                       const struct bus_properties_map *map,
+                                       void *userdata) {
+        const char *member;
+        int r, invalidated, i;
+
+        /* skip interface, but allow callers to do that themselves */
+        sd_bus_message_skip(m, "s");
+
+        r = bus_message_map_all_properties(m, map, userdata);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
+        if (r < 0)
+                return r;
+
+        invalidated = 0;
+        while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
+                for (i = 0; map[i].member; i++)
+                        if (streq(map[i].member, member)) {
+                                ++invalidated;
+                                break;
+                        }
+
+        return invalidated;
 }
 
 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h
index 20739a9..1c6be31 100644
--- a/src/libsystemd-bus/bus-util.h
+++ b/src/libsystemd-bus/bus-util.h
@@ -46,6 +46,12 @@ struct bus_properties_map {
 
 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
 
+int bus_message_map_all_properties(sd_bus_message *m,
+                                   const struct bus_properties_map *map,
+                                   void *userdata);
+int bus_message_map_properties_changed(sd_bus_message *m,
+                                       const struct bus_properties_map *map,
+                                       void *userdata);
 int bus_map_all_properties(sd_bus *bus,
                            const char *destination,
                            const char *path,
-- 
1.8.4.2



More information about the systemd-devel mailing list