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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel