+ SET_FOREACH(other, n->meta.dependencies[NAME_WANTS], state)
+ if (!NAME_IS_ACTIVE_OR_ACTIVATING(name_active_state(other)))
+ manager_add_job(n->meta.manager, JOB_START, other, JOB_FAIL, false, NULL);
+
+ SET_FOREACH(other, n->meta.dependencies[NAME_CONFLICTS], state)
+ if (!NAME_IS_ACTIVE_OR_ACTIVATING(name_active_state(other)))
+ manager_add_job(n->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL);
+}
+
+static void retroactively_stop_dependencies(Name *n) {
+ void *state;
+ Name *other;
+
+ assert(n);
+ assert(NAME_IS_INACTIVE_OR_DEACTIVATING(name_active_state(n)));
+
+ SET_FOREACH(other, n->meta.dependencies[NAME_REQUIRED_BY], state)
+ if (!NAME_IS_INACTIVE_OR_DEACTIVATING(name_active_state(other)))
+ manager_add_job(n->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL);
+}
+
+void name_notify(Name *n, NameActiveState os, NameActiveState ns) {
+ assert(n);
+ assert(os < _NAME_ACTIVE_STATE_MAX);
+ assert(ns < _NAME_ACTIVE_STATE_MAX);
+ assert(!(os == NAME_ACTIVE && ns == NAME_ACTIVATING));
+ assert(!(os == NAME_INACTIVE && ns == NAME_DEACTIVATING));
+
+ if (os == ns)
+ return;
+
+ if (n->meta.job) {
+
+ if (n->meta.job->state == JOB_WAITING)
+
+ /* So we reached a different state for this
+ * job. Let's see if we can run it now if it
+ * failed previously due to EAGAIN. */
+ job_run_and_invalidate(n->meta.job);
+
+ else {
+ assert(n->meta.job->state == JOB_RUNNING);
+
+ /* Let's check of this state change
+ * constitutes a finished job, or maybe
+ * cotradicts a running job and hence needs to
+ * invalidate jobs. */
+
+ switch (n->meta.job->type) {
+
+ case JOB_START:
+ case JOB_VERIFY_ACTIVE:
+
+ if (NAME_IS_ACTIVE_OR_RELOADING(ns)) {
+ job_finish_and_invalidate(n->meta.job, true);
+ return;
+ } else if (ns == NAME_ACTIVATING)
+ return;
+ else
+ job_finish_and_invalidate(n->meta.job, false);
+
+ break;
+
+ case JOB_RELOAD:
+ case JOB_RELOAD_OR_START:
+
+ if (ns == NAME_ACTIVE) {
+ job_finish_and_invalidate(n->meta.job, true);
+ return;
+ } else if (ns == NAME_ACTIVATING || ns == NAME_ACTIVE_RELOADING)
+ return;
+ else
+ job_finish_and_invalidate(n->meta.job, false);
+
+ break;
+
+ case JOB_STOP:
+ case JOB_RESTART:
+ case JOB_TRY_RESTART:
+
+ if (ns == NAME_INACTIVE) {
+ job_finish_and_invalidate(n->meta.job, true);
+ return;
+ } else if (ns == NAME_DEACTIVATING)
+ return;
+ else
+ job_finish_and_invalidate(n->meta.job, false);
+
+ break;
+
+ default:
+ assert_not_reached("Job type unknown");
+ }
+ }
+ }
+
+ /* If this state change happened without being requested by a
+ * job, then let's retroactively start or stop dependencies */
+
+ if (NAME_IS_INACTIVE_OR_DEACTIVATING(os) && NAME_IS_ACTIVE_OR_ACTIVATING(ns))
+ retroactively_start_dependencies(n);
+ else if (NAME_IS_ACTIVE_OR_ACTIVATING(os) && NAME_IS_INACTIVE_OR_DEACTIVATING(ns))
+ retroactively_stop_dependencies(n);