1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
11 NameType name_type_from_string(const char *n) {
13 static const char* suffixes[_NAME_TYPE_MAX] = {
14 [NAME_SERVICE] = ".service",
15 [NAME_TIMER] = ".timer",
16 [NAME_SOCKET] = ".socket",
17 [NAME_MILESTONE] = ".milestone",
18 [NAME_DEVICE] = ".device",
19 [NAME_MOUNT] = ".mount",
20 [NAME_AUTOMOUNT] = ".automount",
21 [NAME_SNAPSHOT] = ".snapshot",
26 for (t = 0; t < _NAME_TYPE_MAX; t++)
27 if (endswith(n, suffixes[t]))
30 return _NAME_TYPE_INVALID;
33 Name *name_new(Manager *m) {
38 if (!(n = new0(Name, 1)))
41 /* Not much initialization happening here at this time */
43 n->meta.type = _NAME_TYPE_INVALID;
44 n->meta.state = NAME_STUB;
46 /* We don't link the name here, that is left for name_link() */
51 int name_link(Name *n) {
56 assert(!n->meta.linked);
58 STRV_FOREACH(t, n->meta.names)
59 if ((r = hashmap_put(n->meta.manager->names, *t, n)) < 0)
62 if (n->meta.state == NAME_STUB)
63 LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
65 n->meta.linked = true;
71 STRV_FOREACH_BACKWARDS(t, n->meta.names)
72 hashmap_remove(n->meta.manager->names, *t);
77 void name_free(Name *name) {
81 /* Detach from next 'bigger' objects */
83 if (name->meta.linked) {
86 STRV_FOREACH(t, name->meta.names)
87 hashmap_remove(name->meta.manager->names, *t);
90 job_free(name->meta.job);
93 /* Free data and next 'smaller' objects */
96 job_free(name->meta.job);
98 /* FIXME: Other names pointing to us should probably drop their refs to us when we get destructed */
99 set_free(name->meta.requires);
100 set_free(name->meta.soft_requires);
101 set_free(name->meta.wants);
102 set_free(name->meta.requisite);
103 set_free(name->meta.soft_requires);
104 set_free(name->meta.conflicts);
105 set_free(name->meta.before);
106 set_free(name->meta.after);
108 switch (name->meta.type) {
112 Socket *s = SOCKET(name);
114 for (i = 0; i < s->n_fds; i++)
115 nointr_close(s->fds[i]);
120 Device *d = DEVICE(name);
127 Mount *m = MOUNT(name);
133 case NAME_AUTOMOUNT: {
134 Automount *a = AUTOMOUNT(name);
144 free(name->meta.description);
145 strv_free(name->meta.names);
150 bool name_is_ready(Name *name) {
154 if (name->meta.state != NAME_LOADED)
157 assert(name->meta.type < _NAME_TYPE_MAX);
159 switch (name->meta.type) {
161 Service *s = SERVICE(name);
164 s->state == SERVICE_RUNNING ||
165 s->state == SERVICE_RELOAD_PRE ||
166 s->state == SERVICE_RELOAD ||
167 s->state == SERVICE_RELOAD_POST;
171 Timer *t = TIMER(name);
174 t->state == TIMER_WAITING ||
175 t->state == TIMER_RUNNING;
179 Socket *s = SOCKET(name);
182 s->state == SOCKET_LISTENING ||
183 s->state == SOCKET_RUNNING;
187 return MILESTONE(name)->state == MILESTONE_ACTIVE;
190 return DEVICE(name)->state == DEVICE_AVAILABLE;
193 return MOUNT(name)->state == MOUNT_MOUNTED;
195 case NAME_AUTOMOUNT: {
196 Automount *a = AUTOMOUNT(name);
199 a->state == AUTOMOUNT_WAITING ||
200 a->state == AUTOMOUNT_RUNNING;
204 return SNAPSHOT(name)->state == SNAPSHOT_ACTIVE;
208 case _NAME_TYPE_INVALID:
212 assert_not_reached("Unknown name type.");
216 static int ensure_in_set(Set **s, void *data) {
223 if (!(*s = set_new(trivial_hash_func, trivial_compare_func)))
226 if ((r = set_put(*s, data) < 0))
233 int name_augment(Name *n) {
240 /* Adds in the missing links to make all dependencies both-ways */
242 SET_FOREACH(other, n->meta.before, state)
243 if ((r = ensure_in_set(&other->meta.after, n) < 0))
245 SET_FOREACH(other, n->meta.after, state)
246 if ((r = ensure_in_set(&other->meta.before, n) < 0))
249 SET_FOREACH(other, n->meta.conflicts, state)
250 if ((r = ensure_in_set(&other->meta.conflicts, n) < 0))
253 SET_FOREACH(other, n->meta.requires, state)
254 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
256 SET_FOREACH(other, n->meta.soft_requires, state)
257 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
259 SET_FOREACH(other, n->meta.requisite, state)
260 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
262 SET_FOREACH(other, n->meta.soft_requisite, state)
263 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))