diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dbus-client-track.c | 251 | ||||
-rw-r--r-- | src/core/dbus-client-track.h | 42 | ||||
-rw-r--r-- | src/core/dbus-job.c | 64 | ||||
-rw-r--r-- | src/core/dbus-manager.c | 99 | ||||
-rw-r--r-- | src/core/dbus-manager.h | 2 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 34 | ||||
-rw-r--r-- | src/core/dbus.c | 95 | ||||
-rw-r--r-- | src/core/dbus.h | 7 | ||||
-rw-r--r-- | src/core/job.c | 22 | ||||
-rw-r--r-- | src/core/job.h | 3 | ||||
-rw-r--r-- | src/core/manager.c | 11 | ||||
-rw-r--r-- | src/core/manager.h | 8 | ||||
-rw-r--r-- | src/core/unit.c | 3 |
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; } |