Rename C++ header files to .hpp
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl-health.cpp
CommitLineData
6c71277b
MD
1/*
2 * lttng-ctl-health.c
3 *
4 * Linux Trace Toolkit Health Control Library
5 *
21cf9b6b 6 * Copyright (C) 2011 EfficiOS Inc.
6c71277b
MD
7 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
ab5be9fa 9 * SPDX-License-Identifier: LGPL-2.1-only
6c71277b 10 *
6c71277b
MD
11 */
12
6c1c0768 13#define _LGPL_SOURCE
6c71277b
MD
14#include <unistd.h>
15#include <sys/types.h>
16#include <stdint.h>
17#include <limits.h>
73d8fe3e 18#include <string.h>
c9e313bc 19#include <lttng/health-internal.hpp>
6c71277b 20
c9e313bc
SM
21#include <bin/lttng-sessiond/health-sessiond.hpp>
22#include <bin/lttng-consumerd/health-consumerd.hpp>
23#include <bin/lttng-relayd/health-relayd.hpp>
24#include <common/defaults.hpp>
25#include <common/utils.hpp>
26#include <common/compat/errno.hpp>
6c71277b 27
c9e313bc 28#include "lttng-ctl-helper.hpp"
6c71277b
MD
29
30enum health_component {
31 HEALTH_COMPONENT_SESSIOND,
32 HEALTH_COMPONENT_CONSUMERD,
33 HEALTH_COMPONENT_RELAYD,
34
35 NR_HEALTH_COMPONENT,
36};
37
38struct lttng_health_thread {
39 struct lttng_health *p;
40 int state;
41};
42
43struct lttng_health {
44 enum health_component component;
45 uint64_t state;
46 unsigned int nr_threads;
47 char health_sock_path[PATH_MAX];
48 /* For consumer health only */
49 enum lttng_health_consumerd consumerd_type;
50 struct lttng_health_thread thread[];
51};
52
53static
4bd69c5f
SM
54const char *get_sessiond_thread_name(health_type_sessiond type) {
55 switch (type)
56 {
57 case HEALTH_SESSIOND_TYPE_CMD:
58 return "Session daemon command";
59 case HEALTH_SESSIOND_TYPE_APP_MANAGE:
60 return "Session daemon application manager";
61 case HEALTH_SESSIOND_TYPE_APP_REG:
62 return "Session daemon application registration";
63 case HEALTH_SESSIOND_TYPE_KERNEL:
64 return "Session daemon kernel";
65 case HEALTH_SESSIOND_TYPE_CONSUMER:
66 return "Session daemon consumer manager";
4bd69c5f
SM
67 case HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY:
68 return "Session daemon application notification manager";
69 case HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH:
70 return "Session daemon application registration dispatcher";
71 case HEALTH_SESSIOND_TYPE_NOTIFICATION:
72 return "Session daemon notification";
73 case HEALTH_SESSIOND_TYPE_ROTATION:
74 return "Session daemon rotation manager";
75 case HEALTH_SESSIOND_TYPE_TIMER:
76 return "Session daemon timer manager";
77 case HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR:
78 return "Session daemon trigger action executor";
79 case NR_HEALTH_SESSIOND_TYPES:
80 abort();
81 }
82
83 abort();
6c71277b
MD
84};
85
86static
4bd69c5f
SM
87const char *get_consumerd_thread_name(health_type_consumerd type) {
88 switch (type) {
89 case HEALTH_CONSUMERD_TYPE_CHANNEL:
90 return "Consumer daemon channel";
91 case HEALTH_CONSUMERD_TYPE_METADATA:
92 return "Consumer daemon metadata";
93 case HEALTH_CONSUMERD_TYPE_DATA:
94 return "Consumer daemon data";
95 case HEALTH_CONSUMERD_TYPE_SESSIOND:
96 return "Consumer daemon session daemon command manager";
97 case HEALTH_CONSUMERD_TYPE_METADATA_TIMER:
98 return "Consumer daemon metadata timer";
99 case NR_HEALTH_CONSUMERD_TYPES:
100 abort();
101 }
102
103 abort();
6c71277b
MD
104};
105
106static
4bd69c5f
SM
107const char *get_relayd_thread_name(health_type_relayd type)
108{
109 switch (type) {
110 case HEALTH_RELAYD_TYPE_DISPATCHER:
111 return "Relay daemon dispatcher";
112 case HEALTH_RELAYD_TYPE_WORKER:
113 return "Relay daemon worker";
114 case HEALTH_RELAYD_TYPE_LISTENER:
115 return "Relay daemon listener";
116 case HEALTH_RELAYD_TYPE_LIVE_DISPATCHER:
117 return "Relay daemon live dispatcher";
118 case HEALTH_RELAYD_TYPE_LIVE_WORKER:
119 return "Relay daemon live worker";
120 case HEALTH_RELAYD_TYPE_LIVE_LISTENER:
121 return "Relay daemon live listener";
122 case NR_HEALTH_RELAYD_TYPES:
123 abort();
124 }
125
126 abort();
127}
6c71277b
MD
128
129static
4bd69c5f
SM
130const char *get_thread_name(int comp, int nr)
131{
132 switch (comp) {
133 case HEALTH_COMPONENT_SESSIOND:
134 return get_sessiond_thread_name((health_type_sessiond) nr);
135 case HEALTH_COMPONENT_CONSUMERD:
136 return get_consumerd_thread_name((health_type_consumerd) nr);
137 case HEALTH_COMPONENT_RELAYD:
138 return get_relayd_thread_name((health_type_relayd) nr);
139 case NR_HEALTH_COMPONENT:
140 abort();
141 }
142
143 abort();
144}
6c71277b
MD
145
146/*
147 * Set health socket path.
148 *
e1b624d0 149 * Returns 0 on success or a negative errno.
6c71277b
MD
150 */
151static
152int set_health_socket_path(struct lttng_health *lh,
153 int tracing_group)
154{
155 uid_t uid;
156 const char *home;
157 int ret;
158 /* Global and home format strings */
159 const char *global_str, *home_str;
160
161 switch (lh->component) {
162 case HEALTH_COMPONENT_SESSIOND:
163 global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
164 home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
165 break;
166 case HEALTH_COMPONENT_CONSUMERD:
167 switch (lh->consumerd_type) {
168 case LTTNG_HEALTH_CONSUMERD_UST_32:
169 global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
170 home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
171 break;
172 case LTTNG_HEALTH_CONSUMERD_UST_64:
173 global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
174 home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
175 break;
176 case LTTNG_HEALTH_CONSUMERD_KERNEL:
177 global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
178 home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
179 break;
180 default:
181 return -EINVAL;
182 }
183 break;
184 case HEALTH_COMPONENT_RELAYD:
185 if (lh->health_sock_path[0] == '\0') {
186 return -EINVAL;
187 } else {
188 return 0;
189 }
190 break; /* Unreached */
191 default:
192 return -EINVAL;
193 }
194
195 uid = getuid();
196
197 if (uid == 0 || tracing_group) {
e1b624d0 198 ret = lttng_strncpy(lh->health_sock_path,
6c71277b
MD
199 global_str,
200 sizeof(lh->health_sock_path));
e1b624d0 201 return ret == 0 ? 0 : -EINVAL;
6c71277b
MD
202 }
203
204 /*
205 * With GNU C < 2.1, snprintf returns -1 if the target buffer
206 * is too small; With GNU C >= 2.1, snprintf returns the
207 * required size (excluding closing null).
208 */
209 home = utils_get_home_dir();
210 if (home == NULL) {
211 /* Fallback in /tmp */
212 home = "/tmp";
213 }
214
411b3154
SM
215 DIAGNOSTIC_PUSH
216 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
6c71277b
MD
217 ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path),
218 home_str, home);
411b3154 219 DIAGNOSTIC_POP
6c71277b
MD
220 if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
221 return -ENOMEM;
222 }
223
224 return 0;
225}
226
227static
228struct lttng_health *lttng_health_create(enum health_component hc,
229 unsigned int nr_threads)
230{
231 struct lttng_health *lh;
232 int i;
233
4bd69c5f 234 lh = (lttng_health *) zmalloc(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
6c71277b
MD
235 if (!lh) {
236 return NULL;
237 }
238
239 lh->component = hc;
240 lh->state = UINT64_MAX; /* All bits in error initially */
241 lh->nr_threads = nr_threads;
242 for (i = 0; i < nr_threads; i++) {
243 lh->thread[i].p = lh;
244 }
245 return lh;
246}
247
248struct lttng_health *lttng_health_create_sessiond(void)
249{
250 struct lttng_health *lh;
251
252 lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND,
253 NR_HEALTH_SESSIOND_TYPES);
254 if (!lh) {
255 return NULL;
256 }
257 return lh;
258}
259
260struct lttng_health *
261 lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
262{
263 struct lttng_health *lh;
264
265 lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD,
266 NR_HEALTH_CONSUMERD_TYPES);
267 if (!lh) {
268 return NULL;
269 }
270 lh->consumerd_type = consumerd;
271 return lh;
272}
273
274struct lttng_health *lttng_health_create_relayd(const char *path)
275{
e1b624d0
JG
276 int ret;
277 struct lttng_health *lh = NULL;
6c71277b
MD
278
279 if (!path) {
e1b624d0 280 goto error;
6c71277b
MD
281 }
282
283 lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
284 NR_HEALTH_RELAYD_TYPES);
285 if (!lh) {
e1b624d0 286 goto error;
6c71277b 287 }
e1b624d0 288
336a72eb
JG
289 ret = lttng_strncpy(lh->health_sock_path, path,
290 sizeof(lh->health_sock_path));
e1b624d0
JG
291 if (ret) {
292 goto error;
293 }
294
6c71277b 295 return lh;
e1b624d0
JG
296
297error:
298 free(lh);
299 return NULL;
6c71277b
MD
300}
301
302void lttng_health_destroy(struct lttng_health *lh)
303{
304 free(lh);
305}
306
307int lttng_health_query(struct lttng_health *health)
308{
309 int sock, ret, i, tracing_group;
310 struct health_comm_msg msg;
311 struct health_comm_reply reply;
312
313 if (!health) {
314 return -EINVAL;
315 }
316
317 tracing_group = lttng_check_tracing_group();
318retry:
319 ret = set_health_socket_path(health, tracing_group);
320 if (ret) {
321 goto error;
322 }
71d01237 323 /* Connect to component */
6c71277b
MD
324 sock = lttcomm_connect_unix_sock(health->health_sock_path);
325 if (sock < 0) {
326 if (tracing_group) {
327 /* For tracing group, fallback to per-user */
328 tracing_group = 0;
329 goto retry;
330 }
331 ret = -1;
332 goto error;
333 }
334
53efb85a 335 memset(&msg, 0, sizeof(msg));
6c71277b
MD
336 msg.cmd = HEALTH_CMD_CHECK;
337
338 ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
339 if (ret < 0) {
340 ret = -1;
341 goto close_error;
342 }
343
344 ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
345 if (ret < 0) {
346 ret = -1;
347 goto close_error;
348 }
349
350 health->state = reply.ret_code;
351 for (i = 0; i < health->nr_threads; i++) {
352 if (health->state & (1ULL << i)) {
353 health->thread[i].state = -1;
354 } else {
355 health->thread[i].state = 0;
356 }
357 }
358
359close_error:
360 {
361 int closeret;
362
363 closeret = close(sock);
a0377dfe 364 LTTNG_ASSERT(!closeret);
6c71277b
MD
365 }
366
367error:
368 if (ret >= 0)
369 ret = 0;
370 return ret;
371}
372
373int lttng_health_state(const struct lttng_health *health)
374{
375 if (!health) {
376 return -EINVAL;
377 }
378
379 if (health->state == 0) {
380 return 0;
381 } else {
382 return -1;
383 }
384}
385
386int lttng_health_get_nr_threads(const struct lttng_health *health)
387{
388 if (!health) {
389 return -EINVAL;
390 }
391 return health->nr_threads;
392}
393
394const struct lttng_health_thread *
395 lttng_health_get_thread(const struct lttng_health *health,
396 unsigned int nth_thread)
397{
398 if (!health || nth_thread >= health->nr_threads) {
399 return NULL;
400 }
401 return &health->thread[nth_thread];
402}
403
404int lttng_health_thread_state(const struct lttng_health_thread *thread)
405{
406 if (!thread) {
407 return -EINVAL;
408 }
409 return thread->state;
410}
411
412const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
413{
414 unsigned int nr;
415
416 if (!thread) {
417 return NULL;
418 }
419 nr = thread - &thread->p->thread[0];
4bd69c5f 420 return get_thread_name (thread->p->component, nr);
6c71277b 421}
This page took 0.064332 seconds and 4 git commands to generate.