ping?
On Tue, Feb 18, 2014 at 12:02 AM, David Herrmann <dh.herrm...@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 > _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel