+void job_free(Job *j) {
+ assert(j);
+
+ /* Detach from next 'bigger' objects */
+ if (j->installed) {
+ bus_job_send_removed_signal(j);
+
+ if (j->unit->meta.job == j)
+ j->unit->meta.job = NULL;
+
+ hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
+ j->installed = false;
+ }
+
+ /* Detach from next 'smaller' objects */
+ manager_transaction_unlink_job(j->manager, j);
+
+ if (j->in_run_queue)
+ LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
+
+ if (j->in_dbus_queue)
+ LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
+
+ free(j);
+}
+
+JobDependency* job_dependency_new(Job *subject, Job *object, bool matters) {
+ JobDependency *l;
+
+ assert(object);
+
+ /* Adds a new job link, which encodes that the 'subject' job
+ * needs the 'object' job in some way. If 'subject' is NULL
+ * this means the 'anchor' job (i.e. the one the user
+ * explcitily asked for) is the requester. */
+
+ if (!(l = new0(JobDependency, 1)))
+ return NULL;
+
+ l->subject = subject;
+ l->object = object;
+ l->matters = matters;
+
+ if (subject)
+ LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
+ else
+ LIST_PREPEND(JobDependency, subject, object->manager->transaction_anchor, l);
+
+ LIST_PREPEND(JobDependency, object, object->object_list, l);
+
+ return l;
+}
+
+void job_dependency_free(JobDependency *l) {
+ assert(l);
+
+ if (l->subject)
+ LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
+ else
+ LIST_REMOVE(JobDependency, subject, l->object->manager->transaction_anchor, l);
+
+ LIST_REMOVE(JobDependency, object, l->object->object_list, l);
+
+ free(l);
+}
+
+void job_dependency_delete(Job *subject, Job *object, bool *matters) {
+ JobDependency *l;
+
+ assert(object);
+
+ LIST_FOREACH(object, l, object->object_list) {
+ assert(l->object == object);
+
+ if (l->subject == subject)
+ break;
+ }
+
+ if (!l) {
+ if (matters)
+ *matters = false;
+ return;
+ }
+
+ if (matters)
+ *matters = l->matters;
+
+ job_dependency_free(l);
+}
+
+void job_dump(Job *j, FILE*f, const char *prefix) {
+
+
+ assert(j);
+ assert(f);
+
+ fprintf(f,
+ "%s→ Job %u:\n"
+ "%s\tAction: %s → %s\n"
+ "%s\tState: %s\n"
+ "%s\tForced: %s\n",
+ prefix, j->id,
+ prefix, unit_id(j->unit), job_type_to_string(j->type),
+ prefix, job_state_to_string(j->state),
+ prefix, yes_no(j->forced));
+}
+
+bool job_is_anchor(Job *j) {
+ JobDependency *l;