summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-client-track.c251
-rw-r--r--src/core/dbus-client-track.h42
-rw-r--r--src/core/dbus-job.c64
-rw-r--r--src/core/dbus-manager.c99
-rw-r--r--src/core/dbus-manager.h2
-rw-r--r--src/core/dbus-unit.c34
-rw-r--r--src/core/dbus.c95
-rw-r--r--src/core/dbus.h7
-rw-r--r--src/core/job.c22
-rw-r--r--src/core/job.h3
-rw-r--r--src/core/manager.c11
-rw-r--r--src/core/manager.h8
-rw-r--r--src/core/unit.c3
13 files changed, 197 insertions, 444 deletions
diff --git a/src/core/dbus-client-track.c b/src/core/dbus-client-track.c
deleted file mode 100644
index 07dfea49e6..0000000000
--- a/src/core/dbus-client-track.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-util.h"
-#include "dbus-client-track.h"
-
-static unsigned long tracked_client_hash(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
- const BusTrackedClient *x = a;
-
- return string_hash_func(x->name, hash_key) ^ trivial_hash_func(x->bus, hash_key);
-}
-
-static int tracked_client_compare(const void *a, const void *b) {
- const BusTrackedClient *x = a, *y = b;
- int r;
-
- r = strcmp(x->name, y->name);
- if (r != 0)
- return r;
-
- if (x->bus < y->bus)
- return -1;
- if (x->bus > y->bus)
- return 1;
-
- return 0;
-}
-
-static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- BusTrackedClient *c = userdata;
- const char *name, *old, *new;
- int r;
-
- assert(bus);
- assert(message);
-
- r = sd_bus_message_read(message, "sss", &name, &old, &new);
- if (r < 0) {
- bus_log_parse_error(r);
- return r;
- }
-
- bus_client_untrack(c->set, bus, name);
- return 0;
-}
-
-static char *build_match(const char *name) {
-
- return strjoin("type='signal',"
- "sender='org.freedesktop.DBus',"
- "path='/org/freedesktop/DBus',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged',"
- "arg0='", name, "'", NULL);
-}
-
-int bus_client_track(Set **s, sd_bus *bus, const char *name) {
- BusTrackedClient *c, *found;
- size_t l;
- int r;
-
- assert(s);
- assert(bus);
-
- r = set_ensure_allocated(s, tracked_client_hash, tracked_client_compare);
- if (r < 0)
- return r;
-
- name = strempty(name);
-
- l = strlen(name);
-
- c = alloca(offsetof(BusTrackedClient, name) + l + 1);
- c->set = *s;
- c->bus = bus;
- strcpy(c->name, name);
-
- found = set_get(*s, c);
- if (found)
- return 0;
-
- c = memdup(c, offsetof(BusTrackedClient, name) + l + 1);
- if (!c)
- return -ENOMEM;
-
- r = set_put(*s, c);
- if (r < 0) {
- free(c);
- return r;
- }
-
- if (!isempty(name)) {
- _cleanup_free_ char *match = NULL;
-
- match = build_match(name);
- if (!match) {
- set_remove(*s, c);
- free(c);
- return -ENOMEM;
- }
-
- r = sd_bus_add_match(bus, match, on_name_owner_changed, c);
- if (r < 0) {
- set_remove(*s, c);
- free(c);
- return r;
- }
- }
-
- sd_bus_ref(c->bus);
- return 1;
-}
-
-static void bus_client_free_one(Set *s, BusTrackedClient *c) {
- assert(s);
- assert(c);
-
- if (!isempty(c->name)) {
- _cleanup_free_ char *match = NULL;
-
- match = build_match(c->name);
- if (match)
- sd_bus_remove_match(c->bus, match, on_name_owner_changed, c);
- }
-
- sd_bus_unref(c->bus);
- set_remove(s, c);
- free(c);
-}
-
-int bus_client_untrack(Set *s, sd_bus *bus, const char *name) {
- BusTrackedClient *c, *found;
- size_t l;
-
- assert(bus);
- assert(s);
- assert(name);
-
- name = strempty(name);
-
- l = strlen(name);
-
- c = alloca(offsetof(BusTrackedClient, name) + l + 1);
- c->bus = bus;
- strcpy(c->name, name);
-
- found = set_get(s, c);
- if (!found)
- return 0;
-
- bus_client_free_one(s, found);
- return 1;
-}
-
-void bus_client_track_free(Set *s) {
- BusTrackedClient *c;
-
- while ((c = set_first(s)))
- bus_client_free_one(s, c);
-
- set_free(s);
-}
-
-int bus_client_untrack_bus(Set *s, sd_bus *bus) {
- BusTrackedClient *c;
- Iterator i;
- int r = 0;
-
- SET_FOREACH(c, s, i)
- if (c->bus == bus) {
- bus_client_free_one(s, c);
- r++;
- }
-
- return r;
-}
-
-void bus_client_track_serialize(Manager *m, FILE *f, Set *s) {
- BusTrackedClient *c;
- Iterator i;
-
- assert(m);
- assert(f);
-
- SET_FOREACH(c, s, i) {
- if (c->bus == m->api_bus)
- fprintf(f, "subscribed=%s\n", isempty(c->name) ? "*" : c->name);
- else
- fprintf(f, "subscribed=%p %s\n", c->bus, isempty(c->name) ? "*" : c->name);
- }
-}
-
-int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line) {
- const char *e, *q, *name;
- sd_bus *bus;
- void *p;
- int r;
-
- e = startswith(line, "subscribed=");
- if (!e)
- return 0;
-
- q = strpbrk(e, WHITESPACE);
- if (!q) {
- if (m->api_bus) {
- bus = m->api_bus;
- name = e;
- goto finish;
- }
-
- return 1;
- }
-
- if (sscanf(e, "%p", &p) != 1) {
- log_debug("Failed to parse subscription pointer.");
- return -EINVAL;
- }
-
- bus = set_get(m->private_buses, p);
- if (!bus)
- return 1;
-
- name = q + strspn(q, WHITESPACE);
-
-finish:
- r = bus_client_track(s, bus, streq(name, "*") ? NULL : name);
- if (r < 0) {
- log_debug("Failed to deserialize client subscription: %s", strerror(-r));
- return r;
- }
-
- return 1;
-}
diff --git a/src/core/dbus-client-track.h b/src/core/dbus-client-track.h
deleted file mode 100644
index 01676479b0..0000000000
--- a/src/core/dbus-client-track.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-#include "set.h"
-#include "manager.h"
-
-typedef struct BusTrackedClient {
- Set *set;
- sd_bus *bus;
- char name[0];
-} BusTrackedClient;
-
-int bus_client_track(Set **s, sd_bus *bus, const char *name);
-
-int bus_client_untrack(Set *s, sd_bus *bus, const char *name);
-int bus_client_untrack_bus(Set *s, sd_bus *bus);
-
-void bus_client_track_free(Set *s);
-
-void bus_client_track_serialize(Manager *m, FILE *f, Set *s);
-int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index a8eae4734e..5c364a4264 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -24,7 +24,7 @@
#include "selinux-access.h"
#include "job.h"
#include "dbus-job.h"
-#include "dbus-client-track.h"
+#include "dbus.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
@@ -79,53 +79,10 @@ const sd_bus_vtable bus_job_vtable[] = {
SD_BUS_VTABLE_END
};
-static int foreach_client(Job *j, int (*send_message)(sd_bus *bus, const char *name, Job *j)) {
- BusTrackedClient *one_destination = NULL;
- Iterator i;
- sd_bus *b;
- unsigned n, m;
- int r, ret;
-
- assert(j);
- assert(send_message);
-
- n = set_size(j->manager->subscribed);
- m = set_size(j->subscribed);
-
- if (n <= 0 && m <= 0)
- return 0;
-
- if (n == 1 && m == 0)
- one_destination = set_first(j->manager->subscribed);
- else if (n == 0 && m == 1)
- one_destination = set_first(j->subscribed);
- else
- one_destination = NULL;
-
- if (one_destination)
- return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
-
- ret = 0;
-
- /* Send to everybody */
- SET_FOREACH(b, j->manager->private_buses, i) {
- r = send_message(b, NULL, j);
- if (r < 0)
- ret = r;
- }
-
- if (j->manager->api_bus) {
- r = send_message(j->manager->api_bus, NULL, j);
- if (r < 0)
- ret = r;
- }
-
- return ret;
-}
-
-static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
+static int send_new_signal(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
+ Job *j = userdata;
int r;
assert(bus);
@@ -148,11 +105,12 @@ static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
if (r < 0)
return r;
- return sd_bus_send_to(bus, m, destination, NULL);
+ return sd_bus_send(bus, m, NULL);
}
-static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
+static int send_changed_signal(sd_bus *bus, void *userdata) {
_cleanup_free_ char *p = NULL;
+ Job *j = userdata;
assert(bus);
assert(j);
@@ -174,16 +132,17 @@ void bus_job_send_change_signal(Job *j) {
j->in_dbus_queue = false;
}
- r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
+ r = bus_foreach_bus(j->manager, j->subscribed, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
if (r < 0)
log_debug("Failed to send job change signal for %u: %s", j->id, strerror(-r));
j->sent_dbus_new_signal = true;
}
-static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
+static int send_removed_signal(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
+ Job *j = userdata;
int r;
assert(bus);
@@ -193,7 +152,6 @@ static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
if (!p)
return -ENOMEM;
-
r = sd_bus_message_new_signal(
bus,
&m,
@@ -207,7 +165,7 @@ static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
if (r < 0)
return r;
- return sd_bus_send_to(bus, m, destination, NULL);
+ return sd_bus_send(bus, m, NULL);
}
void bus_job_send_removed_signal(Job *j) {
@@ -218,7 +176,7 @@ void bus_job_send_removed_signal(Job *j) {
if (!j->sent_dbus_new_signal)
bus_job_send_change_signal(j);
- r = foreach_client(j, send_removed_signal);
+ r = bus_foreach_bus(j->manager, j->subscribed, send_removed_signal, j);
if (r < 0)
log_debug("Failed to send job remove signal for %u: %s", j->id, strerror(-r));
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index f1e344c180..34ef1f5d29 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -37,7 +37,6 @@
#include "dbus-manager.h"
#include "dbus-unit.h"
#include "dbus-snapshot.h"
-#include "dbus-client-track.h"
#include "dbus-execute.h"
#include "bus-errors.h"
@@ -824,11 +823,23 @@ static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata
if (r < 0)
return r;
- r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
+ if (bus == m->api_bus) {
+
+ /* Note that direct bus connection subscribe by
+ * default, we only track peers on the API bus here */
+
+ if (!m->subscribed) {
+ r = sd_bus_track_new(bus, &m->subscribed, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_track_add_sender(m->subscribed, message);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
+ }
return sd_bus_reply_method_return(message, NULL);
}
@@ -845,11 +856,13 @@ static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userda
if (r < 0)
return r;
- r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
+ if (bus == m->api_bus) {
+ r = sd_bus_track_remove_sender(m->subscribed, message);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
+ }
return sd_bus_reply_method_return(message, NULL);
}
@@ -1348,7 +1361,7 @@ static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void
return sd_bus_reply_method_return(message, "s", default_target);
}
-static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
+static int send_unit_files_changed(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
int r;
@@ -1358,7 +1371,7 @@ static int send_unit_files_changed(sd_bus *bus, const char *destination, void *u
if (r < 0)
return r;
- return sd_bus_send_to(bus, message, destination, NULL);
+ return sd_bus_send(bus, message, NULL);
}
static int reply_unit_file_changes_and_free(
@@ -1374,7 +1387,7 @@ static int reply_unit_file_changes_and_free(
int r;
if (n_changes > 0)
- bus_manager_foreach_client(m, send_unit_files_changed, NULL);
+ bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
@@ -1656,41 +1669,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_VTABLE_END
};
-int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
- Iterator i;
- sd_bus *b;
- unsigned n;
- int r, ret;
-
- n = set_size(m->subscribed);
- if (n <= 0)
- return 0;
- if (n == 1) {
- BusTrackedClient *d;
-
- assert_se(d = set_first(m->subscribed));
- return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
- }
-
- ret = 0;
-
- /* Send to everybody */
- SET_FOREACH(b, m->private_buses, i) {
- r = send_message(b, NULL, userdata);
- if (r < 0)
- ret = r;
- }
-
- if (m->api_bus) {
- r = send_message(m->api_bus, NULL, userdata);
- if (r < 0)
- ret = r;
- }
-
- return ret;
-}
-
-static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
+static int send_finished(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
usec_t *times = userdata;
int r;
@@ -1706,7 +1685,7 @@ static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
if (r < 0)
return r;
- return sd_bus_send_to(bus, message, destination, NULL);
+ return sd_bus_send(bus, message, NULL);
}
void bus_manager_send_finished(
@@ -1722,13 +1701,23 @@ void bus_manager_send_finished(
assert(m);
- r = bus_manager_foreach_client(m, send_finished,
- (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
+ r = bus_foreach_bus(
+ m,
+ NULL,
+ send_finished,
+ (usec_t[6]) {
+ firmware_usec,
+ loader_usec,
+ kernel_usec,
+ initrd_usec,
+ userspace_usec,
+ total_usec
+ });
if (r < 0)
log_debug("Failed to send finished signal: %s", strerror(-r));
}
-static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
+static int send_reloading(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *message = NULL;
int r;
@@ -1742,7 +1731,7 @@ static int send_reloading(sd_bus *bus, const char *destination, void *userdata)
if (r < 0)
return r;
- return sd_bus_send_to(bus, message, destination, NULL);
+ return sd_bus_send(bus, message, NULL);
}
void bus_manager_send_reloading(Manager *m, bool active) {
@@ -1750,7 +1739,7 @@ void bus_manager_send_reloading(Manager *m, bool active) {
assert(m);
- r = bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
+ r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
if (r < 0)
log_debug("Failed to send reloading signal: %s", strerror(-r));
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
index 0ef99fad41..e1903fa16a 100644
--- a/src/core/dbus-manager.h
+++ b/src/core/dbus-manager.h
@@ -26,7 +26,5 @@
extern const sd_bus_vtable bus_manager_vtable[];
-int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata);
-
void bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
void bus_manager_send_reloading(Manager *m, bool active);
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 24d8a598e7..515ac8b78c 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -26,10 +26,10 @@
#include "strv.h"
#include "path-util.h"
#include "fileio.h"
-#include "dbus-unit.h"
-#include "dbus-manager.h"
#include "bus-errors.h"
-#include "dbus-client-track.h"
+#include "dbus.h"
+#include "dbus-manager.h"
+#include "dbus-unit.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
@@ -589,7 +589,7 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
SD_BUS_VTABLE_END
};
-static int send_new_signal(sd_bus *bus, const char *destination, void *userdata) {
+static int send_new_signal(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Unit *u = userdata;
@@ -615,10 +615,10 @@ static int send_new_signal(sd_bus *bus, const char *destination, void *userdata)
if (r < 0)
return r;
- return sd_bus_send_to(bus, m, destination, NULL);
+ return sd_bus_send(bus, m, NULL);
}
-static int send_changed_signal(sd_bus *bus, const char *destination, void *userdata) {
+static int send_changed_signal(sd_bus *bus, void *userdata) {
_cleanup_free_ char *p = NULL;
Unit *u = userdata;
int r;
@@ -667,14 +667,14 @@ void bus_unit_send_change_signal(Unit *u) {
if (!u->id)
return;
- r = bus_manager_foreach_client(u->manager, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
+ r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
if (r < 0)
log_debug("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
u->sent_dbus_new_signal = true;
}
-static int send_removed_signal(sd_bus *bus, const char *destination, void *userdata) {
+static int send_removed_signal(sd_bus *bus, void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
Unit *u = userdata;
@@ -700,7 +700,7 @@ static int send_removed_signal(sd_bus *bus, const char *destination, void *userd
if (r < 0)
return r;
- return sd_bus_send_to(bus, m, destination, NULL);
+ return sd_bus_send(bus, m, NULL);
}
void bus_unit_send_removed_signal(Unit *u) {
@@ -713,7 +713,7 @@ void bus_unit_send_removed_signal(Unit *u) {
if (!u->id)
return;
- r = bus_manager_foreach_client(u->manager, send_removed_signal, u);
+ r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u);
if (r < 0)
log_debug("Failed to send unit remove signal for %s: %s", u->id, strerror(-r));
}
@@ -765,9 +765,17 @@ int bus_unit_queue_job(
if (r < 0)
return r;
- r = bus_client_track(&j->subscribed, bus, sd_bus_message_get_sender(message));
- if (r < 0)
- return r;
+ if (bus == u->manager->api_bus) {
+ if (!j->subscribed) {
+ r = sd_bus_track_new(bus, &j->subscribed, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_track_add_sender(j->subscribed, message);
+ if (r < 0)
+ return r;
+ }
path = job_dbus_path(j);
if (!path)
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 1059415711..be8dfc90f8 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -41,7 +41,6 @@
#include "bus-error.h"
#include "bus-errors.h"
#include "strxcpyx.h"
-#include "dbus-client-track.h"
#include "bus-internal.h"
#include "selinux-access.h"
@@ -1040,9 +1039,12 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
return;
/* Get rid of tracked clients on this bus */
- bus_client_untrack_bus(m->subscribed, *bus);
+ if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
+ m->subscribed = sd_bus_track_unref(m->subscribed);
+
HASHMAP_FOREACH(j, m->jobs, i)
- bus_client_untrack_bus(j->subscribed, *bus);
+ if (j->subscribed && sd_bus_track_get_bus(j->subscribed) == *bus)
+ j->subscribed = sd_bus_track_unref(j->subscribed);
/* Get rid of queued message on this bus */
if (m->queued_message_bus == *bus) {
@@ -1075,7 +1077,11 @@ void bus_done(Manager *m) {
destroy_bus(m, &b);
set_free(m->private_buses);
- set_free(m->subscribed);
+ m->private_buses = NULL;
+
+ m->subscribed = sd_bus_track_unref(m->subscribed);
+ strv_free(m->deserialized_subscribed);
+ m->deserialized_subscribed = NULL;
if (m->private_listen_event_source)
m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
@@ -1126,16 +1132,85 @@ int bus_fdset_add_all(Manager *m, FDSet *fds) {
return 0;
}
-void bus_serialize(Manager *m, FILE *f) {
- assert(m);
+int bus_foreach_bus(
+ Manager *m,
+ sd_bus_track *subscribed2,
+ int (*send_message)(sd_bus *bus, void *userdata),
+ void *userdata) {
+
+ Iterator i;
+ sd_bus *b;
+ int r, ret = 0;
+
+ /* Send to all direct busses, unconditionally */
+ SET_FOREACH(b, m->private_buses, i) {
+ r = send_message(b, userdata);
+ if (r < 0)
+ ret = r;
+ }
+
+ /* Send to API bus, but only if somebody is subscribed */
+ if (sd_bus_track_count(m->subscribed) > 0 ||
+ sd_bus_track_count(subscribed2) > 0) {
+ r = send_message(m->api_bus, userdata);
+ if (r < 0)
+ ret = r;
+ }
+
+ return ret;
+}
+
+void bus_track_serialize(sd_bus_track *t, FILE *f) {
+ const char *n;
+
+ assert(t);
assert(f);
- bus_client_track_serialize(m, f, m->subscribed);
+ for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
+ fprintf(f, "subscribed=%s\n", n);
}
-int bus_deserialize_item(Manager *m, const char *line) {
- assert(m);
+int bus_track_deserialize_item(char ***l, const char *line) {
+ const char *e;
+
+ assert(l);
assert(line);
- return bus_client_track_deserialize_item(m, &m->subscribed, line);
+ e = startswith(line, "subscribed=");
+ if (!e)
+ return 0;
+
+ return strv_extend(l, e);
+}
+
+int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
+ int r = 0;
+
+ assert(m);
+ assert(t);
+ assert(l);
+
+ if (!strv_isempty(*l) && m->api_bus) {
+ char **i;
+
+ if (!*t) {
+ r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ r = 0;
+ STRV_FOREACH(i, *l) {
+ int k;
+
+ k = sd_bus_track_add_name(*t, *i);
+ if (k < 0)
+ r = k;
+ }
+ }
+
+ strv_free(*l);
+ *l = NULL;
+
+ return r;
}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index a3bef47d5d..bfb236ec8e 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -30,5 +30,8 @@ void bus_done(Manager *m);
int bus_fdset_add_all(Manager *m, FDSet *fds);
-void bus_serialize(Manager *m, FILE *f);
-int bus_deserialize_item(Manager *m, const char *line);
+void bus_track_serialize(sd_bus_track *t, FILE *f);
+int bus_track_deserialize_item(char ***l, const char *line);
+int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l);
+
+int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
diff --git a/src/core/job.c b/src/core/job.c
index 0cd4397bf2..9c099c686f 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -37,7 +37,7 @@
#include "special.h"
#include "async.h"
#include "virt.h"
-#include "dbus-client-track.h"
+#include "dbus.h"
Job* job_new_raw(Unit *unit) {
Job *j;
@@ -90,7 +90,8 @@ void job_free(Job *j) {
sd_event_source_unref(j->timer_event_source);
- bus_client_track_free(j->subscribed);
+ sd_bus_track_unref(j->subscribed);
+ strv_free(j->deserialized_subscribed);
free(j);
}
@@ -931,7 +932,7 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
if (j->begin_usec > 0)
fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
- bus_client_track_serialize(j->manager, f, j->subscribed);
+ bus_track_serialize(j->subscribed, f);
/* End marker */
fputc('\n', f);
@@ -1035,13 +1036,10 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
else
j->begin_usec = ull;
- } else {
- char t[strlen(l) + 1 + strlen(v) + 1];
+ } else if (streq(l, "subscribed")) {
- strcpy(stpcpy(stpcpy(t, l), "="), v);
-
- if (bus_client_track_deserialize_item(j->manager, &j->subscribed, t) == 0)
- log_debug("Unknown deserialization key '%s'", l);
+ if (strv_extend(&j->deserialized_subscribed, v) < 0)
+ return log_oom();
}
}
}
@@ -1051,6 +1049,12 @@ int job_coldplug(Job *j) {
assert(j);
+ /* After deserialization is complete and the bus connection
+ * set up again, let's start watching our subscribers again */
+ r = bus_track_coldplug(j->manager, &j->subscribed, &j->deserialized_subscribed);
+ if (r < 0)
+ return r;
+
if (j->begin_usec == 0 || j->unit->job_timeout == 0)
return 0;
diff --git a/src/core/job.h b/src/core/job.h
index 8cc3a02192..30d41d9edd 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -146,7 +146,8 @@ struct Job {
usec_t begin_usec;
/* There can be more than one client, because of job merging. */
- Set *subscribed;
+ sd_bus_track *subscribed;
+ char **deserialized_subscribed;
JobResult result;
diff --git a/src/core/manager.c b/src/core/manager.c
index f5801b4749..9172a244ae 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -839,7 +839,7 @@ int manager_enumerate(Manager *m) {
}
static int manager_coldplug(Manager *m) {
- int r = 0, q;
+ int r = 0;
Iterator i;
Unit *u;
char *k;
@@ -848,12 +848,14 @@ static int manager_coldplug(Manager *m) {
/* Then, let's set up their initial state. */
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+ int q;
/* ignore aliases */
if (u->id != k)
continue;
- if ((q = unit_coldplug(u)) < 0)
+ q = unit_coldplug(u);
+ if (q < 0)
r = q;
}
@@ -996,6 +998,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
* didn't, then let's create the bus now. */
manager_setup_kdbus(m);
manager_connect_bus(m, !!serialization);
+ bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed);
/* Third, fire things up! */
q = manager_coldplug(m);
@@ -2102,7 +2105,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
fprintf(f, "kdbus-fd=%i\n", copy);
}
- bus_serialize(m, f);
+ bus_track_serialize(m->subscribed, f);
fputc('\n', f);
@@ -2279,7 +2282,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
m->kdbus_fd = fdset_remove(fds, fd);
}
- } else if (bus_deserialize_item(m, l) == 0)
+ } else if (bus_track_deserialize_item(&m->deserialized_subscribed, l) == 0)
log_debug("Unknown serialization item '%s'", l);
}
diff --git a/src/core/manager.h b/src/core/manager.h
index 9dee48ddde..398c8e642e 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -167,7 +167,13 @@ struct Manager {
Set *private_buses;
int private_listen_fd;
sd_event_source *private_listen_event_source;
- Set *subscribed;
+
+ /* Contains all the clients that are subscribed to signals via
+ the API bus. Note that private bus connections are always
+ considered subscribes, since they last for very short only,
+ and it is much simpler that way. */
+ sd_bus_track *subscribed;
+ char **deserialized_subscribed;
sd_bus_message *queued_message; /* This is used during reloading:
* before the reload we queue the
diff --git a/src/core/unit.c b/src/core/unit.c
index 05470739d2..1c0b0c72ac 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -328,7 +328,8 @@ void unit_add_to_dbus_queue(Unit *u) {
return;
/* Shortcut things if nobody cares */
- if (set_isempty(u->manager->subscribed)) {
+ if (sd_bus_track_count(u->manager->subscribed) <= 0 &&
+ set_isempty(u->manager->private_buses)) {
u->sent_dbus_new_signal = true;
return;
}