1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
10 #include "load-fragment.h"
12 Manager* manager_new(void) {
15 if (!(m = new0(Manager, 1)))
18 if (!(m->names = hashmap_new(string_hash_func, string_compare_func)))
21 if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
24 if (!(m->jobs_to_add = hashmap_new(trivial_hash_func, trivial_compare_func)))
27 if (!(m->jobs_to_remove = set_new(trivial_hash_func, trivial_compare_func)))
37 void manager_free(Manager *m) {
42 while ((n = hashmap_first(m->names)))
45 hashmap_free(m->names);
46 hashmap_free(m->jobs);
48 /* FIXME: This is incomplete */
50 hashmap_free(m->jobs_to_add);
51 set_free(m->jobs_to_remove);
56 int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_ret) {
63 assert(type < _JOB_TYPE_MAX);
65 assert(mode < _JOB_MODE_MAX);
68 /* Check for conflicts, first against the jobs we shall
70 if ((other = hashmap_get(m->jobs_to_add, name))) {
72 if (other->type != type)
75 } else if (name->meta.job) {
77 if (name->meta.job->type != type) {
82 if ((r = set_put(m->jobs_to_remove, name->meta.job)) < 0)
87 if (!(ret = job_new(m, type, name)))
90 if ((r = hashmap_put(m->jobs_to_add, name, ret)) < 0)
93 if (type == JOB_START || type == JOB_VERIFY_STARTED || type == JOB_RESTART_FINISH) {
94 SET_FOREACH(dep, ret->name->meta.requires, state)
95 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
97 SET_FOREACH(dep, ret->name->meta.soft_requires, state)
98 if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
100 SET_FOREACH(dep, ret->name->meta.wants, state)
101 if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
103 SET_FOREACH(dep, ret->name->meta.requisite, state)
104 if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, mode, NULL)) < 0)
106 SET_FOREACH(dep, ret->name->meta.soft_requisite, state)
107 if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, JOB_FAIL, NULL)) < 0)
109 SET_FOREACH(dep, ret->name->meta.conflicts, state)
110 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
113 } else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) {
115 SET_FOREACH(dep, ret->name->meta.required_by, state)
116 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
132 Job *manager_get_job(Manager *m, uint32_t id) {
135 return hashmap_get(m->jobs, UINT32_TO_PTR(id));
138 Name *manager_get_name(Manager *m, const char *name) {
142 return hashmap_get(m->names, name);
145 static int detect_type(Name *name) {
150 name->meta.type = _NAME_TYPE_INVALID;
152 STRV_FOREACH(n, name->meta.names) {
155 if ((t = name_type_from_string(*n)) == _NAME_TYPE_INVALID)
158 if (name->meta.type == _NAME_TYPE_INVALID) {
163 if (name->meta.type != t)
170 static int service_load_sysv(Service *s) {
173 /* Load service data from SysV init scripts, preferably with
179 static int name_load_fstab(Name *n) {
181 assert(n->meta.type == NAME_MOUNT || n->meta.type == NAME_AUTOMOUNT);
183 /* Load mount data from /etc/fstab */
188 static int snapshot_load(Snapshot *s) {
191 /* Load snapshots from disk */
196 static int name_load_dropin(Name *n) {
199 /* Load dependencies from drop-in directories */
204 static int load(Name *name) {
209 if (name->meta.state != NAME_STUB)
212 if ((r = detect_type(name)) < 0)
215 if (name->meta.type == NAME_SERVICE) {
217 /* Load a .service file */
218 if ((r = name_load_fragment(name)) == 0)
221 /* Load a classic init script */
223 if ((r = service_load_sysv(SERVICE(name))) == 0)
226 } else if (name->meta.type == NAME_MOUNT ||
227 name->meta.type == NAME_AUTOMOUNT) {
229 if ((r = name_load_fstab(name)) == 0)
232 } else if (name->meta.type == NAME_SNAPSHOT) {
234 if ((r = snapshot_load(SNAPSHOT(name))) == 0)
238 if ((r = name_load_fragment(name)) == 0)
242 name->meta.state = NAME_FAILED;
246 if ((r = name_load_dropin(name)) < 0)
249 name->meta.state = NAME_LOADED;
253 static int dispatch_load_queue(Manager *m) {
258 /* Make sure we are not run recursively */
259 if (m->dispatching_load_queue)
262 m->dispatching_load_queue = true;
264 /* Dispatches the load queue. Takes a name from the queue and
265 * tries to load its data until the queue is empty */
267 while ((meta = m->load_queue)) {
269 LIST_REMOVE(Meta, m->load_queue, meta);
272 m->dispatching_load_queue = false;
277 int manager_load_name(Manager *m, const char *name, Name **_ret) {
286 if (!name_is_valid(name))
289 /* This will load the service information files, but not actually
290 * start any services or anything */
292 if ((ret = manager_get_name(m, name)))
295 if ((t = name_type_from_string(name)) == _NAME_TYPE_INVALID)
298 if (!(ret = name_new(m)))
303 if (!(ret->meta.names = strv_new(name, NULL))) {
308 if ((r = name_link(ret)) < 0) {
313 /* At this point the new entry is created and linked. However,
314 * not loaded. Now load this entry and all its dependencies
317 dispatch_load_queue(m);