core: serialize/deserialize bus subscribers

This commit is contained in:
Lennart Poettering 2013-07-10 19:24:03 +02:00
parent 376dd21dc0
commit 6fa4853328
12 changed files with 104 additions and 42 deletions

View File

@ -1057,17 +1057,9 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
SELINUX_ACCESS_CHECK(connection, message, "status");
s = BUS_CONNECTION_SUBSCRIBED(m, connection);
if (!s) {
s = set_new(string_hash_func, string_compare_func);
if (!s)
goto oom;
if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
set_free(s);
goto oom;
}
}
s = bus_acquire_subscribed(m, connection);
if (!s)
goto oom;
client = strdup(bus_message_get_sender_with_fallback(message));
if (!client)

View File

@ -1135,19 +1135,19 @@ int bus_init(Manager *m, bool try_bus_connect) {
if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
goto oom;
return log_oom();
if (m->name_data_slot < 0)
if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
goto oom;
return log_oom();
if (m->conn_data_slot < 0)
if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
goto oom;
return log_oom();
if (m->subscribed_data_slot < 0)
if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
goto oom;
return log_oom();
if (try_bus_connect) {
if ((r = bus_init_system(m)) < 0 ||
@ -1155,16 +1155,14 @@ int bus_init(Manager *m, bool try_bus_connect) {
return r;
}
if ((r = bus_init_private(m)) < 0)
r = bus_init_private(m);
if (r < 0)
return r;
return 0;
oom:
return log_oom();
}
static void shutdown_connection(Manager *m, DBusConnection *c) {
Set *s;
Job *j;
Iterator i;
@ -1180,15 +1178,7 @@ static void shutdown_connection(Manager *m, DBusConnection *c) {
set_remove(m->bus_connections, c);
set_remove(m->bus_connections_for_dispatch, c);
if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
char *t;
while ((t = set_steal_first(s)))
free(t);
set_free(s);
}
set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
if (m->queued_message_connection == c) {
m->queued_message_connection = NULL;
@ -1259,10 +1249,10 @@ void bus_done(Manager *m) {
set_free(m->bus_connections_for_dispatch);
if (m->name_data_slot >= 0)
dbus_pending_call_free_data_slot(&m->name_data_slot);
dbus_pending_call_free_data_slot(&m->name_data_slot);
if (m->conn_data_slot >= 0)
dbus_pending_call_free_data_slot(&m->conn_data_slot);
dbus_pending_call_free_data_slot(&m->conn_data_slot);
if (m->subscribed_data_slot >= 0)
dbus_connection_free_data_slot(&m->subscribed_data_slot);
@ -1488,3 +1478,69 @@ finish:
if (message)
dbus_message_unref(message);
}
Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
Set *s;
assert(m);
assert(c);
s = BUS_CONNECTION_SUBSCRIBED(m, c);
if (s)
return s;
s = set_new(string_hash_func, string_compare_func);
if (!s)
return NULL;
if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
set_free(s);
return NULL;
}
return s;
}
void bus_serialize(Manager *m, FILE *f) {
char *client;
Iterator i;
Set *s;
assert(m);
assert(f);
if (!m->api_bus)
return;
s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
SET_FOREACH(client, s, i)
fprintf(f, "subscribed=%s\n", client);
}
int bus_deserialize_item(Manager *m, const char *line) {
const char *e;
char *b;
Set *s;
assert(m);
assert(line);
if (!m->api_bus)
return 0;
e = startswith(line, "subscribed=");
if (!e)
return 0;
s = bus_acquire_subscribed(m, m->api_bus);
if (!s)
return -ENOMEM;
b = strdup(e);
if (!b)
return -ENOMEM;
set_consume(s, b);
return 1;
}

View File

@ -44,6 +44,11 @@ int bus_fdset_add_all(Manager *m, FDSet *fds);
void bus_broadcast_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);
Set *bus_acquire_subscribed(Manager *m, DBusConnection *c);
void bus_serialize(Manager *m, FILE *f);
int bus_deserialize_item(Manager *m, const char *line);
#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)

View File

@ -1613,7 +1613,7 @@ int main(int argc, char *argv[]) {
if (arg_running_as == SYSTEMD_SYSTEM)
bump_rlimit_nofile(&saved_rlimit_nofile);
r = manager_new(arg_running_as, &m);
r = manager_new(arg_running_as, !!serialization, &m);
if (r < 0) {
log_error("Failed to allocate manager object: %s", strerror(-r));
goto finish;

View File

@ -424,7 +424,7 @@ static void manager_strip_environment(Manager *m) {
strv_env_clean(m->environment);
}
int manager_new(SystemdRunningAs running_as, Manager **_m) {
int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
Manager *m;
int r = -ENOMEM;
@ -476,7 +476,8 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
if (!m->cgroup_unit)
goto fail;
if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
m->watch_bus = hashmap_new(string_hash_func, string_compare_func);
if (!m->watch_bus)
goto fail;
m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
@ -502,7 +503,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
/* Try to connect to the busses, if possible. */
if ((running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")) ||
running_as == SYSTEMD_SYSTEM) {
r = bus_init(m, running_as != SYSTEMD_SYSTEM);
r = bus_init(m, reexecuting || running_as != SYSTEMD_SYSTEM);
if (r < 0)
goto fail;
} else
@ -2041,6 +2042,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
}
}
bus_serialize(m, f);
fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units, i) {
@ -2054,7 +2057,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
fputs(u->id, f);
fputc('\n', f);
if ((r = unit_serialize(u, f, fds, !switching_root)) < 0) {
r = unit_serialize(u, f, fds, !switching_root);
if (r < 0) {
m->n_reloading --;
return r;
}
@ -2159,7 +2163,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
strv_free(m->environment);
m->environment = e;
} else
} else if (bus_deserialize_item(m, l) == 0)
log_debug("Unknown serialization item '%s'", l);
}

View File

@ -248,7 +248,7 @@ struct Manager {
char *switch_root_init;
};
int manager_new(SystemdRunningAs running_as, Manager **m);
int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m);
void manager_free(Manager *m);
int manager_enumerate(Manager *m);

View File

@ -2128,7 +2128,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
if (!unit_can_serialize(u))
return 0;
if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0)
r = UNIT_VTABLE(u)->serialize(u, f, fds);
if (r < 0)
return r;

View File

@ -2411,6 +2411,7 @@ DBusHandlerResult bus_message_filter(
if (u)
user_add_to_gc_queue(u);
}
} else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) {
const char *path, *unit;

View File

@ -50,9 +50,12 @@ int set_put(Set *s, void *value) {
}
int set_consume(Set *s, void *value) {
int r = set_put(s, value);
int r;
r = set_put(s, value);
if (r < 0)
free(value);
return r;
}

View File

@ -33,7 +33,7 @@ int main(int argc, char *argv[]) {
assert_se(set_unit_path("test") >= 0);
assert_se(manager_new(SYSTEMD_SYSTEM, &m) >= 0);
assert_se(manager_new(SYSTEMD_SYSTEM, false, &m) >= 0);
printf("Load1:\n");
assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);

View File

@ -34,7 +34,7 @@ int main(int argc, char *argv[]) {
/* prepare the test */
assert_se(set_unit_path(TEST_DIR) >= 0);
r = manager_new(SYSTEMD_USER, &m);
r = manager_new(SYSTEMD_USER, false, &m);
if (r == -EPERM) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;

View File

@ -123,7 +123,7 @@ static int test_unit_printf(void) {
assert_se((root = getpwnam("root")));
assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
r = manager_new(SYSTEMD_USER, &m);
r = manager_new(SYSTEMD_USER, false, &m);
if (r == -EPERM) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;