[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