4 * Linux Trace Toolkit Health Control Library
6 * Copyright (C) 2011 EfficiOS Inc.
7 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * SPDX-License-Identifier: LGPL-2.1-only
15 #include <sys/types.h>
19 #include <lttng/health-internal.h>
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>
26 #include <common/compat/errno.h>
28 #include "lttng-ctl-helper.h"
30 enum health_component
{
31 HEALTH_COMPONENT_SESSIOND
,
32 HEALTH_COMPONENT_CONSUMERD
,
33 HEALTH_COMPONENT_RELAYD
,
38 struct lttng_health_thread
{
39 struct lttng_health
*p
;
44 enum health_component component
;
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
[];
54 const char *get_sessiond_thread_name(health_type_sessiond type
) {
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";
67 case HEALTH_SESSIOND_TYPE_HT_CLEANUP
:
68 return "Session daemon hash table cleanup";
69 case HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY
:
70 return "Session daemon application notification manager";
71 case HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH
:
72 return "Session daemon application registration dispatcher";
73 case HEALTH_SESSIOND_TYPE_NOTIFICATION
:
74 return "Session daemon notification";
75 case HEALTH_SESSIOND_TYPE_ROTATION
:
76 return "Session daemon rotation manager";
77 case HEALTH_SESSIOND_TYPE_TIMER
:
78 return "Session daemon timer manager";
79 case HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR
:
80 return "Session daemon trigger action executor";
81 case NR_HEALTH_SESSIOND_TYPES
:
89 const char *get_consumerd_thread_name(health_type_consumerd type
) {
91 case HEALTH_CONSUMERD_TYPE_CHANNEL
:
92 return "Consumer daemon channel";
93 case HEALTH_CONSUMERD_TYPE_METADATA
:
94 return "Consumer daemon metadata";
95 case HEALTH_CONSUMERD_TYPE_DATA
:
96 return "Consumer daemon data";
97 case HEALTH_CONSUMERD_TYPE_SESSIOND
:
98 return "Consumer daemon session daemon command manager";
99 case HEALTH_CONSUMERD_TYPE_METADATA_TIMER
:
100 return "Consumer daemon metadata timer";
101 case NR_HEALTH_CONSUMERD_TYPES
:
109 const char *get_relayd_thread_name(health_type_relayd type
)
112 case HEALTH_RELAYD_TYPE_DISPATCHER
:
113 return "Relay daemon dispatcher";
114 case HEALTH_RELAYD_TYPE_WORKER
:
115 return "Relay daemon worker";
116 case HEALTH_RELAYD_TYPE_LISTENER
:
117 return "Relay daemon listener";
118 case HEALTH_RELAYD_TYPE_LIVE_DISPATCHER
:
119 return "Relay daemon live dispatcher";
120 case HEALTH_RELAYD_TYPE_LIVE_WORKER
:
121 return "Relay daemon live worker";
122 case HEALTH_RELAYD_TYPE_LIVE_LISTENER
:
123 return "Relay daemon live listener";
124 case NR_HEALTH_RELAYD_TYPES
:
132 const char *get_thread_name(int comp
, int nr
)
135 case HEALTH_COMPONENT_SESSIOND
:
136 return get_sessiond_thread_name((health_type_sessiond
) nr
);
137 case HEALTH_COMPONENT_CONSUMERD
:
138 return get_consumerd_thread_name((health_type_consumerd
) nr
);
139 case HEALTH_COMPONENT_RELAYD
:
140 return get_relayd_thread_name((health_type_relayd
) nr
);
141 case NR_HEALTH_COMPONENT
:
149 * Set health socket path.
151 * Returns 0 on success or a negative errno.
154 int set_health_socket_path(struct lttng_health
*lh
,
160 /* Global and home format strings */
161 const char *global_str
, *home_str
;
163 switch (lh
->component
) {
164 case HEALTH_COMPONENT_SESSIOND
:
165 global_str
= DEFAULT_GLOBAL_HEALTH_UNIX_SOCK
;
166 home_str
= DEFAULT_HOME_HEALTH_UNIX_SOCK
;
168 case HEALTH_COMPONENT_CONSUMERD
:
169 switch (lh
->consumerd_type
) {
170 case LTTNG_HEALTH_CONSUMERD_UST_32
:
171 global_str
= DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK
;
172 home_str
= DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK
;
174 case LTTNG_HEALTH_CONSUMERD_UST_64
:
175 global_str
= DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK
;
176 home_str
= DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK
;
178 case LTTNG_HEALTH_CONSUMERD_KERNEL
:
179 global_str
= DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK
;
180 home_str
= DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK
;
186 case HEALTH_COMPONENT_RELAYD
:
187 if (lh
->health_sock_path
[0] == '\0') {
192 break; /* Unreached */
199 if (uid
== 0 || tracing_group
) {
200 ret
= lttng_strncpy(lh
->health_sock_path
,
202 sizeof(lh
->health_sock_path
));
203 return ret
== 0 ? 0 : -EINVAL
;
207 * With GNU C < 2.1, snprintf returns -1 if the target buffer
208 * is too small; With GNU C >= 2.1, snprintf returns the
209 * required size (excluding closing null).
211 home
= utils_get_home_dir();
213 /* Fallback in /tmp */
218 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
219 ret
= snprintf(lh
->health_sock_path
, sizeof(lh
->health_sock_path
),
222 if ((ret
< 0) || (ret
>= sizeof(lh
->health_sock_path
))) {
230 struct lttng_health
*lttng_health_create(enum health_component hc
,
231 unsigned int nr_threads
)
233 struct lttng_health
*lh
;
236 lh
= (lttng_health
*) zmalloc(sizeof(*lh
) + sizeof(lh
->thread
[0]) * nr_threads
);
242 lh
->state
= UINT64_MAX
; /* All bits in error initially */
243 lh
->nr_threads
= nr_threads
;
244 for (i
= 0; i
< nr_threads
; i
++) {
245 lh
->thread
[i
].p
= lh
;
250 struct lttng_health
*lttng_health_create_sessiond(void)
252 struct lttng_health
*lh
;
254 lh
= lttng_health_create(HEALTH_COMPONENT_SESSIOND
,
255 NR_HEALTH_SESSIOND_TYPES
);
262 struct lttng_health
*
263 lttng_health_create_consumerd(enum lttng_health_consumerd consumerd
)
265 struct lttng_health
*lh
;
267 lh
= lttng_health_create(HEALTH_COMPONENT_CONSUMERD
,
268 NR_HEALTH_CONSUMERD_TYPES
);
272 lh
->consumerd_type
= consumerd
;
276 struct lttng_health
*lttng_health_create_relayd(const char *path
)
279 struct lttng_health
*lh
= NULL
;
285 lh
= lttng_health_create(HEALTH_COMPONENT_RELAYD
,
286 NR_HEALTH_RELAYD_TYPES
);
291 ret
= lttng_strncpy(lh
->health_sock_path
, path
,
292 sizeof(lh
->health_sock_path
));
304 void lttng_health_destroy(struct lttng_health
*lh
)
309 int lttng_health_query(struct lttng_health
*health
)
311 int sock
, ret
, i
, tracing_group
;
312 struct health_comm_msg msg
;
313 struct health_comm_reply reply
;
319 tracing_group
= lttng_check_tracing_group();
321 ret
= set_health_socket_path(health
, tracing_group
);
325 /* Connect to component */
326 sock
= lttcomm_connect_unix_sock(health
->health_sock_path
);
329 /* For tracing group, fallback to per-user */
337 memset(&msg
, 0, sizeof(msg
));
338 msg
.cmd
= HEALTH_CMD_CHECK
;
340 ret
= lttcomm_send_unix_sock(sock
, (void *)&msg
, sizeof(msg
));
346 ret
= lttcomm_recv_unix_sock(sock
, (void *)&reply
, sizeof(reply
));
352 health
->state
= reply
.ret_code
;
353 for (i
= 0; i
< health
->nr_threads
; i
++) {
354 if (health
->state
& (1ULL << i
)) {
355 health
->thread
[i
].state
= -1;
357 health
->thread
[i
].state
= 0;
365 closeret
= close(sock
);
366 LTTNG_ASSERT(!closeret
);
375 int lttng_health_state(const struct lttng_health
*health
)
381 if (health
->state
== 0) {
388 int lttng_health_get_nr_threads(const struct lttng_health
*health
)
393 return health
->nr_threads
;
396 const struct lttng_health_thread
*
397 lttng_health_get_thread(const struct lttng_health
*health
,
398 unsigned int nth_thread
)
400 if (!health
|| nth_thread
>= health
->nr_threads
) {
403 return &health
->thread
[nth_thread
];
406 int lttng_health_thread_state(const struct lttng_health_thread
*thread
)
411 return thread
->state
;
414 const char *lttng_health_thread_name(const struct lttng_health_thread
*thread
)
421 nr
= thread
- &thread
->p
->thread
[0];
422 return get_thread_name (thread
->p
->component
, nr
);