sessiond: trigger: run trigger actions through an action executor
[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>
18#include <errno.h>
73d8fe3e 19#include <string.h>
6c71277b
MD
20#include <lttng/health-internal.h>
21
22#include <bin/lttng-sessiond/health-sessiond.h>
23#include <bin/lttng-consumerd/health-consumerd.h>
24#include <bin/lttng-relayd/health-relayd.h>
25#include <common/defaults.h>
26#include <common/utils.h>
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 *
97 * Returns 0 on success or -ENOMEM.
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) {
146 lttng_ctl_copy_string(lh->health_sock_path,
147 global_str,
148 sizeof(lh->health_sock_path));
149 return 0;
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{
221 struct lttng_health *lh;
222
223 if (!path) {
224 return NULL;
225 }
226
227 lh = lttng_health_create(HEALTH_COMPONENT_RELAYD,
228 NR_HEALTH_RELAYD_TYPES);
229 if (!lh) {
230 return NULL;
231 }
232 lttng_ctl_copy_string(lh->health_sock_path, path,
233 sizeof(lh->health_sock_path));
234 return lh;
235}
236
237void lttng_health_destroy(struct lttng_health *lh)
238{
239 free(lh);
240}
241
242int lttng_health_query(struct lttng_health *health)
243{
244 int sock, ret, i, tracing_group;
245 struct health_comm_msg msg;
246 struct health_comm_reply reply;
247
248 if (!health) {
249 return -EINVAL;
250 }
251
252 tracing_group = lttng_check_tracing_group();
253retry:
254 ret = set_health_socket_path(health, tracing_group);
255 if (ret) {
256 goto error;
257 }
71d01237 258 /* Connect to component */
6c71277b
MD
259 sock = lttcomm_connect_unix_sock(health->health_sock_path);
260 if (sock < 0) {
261 if (tracing_group) {
262 /* For tracing group, fallback to per-user */
263 tracing_group = 0;
264 goto retry;
265 }
266 ret = -1;
267 goto error;
268 }
269
53efb85a 270 memset(&msg, 0, sizeof(msg));
6c71277b
MD
271 msg.cmd = HEALTH_CMD_CHECK;
272
273 ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg));
274 if (ret < 0) {
275 ret = -1;
276 goto close_error;
277 }
278
279 ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply));
280 if (ret < 0) {
281 ret = -1;
282 goto close_error;
283 }
284
285 health->state = reply.ret_code;
286 for (i = 0; i < health->nr_threads; i++) {
287 if (health->state & (1ULL << i)) {
288 health->thread[i].state = -1;
289 } else {
290 health->thread[i].state = 0;
291 }
292 }
293
294close_error:
295 {
296 int closeret;
297
298 closeret = close(sock);
299 assert(!closeret);
300 }
301
302error:
303 if (ret >= 0)
304 ret = 0;
305 return ret;
306}
307
308int lttng_health_state(const struct lttng_health *health)
309{
310 if (!health) {
311 return -EINVAL;
312 }
313
314 if (health->state == 0) {
315 return 0;
316 } else {
317 return -1;
318 }
319}
320
321int lttng_health_get_nr_threads(const struct lttng_health *health)
322{
323 if (!health) {
324 return -EINVAL;
325 }
326 return health->nr_threads;
327}
328
329const struct lttng_health_thread *
330 lttng_health_get_thread(const struct lttng_health *health,
331 unsigned int nth_thread)
332{
333 if (!health || nth_thread >= health->nr_threads) {
334 return NULL;
335 }
336 return &health->thread[nth_thread];
337}
338
339int lttng_health_thread_state(const struct lttng_health_thread *thread)
340{
341 if (!thread) {
342 return -EINVAL;
343 }
344 return thread->state;
345}
346
347const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
348{
349 unsigned int nr;
350
351 if (!thread) {
352 return NULL;
353 }
354 nr = thread - &thread->p->thread[0];
355 return thread_name[thread->p->component][nr];
356}
This page took 0.051784 seconds and 4 git commands to generate.