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