summaryrefslogtreecommitdiffstats
path: root/src/core/unit-dependency-atom.c
blob: 81333523e73865ee8166ae3fe5fc2a33a3040fbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "unit-dependency-atom.h"

static const UnitDependencyAtom atom_map[_UNIT_DEPENDENCY_MAX] = {
        /* A table that maps high-level dependency types to low-level dependency "atoms". The latter actually
         * describe specific facets of dependency behaviour. The former combine them into one user-facing
         * concept. Atoms are a bit mask, though a bunch of dependency types have only a single bit set.
         *
         * Typically when the user configures a dependency they go via dependency type, but when we act on
         * them we go by atom.
         *
         * NB: when you add a new dependency type here, make sure to also add one to the (best-effort)
         * reverse table in unit_dependency_from_unique_atom() further down. */

        [UNIT_REQUIRES]               = UNIT_ATOM_PULL_IN_START |
                                        UNIT_ATOM_RETROACTIVE_START_REPLACE |
                                        UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                                        UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_REQUISITE]              = UNIT_ATOM_PULL_IN_VERIFY |
                                        UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                                        UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_WANTS]                  = UNIT_ATOM_PULL_IN_START_IGNORED |
                                        UNIT_ATOM_RETROACTIVE_START_FAIL |
                                        UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                                        UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_BINDS_TO]               = UNIT_ATOM_PULL_IN_START |
                                        UNIT_ATOM_RETROACTIVE_START_REPLACE |
                                        UNIT_ATOM_CANNOT_BE_ACTIVE_WITHOUT |
                                        UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                                        UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_PART_OF]                = UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_UPHOLDS]                = UNIT_ATOM_PULL_IN_START_IGNORED |
                                        UNIT_ATOM_RETROACTIVE_START_REPLACE |
                                        UNIT_ATOM_ADD_START_WHEN_UPHELD_QUEUE |
                                        UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                                        UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE,

        [UNIT_REQUIRED_BY]            = UNIT_ATOM_PROPAGATE_STOP |
                                        UNIT_ATOM_PROPAGATE_RESTART |
                                        UNIT_ATOM_PROPAGATE_START_FAILURE |
                                        UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED |
                                        UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES,

        [UNIT_REQUISITE_OF]           = UNIT_ATOM_PROPAGATE_STOP |
                                        UNIT_ATOM_PROPAGATE_RESTART |
                                        UNIT_ATOM_PROPAGATE_START_FAILURE |
                                        UNIT_ATOM_PROPAGATE_INACTIVE_START_AS_FAILURE |
                                        UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED |
                                        UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES,

        [UNIT_WANTED_BY]              = UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES |
                                        UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED,

        [UNIT_BOUND_BY]               = UNIT_ATOM_RETROACTIVE_STOP_ON_STOP |
                                        UNIT_ATOM_PROPAGATE_STOP |
                                        UNIT_ATOM_PROPAGATE_RESTART |
                                        UNIT_ATOM_PROPAGATE_START_FAILURE |
                                        UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED |
                                        UNIT_ATOM_ADD_CANNOT_BE_ACTIVE_WITHOUT_QUEUE |
                                        UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES,

        [UNIT_UPHELD_BY]              = UNIT_ATOM_START_STEADILY |
                                        UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES |
                                        UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED,

        [UNIT_CONSISTS_OF]            = UNIT_ATOM_PROPAGATE_STOP |
                                        UNIT_ATOM_PROPAGATE_RESTART,

        [UNIT_CONFLICTS]              = UNIT_ATOM_PULL_IN_STOP |
                                        UNIT_ATOM_RETROACTIVE_STOP_ON_START,

        [UNIT_CONFLICTED_BY]          = UNIT_ATOM_PULL_IN_STOP_IGNORED |
                                        UNIT_ATOM_RETROACTIVE_STOP_ON_START |
                                        UNIT_ATOM_PROPAGATE_STOP_FAILURE,

        [UNIT_PROPAGATES_STOP_TO]     = UNIT_ATOM_RETROACTIVE_STOP_ON_STOP |
                                        UNIT_ATOM_PROPAGATE_STOP,

        /* These are simple dependency types: they consist of a single atom only */
        [UNIT_ON_FAILURE]             = UNIT_ATOM_ON_FAILURE,
        [UNIT_ON_SUCCESS]             = UNIT_ATOM_ON_SUCCESS,
        [UNIT_ON_FAILURE_OF]          = UNIT_ATOM_ON_FAILURE_OF,
        [UNIT_ON_SUCCESS_OF]          = UNIT_ATOM_ON_SUCCESS_OF,
        [UNIT_BEFORE]                 = UNIT_ATOM_BEFORE,
        [UNIT_AFTER]                  = UNIT_ATOM_AFTER,
        [UNIT_TRIGGERS]               = UNIT_ATOM_TRIGGERS,
        [UNIT_TRIGGERED_BY]           = UNIT_ATOM_TRIGGERED_BY,
        [UNIT_PROPAGATES_RELOAD_TO]   = UNIT_ATOM_PROPAGATES_RELOAD_TO,
        [UNIT_JOINS_NAMESPACE_OF]     = UNIT_ATOM_JOINS_NAMESPACE_OF,
        [UNIT_REFERENCES]             = UNIT_ATOM_REFERENCES,
        [UNIT_REFERENCED_BY]          = UNIT_ATOM_REFERENCED_BY,
        [UNIT_IN_SLICE]               = UNIT_ATOM_IN_SLICE,
        [UNIT_SLICE_OF]               = UNIT_ATOM_SLICE_OF,

        /* These are dependency types without effect on our state engine. We maintain them only to make
         * things discoverable/debuggable as they are the inverse dependencies to some of the above. As they
         * have no effect of their own, they all map to no atoms at all, i.e. the value 0. */
        [UNIT_RELOAD_PROPAGATED_FROM] = 0,
        [UNIT_STOP_PROPAGATED_FROM]   = 0,
};

UnitDependencyAtom unit_dependency_to_atom(UnitDependency d) {
        if (d < 0)
                return _UNIT_DEPENDENCY_ATOM_INVALID;

        assert(d < _UNIT_DEPENDENCY_MAX);

        return atom_map[d];
}

UnitDependency unit_dependency_from_unique_atom(UnitDependencyAtom atom) {

        /* This is a "best-effort" function that maps the specified 'atom' mask to a dependency type that is
         * is equal to or has a superset of bits set if that's uniquely possible. The idea is that this
         * function is used when iterating through deps that have a specific atom: if there's exactly one
         * dependency type of the specific atom we don't need iterate through all deps a unit has, but can
         * pinpoint things directly.
         *
         * This function will return _UNIT_DEPENDENCY_INVALID in case the specified value is not known or not
         * uniquely defined, i.e. there are multiple dependencies with the atom or the combination set. */

        switch ((int64_t) atom) {

                /* Note that we can't list UNIT_REQUIRES here since it's a true subset of UNIT_BINDS_TO, and
                 * hence its atom bits not uniquely mappable. */

        case UNIT_ATOM_PULL_IN_VERIFY |
                UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE:
        case UNIT_ATOM_PULL_IN_VERIFY: /* a single dep type uses this atom */
                return UNIT_REQUISITE;

        case UNIT_ATOM_PULL_IN_START_IGNORED |
                UNIT_ATOM_RETROACTIVE_START_FAIL |
                UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE:
        case UNIT_ATOM_RETROACTIVE_START_FAIL:
                return UNIT_WANTS;

        case UNIT_ATOM_PULL_IN_START |
                UNIT_ATOM_RETROACTIVE_START_REPLACE |
                UNIT_ATOM_CANNOT_BE_ACTIVE_WITHOUT |
                UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE:
        case UNIT_ATOM_CANNOT_BE_ACTIVE_WITHOUT:
                return UNIT_BINDS_TO;

        case UNIT_ATOM_PULL_IN_START_IGNORED |
                UNIT_ATOM_RETROACTIVE_START_REPLACE |
                UNIT_ATOM_ADD_START_WHEN_UPHELD_QUEUE |
                UNIT_ATOM_ADD_STOP_WHEN_UNNEEDED_QUEUE |
                UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE:
        case UNIT_ATOM_ADD_START_WHEN_UPHELD_QUEUE:
                return UNIT_UPHOLDS;

        case UNIT_ATOM_PROPAGATE_STOP |
                UNIT_ATOM_PROPAGATE_RESTART |
                UNIT_ATOM_PROPAGATE_START_FAILURE |
                UNIT_ATOM_PROPAGATE_INACTIVE_START_AS_FAILURE |
                UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED |
                UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES:
        case UNIT_ATOM_PROPAGATE_INACTIVE_START_AS_FAILURE:
                return UNIT_REQUISITE_OF;

        case UNIT_ATOM_RETROACTIVE_STOP_ON_STOP |
                UNIT_ATOM_PROPAGATE_STOP |
                UNIT_ATOM_PROPAGATE_RESTART |
                UNIT_ATOM_PROPAGATE_START_FAILURE |
                UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED |
                UNIT_ATOM_ADD_CANNOT_BE_ACTIVE_WITHOUT_QUEUE |
                UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES:
        case UNIT_ATOM_ADD_CANNOT_BE_ACTIVE_WITHOUT_QUEUE:
                return UNIT_BOUND_BY;

        case UNIT_ATOM_START_STEADILY |
                UNIT_ATOM_DEFAULT_TARGET_DEPENDENCIES |
                UNIT_ATOM_PINS_STOP_WHEN_UNNEEDED:
        case UNIT_ATOM_START_STEADILY:
                return UNIT_UPHELD_BY;

        case UNIT_ATOM_PULL_IN_STOP |
                UNIT_ATOM_RETROACTIVE_STOP_ON_START:
        case UNIT_ATOM_PULL_IN_STOP:
                return UNIT_CONFLICTS;

        case UNIT_ATOM_PULL_IN_STOP_IGNORED |
                UNIT_ATOM_RETROACTIVE_STOP_ON_START |
                UNIT_ATOM_PROPAGATE_STOP_FAILURE:
        case UNIT_ATOM_PULL_IN_STOP_IGNORED:
        case UNIT_ATOM_PROPAGATE_STOP_FAILURE:
                return UNIT_CONFLICTED_BY;

        /* And now, the simple ones */

        case UNIT_ATOM_ON_FAILURE:
                return UNIT_ON_FAILURE;

        case UNIT_ATOM_ON_SUCCESS:
                return UNIT_ON_SUCCESS;

        case UNIT_ATOM_ON_SUCCESS_OF:
                return UNIT_ON_SUCCESS_OF;

        case UNIT_ATOM_ON_FAILURE_OF:
                return UNIT_ON_FAILURE_OF;

        case UNIT_ATOM_BEFORE:
                return UNIT_BEFORE;

        case UNIT_ATOM_AFTER:
                return UNIT_AFTER;

        case UNIT_ATOM_TRIGGERS:
                return UNIT_TRIGGERS;

        case UNIT_ATOM_TRIGGERED_BY:
                return UNIT_TRIGGERED_BY;

        case UNIT_ATOM_PROPAGATES_RELOAD_TO:
                return UNIT_PROPAGATES_RELOAD_TO;

        case UNIT_ATOM_JOINS_NAMESPACE_OF:
                return UNIT_JOINS_NAMESPACE_OF;

        case UNIT_ATOM_REFERENCES:
                return UNIT_REFERENCES;

        case UNIT_ATOM_REFERENCED_BY:
                return UNIT_REFERENCED_BY;

        case UNIT_ATOM_IN_SLICE:
                return UNIT_IN_SLICE;

        case UNIT_ATOM_SLICE_OF:
                return UNIT_SLICE_OF;

        default:
                return _UNIT_DEPENDENCY_INVALID;
        }
}