[systemd-devel] [RFC] bus: add sd_bus_emit_object_{added, removed}()

David Herrmann dh.herrmann at gmail.com
Mon Mar 3 11:21:16 PST 2014


ping?

On Tue, Feb 18, 2014 at 12:02 AM, David Herrmann <dh.herrmann at gmail.com> wrote:
> The ObjectManager dbus interface provides an InterfacesAdded signal to
> notify others about new interfaces that are added to an object. The same
> signal is also used to advertise new objects (by adding the first
> interface to a given object path) and delete them.
>
> However, our internal helpers sd_bus_emit_interfaces_{added,removed}()
> cannot properly deal with built-in interfaces like DBus.Properties as
> there's no vtable for it. Therefore, to avoid callers to track these
> internal interfaces, we provide two separate helpers which explicitly add
> these interfaces to the signal.
>
> sd_bus_emit_object_added() traverses the list of all vtables and fallback
> vtables (making sure a fallback never overwrites a real vtable!) and also
> adds built-in interfaces.
>
> sd_bus_emit_object_removed(): WIP
> ---
> Hi
>
> This is untested and I just wanted to get some feedback whether that's the way
> to go. Given the previous discussion we decided on two new entry-points to add
> and remove objects. For convenience, I now tried to omit any "char **interfaces"
> argument to object_added() and just try to figure them out on my own.
>
> However, on object_removed() I cannot do that as node_vtable_get_userdata() is
> very likely to return "0" for all these objects. So there is no way to figure
> out which interfaces actually existed on that thing. We would require users to
> call it *before* destroying/unlinking the actual object. I don't know whether
> that's ok to assume?
>
> If not, we can just add a "char **interfaces" argument, but then it would differ
> from object_added().. Not sure what sounds better..
>
> Cheers
> David
>
>  src/libsystemd/sd-bus/bus-objects.c | 210 ++++++++++++++++++++++++++++++++++++
>  src/systemd/sd-bus.h                |   2 +
>  2 files changed, 212 insertions(+)
>
> diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
> index b116a5d..0c099a3 100644
> --- a/src/libsystemd/sd-bus/bus-objects.c
> +++ b/src/libsystemd/sd-bus/bus-objects.c
> @@ -2469,6 +2469,216 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
>          return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
>  }
>
> +static int object_added_append_all_prefix(
> +                sd_bus *bus,
> +                sd_bus_message *m,
> +                Set *s,
> +                const char *prefix,
> +                const char *path,
> +                bool require_fallback) {
> +
> +        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
> +        const char *previous_interface = NULL;
> +        struct node_vtable *c;
> +        struct node *n;
> +        void *u = NULL;
> +        int r;
> +
> +        assert(bus);
> +        assert(m);
> +        assert(s);
> +        assert(prefix);
> +        assert(path);
> +
> +        n = hashmap_get(bus->nodes, prefix);
> +        if (!n)
> +                return 0;
> +
> +        LIST_FOREACH(vtables, c, n->vtables) {
> +                if (require_fallback && !c->is_fallback)
> +                        continue;
> +
> +                r = node_vtable_get_userdata(bus, path, c, &u, &error);
> +                if (r < 0)
> +                        return r;
> +                if (bus->nodes_modified)
> +                        return 0;
> +                if (r == 0)
> +                        continue;
> +
> +                if (!streq_ptr(c->interface, previous_interface)) {
> +                        /* interface already handled by a previous run? */
> +                        if (set_get(s, c->interface))
> +                                continue;
> +
> +                        /* prevent fallbacks from overwriting specific objs */
> +                        r = set_put(s, c->interface);
> +                        if (r < 0)
> +                                return r;
> +
> +                        if (previous_interface) {
> +                                r = sd_bus_message_close_container(m);
> +                                if (r < 0)
> +                                        return r;
> +
> +                                r = sd_bus_message_close_container(m);
> +                                if (r < 0)
> +                                        return r;
> +                        }
> +
> +                        r = sd_bus_message_open_container(m, 'e', "sa{sv}");
> +                        if (r < 0)
> +                                return r;
> +
> +                        r = sd_bus_message_append_basic(m, 's', c->interface);
> +                        if (r < 0)
> +                                return r;
> +
> +                        r = sd_bus_message_open_container(m, 'a', "{sv}");
> +                        if (r < 0)
> +                                return r;
> +
> +                        previous_interface = c->interface;
> +                }
> +
> +                r = vtable_append_all_properties(bus, m, path, c, u, &error);
> +                if (r < 0)
> +                        return r;
> +                if (bus->nodes_modified)
> +                        return 0;
> +        }
> +
> +        if (previous_interface) {
> +                r = sd_bus_message_close_container(m);
> +                if (r < 0)
> +                        return r;
> +
> +                r = sd_bus_message_close_container(m);
> +                if (r < 0)
> +                        return r;
> +        }
> +
> +        return 0;
> +}
> +
> +static int object_added_append_builtin(
> +                sd_bus *bus,
> +                sd_bus_message *m,
> +                const char *interface) {
> +
> +        int r;
> +
> +        r = sd_bus_message_open_container(m, 'e', "sa{sv}");
> +        if (r < 0)
> +                return r;
> +
> +        r = sd_bus_message_append_basic(m, 's', interface);
> +        if (r < 0)
> +                return r;
> +
> +        r = sd_bus_message_open_container(m, 'a', "{sv}");
> +        if (r < 0)
> +                return r;
> +
> +        r = sd_bus_message_close_container(m);
> +        if (r < 0)
> +                return r;
> +
> +        r = sd_bus_message_close_container(m);
> +        if (r < 0)
> +                return r;
> +
> +        return 0;
> +}
> +
> +static int object_added_append_all(
> +                sd_bus *bus,
> +                sd_bus_message *m,
> +                const char *path) {
> +
> +        _cleanup_set_free_ Set *s = NULL;
> +        char *prefix;
> +        int r;
> +
> +        assert(bus);
> +        assert(m);
> +        assert(path);
> +
> +        s = set_new(string_hash_func, string_compare_func);
> +        if (!s)
> +                return -ENOMEM;
> +
> +        r = object_added_append_builtin(bus, m, "org.freedesktop.DBus.Properties");
> +        if (r < 0)
> +                return r;
> +        r = object_added_append_builtin(bus, m, "org.freedesktop.DBus.Introspectable");
> +        if (r < 0)
> +                return r;
> +        r = object_added_append_builtin(bus, m, "org.freedesktop.DBus.ObjectManager");
> +        if (r < 0)
> +                return r;
> +        r = object_added_append_builtin(bus, m, "org.freedesktop.DBus.Peer");
> +        if (r < 0)
> +                return r;
> +
> +        r = object_added_append_all_prefix(bus, m, s, path, path, false);
> +        if (r < 0)
> +                return r;
> +        if (bus->nodes_modified)
> +                return 0;
> +
> +        prefix = alloca(strlen(path) + 1);
> +        OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
> +                r = object_added_append_all_prefix(bus, m, s, prefix, path, true);
> +                if (r < 0)
> +                        return r;
> +                if (bus->nodes_modified)
> +                        return 0;
> +        }
> +
> +        return 0;
> +}
> +
> +_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
> +        BUS_DONT_DESTROY(bus);
> +
> +        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
> +        int r;
> +
> +        assert_return(bus, -EINVAL);
> +        assert_return(object_path_is_valid(path), -EINVAL);
> +        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
> +        assert_return(!bus_pid_changed(bus), -ECHILD);
> +
> +        do {
> +                bus->nodes_modified = false;
> +                m = sd_bus_message_unref(m);
> +
> +                r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded", &m);
> +                if (r < 0)
> +                        return r;
> +
> +                r = sd_bus_message_append_basic(m, 'o', path);
> +                if (r < 0)
> +                        return r;
> +
> +                r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
> +                if (r < 0)
> +                        return r;
> +
> +                r = object_added_append_all(bus, m, path);
> +                if (r != 0)
> +                        return r;
> +
> +                r = sd_bus_message_close_container(m);
> +                if (r < 0)
> +                        return r;
> +
> +        } while (bus->nodes_modified);
> +
> +        return sd_bus_send(bus, m, NULL);
> +}
> +
>  _public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
>          struct node *n;
>
> diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
> index 34d4263..0236e53 100644
> --- a/src/systemd/sd-bus.h
> +++ b/src/systemd/sd-bus.h
> @@ -279,6 +279,8 @@ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **inte
>  int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_;
>  int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces);
>  int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_;
> +int sd_bus_emit_object_added(sd_bus *bus, const char *path);
> +int sd_bus_emit_object_removed(sd_bus *bus, const char *path);
>
>  int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
>
> --
> 1.9.0
>


More information about the systemd-devel mailing list