if (u->meta.load_state == UNIT_LOADED) {
fprintf(f,
- "%s\tRecursive Stop: %s\n"
"%s\tStopWhenUnneeded: %s\n"
"%s\tRefuseManualStart: %s\n"
"%s\tRefuseManualStop: %s\n"
- "%s\tDefaultDependencies: %s\n"
- "%s\tIgnoreDependencyFailure: %s\n",
- prefix, yes_no(u->meta.recursive_stop),
+ "%s\tDefaultDependencies: %s\n",
prefix, yes_no(u->meta.stop_when_unneeded),
prefix, yes_no(u->meta.refuse_manual_start),
prefix, yes_no(u->meta.refuse_manual_stop),
- prefix, yes_no(u->meta.default_dependencies),
- prefix, yes_no(u->meta.ignore_dependency_failure));
+ prefix, yes_no(u->meta.default_dependencies));
LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
fprintf(f, "%s\tControlGroup: %s:%s\n",
if ((r = unit_add_default_target_dependency(u, target)) < 0)
return r;
+ SET_FOREACH(target, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if ((r = unit_add_default_target_dependency(u, target)) < 0)
+ return r;
+
return 0;
}
*/
int unit_start(Unit *u) {
UnitActiveState state;
+ Unit *following;
assert(u);
if (UNIT_IS_ACTIVE_OR_RELOADING(state))
return -EALREADY;
- /* If it is stopped, but we cannot start it, then fail */
- if (!UNIT_VTABLE(u)->start)
- return -EBADR;
-
/* If the conditions failed, don't do anything at all */
if (!condition_test_list(u->meta.conditions)) {
log_debug("Starting of %s requested but condition failed. Ignoring.", u->meta.id);
return -EALREADY;
}
+ /* Forward to the main object, if we aren't it. */
+ if ((following = unit_following(u))) {
+ log_debug("Redirecting start request from %s to %s.", u->meta.id, following->meta.id);
+ return unit_start(following);
+ }
+
+ /* If it is stopped, but we cannot start it, then fail */
+ if (!UNIT_VTABLE(u)->start)
+ return -EBADR;
+
/* We don't suppress calls to ->start() here when we are
* already starting, to allow this request to be used as a
* "hurry up" call, for example when the unit is in some "auto
unit_add_to_dbus_queue(u);
unit_status_printf(u, "Starting %s...\n", unit_description(u));
-
return UNIT_VTABLE(u)->start(u);
}
*/
int unit_stop(Unit *u) {
UnitActiveState state;
+ Unit *following;
assert(u);
if (UNIT_IS_INACTIVE_OR_FAILED(state))
return -EALREADY;
+ if ((following = unit_following(u))) {
+ log_debug("Redirecting stop request from %s to %s.", u->meta.id, following->meta.id);
+ return unit_stop(following);
+ }
+
if (!UNIT_VTABLE(u)->stop)
return -EBADR;
unit_add_to_dbus_queue(u);
unit_status_printf(u, "Stopping %s...\n", unit_description(u));
-
return UNIT_VTABLE(u)->stop(u);
}
*/
int unit_reload(Unit *u) {
UnitActiveState state;
+ Unit *following;
assert(u);
if (state != UNIT_ACTIVE)
return -ENOEXEC;
+ if ((following = unit_following(u))) {
+ log_debug("Redirecting reload request from %s to %s.", u->meta.id, following->meta.id);
+ return unit_reload(following);
+ }
+
unit_add_to_dbus_queue(u);
return UNIT_VTABLE(u)->reload(u);
}
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
return;
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ return;
+
log_info("Service %s is not needed anymore. Stopping.", u->meta.id);
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BIND_TO], i)
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_WANTS], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTED_BY], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
}
assert(u);
assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
- if (u->meta.recursive_stop) {
- /* Pull down units need us recursively if enabled */
- SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
- }
+ /* Pull down units which are bound to us recursively if enabled */
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
/* Garbage collect services that might not be needed anymore, if enabled */
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BIND_TO], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ unit_check_unneeded(other);
}
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
case JOB_VERIFY_ACTIVE:
case JOB_START:
+ case JOB_STOP:
return true;
- case JOB_STOP:
case JOB_RESTART:
case JOB_TRY_RESTART:
return unit_can_start(u);
[UNIT_WANTS] = UNIT_WANTED_BY,
[UNIT_REQUISITE] = UNIT_REQUIRED_BY,
[UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
+ [UNIT_BIND_TO] = UNIT_BOUND_BY,
[UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
[UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
[UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
+ [UNIT_BOUND_BY] = UNIT_BIND_TO,
[UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
[UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
[UNIT_BEFORE] = UNIT_AFTER,
(d == UNIT_REQUIRES ||
d == UNIT_REQUIRES_OVERRIDABLE ||
d == UNIT_REQUISITE ||
- d == UNIT_REQUISITE_OVERRIDABLE)) {
+ d == UNIT_REQUISITE_OVERRIDABLE ||
+ d == UNIT_BIND_TO)) {
return -EINVAL;
}
continue;
} else if (streq(l, "inactive-exit-timestamp")) {
- dual_timestamp_deserialize(f, v, &u->meta.inactive_exit_timestamp);
+ dual_timestamp_deserialize(v, &u->meta.inactive_exit_timestamp);
continue;
} else if (streq(l, "active-enter-timestamp")) {
- dual_timestamp_deserialize(f, v, &u->meta.active_enter_timestamp);
+ dual_timestamp_deserialize(v, &u->meta.active_enter_timestamp);
continue;
} else if (streq(l, "active-exit-timestamp")) {
- dual_timestamp_deserialize(f, v, &u->meta.active_exit_timestamp);
+ dual_timestamp_deserialize(v, &u->meta.active_exit_timestamp);
continue;
} else if (streq(l, "inactive-enter-timestamp")) {
- dual_timestamp_deserialize(f, v, &u->meta.inactive_enter_timestamp);
+ dual_timestamp_deserialize(v, &u->meta.inactive_enter_timestamp);
continue;
}
if (r < 0)
return r;
- if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, device, true)) < 0)
+ if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BIND_TO, device, true)) < 0)
return r;
if (wants)
return UNIT_VTABLE(u)->kill(u, w, m, signo, error);
}
+
+int unit_following_set(Unit *u, Set **s) {
+ assert(u);
+ assert(s);
+
+ if (UNIT_VTABLE(u)->following_set)
+ return UNIT_VTABLE(u)->following_set(u, s);
+
+ *s = NULL;
+ return 0;
+}
+
static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
[UNIT_STUB] = "stub",
[UNIT_LOADED] = "loaded",
[UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
[UNIT_REQUIRED_BY] = "RequiredBy",
[UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
+ [UNIT_BIND_TO] = "BindTo",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_CONFLICTS] = "Conflicts",
[UNIT_CONFLICTED_BY] = "ConflictedBy",
+ [UNIT_BOUND_BY] = "BoundBy",
[UNIT_BEFORE] = "Before",
[UNIT_AFTER] = "After",
[UNIT_REFERENCES] = "References",