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
14 #include "lttng-ctl-helper.hpp"
16 #include <common/compat/errno.hpp>
17 #include <common/compiler.hpp>
18 #include <common/defaults.hpp>
19 #include <common/utils.hpp>
21 #include <lttng/health-internal.hpp>
23 #include <bin/lttng-consumerd/health-consumerd.hpp>
24 #include <bin/lttng-relayd/health-relayd.hpp>
25 #include <bin/lttng-sessiond/health-sessiond.hpp>
29 #include <sys/types.h>
32 enum health_component
{
33 HEALTH_COMPONENT_SESSIOND
,
34 HEALTH_COMPONENT_CONSUMERD
,
35 HEALTH_COMPONENT_RELAYD
,
40 struct lttng_health_thread
{
41 struct lttng_health
*p
;
46 enum health_component component
;
48 unsigned int nr_threads
;
49 char health_sock_path
[PATH_MAX
];
50 /* For consumer health only */
51 enum lttng_health_consumerd consumerd_type
;
52 struct lttng_health_thread thread
[LTTNG_FLEXIBLE_ARRAY_MEMBER_LENGTH
];
55 static const char *get_sessiond_thread_name(health_type_sessiond type
)
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";
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
:
87 static const char *get_consumerd_thread_name(health_type_consumerd 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
:
107 static const char *get_relayd_thread_name(health_type_relayd 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
:
129 static const char *get_thread_name(int comp
, int nr
)
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
:
146 * Set health socket path.
148 * Returns 0 on success or a negative errno.
150 static int set_health_socket_path(struct lttng_health
*lh
, int tracing_group
)
155 /* Global and home format strings */
156 const char *global_str
, *home_str
;
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
;
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
;
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
;
173 case LTTNG_HEALTH_CONSUMERD_KERNEL
:
174 global_str
= DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK
;
175 home_str
= DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK
;
181 case HEALTH_COMPONENT_RELAYD
:
182 if (lh
->health_sock_path
[0] == '\0') {
187 break; /* Unreached */
194 if (uid
== 0 || tracing_group
) {
195 ret
= lttng_strncpy(lh
->health_sock_path
, global_str
, sizeof(lh
->health_sock_path
));
196 return ret
== 0 ? 0 : -EINVAL
;
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).
204 home
= utils_get_home_dir();
205 if (home
== nullptr) {
206 /* Fallback in /tmp */
211 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
212 ret
= snprintf(lh
->health_sock_path
, sizeof(lh
->health_sock_path
), home_str
, home
);
214 if ((ret
< 0) || (ret
>= sizeof(lh
->health_sock_path
))) {
221 static struct lttng_health
*lttng_health_create(enum health_component hc
, unsigned int nr_threads
)
223 struct lttng_health
*lh
;
226 lh
= zmalloc
<lttng_health
>(sizeof(*lh
) + sizeof(lh
->thread
[0]) * nr_threads
);
232 lh
->state
= UINT64_MAX
; /* All bits in error initially */
233 lh
->nr_threads
= nr_threads
;
234 for (i
= 0; i
< nr_threads
; i
++) {
235 lh
->thread
[i
].p
= lh
;
240 struct lttng_health
*lttng_health_create_sessiond(void)
242 struct lttng_health
*lh
;
244 lh
= lttng_health_create(HEALTH_COMPONENT_SESSIOND
, NR_HEALTH_SESSIOND_TYPES
);
251 struct lttng_health
*lttng_health_create_consumerd(enum lttng_health_consumerd consumerd
)
253 struct lttng_health
*lh
;
255 lh
= lttng_health_create(HEALTH_COMPONENT_CONSUMERD
, NR_HEALTH_CONSUMERD_TYPES
);
259 lh
->consumerd_type
= consumerd
;
263 struct lttng_health
*lttng_health_create_relayd(const char *path
)
266 struct lttng_health
*lh
= nullptr;
272 lh
= lttng_health_create(HEALTH_COMPONENT_RELAYD
, NR_HEALTH_RELAYD_TYPES
);
277 ret
= lttng_strncpy(lh
->health_sock_path
, path
, sizeof(lh
->health_sock_path
));
289 void lttng_health_destroy(struct lttng_health
*lh
)
294 int lttng_health_query(struct lttng_health
*health
)
296 int sock
, ret
, i
, tracing_group
;
297 struct health_comm_msg msg
;
298 struct health_comm_reply reply
;
304 tracing_group
= lttng_check_tracing_group();
306 ret
= set_health_socket_path(health
, tracing_group
);
310 /* Connect to component */
311 sock
= lttcomm_connect_unix_sock(health
->health_sock_path
);
314 /* For tracing group, fallback to per-user */
322 memset(&msg
, 0, sizeof(msg
));
323 msg
.cmd
= HEALTH_CMD_CHECK
;
325 ret
= lttcomm_send_unix_sock(sock
, (void *) &msg
, sizeof(msg
));
331 ret
= lttcomm_recv_unix_sock(sock
, (void *) &reply
, sizeof(reply
));
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;
342 health
->thread
[i
].state
= 0;
350 closeret
= close(sock
);
351 LTTNG_ASSERT(!closeret
);
360 int lttng_health_state(const struct lttng_health
*health
)
366 if (health
->state
== 0) {
373 int lttng_health_get_nr_threads(const struct lttng_health
*health
)
378 return health
->nr_threads
;
381 const struct lttng_health_thread
*lttng_health_get_thread(const struct lttng_health
*health
,
382 unsigned int nth_thread
)
384 if (!health
|| nth_thread
>= health
->nr_threads
) {
387 return &health
->thread
[nth_thread
];
390 int lttng_health_thread_state(const struct lttng_health_thread
*thread
)
395 return thread
->state
;
398 const char *lttng_health_thread_name(const struct lttng_health_thread
*thread
)
405 nr
= thread
- &thread
->p
->thread
[0];
406 return get_thread_name(thread
->p
->component
, nr
);