LCOV - code coverage report
Current view: top level - core - target.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 47 87 54.0 %
Date: 2019-08-22 15:41:25 Functions: 6 11 54.5 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "dbus-target.h"
       4             : #include "dbus-unit.h"
       5             : #include "log.h"
       6             : #include "serialize.h"
       7             : #include "special.h"
       8             : #include "string-util.h"
       9             : #include "target.h"
      10             : #include "unit-name.h"
      11             : #include "unit.h"
      12             : 
      13             : static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
      14             :         [TARGET_DEAD] = UNIT_INACTIVE,
      15             :         [TARGET_ACTIVE] = UNIT_ACTIVE
      16             : };
      17             : 
      18          18 : static void target_set_state(Target *t, TargetState state) {
      19             :         TargetState old_state;
      20          18 :         assert(t);
      21             : 
      22          18 :         if (t->state != state)
      23          18 :                 bus_unit_send_pending_change_signal(UNIT(t), false);
      24             : 
      25          18 :         old_state = t->state;
      26          18 :         t->state = state;
      27             : 
      28          18 :         if (state != old_state)
      29          18 :                 log_debug("%s changed %s -> %s",
      30             :                           UNIT(t)->id,
      31             :                           target_state_to_string(old_state),
      32             :                           target_state_to_string(state));
      33             : 
      34          18 :         unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
      35          18 : }
      36             : 
      37          41 : static int target_add_default_dependencies(Target *t) {
      38             : 
      39             :         static const UnitDependency deps[] = {
      40             :                 UNIT_REQUIRES,
      41             :                 UNIT_REQUISITE,
      42             :                 UNIT_WANTS,
      43             :                 UNIT_BINDS_TO,
      44             :                 UNIT_PART_OF
      45             :         };
      46             : 
      47             :         int r;
      48             :         unsigned k;
      49             : 
      50          41 :         assert(t);
      51             : 
      52          41 :         if (!UNIT(t)->default_dependencies)
      53           8 :                 return 0;
      54             : 
      55             :         /* Imply ordering for requirement dependencies on target units. Note that when the user created a contradicting
      56             :          * ordering manually we won't add anything in here to make sure we don't create a loop. */
      57             : 
      58         198 :         for (k = 0; k < ELEMENTSOF(deps); k++) {
      59             :                 Unit *other;
      60             :                 Iterator i;
      61             :                 void *v;
      62             : 
      63         253 :                 HASHMAP_FOREACH_KEY(v, other, UNIT(t)->dependencies[deps[k]], i) {
      64          88 :                         r = unit_add_default_target_dependency(other, UNIT(t));
      65          88 :                         if (r < 0)
      66           0 :                                 return r;
      67             :                 }
      68             :         }
      69             : 
      70          33 :         if (unit_has_name(UNIT(t), SPECIAL_SHUTDOWN_TARGET))
      71           0 :                 return 0;
      72             : 
      73             :         /* Make sure targets are unloaded on shutdown */
      74          33 :         return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
      75             : }
      76             : 
      77         110 : static int target_load(Unit *u) {
      78         110 :         Target *t = TARGET(u);
      79             :         int r;
      80             : 
      81         110 :         assert(t);
      82             : 
      83         110 :         r = unit_load_fragment_and_dropin(u);
      84         110 :         if (r < 0)
      85          69 :                 return r;
      86             : 
      87             :         /* This is a new unit? Then let's add in some extras */
      88          41 :         if (u->load_state == UNIT_LOADED) {
      89          41 :                 r = target_add_default_dependencies(t);
      90          41 :                 if (r < 0)
      91           0 :                         return r;
      92             :         }
      93             : 
      94          41 :         return 0;
      95             : }
      96             : 
      97           0 : static int target_coldplug(Unit *u) {
      98           0 :         Target *t = TARGET(u);
      99             : 
     100           0 :         assert(t);
     101           0 :         assert(t->state == TARGET_DEAD);
     102             : 
     103           0 :         if (t->deserialized_state != t->state)
     104           0 :                 target_set_state(t, t->deserialized_state);
     105             : 
     106           0 :         return 0;
     107             : }
     108             : 
     109          30 : static void target_dump(Unit *u, FILE *f, const char *prefix) {
     110          30 :         Target *t = TARGET(u);
     111             : 
     112          30 :         assert(t);
     113          30 :         assert(f);
     114             : 
     115          30 :         fprintf(f,
     116             :                 "%sTarget State: %s\n",
     117             :                 prefix, target_state_to_string(t->state));
     118          30 : }
     119             : 
     120          18 : static int target_start(Unit *u) {
     121          18 :         Target *t = TARGET(u);
     122             :         int r;
     123             : 
     124          18 :         assert(t);
     125          18 :         assert(t->state == TARGET_DEAD);
     126             : 
     127          18 :         r = unit_acquire_invocation_id(u);
     128          18 :         if (r < 0)
     129           0 :                 return r;
     130             : 
     131          18 :         target_set_state(t, TARGET_ACTIVE);
     132          18 :         return 1;
     133             : }
     134             : 
     135           0 : static int target_stop(Unit *u) {
     136           0 :         Target *t = TARGET(u);
     137             : 
     138           0 :         assert(t);
     139           0 :         assert(t->state == TARGET_ACTIVE);
     140             : 
     141           0 :         target_set_state(t, TARGET_DEAD);
     142           0 :         return 1;
     143             : }
     144             : 
     145           0 : static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
     146           0 :         Target *s = TARGET(u);
     147             : 
     148           0 :         assert(s);
     149           0 :         assert(f);
     150           0 :         assert(fds);
     151             : 
     152           0 :         (void) serialize_item(f, "state", target_state_to_string(s->state));
     153           0 :         return 0;
     154             : }
     155             : 
     156           0 : static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     157           0 :         Target *s = TARGET(u);
     158             : 
     159           0 :         assert(u);
     160           0 :         assert(key);
     161           0 :         assert(value);
     162           0 :         assert(fds);
     163             : 
     164           0 :         if (streq(key, "state")) {
     165             :                 TargetState state;
     166             : 
     167           0 :                 state = target_state_from_string(value);
     168           0 :                 if (state < 0)
     169           0 :                         log_debug("Failed to parse state value %s", value);
     170             :                 else
     171           0 :                         s->deserialized_state = state;
     172             : 
     173             :         } else
     174           0 :                 log_debug("Unknown serialization key '%s'", key);
     175             : 
     176           0 :         return 0;
     177             : }
     178             : 
     179         707 : _pure_ static UnitActiveState target_active_state(Unit *u) {
     180         707 :         assert(u);
     181             : 
     182         707 :         return state_translation_table[TARGET(u)->state];
     183             : }
     184             : 
     185           0 : _pure_ static const char *target_sub_state_to_string(Unit *u) {
     186           0 :         assert(u);
     187             : 
     188           0 :         return target_state_to_string(TARGET(u)->state);
     189             : }
     190             : 
     191             : const UnitVTable target_vtable = {
     192             :         .object_size = sizeof(Target),
     193             : 
     194             :         .sections =
     195             :                 "Unit\0"
     196             :                 "Target\0"
     197             :                 "Install\0",
     198             : 
     199             :         .load = target_load,
     200             :         .coldplug = target_coldplug,
     201             : 
     202             :         .dump = target_dump,
     203             : 
     204             :         .start = target_start,
     205             :         .stop = target_stop,
     206             : 
     207             :         .serialize = target_serialize,
     208             :         .deserialize_item = target_deserialize_item,
     209             : 
     210             :         .active_state = target_active_state,
     211             :         .sub_state_to_string = target_sub_state_to_string,
     212             : 
     213             :         .bus_vtable = bus_target_vtable,
     214             : 
     215             :         .status_message_formats = {
     216             :                 .finished_start_job = {
     217             :                         [JOB_DONE]       = "Reached target %s.",
     218             :                 },
     219             :                 .finished_stop_job = {
     220             :                         [JOB_DONE]       = "Stopped target %s.",
     221             :                 },
     222             :         },
     223             : };

Generated by: LCOV version 1.14