]>
git.ipfire.org Git - people/ms/systemd.git/blob - manager.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
11 Manager
* manager_new(void) {
14 if (!(m
= new0(Manager
, 1)))
17 if (!(m
->names
= hashmap_new(string_hash_func
, string_compare_func
)))
20 if (!(m
->jobs
= hashmap_new(trivial_hash_func
, trivial_compare_func
)))
23 if (!(m
->jobs_to_add
= hashmap_new(trivial_hash_func
, trivial_compare_func
)))
26 if (!(m
->jobs_to_remove
= set_new(trivial_hash_func
, trivial_compare_func
)))
36 void manager_free(Manager
*m
) {
41 while ((n
= hashmap_first(m
->names
)))
44 hashmap_free(m
->names
);
45 hashmap_free(m
->jobs
);
47 /* FIXME: This is incomplete */
49 hashmap_free(m
->jobs_to_add
);
50 set_free(m
->jobs_to_remove
);
55 int manager_add_job(Manager
*m
, JobType type
, Name
*name
, JobMode mode
, Job
**_ret
) {
62 assert(type
< _JOB_TYPE_MAX
);
64 assert(mode
< _JOB_MODE_MAX
);
67 /* Check for conflicts, first against the jobs we shall
69 if ((other
= hashmap_get(m
->jobs_to_add
, name
))) {
71 if (other
->type
!= type
)
74 } else if (name
->meta
.job
) {
76 if (name
->meta
.job
->type
!= type
) {
81 if ((r
= set_put(m
->jobs_to_remove
, name
->meta
.job
)) < 0)
86 if (!(ret
= job_new(m
, type
, name
)))
89 if ((r
= hashmap_put(m
->jobs_to_add
, name
, ret
)) < 0)
92 if (type
== JOB_START
|| type
== JOB_VERIFY_STARTED
|| type
== JOB_RESTART_FINISH
) {
93 SET_FOREACH(dep
, ret
->name
->meta
.requires
, state
)
94 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
96 SET_FOREACH(dep
, ret
->name
->meta
.soft_requires
, state
)
97 if ((r
= manager_add_job(m
, type
, dep
, JOB_FAIL
, NULL
)) < 0)
99 SET_FOREACH(dep
, ret
->name
->meta
.wants
, state
)
100 if ((r
= manager_add_job(m
, type
, dep
, JOB_FAIL
, NULL
)) < 0)
102 SET_FOREACH(dep
, ret
->name
->meta
.requisite
, state
)
103 if ((r
= manager_add_job(m
, JOB_VERIFY_STARTED
, dep
, mode
, NULL
)) < 0)
105 SET_FOREACH(dep
, ret
->name
->meta
.soft_requisite
, state
)
106 if ((r
= manager_add_job(m
, JOB_VERIFY_STARTED
, dep
, JOB_FAIL
, NULL
)) < 0)
108 SET_FOREACH(dep
, ret
->name
->meta
.conflicts
, state
)
109 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
112 } else if (type
== JOB_STOP
|| type
== JOB_RESTART
|| type
== JOB_TRY_RESTART
) {
114 SET_FOREACH(dep
, ret
->name
->meta
.required_by
, state
)
115 if ((r
= manager_add_job(m
, type
, dep
, mode
, NULL
)) < 0)
131 Job
*manager_get_job(Manager
*m
, uint32_t id
) {
134 return hashmap_get(m
->jobs
, UINT32_TO_PTR(id
));
137 Name
*manager_get_name(Manager
*m
, const char *name
) {
141 return hashmap_get(m
->names
, name
);
144 static int detect_type(Name
*name
) {
149 name
->meta
.type
= _NAME_TYPE_INVALID
;
151 STRV_FOREACH(n
, name
->meta
.names
) {
154 if ((t
= name_type_from_string(*n
)) == _NAME_TYPE_INVALID
)
157 if (name
->meta
.type
== _NAME_TYPE_INVALID
) {
162 if (name
->meta
.type
!= t
)
169 static int fragment_load(Name
*n
) {
177 static int sysv_load(Service
*s
) {
185 static int fstab_load(Name
*n
) {
187 assert(n
->meta
.type
== NAME_MOUNT
|| n
->meta
.type
== NAME_AUTOMOUNT
);
194 static int snapshot_load(Snapshot
*s
) {
202 static int load(Name
*name
) {
207 if (name
->meta
.state
!= NAME_STUB
)
210 if ((r
= detect_type(name
)) < 0)
213 if (name
->meta
.type
== NAME_SERVICE
) {
215 /* Load a .service file */
216 if ((r
= fragment_load(name
)) == 0)
219 /* Load a classic init script */
221 if ((r
= sysv_load(SERVICE(name
))) == 0)
224 } else if (name
->meta
.type
== NAME_MOUNT
||
225 name
->meta
.type
== NAME_AUTOMOUNT
) {
227 if ((r
= fstab_load(name
)) == 0)
230 } else if (name
->meta
.type
== NAME_SNAPSHOT
) {
232 if ((r
= snapshot_load(SNAPSHOT(name
))) == 0)
236 if ((r
= fragment_load(name
)) == 0)
240 name
->meta
.state
= NAME_FAILED
;
244 name
->meta
.state
= NAME_LOADED
;
248 static int dispatch_load_queue(Manager
*m
) {
253 /* Dispatches the load queue. Takes a name from the queue and
254 * tries to load its data until the queue is empty */
256 while ((meta
= m
->load_queue
)) {
258 LIST_REMOVE(Meta
, m
->load_queue
, meta
);
266 int manager_load_name(Manager
*m
, const char *name
, Name
**_ret
) {
274 /* This will load the service information files, but not actually
275 * start any services or anything */
278 if ((ret
= manager_get_name(m
, name
)))
281 if ((t
= name_type_from_string(name
)) == _NAME_TYPE_INVALID
)
284 if (!(ret
= name_new(m
)))
289 if (!(ret
->meta
.names
= strv_new(name
, NULL
))) {
294 if ((r
= name_link(ret
)) < 0) {
299 /* At this point the new entry is created and linked. However,
300 * not loaded. Now load this entry and all its dependencies
303 dispatch_load_queue(m
);