lttng-ctl: health: remove unreachable condition
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl-health.c
CommitLineData
6c71277b
MD
1/*
2 * lttng-ctl-health.c
3 *
4 * Linux Trace Toolkit Health Control Library
5 *
6 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
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>
6c71277b
MD
19#include <lttng/health-internal.h>
20
21#include <bin/lttng-sessiond/health-sessiond.h>
22#include <bin/lttng-consumerd/health-consumerd.h>
23#include <bin/lttng-relayd/health-relayd.h>
24#include <common/defaults.h>
25#include <common/utils.h>
edf4b93e 26#include <common/compat/errno.h>
6c71277b
MD
27
28#include "lttng-ctl-helper.h"
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
54const char *sessiond_thread_name[NR_HEALTH_SESSIOND_TYPES] = {
55 [ HEALTH_SESSIOND_TYPE_CMD ] = "Session daemon command",
56 [ HEALTH_SESSIOND_TYPE_APP_MANAGE ] = "Session daemon application manager",
57 [ HEALTH_SESSIOND_TYPE_APP_REG ] = "Session daemon application registration",
58 [ HEALTH_SESSIOND_TYPE_KERNEL ] = "Session daemon kernel",
59 [ HEALTH_SESSIOND_TYPE_CONSUMER ] = "Session daemon consumer manager",
60 [ HEALTH_SESSIOND_TYPE_HT_CLEANUP ] = "Session daemon hash table cleanup",
61 [ HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY ] = "Session daemon application notification manager",
62 [ HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH ] = "Session daemon application registration dispatcher",
db66e574 63 [ HEALTH_SESSIOND_TYPE_ROTATION ] = "Session daemon rotation manager",
d086f507 64 [ HEALTH_SESSIOND_TYPE_TIMER ] = "Session daemon timer manager",
f2b3ef9f 65 [ HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR ] = "Session daemon trigger action executor",
6c71277b
MD
66};
67
68static
69const char *consumerd_thread_name[NR_HEALTH_CONSUMERD_TYPES] = {
70 [ HEALTH_CONSUMERD_TYPE_CHANNEL ] = "Consumer daemon channel",
71 [ HEALTH_CONSUMERD_TYPE_METADATA ] = "Consumer daemon metadata",
72 [ HEALTH_CONSUMERD_TYPE_DATA ] = "Consumer daemon data",
73 [ HEALTH_CONSUMERD_TYPE_SESSIOND ] = "Consumer daemon session daemon command manager",
74 [ HEALTH_CONSUMERD_TYPE_METADATA_TIMER ] = "Consumer daemon metadata timer",
75};
76
77static
78const char *relayd_thread_name[NR_HEALTH_RELAYD_TYPES] = {
79 [ HEALTH_RELAYD_TYPE_DISPATCHER ] = "Relay daemon dispatcher",
80 [ HEALTH_RELAYD_TYPE_WORKER ] = "Relay daemon worker",
81 [ HEALTH_RELAYD_TYPE_LISTENER ] = "Relay daemon listener",
e7b0d526
MD
82 [ HEALTH_RELAYD_TYPE_LIVE_DISPATCHER ] = "Relay daemon live dispatcher",
83 [ HEALTH_RELAYD_TYPE_LIVE_WORKER ] = "Relay daemon live worker",
84 [ HEALTH_RELAYD_TYPE_LIVE_LISTENER ] = "Relay daemon live listener",
6c71277b
MD
85};
86
87static
88const char **thread_name[NR_HEALTH_COMPONENT] = {
89 [ HEALTH_COMPONENT_SESSIOND ] = sessiond_thread_name,
90 [ HEALTH_COMPONENT_CONSUMERD] = consumerd_thread_name,
91 [ HEALTH_COMPONENT_RELAYD ] = relayd_thread_name,
92};
93
94/*
95 * Set health socket path.
96 *
e1b624d0 97 * Returns 0 on success or a negative errno.
6c71277b
MD
98 */
99static
100int set_health_socket_path(struct lttng_health *lh,
101 int tracing_group)
102{
103 uid_t uid;
104 const char *home;
105 int ret;
106 /* Global and home format strings */
107 const char *global_str, *home_str;
108
109 switch (lh->component) {
110 case HEALTH_COMPONENT_SESSIOND:
111 global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
112 home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
113 break;
114 case HEALTH_COMPONENT_CONSUMERD:
115 switch (lh->consumerd_type) {
116 case LTTNG_HEALTH_CONSUMERD_UST_32:
117 global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
118 home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
119 break;
120 case LTTNG_HEALTH_CONSUMERD_UST_64:
121 global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
122 home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
123 break;
124 case LTTNG_HEALTH_CONSUMERD_KERNEL:
125 global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
126 home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
127 break;
128 default:
129 return -EINVAL;
130 }
131 break;
132 case HEALTH_COMPONENT_RELAYD:
133 if (lh->health_sock_path[0] == '\0') {
134 return -EINVAL;
135 } else {
136 return 0;
137 }
138 break; /* Unreached */
139 default:
140 return -EINVAL;
141 }
142
143 uid = getuid();
144
145 if (uid == 0 || tracing_group) {
e1b624d0 146 ret = lttng_strncpy(lh->health_sock_path,
6c71277b
MD
147 global_str,
148 sizeof(lh->health_sock_path));
e1b624d0 149 return ret == 0 ? 0 : -EINVAL;
6c71277b
MD
150 }
151
152 /*
153 * With GNU C < 2.1, snprintf returns -1 if the target buffer
154 * is too small; With GNU C >= 2.1, snprintf returns the
155 * required size (excluding closing null).
156 */
157 home = utils_get_home_dir();
158 if (home == NULL) {
159 /* Fallback in /tmp */
160 home = "/tmp";
161 }
162
163 ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path),
164 home_str, home);
165 if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
166 return -ENOMEM;
167 }
168
169 return 0;
170}
171
172static
173struct lttng_health *lttng_health_create(enum health_component hc,
174 unsigned int nr_threads)
175{
176 struct lttng_health *lh;
177 int i;
178
179 lh = zmalloc(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
180 if (!lh) {
181 return NULL;
182 }
183
184 lh->component = hc;
185 lh->state = UINT64_MAX; /* All bits in error initially */
186 lh->nr_threads = nr_threads;
187 for (i = 0; i < nr_threads; i++) {
188 lh->thread[i].p = lh;
189 }
190 return lh;
191}
192
193struct lttng_health *lttng_health_create_sessiond(void)
194{
195 struct lttng_health *lh;
196
197 lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND,
198 NR_HEALTH_SESSIOND_TYPES);
199 if (!lh) {
200 return NULL;
201 }
202 return lh;
203}
204
205struct lttng_health *
206 lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
207{
208 struct lttng_health *lh;
209
210 lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD,
211 NR_HEALTH_CONSUMERD_TYPES);
212 if (!lh) {
213 return NULL;
214 }
215 lh->consumerd_type = consumerd;
216 return lh;
217}
218
219struct lttng_health *lttng_health_create_relayd(const char *path)
220{
e1b624d0
JG
221 int ret;
222 struct lttng_health *lh = NULL;
6c71277b
MD
223
224 if (!path) {
e1b624d0 225 goto error;
6c71277b
MD
226 }
227
228 lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
229 NR_HEALTH_RELAYD_TYPES);
230 if (!lh) {
e1b624d0 231 goto error;
6c71277b 232 }
e1b624d0 233
336a72eb
JG
234 ret = lttng_strncpy(lh->health_sock_path, path,
235 sizeof(lh->health_sock_path));
e1b624d0
JG
236 if (ret) {
237 goto error;
238 }
239
6c71277b 240 return lh;
e1b624d0
JG
241
242error:
243 free(lh);
244 return NULL;
6c71277b
MD
245}
246
247void lttng_health_destroy(struct lttng_health *lh)
248{
249 free(lh);
250}
251
252int lttng_health_query(struct lttng_health *health)
253{
254 int sock, ret, i, tracing_group;
255 struct health_comm_msg msg;
256 struct health_comm_reply reply;
257
258 if (!health) {
259 return -EINVAL;
260 }
261
262 tracing_group = lttng_check_tracing_group();
263retry:
264 ret = set_health_socket_path(health, tracing_group);
265 if (ret) {
266 goto error;
267 }
71d01237 268 /* Connect to component */
6c71277b
MD
269 sock = lttcomm_connect_unix_sock(health->health_sock_path);
270 if (sock < 0) {
271 if (tracing_group) {
272 /* For tracing group, fallback to per-user */
273 tracing_group = 0;
274 goto retry;
275 }
276 ret = -1;
277 goto error;
278 }
279
53efb85a 280 memset(&msg, 0, sizeof(msg));
6c71277b
MD
281 msg.cmd = HEALTH_CMD_CHECK;
282
283 ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
284 if (ret < 0) {
285 ret = -1;
286 goto close_error;
287 }
288
289 ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
290 if (ret < 0) {
291 ret = -1;
292 goto close_error;
293 }
294
295 health->state = reply.ret_code;
296 for (i = 0; i < health->nr_threads; i++) {
297 if (health->state & (1ULL << i)) {
298 health->thread[i].state = -1;
299 } else {
300 health->thread[i].state = 0;
301 }
302 }
303
304close_error:
305 {
306 int closeret;
307
308 closeret = close(sock);
309 assert(!closeret);
310 }
311
312error:
313 if (ret >= 0)
314 ret = 0;
315 return ret;
316}
317
318int lttng_health_state(const struct lttng_health *health)
319{
320 if (!health) {
321 return -EINVAL;
322 }
323
324 if (health->state == 0) {
325 return 0;
326 } else {
327 return -1;
328 }
329}
330
331int lttng_health_get_nr_threads(const struct lttng_health *health)
332{
333 if (!health) {
334 return -EINVAL;
335 }
336 return health->nr_threads;
337}
338
339const struct lttng_health_thread *
340 lttng_health_get_thread(const struct lttng_health *health,
341 unsigned int nth_thread)
342{
343 if (!health || nth_thread >= health->nr_threads) {
344 return NULL;
345 }
346 return &health->thread[nth_thread];
347}
348
349int lttng_health_thread_state(const struct lttng_health_thread *thread)
350{
351 if (!thread) {
352 return -EINVAL;
353 }
354 return thread->state;
355}
356
357const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
358{
359 unsigned int nr;
360
361 if (!thread) {
362 return NULL;
363 }
364 nr = thread - &thread->p->thread[0];
365 return thread_name[thread->p->component][nr];
366}
This page took 0.053251 seconds and 4 git commands to generate.