summaryrefslogtreecommitdiff
path: root/src/core/dbus.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@zonque.org>2015-08-05 17:47:45 +0200
committerDaniel Mack <daniel@zonque.org>2015-08-06 10:14:41 +0200
commitbbc2908635ca3ded9162504683fa126809f0ec14 (patch)
treed667bb2afaaef914cbc262e3b6e4220325722bbf /src/core/dbus.c
parentd5972272d2b725ab6a2789899f8b6c1d2a8113e3 (diff)
core: dbus: track bus names per unit
Currently, PID1 installs an unfiltered NameOwnerChanged signal match, and dispatches the signals itself. This does not scale, as right now, PID1 wakes up every time a bus client connects. To fix this, install individual matches once they are requested by unit_watch_bus_name(), and remove the watches again through their slot in unit_unwatch_bus_name(). If the bus is not available during unit_watch_bus_name(), just store name in the 'watch_bus' hashmap, and let bus_setup_api() do the installing later.
Diffstat (limited to 'src/core/dbus.c')
-rw-r--r--src/core/dbus.c50
1 files changed, 15 insertions, 35 deletions
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 057653a8b5..44bf5cab28 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -140,28 +140,6 @@ static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_e
return 0;
}
-static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- const char *name, *old_owner, *new_owner;
- Manager *m = userdata;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
- if (r < 0) {
- bus_log_parse_error(r);
- return 0;
- }
-
- manager_dispatch_bus_name_owner_changed(
- m, name,
- isempty(old_owner) ? NULL : old_owner,
- isempty(new_owner) ? NULL : new_owner);
-
- return 0;
-}
-
static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
@@ -762,13 +740,21 @@ static int bus_list_names(Manager *m, sd_bus *bus) {
/* This is a bit hacky, we say the owner of the name is the
* name itself, because we don't want the extra traffic to
* figure out the real owner. */
- STRV_FOREACH(i, names)
- manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
+ STRV_FOREACH(i, names) {
+ Unit *u;
+
+ u = hashmap_get(m->watch_bus, *i);
+ if (u)
+ UNIT_VTABLE(u)->bus_name_owner_change(u, *i, NULL, *i);
+ }
return 0;
}
static int bus_setup_api(Manager *m, sd_bus *bus) {
+ Iterator i;
+ char *name;
+ Unit *u;
int r;
assert(m);
@@ -786,17 +772,11 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
if (r < 0)
return r;
- r = sd_bus_add_match(
- bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.DBus',"
- "path='/org/freedesktop/DBus',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged'",
- signal_name_owner_changed, m);
- if (r < 0)
- log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
+ HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
+ r = unit_install_bus_match(bus, u, name);
+ if (r < 0)
+ log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
+ }
r = sd_bus_add_match(
bus,