1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "unit-dependency-atom.h"
10 #include "unit-name.h"
13 typedef struct ActivationDetails ActivationDetails
;
14 typedef struct Job Job
;
15 typedef struct JobDependency JobDependency
;
16 typedef enum JobType JobType
;
17 typedef enum JobState JobState
;
18 typedef enum JobMode JobMode
;
19 typedef enum JobResult JobResult
;
21 /* Be careful when changing the job types! Adjust job_merging_table[] accordingly! */
23 JOB_START
, /* if a unit does not support being started, we'll just wait until it becomes active */
28 JOB_RELOAD
, /* if running, reload */
30 /* Note that restarts are first treated like JOB_STOP, but
31 * then instead of finishing are patched to become
33 JOB_RESTART
, /* If running, stop. Then start unconditionally. */
35 _JOB_TYPE_MAX_MERGING
,
37 /* JOB_NOP can enter into a transaction, but as it won't pull in
38 * any dependencies and it uses the special 'nop_job' slot in Unit,
39 * it won't have to merge with anything (except possibly into another
40 * JOB_NOP, previously installed). JOB_NOP is special-cased in
41 * job_type_is_*() functions so that the transaction can be
43 JOB_NOP
= _JOB_TYPE_MAX_MERGING
, /* do nothing */
45 _JOB_TYPE_MAX_IN_TRANSACTION
,
47 /* JOB_TRY_RESTART can never appear in a transaction, because
48 * it always collapses into JOB_RESTART or JOB_NOP before entering.
49 * Thus we never need to merge it with anything. */
50 JOB_TRY_RESTART
= _JOB_TYPE_MAX_IN_TRANSACTION
, /* if running, stop and then start */
52 /* Similar to JOB_TRY_RESTART but collapses to JOB_RELOAD or JOB_NOP */
55 /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result
56 * from transaction merging (there's no way for JOB_RELOAD and
57 * JOB_START to meet in one transaction). It can result from a merge
58 * during job installation, but then it will immediately collapse into
59 * one of the two simpler types. */
60 JOB_RELOAD_OR_START
, /* if running, reload, otherwise start */
63 _JOB_TYPE_INVALID
= -EINVAL
,
70 _JOB_STATE_INVALID
= -EINVAL
,
74 JOB_FAIL
, /* Fail if a conflicting job is already queued */
75 JOB_REPLACE
, /* Replace an existing conflicting job */
76 JOB_REPLACE_IRREVERSIBLY
,/* Like JOB_REPLACE + produce irreversible jobs */
77 JOB_ISOLATE
, /* Start a unit, and stop all others */
78 JOB_FLUSH
, /* Flush out all other queued jobs when queueing this one */
79 JOB_IGNORE_DEPENDENCIES
, /* Ignore both requirement and ordering dependencies */
80 JOB_IGNORE_REQUIREMENTS
, /* Ignore requirement dependencies */
81 JOB_TRIGGERING
, /* Adds TRIGGERED_BY dependencies to the same transaction */
82 JOB_RESTART_DEPENDENCIES
,/* A "start" job for the specified unit becomes "restart" for depending units */
84 _JOB_MODE_INVALID
= -EINVAL
,
88 JOB_DONE
, /* Job completed successfully (or skipped due to an unmet ConditionXYZ=) */
89 JOB_CANCELED
, /* Job canceled by a conflicting job installation or by explicit cancel request */
90 JOB_TIMEOUT
, /* Job timeout elapsed */
91 JOB_FAILED
, /* Job failed */
92 JOB_DEPENDENCY
, /* A required dependency job did not result in JOB_DONE */
93 JOB_SKIPPED
, /* Negative result of JOB_VERIFY_ACTIVE or skip due to ExecCondition= */
94 JOB_INVALID
, /* JOB_RELOAD of inactive unit */
95 JOB_ASSERT
, /* Couldn't start a unit, because an assert didn't hold */
96 JOB_UNSUPPORTED
, /* Couldn't start a unit, because the unit type is not supported on the system */
97 JOB_COLLECTED
, /* Job was garbage collected, since nothing needed it anymore */
98 JOB_ONCE
, /* Unit was started before, and hence can't be started again */
100 _JOB_RESULT_INVALID
= -EINVAL
,
103 struct JobDependency
{
104 /* Encodes that the 'subject' job needs the 'object' job in
105 * some way. This structure is used only while building a transaction. */
109 LIST_FIELDS(JobDependency
, subject
);
110 LIST_FIELDS(JobDependency
, object
);
120 LIST_FIELDS(Job
, transaction
);
121 LIST_FIELDS(Job
, dbus_queue
);
122 LIST_FIELDS(Job
, gc_queue
);
124 LIST_HEAD(JobDependency
, subject_list
);
125 LIST_HEAD(JobDependency
, object_list
);
127 /* Used for graph algs as a "I have been here" marker */
136 sd_event_source
*timer_event_source
;
138 usec_t begin_running_usec
;
141 * This tracks where to send signals, and also which clients
142 * are allowed to call DBus methods on the job (other than
145 * There can be more than one client, because of job merging.
147 sd_bus_track
*bus_track
;
148 char **deserialized_clients
;
152 unsigned run_queue_idx
;
154 /* If the job had a specific trigger that needs to be advertised (eg: a path unit), store it. */
155 ActivationDetails
*activation_details
;
159 bool matters_to_anchor
:1;
160 bool in_dbus_queue
:1;
161 bool sent_dbus_new_signal
:1;
165 bool ref_by_private_bus
:1;
168 Job
* job_new(Unit
*unit
, JobType type
);
169 Job
* job_new_raw(Unit
*unit
);
170 void job_unlink(Job
*job
);
171 Job
* job_free(Job
*job
);
172 Job
* job_install(Job
*j
, JobMode mode
);
173 int job_install_deserialized(Job
*j
);
174 void job_uninstall(Job
*j
);
175 void job_dump(Job
*j
, FILE *f
, const char *prefix
);
176 int job_serialize(Job
*j
, FILE *f
);
177 int job_deserialize(Job
*j
, FILE *f
);
178 int job_coldplug(Job
*j
);
180 JobDependency
* job_dependency_new(Job
*subject
, Job
*object
, bool matters
, bool conflicts
);
181 void job_dependency_free(JobDependency
*l
);
183 int job_merge(Job
*j
, Job
*other
);
185 JobType
job_type_lookup_merge(JobType a
, JobType b
) _pure_
;
187 _pure_
static inline bool job_type_is_mergeable(JobType a
, JobType b
) {
188 return job_type_lookup_merge(a
, b
) >= 0;
191 _pure_
static inline bool job_type_is_conflicting(JobType a
, JobType b
) {
192 return a
!= JOB_NOP
&& b
!= JOB_NOP
&& !job_type_is_mergeable(a
, b
);
195 _pure_
static inline bool job_type_is_superset(JobType a
, JobType b
) {
196 /* Checks whether operation a is a "superset" of b in its actions */
201 return a
== job_type_lookup_merge(a
, b
);
204 bool job_type_is_redundant(JobType a
, UnitActiveState b
) _pure_
;
206 /* Collapses a state-dependent job type into a simpler type by observing
207 * the state of the unit which it is going to be applied to. */
208 JobType
job_type_collapse(JobType t
, Unit
*u
);
210 int job_type_merge_and_collapse(JobType
*a
, JobType b
, Unit
*u
);
212 void job_add_to_run_queue(Job
*j
);
213 void job_add_to_dbus_queue(Job
*j
);
215 int job_start_timer(Job
*j
, bool job_running
);
217 int job_run_and_invalidate(Job
*j
);
218 int job_finish_and_invalidate(Job
*j
, JobResult result
, bool recursive
, bool already
);
220 char *job_dbus_path(Job
*j
);
222 void job_shutdown_magic(Job
*j
);
224 int job_get_timeout(Job
*j
, usec_t
*ret
);
226 bool job_may_gc(Job
*j
);
227 void job_add_to_gc_queue(Job
*j
);
229 int job_get_before(Job
*j
, Job
*** ret
);
230 int job_get_after(Job
*j
, Job
*** ret
);
232 DEFINE_TRIVIAL_CLEANUP_FUNC(Job
*, job_free
);
234 const char* job_type_to_string(JobType t
) _const_
;
235 JobType
job_type_from_string(const char *s
) _pure_
;
237 const char* job_state_to_string(JobState t
) _const_
;
238 JobState
job_state_from_string(const char *s
) _pure_
;
240 const char* job_mode_to_string(JobMode t
) _const_
;
241 JobMode
job_mode_from_string(const char *s
) _pure_
;
243 const char* job_result_to_string(JobResult t
) _const_
;
244 JobResult
job_result_from_string(const char *s
) _pure_
;
246 const char* job_type_to_access_method(JobType t
);
248 int job_compare(Job
*a
, Job
*b
, UnitDependencyAtom assume_dep
);
250 void job_set_activation_details(Job
*j
, ActivationDetails
*info
);