]>
git.ipfire.org Git - people/ms/systemd.git/blob - manager.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
11 #include "load-fragment.h"
13 Manager
* manager_new(void) {
16 if (!(m
= new0(Manager
, 1)))
19 if (!(m
->names
= hashmap_new(string_hash_func
, string_compare_func
)))
22 if (!(m
->jobs
= hashmap_new(trivial_hash_func
, trivial_compare_func
)))
25 if (!(m
->jobs_to_add
= hashmap_new(trivial_hash_func
, trivial_compare_func
)))
28 if (!(m
->jobs_to_remove
= set_new(trivial_hash_func
, trivial_compare_func
)))
38 void manager_free(Manager
*m
) {
43 while ((n
= hashmap_first(m
->names
)))
46 hashmap_free(m
->names
);
47 hashmap_free(m
->jobs
);
49 /* FIXME: This is incomplete */
51 hashmap_free(m
->jobs_to_add
);
52 set_free(m
->jobs_to_remove
);
57 static void transaction_abort(Manager
*m
) {
61 assert(m
->n_dependency_depth
== 0);
63 while ((j
= hashmap_steal_first(m
->jobs_to_add
)))
66 set_clear(m
->jobs_to_remove
);
69 static int transaction_activate(Manager
*m
) {
75 assert(m
->n_dependency_depth
== 0);
77 /* This applies the changes recorded in jobs_to_add and
78 * jobs_to_remove to the actual list of jobs */
80 HASHMAP_FOREACH(j
, m
->jobs_to_add
, state
) {
83 if ((r
= hashmap_put(j
->manager
->jobs
, UINT32_TO_PTR(j
->id
), j
)) < 0)
87 /* all entries are now registered, now make sure the names
90 while ((j
= hashmap_steal_first(m
->jobs_to_add
))) {
91 j
->name
->meta
.job
= j
;
95 while ((j
= set_steal_first(m
->jobs_to_remove
)))
102 HASHMAP_FOREACH(j
, m
->jobs_to_add
, state
)
103 hashmap_remove(j
->manager
->jobs
, UINT32_TO_PTR(j
->id
));
105 transaction_abort(m
);
109 int manager_add_job(Manager
*m
, JobType type
, Name
*name
, JobMode mode
, Job
**_ret
) {
116 assert(type
< _JOB_TYPE_MAX
);
118 assert(mode
< _JOB_MODE_MAX
);
120 /* Check for conflicts, first against the jobs we shall
122 if ((other
= hashmap_get(m
->jobs_to_add
, name
))) {
124 if (other
->type
!= type
)
127 } else if (name
->meta
.job
) {
129 if (name
->meta
.job
->type
!= type
) {
131 if (mode
== JOB_FAIL
)
134 if ((r
= set_put(m
->jobs_to_remove
, name
->meta
.job
)) < 0)
139 if (!(ret
= job_new(m
, type
, name
)))
142 m
->n_dependency_depth
++;
144 if ((r
= hashmap_put(m
->jobs_to_add
, name
, ret
)) < 0)
147 if (type
== JOB_START
|| type
== JOB_VERIFY_STARTED
|| type
== JOB_RESTART_FINISH
) {
148 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_REQUIRES
], state
)
149 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
151 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_SOFT_REQUIRES
], state
)
152 if ((r
= manager_add_job(m
, type
, dep
, JOB_FAIL
, NULL
)) < 0)
154 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_WANTS
], state
)
155 if ((r
= manager_add_job(m
, type
, dep
, JOB_FAIL
, NULL
)) < 0)
157 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_REQUISITE
], state
)
158 if ((r
= manager_add_job(m
, JOB_VERIFY_STARTED
, dep
, mode
, NULL
)) < 0)
160 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_SOFT_REQUISITE
], state
)
161 if ((r
= manager_add_job(m
, JOB_VERIFY_STARTED
, dep
, JOB_FAIL
, NULL
)) < 0)
163 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_CONFLICTS
], state
)
164 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
167 } else if (type
== JOB_STOP
|| type
== JOB_RESTART
|| type
== JOB_TRY_RESTART
) {
169 SET_FOREACH(dep
, ret
->name
->meta
.dependencies
[NAME_REQUIRED_BY
], state
)
170 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
174 if (--m
->n_dependency_depth
<= 0)
175 if ((r
= transaction_activate(m
)) < 0) {
176 transaction_abort(m
);
189 if (--m
->n_dependency_depth
<= 0)
190 transaction_abort(m
);
196 Job
*manager_get_job(Manager
*m
, uint32_t id
) {
199 return hashmap_get(m
->jobs
, UINT32_TO_PTR(id
));
202 Name
*manager_get_name(Manager
*m
, const char *name
) {
206 return hashmap_get(m
->names
, name
);
209 static int verify_type(Name
*name
) {
215 /* Checks that all aliases of this name have the same and valid type */
217 SET_FOREACH(n
, name
->meta
.names
, state
) {
220 if ((t
= name_type_from_string(n
)) == _NAME_TYPE_INVALID
)
223 if (name
->meta
.type
== _NAME_TYPE_INVALID
) {
228 if (name
->meta
.type
!= t
)
232 if (name
->meta
.type
== _NAME_TYPE_INVALID
)
238 static int service_load_sysv(Service
*s
) {
241 /* Load service data from SysV init scripts, preferably with
247 static int name_load_fstab(Name
*n
) {
249 assert(n
->meta
.type
== NAME_MOUNT
|| n
->meta
.type
== NAME_AUTOMOUNT
);
251 /* Load mount data from /etc/fstab */
256 static int snapshot_load(Snapshot
*s
) {
259 /* Load snapshots from disk */
264 static int name_load_dropin(Name
*n
) {
267 /* Load dependencies from drop-in directories */
272 static int load(Name
*name
) {
277 if (name
->meta
.state
!= NAME_STUB
)
280 if ((r
= verify_type(name
)) < 0)
283 if (name
->meta
.type
== NAME_SERVICE
) {
285 /* Load a .service file */
286 if ((r
= name_load_fragment(name
)) == 0)
289 /* Load a classic init script */
291 if ((r
= service_load_sysv(SERVICE(name
))) == 0)
294 } else if (name
->meta
.type
== NAME_MOUNT
||
295 name
->meta
.type
== NAME_AUTOMOUNT
) {
297 if ((r
= name_load_fstab(name
)) == 0)
300 } else if (name
->meta
.type
== NAME_SNAPSHOT
) {
302 if ((r
= snapshot_load(SNAPSHOT(name
))) == 0)
306 if ((r
= name_load_fragment(name
)) == 0)
310 name
->meta
.state
= NAME_FAILED
;
314 if ((r
= name_load_dropin(name
)) < 0)
317 if ((r
= name_link_names(name
)) < 0)
320 name
->meta
.state
= NAME_LOADED
;
324 static int dispatch_load_queue(Manager
*m
) {
329 /* Make sure we are not run recursively */
330 if (m
->dispatching_load_queue
)
333 m
->dispatching_load_queue
= true;
335 /* Dispatches the load queue. Takes a name from the queue and
336 * tries to load its data until the queue is empty */
338 while ((meta
= m
->load_queue
)) {
340 LIST_REMOVE(Meta
, m
->load_queue
, meta
);
343 m
->dispatching_load_queue
= false;
348 int manager_load_name(Manager
*m
, const char *name
, Name
**_ret
) {
358 if (!name_is_valid(name
))
361 /* This will load the service information files, but not actually
362 * start any services or anything */
364 if ((ret
= manager_get_name(m
, name
)))
367 if ((t
= name_type_from_string(name
)) == _NAME_TYPE_INVALID
)
370 if (!(ret
= name_new(m
)))
375 if (!(n
= strdup(name
))) {
380 if (set_put(ret
->meta
.names
, n
) < 0) {
386 if ((r
= name_link(ret
)) < 0) {
391 /* At this point the new entry is created and linked. However,
392 * not loaded. Now load this entry and all its dependencies
395 dispatch_load_queue(m
);
403 void manager_dump_jobs(Manager
*s
, FILE *f
) {
410 HASHMAP_FOREACH(j
, s
->jobs
, state
)
414 void manager_dump_names(Manager
*s
, FILE *f
) {
422 HASHMAP_FOREACH_KEY(n
, t
, s
->names
, state
)