]> git.ipfire.org Git - people/ms/systemd.git/blame - manager.c
add missing newlines
[people/ms/systemd.git] / manager.c
CommitLineData
60918275
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3#include <assert.h>
4#include <errno.h>
87d1515d 5#include <string.h>
60918275
LP
6
7#include "manager.h"
8#include "hashmap.h"
9#include "macro.h"
10#include "strv.h"
223dabab 11#include "load-fragment.h"
60918275
LP
12
13Manager* manager_new(void) {
14 Manager *m;
15
16 if (!(m = new0(Manager, 1)))
17 return NULL;
18
19 if (!(m->names = hashmap_new(string_hash_func, string_compare_func)))
20 goto fail;
21
22 if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
23 goto fail;
24
25 if (!(m->jobs_to_add = hashmap_new(trivial_hash_func, trivial_compare_func)))
26 goto fail;
27
28 if (!(m->jobs_to_remove = set_new(trivial_hash_func, trivial_compare_func)))
29 goto fail;
30
31 return m;
32
33fail:
34 manager_free(m);
35 return NULL;
36}
37
38void manager_free(Manager *m) {
39 Name *n;
40
41 assert(m);
42
43 while ((n = hashmap_first(m->names)))
44 name_free(n);
45
46 hashmap_free(m->names);
47 hashmap_free(m->jobs);
48
49 /* FIXME: This is incomplete */
50
51 hashmap_free(m->jobs_to_add);
52 set_free(m->jobs_to_remove);
53
54 free(m);
55}
56
57int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_ret) {
58 Job *ret, *other;
59 void *state;
60 Name *dep;
61 int r;
62
63 assert(m);
64 assert(type < _JOB_TYPE_MAX);
65 assert(name);
66 assert(mode < _JOB_MODE_MAX);
67 assert(_ret);
68
69 /* Check for conflicts, first against the jobs we shall
70 * create */
71 if ((other = hashmap_get(m->jobs_to_add, name))) {
72
73 if (other->type != type)
74 return -EEXIST;
75
76 } else if (name->meta.job) {
77
78 if (name->meta.job->type != type) {
79
80 if (mode == JOB_FAIL)
81 return -EEXIST;
82
83 if ((r = set_put(m->jobs_to_remove, name->meta.job)) < 0)
84 return r;
85 }
86 }
87
88 if (!(ret = job_new(m, type, name)))
89 return -ENOMEM;
90
91 if ((r = hashmap_put(m->jobs_to_add, name, ret)) < 0)
92 goto fail;
93
94 if (type == JOB_START || type == JOB_VERIFY_STARTED || type == JOB_RESTART_FINISH) {
87d1515d 95 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRES], state)
60918275
LP
96 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
97 goto fail;
87d1515d 98 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUIRES], state)
60918275
LP
99 if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
100 goto fail;
87d1515d 101 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_WANTS], state)
60918275
LP
102 if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
103 goto fail;
87d1515d 104 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUISITE], state)
60918275
LP
105 if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, mode, NULL)) < 0)
106 goto fail;
87d1515d 107 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUISITE], state)
60918275
LP
108 if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, JOB_FAIL, NULL)) < 0)
109 goto fail;
87d1515d 110 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_CONFLICTS], state)
60918275
LP
111 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
112 goto fail;
113
114 } else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) {
115
87d1515d 116 SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRED_BY], state)
60918275
LP
117 if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
118 goto fail;
119 }
120
121 if (_ret)
122 *_ret = ret;
123
124 return 0;
125
126fail:
127 job_free(ret);
128
129 return r;
130}
131
132
133Job *manager_get_job(Manager *m, uint32_t id) {
134 assert(m);
135
136 return hashmap_get(m->jobs, UINT32_TO_PTR(id));
137}
138
139Name *manager_get_name(Manager *m, const char *name) {
140 assert(m);
141 assert(name);
142
143 return hashmap_get(m->names, name);
144}
145
87d1515d
LP
146static int verify_type(Name *name) {
147 char *n;
148 void *state;
60918275
LP
149
150 assert(name);
151
87d1515d 152 /* Checks that all aliases of this name have the same and valid type */
60918275 153
87d1515d 154 SET_FOREACH(n, name->meta.names, state) {
60918275
LP
155 NameType t;
156
87d1515d 157 if ((t = name_type_from_string(n)) == _NAME_TYPE_INVALID)
60918275
LP
158 return -EINVAL;
159
160 if (name->meta.type == _NAME_TYPE_INVALID) {
161 name->meta.type = t;
162 continue;
163 }
164
165 if (name->meta.type != t)
166 return -EINVAL;
167 }
168
87d1515d
LP
169 if (name->meta.type == _NAME_TYPE_INVALID)
170 return -EINVAL;
171
60918275
LP
172 return 0;
173}
174
223dabab 175static int service_load_sysv(Service *s) {
60918275
LP
176 assert(s);
177
223dabab
LP
178 /* Load service data from SysV init scripts, preferably with
179 * LSB headers ... */
60918275
LP
180
181 return 0;
182}
183
223dabab 184static int name_load_fstab(Name *n) {
60918275
LP
185 assert(n);
186 assert(n->meta.type == NAME_MOUNT || n->meta.type == NAME_AUTOMOUNT);
187
223dabab 188 /* Load mount data from /etc/fstab */
60918275
LP
189
190 return 0;
191}
192
193static int snapshot_load(Snapshot *s) {
194 assert(s);
195
223dabab
LP
196 /* Load snapshots from disk */
197
198 return 0;
199}
200
201static int name_load_dropin(Name *n) {
202 assert(n);
203
204 /* Load dependencies from drop-in directories */
60918275
LP
205
206 return 0;
207}
208
209static int load(Name *name) {
210 int r;
211
212 assert(name);
213
214 if (name->meta.state != NAME_STUB)
215 return 0;
216
87d1515d 217 if ((r = verify_type(name)) < 0)
60918275
LP
218 return r;
219
220 if (name->meta.type == NAME_SERVICE) {
221
222 /* Load a .service file */
223dabab 223 if ((r = name_load_fragment(name)) == 0)
60918275
LP
224 goto finish;
225
226 /* Load a classic init script */
227 if (r == -ENOENT)
223dabab 228 if ((r = service_load_sysv(SERVICE(name))) == 0)
60918275
LP
229 goto finish;
230
231 } else if (name->meta.type == NAME_MOUNT ||
232 name->meta.type == NAME_AUTOMOUNT) {
233
223dabab 234 if ((r = name_load_fstab(name)) == 0)
60918275
LP
235 goto finish;
236
237 } else if (name->meta.type == NAME_SNAPSHOT) {
238
239 if ((r = snapshot_load(SNAPSHOT(name))) == 0)
240 goto finish;
241
242 } else {
223dabab 243 if ((r = name_load_fragment(name)) == 0)
60918275
LP
244 goto finish;
245 }
246
247 name->meta.state = NAME_FAILED;
248 return r;
249
250finish:
223dabab
LP
251 if ((r = name_load_dropin(name)) < 0)
252 return r;
253
60918275
LP
254 name->meta.state = NAME_LOADED;
255 return 0;
256}
257
258static int dispatch_load_queue(Manager *m) {
259 Meta *meta;
260
261 assert(m);
262
223dabab
LP
263 /* Make sure we are not run recursively */
264 if (m->dispatching_load_queue)
265 return 0;
266
267 m->dispatching_load_queue = true;
268
60918275
LP
269 /* Dispatches the load queue. Takes a name from the queue and
270 * tries to load its data until the queue is empty */
271
272 while ((meta = m->load_queue)) {
273 load(NAME(meta));
274 LIST_REMOVE(Meta, m->load_queue, meta);
275 }
276
223dabab
LP
277 m->dispatching_load_queue = false;
278
60918275
LP
279 return 0;
280}
281
60918275
LP
282int manager_load_name(Manager *m, const char *name, Name **_ret) {
283 Name *ret;
284 NameType t;
285 int r;
87d1515d 286 char *n;
60918275
LP
287
288 assert(m);
289 assert(name);
290 assert(_ret);
60918275 291
223dabab
LP
292 if (!name_is_valid(name))
293 return -EINVAL;
294
295 /* This will load the service information files, but not actually
296 * start any services or anything */
60918275
LP
297
298 if ((ret = manager_get_name(m, name)))
299 goto finish;
300
301 if ((t = name_type_from_string(name)) == _NAME_TYPE_INVALID)
302 return -EINVAL;
303
304 if (!(ret = name_new(m)))
305 return -ENOMEM;
306
307 ret->meta.type = t;
308
87d1515d
LP
309 if (!(n = strdup(name))) {
310 name_free(ret);
311 return -ENOMEM;
312 }
313
314 if (set_put(ret->meta.names, n) < 0) {
60918275 315 name_free(ret);
87d1515d 316 free(n);
60918275
LP
317 return -ENOMEM;
318 }
319
320 if ((r = name_link(ret)) < 0) {
321 name_free(ret);
322 return r;
323 }
324
325 /* At this point the new entry is created and linked. However,
326 * not loaded. Now load this entry and all its dependencies
327 * recursively */
328
329 dispatch_load_queue(m);
330
331finish:
332
333 *_ret = ret;
334 return 0;
335}