chiark / gitweb /
bbb821489518449da20992bb8e4863a474084f91
[elogind.git] / job.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 #include <assert.h>
4
5 #include "macro.h"
6 #include "job.h"
7
8 Job* job_new(Manager *m, JobType type, Name *name) {
9         Job *j;
10
11         assert(m);
12         assert(type < _JOB_TYPE_MAX);
13         assert(name);
14
15         if (!(j = new0(Job, 1)))
16                 return NULL;
17
18         j->manager = m;
19         j->id = m->current_job_id++;
20         j->type = type;
21         j->name = name;
22
23         /* We don't link it here, that's what job_dependency() is for */
24
25         return j;
26 }
27
28 void job_free(Job *j) {
29         assert(j);
30
31         /* Detach from next 'bigger' objects */
32
33         if (j->linked) {
34                 if (j->name->meta.job == j)
35                         j->name->meta.job = NULL;
36
37                 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
38         }
39
40         manager_transaction_unlink_job(j->manager, j);
41
42         free(j);
43 }
44
45 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters) {
46         JobDependency *l;
47
48         assert(object);
49
50         /* Adds a new job link, which encodes that the 'subject' job
51          * needs the 'object' job in some way. If 'subject' is NULL
52          * this means the 'anchor' job (i.e. the one the user
53          * explcitily asked for) is the requester. */
54
55         if (!(l = new0(JobDependency, 1)))
56                 return NULL;
57
58         l->subject = subject;
59         l->object = object;
60         l->matters = matters;
61
62         if (subject) {
63                 l->subject_next = subject->subject_list;
64                 subject->subject_list = l;
65         } else {
66                 l->subject_next = object->manager->transaction_anchor;
67                 object->manager->transaction_anchor = l;
68         }
69
70         if (l->subject_next)
71                 l->subject_next->subject_prev = l;
72         l->subject_prev = NULL;
73
74         if ((l->object_next = object->object_list))
75                 l->object_next->object_prev = l;
76         l->object_prev = NULL;
77         object->object_list = l;
78
79         return l;
80 }
81
82 void job_dependency_free(JobDependency *l) {
83         assert(l);
84
85         if (l->subject_prev)
86                 l->subject_prev->subject_next = l->subject_next;
87         else if (l->subject)
88                 l->subject->subject_list = l->subject_next;
89         else
90                 l->object->manager->transaction_anchor = l->subject_next;
91
92         if (l->subject_next)
93                 l->subject_next->subject_prev = l->subject_prev;
94
95         if (l->object_prev)
96                 l->object_prev->object_next = l->object_next;
97         else
98                 l->object->object_list = l->object_next;
99
100         if (l->object_next)
101                 l->object_next->object_prev = l->object_prev;
102
103         free(l);
104 }
105
106 void job_dependency_delete(Job *subject, Job *object, bool *matters) {
107         JobDependency *l;
108
109         assert(object);
110
111         for (l = object->object_list; l; l = l->object_next) {
112                 assert(l->object == object);
113
114                 if (l->subject == subject)
115                         break;
116         }
117
118         if (!l) {
119                 if (matters)
120                         *matters = false;
121                 return;
122         }
123
124         if (matters)
125                 *matters = l->matters;
126
127         job_dependency_free(l);
128 }
129
130 void job_dump(Job *j, FILE*f, const char *prefix) {
131
132         static const char* const job_type_table[_JOB_TYPE_MAX] = {
133                 [JOB_START] = "start",
134                 [JOB_STOP] = "stop",
135                 [JOB_VERIFY_STARTED] = "verify-started",
136                 [JOB_RELOAD] = "reload",
137                 [JOB_RELOAD_OR_START] = "reload-or-start",
138                 [JOB_RESTART] = "restart",
139                 [JOB_TRY_RESTART] = "try-restart",
140         };
141
142         static const char* const job_state_table[_JOB_STATE_MAX] = {
143                 [JOB_WAITING] = "waiting",
144                 [JOB_RUNNING] = "running",
145                 [JOB_DONE] = "done"
146         };
147
148         assert(j);
149         assert(f);
150
151         fprintf(f,
152                 "%sJob %u:\n"
153                 "%s\tAction: %s → %s\n"
154                 "%s\tState: %s\n",
155                 prefix, j->id,
156                 prefix, name_id(j->name), job_type_table[j->type],
157                 prefix, job_state_table[j->state]);
158 }
159
160 bool job_is_anchor(Job *j) {
161         JobDependency *l;
162
163         assert(j);
164
165         for (l = j->object_list; l; l = l->object_next)
166                 if (!l->subject)
167                         return true;
168
169         return false;
170 }