From: Lennart Poettering Date: Fri, 20 Aug 2010 00:26:05 +0000 (+0200) Subject: dbus: follow standardized fdo PropertiesChanged signal spec X-Git-Tag: v8~30 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4e2ceae941d02de5574becbfd3b4db15de2eda3;p=systemd dbus: follow standardized fdo PropertiesChanged signal spec --- diff --git a/fixme b/fixme index 855f9d6c..b1474f52 100644 --- a/fixme +++ b/fixme @@ -40,8 +40,6 @@ * write utmp record a la upstart for processes -* follow property change dbus spec - * selinux policy loading * place /etc/inittab with explaining blurb. @@ -62,6 +60,10 @@ * bash completion a la gdbus +* fstab mit tüdelchen + +* api mounts gegen fstab mergen und remounten + External: * procps, psmisc, sysvinit-tools, hostname → util-linux-ng diff --git a/src/automount.c b/src/automount.c index d5da497c..b32e0027 100644 --- a/src/automount.c +++ b/src/automount.c @@ -843,6 +843,7 @@ const UnitVTable automount_vtable = { .reset_maintenance = automount_reset_maintenance, + .bus_interface = "org.freedesktop.systemd1.Automount", .bus_message_handler = bus_automount_message_handler, .shutdown = automount_shutdown diff --git a/src/dbus-automount.c b/src/dbus-automount.c index b7b31a19..3bccb4e5 100644 --- a/src/dbus-automount.c +++ b/src/dbus-automount.c @@ -34,6 +34,7 @@ BUS_UNIT_INTERFACE \ BUS_AUTOMOUNT_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" diff --git a/src/dbus-device.c b/src/dbus-device.c index bb8b40ec..fcb05a44 100644 --- a/src/dbus-device.c +++ b/src/dbus-device.c @@ -33,11 +33,16 @@ BUS_UNIT_INTERFACE \ BUS_DEVICE_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_device_interface[] = BUS_DEVICE_INTERFACE; +const char bus_device_invalidating_properties[] = + "SysFSPath\0" + "\0"; + DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) { const BusProperty properties[] = { BUS_UNIT_PROPERTIES, diff --git a/src/dbus-device.h b/src/dbus-device.h index 639255db..fba270b4 100644 --- a/src/dbus-device.h +++ b/src/dbus-device.h @@ -29,5 +29,6 @@ DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_device_interface[]; +extern const char bus_device_invalidating_properties[]; #endif diff --git a/src/dbus-job.c b/src/dbus-job.c index 727e2ac6..0f76c7d8 100644 --- a/src/dbus-job.c +++ b/src/dbus-job.c @@ -28,7 +28,6 @@ #define BUS_JOB_INTERFACE \ " \n" \ " \n" \ - " \n" \ " \n" \ " \n" \ " \n" \ @@ -40,11 +39,16 @@ "\n" \ BUS_JOB_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_job_interface[] = BUS_JOB_INTERFACE; +#define INVALIDATING_PROPERTIES \ + "State\0" \ + "\0" \ + static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState); static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType); @@ -187,10 +191,11 @@ void bus_job_send_change_signal(Job *j) { goto oom; if (j->sent_dbus_new_signal) { - /* Send a change signal */ + /* Send a properties changed signal */ - if (!(m = dbus_message_new_signal(p, "org.freedesktop.systemd1.Job", "Changed"))) + if (!(m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Job", INVALIDATING_PROPERTIES))) goto oom; + } else { /* Send a new signal */ diff --git a/src/dbus-manager.c b/src/dbus-manager.c index 1fca8b55..eb376845 100644 --- a/src/dbus-manager.c +++ b/src/dbus-manager.c @@ -148,6 +148,7 @@ "\n" \ BUS_MANAGER_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE #define INTROSPECTION_END \ diff --git a/src/dbus-mount.c b/src/dbus-mount.c index 933e3bb3..92d74cb9 100644 --- a/src/dbus-mount.c +++ b/src/dbus-mount.c @@ -46,11 +46,22 @@ BUS_UNIT_INTERFACE \ BUS_MOUNT_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_mount_interface[] = BUS_MOUNT_INTERFACE; +const char bus_mount_invalidating_properties[] = + "What\0" + "Options\0" + "Type\0" + "ExecMount\0" + "ExecUnmount\0" + "ExecRemount\0" + "ControlPID\0" + "\0"; + static int bus_mount_append_what(Manager *n, DBusMessageIter *i, const char *property, void *data) { Mount *m = data; const char *d; diff --git a/src/dbus-mount.h b/src/dbus-mount.h index c9ab73f4..b5613fa7 100644 --- a/src/dbus-mount.h +++ b/src/dbus-mount.h @@ -29,5 +29,6 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_mount_interface[]; +extern const char bus_mount_invalidating_properties[]; #endif diff --git a/src/dbus-path.c b/src/dbus-path.c index 45472e58..c8c302ab 100644 --- a/src/dbus-path.c +++ b/src/dbus-path.c @@ -37,6 +37,7 @@ BUS_UNIT_INTERFACE \ BUS_PATH_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" diff --git a/src/dbus-service.c b/src/dbus-service.c index 59222066..86c18ddd 100644 --- a/src/dbus-service.c +++ b/src/dbus-service.c @@ -59,11 +59,25 @@ BUS_UNIT_INTERFACE \ BUS_SERVICE_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_service_interface[] = BUS_SERVICE_INTERFACE; +const char bus_service_invalidating_properties[] = + "ExecStartPre\0" + "ExecStart\0" + "ExecStartPost\0" + "ExecReload\0" + "ExecStop\0" + "ExecStopPost\0" + "ExecMain\0" + "MainPID\0" + "ControlPID\0" + "StatusText\0" + "\0"; + static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType); static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart); static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess); diff --git a/src/dbus-service.h b/src/dbus-service.h index 4f628eda..d6eab65c 100644 --- a/src/dbus-service.h +++ b/src/dbus-service.h @@ -29,5 +29,6 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_service_interface[]; +extern const char bus_service_invalidating_properties[]; #endif diff --git a/src/dbus-snapshot.c b/src/dbus-snapshot.c index ecb7ec8e..efaec7df 100644 --- a/src/dbus-snapshot.c +++ b/src/dbus-snapshot.c @@ -34,6 +34,7 @@ BUS_UNIT_INTERFACE \ BUS_SNAPSHOT_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" diff --git a/src/dbus-socket.c b/src/dbus-socket.c index 9406bb29..5931f006 100644 --- a/src/dbus-socket.c +++ b/src/dbus-socket.c @@ -60,11 +60,22 @@ BUS_UNIT_INTERFACE \ BUS_SOCKET_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_socket_interface[] = BUS_SOCKET_INTERFACE; +const char bus_socket_invalidating_properties[] = + "ExecStartPre\0" + "ExecStartPost\0" + "ExecStopPre\0" + "ExecStopPost\0" + "ControlPID\0" + "NAccepted\0" + "NConnections\0" + "\0"; + static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) { diff --git a/src/dbus-socket.h b/src/dbus-socket.h index 71d5b4fa..069a2f5d 100644 --- a/src/dbus-socket.h +++ b/src/dbus-socket.h @@ -29,5 +29,6 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_socket_interface[]; +extern const char bus_socket_invalidating_properties[]; #endif diff --git a/src/dbus-swap.c b/src/dbus-swap.c index 1de44279..c345d4bc 100644 --- a/src/dbus-swap.c +++ b/src/dbus-swap.c @@ -37,11 +37,17 @@ BUS_UNIT_INTERFACE \ BUS_SWAP_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_swap_interface[] = BUS_SWAP_INTERFACE; +const char bus_swap_invalidating_properties[] = + "What\0" + "Priority\0" + "\0"; + static int bus_swap_append_priority(Manager *m, DBusMessageIter *i, const char *property, void *data) { Swap *s = data; dbus_int32_t j; diff --git a/src/dbus-swap.h b/src/dbus-swap.h index 5eeb02a1..15b91472 100644 --- a/src/dbus-swap.h +++ b/src/dbus-swap.h @@ -30,5 +30,6 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_swap_interface[]; +extern const char bus_swap_invalidating_properties[]; #endif diff --git a/src/dbus-target.c b/src/dbus-target.c index 03e8fc8b..69e82120 100644 --- a/src/dbus-target.c +++ b/src/dbus-target.c @@ -34,6 +34,7 @@ BUS_UNIT_INTERFACE \ BUS_TARGET_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" diff --git a/src/dbus-timer.c b/src/dbus-timer.c index 6dfadf21..e57e9730 100644 --- a/src/dbus-timer.c +++ b/src/dbus-timer.c @@ -38,11 +38,17 @@ BUS_UNIT_INTERFACE \ BUS_TIMER_INTERFACE \ BUS_PROPERTIES_INTERFACE \ + BUS_PEER_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE \ "\n" const char bus_timer_interface[] = BUS_TIMER_INTERFACE; +const char bus_timer_invalidating_properties[] = + "Timers\0" + "NextElapseUSec\0" + "\0"; + static int bus_timer_append_timers(Manager *m, DBusMessageIter *i, const char *property, void *data) { Timer *p = data; DBusMessageIter sub, sub2; diff --git a/src/dbus-timer.h b/src/dbus-timer.h index 6f35aa72..e692e12f 100644 --- a/src/dbus-timer.h +++ b/src/dbus-timer.h @@ -29,5 +29,6 @@ DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message); extern const char bus_timer_interface[]; +extern const char bus_timer_invalidating_properties[]; #endif diff --git a/src/dbus-unit.c b/src/dbus-unit.c index ca4e5f24..519aa5c3 100644 --- a/src/dbus-unit.c +++ b/src/dbus-unit.c @@ -28,6 +28,18 @@ const char bus_unit_interface[] = BUS_UNIT_INTERFACE; +#define INVALIDATING_PROPERTIES \ + "LoadState\0" \ + "ActiveState\0" \ + "SubState\0" \ + "InactiveExitTimestamp\0" \ + "ActiveEnterTimestamp\0" \ + "ActiveExitTimestamp\0" \ + "InactiveEnterTimestamp\0" \ + "Job\0" \ + "NeedDaemonReload\0" \ + "\0" + int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data) { char *t; Iterator j; @@ -470,10 +482,27 @@ void bus_unit_send_change_signal(Unit *u) { goto oom; if (u->meta.sent_dbus_new_signal) { - /* Send a change signal */ + /* Send a properties changed signal. First for the + * specific type, then for the generic unit. The + * clients may rely on this order to get atomic + * behaviour if needed. */ + + if (UNIT_VTABLE(u)->bus_invalidating_properties) { + + if (!(m = bus_properties_changed_new(p, + UNIT_VTABLE(u)->bus_interface, + UNIT_VTABLE(u)->bus_invalidating_properties))) + goto oom; + + if (bus_broadcast(u->meta.manager, m) < 0) + goto oom; - if (!(m = dbus_message_new_signal(p, "org.freedesktop.systemd1.Unit", "Changed"))) + dbus_message_unref(m); + } + + if (!(m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit", INVALIDATING_PROPERTIES))) goto oom; + } else { /* Send a new signal */ diff --git a/src/dbus-unit.h b/src/dbus-unit.h index 8f17bf23..cc55ad7c 100644 --- a/src/dbus-unit.h +++ b/src/dbus-unit.h @@ -57,7 +57,6 @@ " \n" \ " \n" \ " \n" \ - " \n" \ " \n" \ " \n" \ " \n" \ diff --git a/src/dbus.c b/src/dbus.c index e8828d02..952806bb 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -1247,6 +1247,7 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu if (!dbus_message_iter_close_container(&iter, &sub)) goto oom; } + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && properties) { const char *interface; const BusProperty *p; @@ -1611,3 +1612,41 @@ bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) { return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c)); } + +DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) { + DBusMessage *m; + DBusMessageIter iter, sub; + const char *i; + + assert(interface); + assert(properties); + + if (!(m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged"))) + goto oom; + + dbus_message_iter_init_append(m, &iter); + + /* We won't send any property values, since they might be + * large and sometimes not cheap to generated */ + + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) || + !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) || + !dbus_message_iter_close_container(&iter, &sub) || + !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) + goto oom; + + NULSTR_FOREACH(i, properties) + if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i)) + goto oom; + + if (!dbus_message_iter_close_container(&iter, &sub)) + goto oom; + + return m; + +oom: + if (m) + dbus_message_unref(m); + + return NULL; +} diff --git a/src/dbus.h b/src/dbus.h index f15a3f99..7c0da332 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -47,6 +47,11 @@ typedef struct BusProperty { " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" #define BUS_INTROSPECTABLE_INTERFACE \ @@ -56,6 +61,14 @@ typedef struct BusProperty { " \n" \ " \n" +#define BUS_PEER_INTERFACE \ + "\n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + "\n" + int bus_init(Manager *m); void bus_done(Manager *m); @@ -108,6 +121,8 @@ int bus_parse_strv(DBusMessage *m, char ***_l); bool bus_has_subscriber(Manager *m); bool bus_connection_has_subscriber(Manager *m, DBusConnection *c); +DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties); + #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) diff --git a/src/device.c b/src/device.c index 7323192a..8074a3ed 100644 --- a/src/device.c +++ b/src/device.c @@ -537,7 +537,9 @@ const UnitVTable device_vtable = { .active_state = device_active_state, .sub_state_to_string = device_sub_state_to_string, + .bus_interface = "org.freedesktop.systemd1.Device", .bus_message_handler = bus_device_message_handler, + .bus_invalidating_properties = bus_device_invalidating_properties, .following = device_following, diff --git a/src/mount.c b/src/mount.c index 89b18431..e0ca5bb5 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1005,6 +1005,9 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { default: assert_not_reached("Uh, control process died at wrong time."); } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); } static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) { @@ -1557,7 +1560,9 @@ const UnitVTable mount_vtable = { .reset_maintenance = mount_reset_maintenance, + .bus_interface = "org.freedesktop.systemd1.Mount", .bus_message_handler = bus_mount_message_handler, + .bus_invalidating_properties = bus_mount_invalidating_properties, .enumerate = mount_enumerate, .shutdown = mount_shutdown diff --git a/src/path.c b/src/path.c index 9af1cd4c..42c64f3e 100644 --- a/src/path.c +++ b/src/path.c @@ -607,5 +607,6 @@ const UnitVTable path_vtable = { .reset_maintenance = path_reset_maintenance, + .bus_interface = "org.freedesktop.systemd1.Path", .bus_message_handler = bus_path_message_handler }; diff --git a/src/service.c b/src/service.c index 66e233a6..d2ef1ad9 100644 --- a/src/service.c +++ b/src/service.c @@ -2454,6 +2454,9 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { } } } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); } static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { @@ -2610,6 +2613,9 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) { } } + + /* Notify clients about changed status or main pid */ + unit_add_to_dbus_queue(u); } static int service_enumerate(Manager *m) { @@ -2944,7 +2950,9 @@ const UnitVTable service_vtable = { .bus_name_owner_change = service_bus_name_owner_change, .bus_query_pid_done = service_bus_query_pid_done, + .bus_interface = "org.freedesktop.systemd1.Service", .bus_message_handler = bus_service_message_handler, + .bus_invalidating_properties = bus_service_invalidating_properties, .enumerate = service_enumerate }; diff --git a/src/snapshot.c b/src/snapshot.c index 2c46837c..f58d46e9 100644 --- a/src/snapshot.c +++ b/src/snapshot.c @@ -292,5 +292,6 @@ const UnitVTable snapshot_vtable = { .active_state = snapshot_active_state, .sub_state_to_string = snapshot_sub_state_to_string, + .bus_interface = "org.freedesktop.systemd1.Snapshot", .bus_message_handler = bus_snapshot_message_handler }; diff --git a/src/socket.c b/src/socket.c index 3a371917..7510a6d6 100644 --- a/src/socket.c +++ b/src/socket.c @@ -659,7 +659,6 @@ static int fifo_address_create( const char *path, mode_t directory_mode, mode_t socket_mode, - const char *label, int *_fd) { int fd = -1, r = 0; @@ -671,7 +670,7 @@ static int fifo_address_create( mkdir_parents(path, directory_mode); - if ((r = label_fifofile_set(label, path)) < 0) + if ((r = label_fifofile_set(path)) < 0) goto fail; /* Enforce the right access mode for the fifo */ @@ -1217,6 +1216,9 @@ static void socket_enter_running(Socket *s, int cfd) { if ((r = manager_add_job(s->meta.manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL)) < 0) goto fail; + + /* Notify clients about changed counters */ + unit_add_to_dbus_queue(UNIT(s)); } return; @@ -1594,6 +1596,9 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { assert_not_reached("Uh, control process died at wrong time."); } } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); } static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) { @@ -1774,5 +1779,7 @@ const UnitVTable socket_vtable = { .reset_maintenance = socket_reset_maintenance, - .bus_message_handler = bus_socket_message_handler + .bus_interface = "org.freedesktop.systemd1.Socket", + .bus_message_handler = bus_socket_message_handler, + .bus_invalidating_properties = bus_socket_invalidating_properties }; diff --git a/src/swap.c b/src/swap.c index ffe76881..c81fd67c 100644 --- a/src/swap.c +++ b/src/swap.c @@ -599,7 +599,9 @@ const UnitVTable swap_vtable = { .check_gc = swap_check_gc, + .bus_interface = "org.freedesktop.systemd1.Swap", .bus_message_handler = bus_swap_message_handler, + .bus_invalidating_properties = bus_swap_invalidating_properties, .reset_maintenance = swap_reset_maintenance, diff --git a/src/systemadm.vala b/src/systemadm.vala index 3610e2b8..4aee1d35 100644 --- a/src/systemadm.vala +++ b/src/systemadm.vala @@ -325,13 +325,19 @@ public class MainWindow : Window { foreach (var i in list) { TreeIter iter; + Properties p = bus.get_object( + "org.freedesktop.systemd1", + i.unit_path, + "org.freedesktop.DBus.Properties") as Properties; + + + p.properties_changed.connect(on_unit_changed); + Unit u = bus.get_object( "org.freedesktop.systemd1", i.unit_path, "org.freedesktop.systemd1.Unit") as Unit; - u.changed.connect(on_unit_changed); - unit_model.append(out iter); unit_model.set(iter, 0, i.id, @@ -352,13 +358,18 @@ public class MainWindow : Window { foreach (var i in list) { TreeIter iter; + Properties p = bus.get_object( + "org.freedesktop.systemd1", + i.job_path, + "org.freedesktop.DBus.Properties") as Properties; + + p.properties_changed.connect(on_job_changed); + Job j = bus.get_object( "org.freedesktop.systemd1", i.job_path, "org.freedesktop.systemd1.Job") as Job; - j.changed.connect(on_job_changed); - job_model.append(out iter); job_model.set(iter, 0, "%u".printf(i.id), @@ -672,15 +683,21 @@ public class MainWindow : Window { } public void on_unit_new(string id, ObjectPath path) { - Unit u = bus.get_object( + Properties p = bus.get_object( "org.freedesktop.systemd1", path, - "org.freedesktop.systemd1.Unit") as Unit; + "org.freedesktop.DBus.Properties") as Properties; - u.changed.connect(on_unit_changed); + p.properties_changed.connect(on_unit_changed); TreeIter iter; unit_model.append(out iter); + + Unit u = bus.get_object( + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit") as Unit; + update_unit_iter(iter, id, u); } @@ -695,15 +712,22 @@ public class MainWindow : Window { } public void on_job_new(uint32 id, ObjectPath path) { - Job j = bus.get_object( + + Properties p = bus.get_object( "org.freedesktop.systemd1", path, - "org.freedesktop.systemd1.Job") as Job; + "org.freedesktop.DBus.Properties") as Properties; - j.changed.connect(on_job_changed); + p.properties_changed.connect(on_job_changed); TreeIter iter; job_model.append(out iter); + + Job j = bus.get_object( + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Job") as Job; + update_job_iter(iter, id, j); } @@ -750,10 +774,15 @@ public class MainWindow : Window { } while (job_model.iter_next(ref iter)); } - public void on_unit_changed(Unit u) { + public void on_unit_changed(Properties p, string iface, HashTable changed_properties, string[] invalidated_properties) { TreeIter iter; string id; + Unit u = bus.get_object( + p.get_bus_name(), + p.get_path(), + "org.freedesktop.systemd1.Unit") as Unit; + if (!(unit_model.get_iter_first(out iter))) return; @@ -776,10 +805,15 @@ public class MainWindow : Window { } while (unit_model.iter_next(ref iter)); } - public void on_job_changed(Job j) { + public void on_job_changed(Properties p, string iface, HashTable changed_properties, string[] invalidated_properties) { TreeIter iter; uint32 id; + Job j = bus.get_object( + p.get_bus_name(), + p.get_path(), + "org.freedesktop.systemd1.Job") as Job; + if (!(job_model.get_iter_first(out iter))) return; diff --git a/src/systemctl.c b/src/systemctl.c index 5bf5e9f3..30f6b2a1 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -2390,14 +2390,23 @@ static DBusHandlerResult monitor_filter(DBusConnection *connection, DBusMessage printf("Job %u removed.\n", id); - } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Unit", "Changed") || - dbus_message_is_signal(message, "org.freedesktop.systemd1.Job", "Changed")) { + } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) { const char *path, *interface, *property = "Id"; DBusMessageIter iter, sub; path = dbus_message_get_path(message); - interface = dbus_message_get_interface(message); + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse message: %s", error.message); + goto finish; + } + + if (!streq(interface, "org.freedesktop.systemd1.Job") && + !streq(interface, "org.freedesktop.systemd1.Unit")) + goto finish; if (!(m = dbus_message_new_method_call( "org.freedesktop.systemd1", @@ -2497,21 +2506,8 @@ static int monitor(DBusConnection *bus, char **args, unsigned n) { dbus_bus_add_match(bus, "type='signal'," "sender='org.freedesktop.systemd1'," - "interface='org.freedesktop.systemd1.Unit'," - "member='Changed'", - &error); - - if (dbus_error_is_set(&error)) { - log_error("Failed to add match: %s", error.message); - r = -EIO; - goto finish; - } - - dbus_bus_add_match(bus, - "type='signal'," - "sender='org.freedesktop.systemd1'," - "interface='org.freedesktop.systemd1.Job'," - "member='Changed'", + "interface='org.freedesktop.DBus.Properties'," + "member='PropertiesChanged'", &error); if (dbus_error_is_set(&error)) { diff --git a/src/systemd-interfaces.vala b/src/systemd-interfaces.vala index 612cb132..9a8c1dcd 100644 --- a/src/systemd-interfaces.vala +++ b/src/systemd-interfaces.vala @@ -50,13 +50,19 @@ public interface Manager : DBus.Object { public abstract JobInfo[] list_jobs() throws DBus.Error; public abstract ObjectPath get_unit(string name) throws DBus.Error; + public abstract ObjectPath get_unit_by_pid(uint32 pid) throws DBus.Error; public abstract ObjectPath load_unit(string name) throws DBus.Error; public abstract ObjectPath get_job(uint32 id) throws DBus.Error; - public abstract ObjectPath start_unit(string name, string mode) throws DBus.Error; - public abstract ObjectPath stop_unit(string name, string mode) throws DBus.Error; - public abstract ObjectPath reload_unit(string name, string mode) throws DBus.Error; - public abstract ObjectPath restart_unit(string name, string mode) throws DBus.Error; + public abstract ObjectPath start_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath stop_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath restart_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath try_restart_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload_or_restart_unit(string name, string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload_or_try_restart_unit(string name, string mode = "replace") throws DBus.Error; + + public abstract void reset_maintenance_unit(string name = "") throws DBus.Error; public abstract void clear_jobs() throws DBus.Error; @@ -89,6 +95,7 @@ public interface Unit : DBus.Object { public abstract string id { owned get; } public abstract string[] names { owned get; } + public abstract string following { owned get; } public abstract string[] requires { owned get; } public abstract string[] requires_overridable { owned get; } public abstract string[] requisite { owned get; } @@ -98,8 +105,10 @@ public interface Unit : DBus.Object { public abstract string[] required_by_overridable { owned get; } public abstract string[] wanted_by { owned get; } public abstract string[] conflicts { owned get; } + public abstract string[] conflicted_by { owned get; } public abstract string[] before { owned get; } public abstract string[] after { owned get; } + public abstract string[] on_failure { owned get; } public abstract string description { owned get; } public abstract string load_state { owned get; } public abstract string active_state { owned get; } @@ -110,19 +119,28 @@ public interface Unit : DBus.Object { public abstract uint64 active_exit_timestamp { owned get; } public abstract uint64 inactive_enter_timestamp { owned get; } public abstract bool can_start { owned get; } + public abstract bool can_stop { owned get; } public abstract bool can_reload { owned get; } public abstract JobLink job { owned get; } public abstract bool recursive_stop { owned get; } public abstract bool stop_when_unneeded { owned get; } + public abstract bool refuse_manual_start { owned get; } + public abstract bool refuse_manual_stop { owned get; } + public abstract bool default_dependencies { owned get; } public abstract string default_control_group { owned get; } public abstract string[] control_groups { owned get; } - - public abstract ObjectPath start(string mode) throws DBus.Error; - public abstract ObjectPath stop(string mode) throws DBus.Error; - public abstract ObjectPath restart(string mode) throws DBus.Error; - public abstract ObjectPath reload(string mode) throws DBus.Error; - - public abstract signal void changed(); + public abstract bool need_daemon_reload { owned get; } + public abstract uint64 job_timeout_usec { owned get; } + + public abstract ObjectPath start(string mode = "replace") throws DBus.Error; + public abstract ObjectPath stop(string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload(string mode = "replace") throws DBus.Error; + public abstract ObjectPath restart(string mode = "replace") throws DBus.Error; + public abstract ObjectPath try_restart(string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload_or_restart(string mode = "replace") throws DBus.Error; + public abstract ObjectPath reload_or_try_restart(string mode = "replace") throws DBus.Error; + + public abstract void reset_maintenance() throws DBus.Error; } [DBus (name = "org.freedesktop.systemd1.Job")] @@ -138,6 +156,10 @@ public interface Job : DBus.Object { public abstract UnitLink unit { owned get; } public abstract void cancel() throws DBus.Error; +} - public abstract signal void changed(); +[DBus (name = "org.freedesktop.DBus.Properties")] +public interface Properties : DBus.Object { + public abstract Value? get(string iface, string property) throws DBus.Error; + public abstract signal void properties_changed(string iface, HashTable changed_properties, string[] invalidated_properties); } diff --git a/src/target.c b/src/target.c index 48137fe3..c7285fa7 100644 --- a/src/target.c +++ b/src/target.c @@ -207,5 +207,6 @@ const UnitVTable target_vtable = { .active_state = target_active_state, .sub_state_to_string = target_sub_state_to_string, + .bus_interface = "org.freedesktop.systemd1.Target", .bus_message_handler = bus_target_message_handler }; diff --git a/src/timer.c b/src/timer.c index 61bd85c7..89deb019 100644 --- a/src/timer.c +++ b/src/timer.c @@ -498,5 +498,7 @@ const UnitVTable timer_vtable = { .reset_maintenance = timer_reset_maintenance, - .bus_message_handler = bus_timer_message_handler + .bus_interface = "org.freedesktop.systemd1.Timer", + .bus_message_handler = bus_timer_message_handler, + .bus_invalidating_properties = bus_timer_invalidating_properties }; diff --git a/src/unit.h b/src/unit.h index 993a6cb7..0362602f 100644 --- a/src/unit.h +++ b/src/unit.h @@ -334,6 +334,14 @@ struct UnitVTable { /* Type specific cleanups. */ void (*shutdown)(Manager *m); + /* When sending out PropertiesChanged signal, which properties + * shall be invalidated? This is a NUL seperated list of + * strings, to minimize relocations a little. */ + const char *bus_invalidating_properties; + + /* The interface name */ + const char *bus_interface; + /* Can units of this type have multiple names? */ bool no_alias:1; diff --git a/src/util.h b/src/util.h index e8d9b3e7..7490236f 100644 --- a/src/util.h +++ b/src/util.h @@ -339,6 +339,9 @@ char *ellipsize(const char *s, unsigned length, unsigned percent); int touch(const char *path); +#define NULSTR_FOREACH(i, l) \ + for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) + const char *ioprio_class_to_string(int i); int ioprio_class_from_string(const char *s);