LCOV - code coverage report
Current view: top level - core - target.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 47 79 59.5 %
Date: 2015-07-29 18:47:03 Functions: 9 13 69.2 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2010 Lennart Poettering
       7             : 
       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.
      12             : 
      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.
      17             : 
      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/>.
      20             : ***/
      21             : 
      22             : 
      23             : #include "unit.h"
      24             : #include "target.h"
      25             : #include "log.h"
      26             : #include "dbus-target.h"
      27             : #include "special.h"
      28             : #include "unit-name.h"
      29             : 
      30             : static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
      31             :         [TARGET_DEAD] = UNIT_INACTIVE,
      32             :         [TARGET_ACTIVE] = UNIT_ACTIVE
      33             : };
      34             : 
      35          30 : static void target_set_state(Target *t, TargetState state) {
      36             :         TargetState old_state;
      37          30 :         assert(t);
      38             : 
      39          30 :         old_state = t->state;
      40          30 :         t->state = state;
      41             : 
      42          30 :         if (state != old_state)
      43          30 :                 log_debug("%s changed %s -> %s",
      44             :                           UNIT(t)->id,
      45             :                           target_state_to_string(old_state),
      46             :                           target_state_to_string(state));
      47             : 
      48          30 :         unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
      49          30 : }
      50             : 
      51          40 : static int target_add_default_dependencies(Target *t) {
      52             : 
      53             :         static const UnitDependency deps[] = {
      54             :                 UNIT_REQUIRES,
      55             :                 UNIT_REQUIRES_OVERRIDABLE,
      56             :                 UNIT_REQUISITE,
      57             :                 UNIT_REQUISITE_OVERRIDABLE,
      58             :                 UNIT_WANTS,
      59             :                 UNIT_BINDS_TO,
      60             :                 UNIT_PART_OF
      61             :         };
      62             : 
      63             :         Iterator i;
      64             :         Unit *other;
      65             :         int r;
      66             :         unsigned k;
      67             : 
      68          40 :         assert(t);
      69             : 
      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. */
      74             : 
      75         320 :         for (k = 0; k < ELEMENTSOF(deps); k++)
      76         630 :                 SET_FOREACH(other, UNIT(t)->dependencies[deps[k]], i) {
      77          70 :                         r = unit_add_default_target_dependency(other, UNIT(t));
      78          70 :                         if (r < 0)
      79           0 :                                 return r;
      80             :                 }
      81             : 
      82             :         /* Make sure targets are unloaded on shutdown */
      83          40 :         return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
      84             : }
      85             : 
      86         100 : static int target_load(Unit *u) {
      87         100 :         Target *t = TARGET(u);
      88             :         int r;
      89             : 
      90         100 :         assert(t);
      91             : 
      92         100 :         r = unit_load_fragment_and_dropin(u);
      93         100 :         if (r < 0)
      94          40 :                 return r;
      95             : 
      96             :         /* This is a new unit? Then let's add in some extras */
      97          60 :         if (u->load_state == UNIT_LOADED && u->default_dependencies) {
      98          40 :                 r = target_add_default_dependencies(t);
      99          40 :                 if (r < 0)
     100           0 :                         return r;
     101             :         }
     102             : 
     103          60 :         return 0;
     104             : }
     105             : 
     106          10 : static int target_coldplug(Unit *u) {
     107          10 :         Target *t = TARGET(u);
     108             : 
     109          10 :         assert(t);
     110          10 :         assert(t->state == TARGET_DEAD);
     111             : 
     112          10 :         if (t->deserialized_state != t->state)
     113           0 :                 target_set_state(t, t->deserialized_state);
     114             : 
     115          10 :         return 0;
     116             : }
     117             : 
     118          24 : static void target_dump(Unit *u, FILE *f, const char *prefix) {
     119          24 :         Target *t = TARGET(u);
     120             : 
     121          24 :         assert(t);
     122          24 :         assert(f);
     123             : 
     124          24 :         fprintf(f,
     125             :                 "%sTarget State: %s\n",
     126             :                 prefix, target_state_to_string(t->state));
     127          24 : }
     128             : 
     129          30 : static int target_start(Unit *u) {
     130          30 :         Target *t = TARGET(u);
     131             : 
     132          30 :         assert(t);
     133          30 :         assert(t->state == TARGET_DEAD);
     134             : 
     135          30 :         target_set_state(t, TARGET_ACTIVE);
     136          30 :         return 1;
     137             : }
     138             : 
     139           0 : static int target_stop(Unit *u) {
     140           0 :         Target *t = TARGET(u);
     141             : 
     142           0 :         assert(t);
     143           0 :         assert(t->state == TARGET_ACTIVE);
     144             : 
     145           0 :         target_set_state(t, TARGET_DEAD);
     146           0 :         return 1;
     147             : }
     148             : 
     149           0 : static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
     150           0 :         Target *s = TARGET(u);
     151             : 
     152           0 :         assert(s);
     153           0 :         assert(f);
     154           0 :         assert(fds);
     155             : 
     156           0 :         unit_serialize_item(u, f, "state", target_state_to_string(s->state));
     157           0 :         return 0;
     158             : }
     159             : 
     160           0 : static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     161           0 :         Target *s = TARGET(u);
     162             : 
     163           0 :         assert(u);
     164           0 :         assert(key);
     165           0 :         assert(value);
     166           0 :         assert(fds);
     167             : 
     168           0 :         if (streq(key, "state")) {
     169             :                 TargetState state;
     170             : 
     171           0 :                 state = target_state_from_string(value);
     172           0 :                 if (state < 0)
     173           0 :                         log_debug("Failed to parse state value %s", value);
     174             :                 else
     175           0 :                         s->deserialized_state = state;
     176             : 
     177             :         } else
     178           0 :                 log_debug("Unknown serialization key '%s'", key);
     179             : 
     180           0 :         return 0;
     181             : }
     182             : 
     183         517 : _pure_ static UnitActiveState target_active_state(Unit *u) {
     184         517 :         assert(u);
     185             : 
     186         517 :         return state_translation_table[TARGET(u)->state];
     187             : }
     188             : 
     189           0 : _pure_ static const char *target_sub_state_to_string(Unit *u) {
     190           0 :         assert(u);
     191             : 
     192           0 :         return target_state_to_string(TARGET(u)->state);
     193             : }
     194             : 
     195             : static const char* const target_state_table[_TARGET_STATE_MAX] = {
     196             :         [TARGET_DEAD] = "dead",
     197             :         [TARGET_ACTIVE] = "active"
     198             : };
     199             : 
     200          32 : DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
     201             : 
     202             : const UnitVTable target_vtable = {
     203             :         .object_size = sizeof(Target),
     204             : 
     205             :         .sections =
     206             :                 "Unit\0"
     207             :                 "Target\0"
     208             :                 "Install\0",
     209             : 
     210             :         .load = target_load,
     211             :         .coldplug = target_coldplug,
     212             : 
     213             :         .dump = target_dump,
     214             : 
     215             :         .start = target_start,
     216             :         .stop = target_stop,
     217             : 
     218             :         .serialize = target_serialize,
     219             :         .deserialize_item = target_deserialize_item,
     220             : 
     221             :         .active_state = target_active_state,
     222             :         .sub_state_to_string = target_sub_state_to_string,
     223             : 
     224             :         .bus_interface = "org.freedesktop.systemd1.Target",
     225             :         .bus_vtable = bus_target_vtable,
     226             : 
     227             :         .status_message_formats = {
     228             :                 .finished_start_job = {
     229             :                         [JOB_DONE]       = "Reached target %s.",
     230             :                 },
     231             :                 .finished_stop_job = {
     232             :                         [JOB_DONE]       = "Stopped target %s.",
     233             :                 },
     234             :         },
     235             : };

Generated by: LCOV version 1.11