1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "dbus-target.h"
28 #include "unit-name.h"
30 static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
31 [TARGET_DEAD] = UNIT_INACTIVE,
32 [TARGET_ACTIVE] = UNIT_ACTIVE
35 static void target_set_state(Target *t, TargetState state) {
36 TargetState old_state;
42 if (state != old_state)
43 log_debug("%s changed %s -> %s",
45 target_state_to_string(old_state),
46 target_state_to_string(state));
48 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
51 static int target_add_default_dependencies(Target *t) {
53 static const UnitDependency deps[] = {
55 UNIT_REQUIRES_OVERRIDABLE,
57 UNIT_REQUISITE_OVERRIDABLE,
70 /* Imply ordering for requirement dependencies on target
71 * units. Note that when the user created a contradicting
72 * ordering manually we won't add anything in here to make
73 * sure we don't create a loop. */
75 for (k = 0; k < ELEMENTSOF(deps); k++)
76 SET_FOREACH(other, UNIT(t)->dependencies[deps[k]], i) {
77 r = unit_add_default_target_dependency(other, UNIT(t));
82 /* Make sure targets are unloaded on shutdown */
83 return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
86 static int target_load(Unit *u) {
87 Target *t = TARGET(u);
92 r = unit_load_fragment_and_dropin(u);
96 /* This is a new unit? Then let's add in some extras */
97 if (u->load_state == UNIT_LOADED && u->default_dependencies) {
98 r = target_add_default_dependencies(t);
106 static int target_coldplug(Unit *u, Hashmap *deferred_work) {
107 Target *t = TARGET(u);
110 assert(t->state == TARGET_DEAD);
112 if (t->deserialized_state != t->state)
113 target_set_state(t, t->deserialized_state);
118 static void target_dump(Unit *u, FILE *f, const char *prefix) {
119 Target *t = TARGET(u);
125 "%sTarget State: %s\n",
126 prefix, target_state_to_string(t->state));
129 static int target_start(Unit *u) {
130 Target *t = TARGET(u);
133 assert(t->state == TARGET_DEAD);
135 target_set_state(t, TARGET_ACTIVE);
139 static int target_stop(Unit *u) {
140 Target *t = TARGET(u);
143 assert(t->state == TARGET_ACTIVE);
145 target_set_state(t, TARGET_DEAD);
149 static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
150 Target *s = TARGET(u);
156 unit_serialize_item(u, f, "state", target_state_to_string(s->state));
160 static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
161 Target *s = TARGET(u);
168 if (streq(key, "state")) {
171 state = target_state_from_string(value);
173 log_debug("Failed to parse state value %s", value);
175 s->deserialized_state = state;
178 log_debug("Unknown serialization key '%s'", key);
183 _pure_ static UnitActiveState target_active_state(Unit *u) {
186 return state_translation_table[TARGET(u)->state];
189 _pure_ static const char *target_sub_state_to_string(Unit *u) {
192 return target_state_to_string(TARGET(u)->state);
195 static const char* const target_state_table[_TARGET_STATE_MAX] = {
196 [TARGET_DEAD] = "dead",
197 [TARGET_ACTIVE] = "active"
200 DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
202 const UnitVTable target_vtable = {
203 .object_size = sizeof(Target),
211 .coldplug = target_coldplug,
215 .start = target_start,
218 .serialize = target_serialize,
219 .deserialize_item = target_deserialize_item,
221 .active_state = target_active_state,
222 .sub_state_to_string = target_sub_state_to_string,
224 .bus_interface = "org.freedesktop.systemd1.Target",
225 .bus_vtable = bus_target_vtable,
227 .status_message_formats = {
228 .finished_start_job = {
229 [JOB_DONE] = "Reached target %s.",
230 [JOB_DEPENDENCY] = "Dependency failed for %s.",
232 .finished_stop_job = {
233 [JOB_DONE] = "Stopped target %s.",