Directory: | src/ |
---|---|
File: | src/worker.c |
Date: | 2024-04-25 03:45:42 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 106 | 151 | 70.2% |
Branches: | 27 | 62 | 43.5% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2022 Egor Tensin <egor@tensin.name> | ||
3 | * This file is part of the "cimple" project. | ||
4 | * For details, see https://github.com/egor-tensin/cimple. | ||
5 | * Distributed under the MIT License. | ||
6 | */ | ||
7 | |||
8 | #include "worker.h" | ||
9 | #include "ci.h" | ||
10 | #include "command.h" | ||
11 | #include "compiler.h" | ||
12 | #include "const.h" | ||
13 | #include "event_loop.h" | ||
14 | #include "git.h" | ||
15 | #include "log.h" | ||
16 | #include "net.h" | ||
17 | #include "process.h" | ||
18 | #include "protocol.h" | ||
19 | #include "run_queue.h" | ||
20 | #include "signal.h" | ||
21 | |||
22 | #include <poll.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | struct worker { | ||
27 | struct settings *settings; | ||
28 | |||
29 | int stopping; | ||
30 | |||
31 | struct cmd_dispatcher *cmd_dispatcher; | ||
32 | |||
33 | struct event_loop *event_loop; | ||
34 | int signalfd; | ||
35 | |||
36 | struct run *run; | ||
37 | }; | ||
38 | |||
39 | 54 | static struct settings *worker_settings_copy(const struct settings *src) | |
40 | { | ||
41 | 54 | struct settings *result = malloc(sizeof(*src)); | |
42 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!result) { |
43 | ✗ | log_errno("malloc"); | |
44 | ✗ | return NULL; | |
45 | } | ||
46 | |||
47 | 54 | result->host = strdup(src->host); | |
48 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!result->host) { |
49 | ✗ | log_errno("strdup"); | |
50 | ✗ | goto free_result; | |
51 | } | ||
52 | |||
53 | 54 | result->port = strdup(src->port); | |
54 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!result->port) { |
55 | ✗ | log_errno("strdup"); | |
56 | ✗ | goto free_host; | |
57 | } | ||
58 | |||
59 | 54 | return result; | |
60 | |||
61 | ✗ | free_host: | |
62 | ✗ | free((void *)result->host); | |
63 | |||
64 | ✗ | free_result: | |
65 | ✗ | free(result); | |
66 | |||
67 | ✗ | return NULL; | |
68 | } | ||
69 | |||
70 | 54 | static void worker_settings_destroy(struct settings *settings) | |
71 | { | ||
72 | 54 | free((void *)settings->port); | |
73 | 54 | free((void *)settings->host); | |
74 | 54 | free(settings); | |
75 | 54 | } | |
76 | |||
77 | 54 | static int worker_set_stopping(UNUSED struct event_loop *loop, UNUSED int fd, UNUSED short revents, | |
78 | void *_worker) | ||
79 | { | ||
80 | 54 | struct worker *worker = (struct worker *)_worker; | |
81 | 54 | worker->stopping = 1; | |
82 | 54 | return 0; | |
83 | } | ||
84 | |||
85 | 9180 | static int worker_handle_cmd_start_run(const struct jsonrpc_request *request, | |
86 | UNUSED struct jsonrpc_response **response, void *_ctx) | ||
87 | { | ||
88 | 9180 | struct cmd_conn_ctx *ctx = (struct cmd_conn_ctx *)_ctx; | |
89 | 9180 | struct worker *worker = (struct worker *)ctx->arg; | |
90 | 9180 | int ret = 0; | |
91 | |||
92 | 9180 | ret = request_parse_start_run(request, &worker->run); | |
93 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) |
94 | ✗ | return ret; | |
95 | |||
96 | 9180 | return ret; | |
97 | } | ||
98 | |||
99 | static struct cmd_desc commands[] = { | ||
100 | {CMD_START_RUN, worker_handle_cmd_start_run}, | ||
101 | }; | ||
102 | |||
103 | static const size_t numof_commands = sizeof(commands) / sizeof(commands[0]); | ||
104 | |||
105 | 54 | int worker_create(struct worker **_worker, const struct settings *settings) | |
106 | { | ||
107 | 54 | int ret = 0; | |
108 | |||
109 | 54 | struct worker *worker = malloc(sizeof(struct worker)); | |
110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!worker) { |
111 | ✗ | log_errno("malloc"); | |
112 | ✗ | return -1; | |
113 | } | ||
114 | |||
115 | 54 | worker->settings = worker_settings_copy(settings); | |
116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!worker->settings) { |
117 | ✗ | ret = -1; | |
118 | ✗ | goto free; | |
119 | } | ||
120 | |||
121 | 54 | worker->stopping = 0; | |
122 | |||
123 | 54 | ret = cmd_dispatcher_create(&worker->cmd_dispatcher, commands, numof_commands, worker); | |
124 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
125 | ✗ | goto free_settings; | |
126 | |||
127 | 54 | ret = event_loop_create(&worker->event_loop); | |
128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
129 | ✗ | goto destroy_cmd_dispatcher; | |
130 | |||
131 | 54 | ret = signalfd_create_sigterms(); | |
132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
133 | ✗ | goto destroy_event_loop; | |
134 | 54 | worker->signalfd = ret; | |
135 | |||
136 | 54 | ret = event_loop_add(worker->event_loop, worker->signalfd, POLLIN, worker_set_stopping, | |
137 | worker); | ||
138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
139 | ✗ | goto close_signalfd; | |
140 | |||
141 | 54 | ret = libgit_init(); | |
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
143 | ✗ | goto close_signalfd; | |
144 | |||
145 | 54 | *_worker = worker; | |
146 | 54 | return ret; | |
147 | |||
148 | ✗ | close_signalfd: | |
149 | ✗ | signalfd_destroy(worker->signalfd); | |
150 | |||
151 | ✗ | destroy_event_loop: | |
152 | ✗ | event_loop_destroy(worker->event_loop); | |
153 | |||
154 | ✗ | destroy_cmd_dispatcher: | |
155 | ✗ | cmd_dispatcher_destroy(worker->cmd_dispatcher); | |
156 | |||
157 | ✗ | free_settings: | |
158 | ✗ | worker_settings_destroy(worker->settings); | |
159 | |||
160 | ✗ | free: | |
161 | ✗ | free(worker); | |
162 | |||
163 | ✗ | return ret; | |
164 | } | ||
165 | |||
166 | 54 | void worker_destroy(struct worker *worker) | |
167 | { | ||
168 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
|
54 | log("Shutting down\n"); |
169 | |||
170 | 54 | libgit_shutdown(); | |
171 | 54 | signalfd_destroy(worker->signalfd); | |
172 | 54 | event_loop_destroy(worker->event_loop); | |
173 | 54 | cmd_dispatcher_destroy(worker->cmd_dispatcher); | |
174 | 54 | worker_settings_destroy(worker->settings); | |
175 | 54 | free(worker); | |
176 | 54 | } | |
177 | |||
178 | 9180 | static int worker_do_run(struct worker *worker) | |
179 | { | ||
180 | 9180 | int ret = 0; | |
181 | |||
182 | 9180 | struct proc_output *result = NULL; | |
183 | 9180 | ret = proc_output_create(&result); | |
184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) |
185 | ✗ | return ret; | |
186 | |||
187 | 9180 | ret = ci_run_git_repo(run_get_repo_url(worker->run), run_get_repo_rev(worker->run), result); | |
188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) { |
189 | ✗ | log_err("Run failed with an error\n"); | |
190 | ✗ | goto free_output; | |
191 | } | ||
192 | |||
193 | 9180 | proc_output_dump(result); | |
194 | |||
195 | 9180 | struct jsonrpc_request *finished_request = NULL; | |
196 | |||
197 | 9180 | ret = request_create_finished_run(&finished_request, run_get_id(worker->run), result); | |
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) |
199 | ✗ | goto free_output; | |
200 | |||
201 | 9180 | ret = net_connect(worker->settings->host, worker->settings->port); | |
202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) |
203 | ✗ | goto free_request; | |
204 | 9180 | int fd = ret; | |
205 | |||
206 | 9180 | ret = jsonrpc_request_send(finished_request, fd); | |
207 |
1/2✓ Branch 0 taken 9180 times.
✗ Branch 1 not taken.
|
9180 | if (ret < 0) |
208 | ✗ | goto close_conn; | |
209 | |||
210 | 9180 | close_conn: | |
211 | 9180 | net_close(fd); | |
212 | |||
213 | 9180 | free_request: | |
214 | 9180 | jsonrpc_request_destroy(finished_request); | |
215 | |||
216 | 9180 | free_output: | |
217 | 9180 | proc_output_destroy(result); | |
218 | |||
219 | 9180 | run_destroy(worker->run); | |
220 | |||
221 | 9180 | return ret; | |
222 | } | ||
223 | |||
224 | 9234 | static int worker_get_run(struct worker *worker) | |
225 | { | ||
226 | 9234 | int ret = 0, fd = -1; | |
227 | |||
228 | 9234 | ret = net_connect(worker->settings->host, worker->settings->port); | |
229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) |
230 | ✗ | return ret; | |
231 | 9234 | fd = ret; | |
232 | |||
233 | 9234 | struct jsonrpc_request *new_worker_request = NULL; | |
234 | 9234 | ret = request_create_new_worker(&new_worker_request); | |
235 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) |
236 | ✗ | goto close; | |
237 | |||
238 | 9234 | ret = jsonrpc_request_send(new_worker_request, fd); | |
239 | 9234 | jsonrpc_request_destroy(new_worker_request); | |
240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) |
241 | ✗ | goto close; | |
242 | |||
243 | 9234 | ret = event_loop_add_once(worker->event_loop, fd, POLLIN, cmd_dispatcher_handle_event, | |
244 | 9234 | worker->cmd_dispatcher); | |
245 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) |
246 | ✗ | goto close; | |
247 | |||
248 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9234 times.
|
9234 | log("Waiting for a new command\n"); |
249 | |||
250 | 9234 | ret = event_loop_run(worker->event_loop); | |
251 |
1/2✓ Branch 0 taken 9234 times.
✗ Branch 1 not taken.
|
9234 | if (ret < 0) |
252 | ✗ | goto close; | |
253 | |||
254 | 9234 | close: | |
255 | 9234 | net_close(fd); | |
256 | |||
257 | 9234 | return ret; | |
258 | } | ||
259 | |||
260 | 54 | int worker_main(struct worker *worker) | |
261 | { | ||
262 | 54 | int ret = 0; | |
263 | |||
264 | while (1) { | ||
265 | 9234 | ret = worker_get_run(worker); | |
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) |
267 | ✗ | return ret; | |
268 | |||
269 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 9180 times.
|
9234 | if (worker->stopping) |
270 | 54 | break; | |
271 | |||
272 | 9180 | ret = worker_do_run(worker); | |
273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (ret < 0) |
274 | ✗ | return ret; | |
275 | } | ||
276 | |||
277 | 54 | return ret; | |
278 | } | ||
279 |