4 * Linux Trace Toolkit Health Control Library
6 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
7 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License, version 2.1 only,
11 * as published by the Free Software Foundation.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
30 #include <lttng/health-internal.h>
32 #include <bin/lttng-sessiond/health-sessiond.h>
33 #include <bin/lttng-consumerd/health-consumerd.h>
34 #include <bin/lttng-relayd/health-relayd.h>
35 #include <common/defaults.h>
36 #include <common/utils.h>
38 #include "lttng-ctl-helper.h"
40 enum health_component
{
41 HEALTH_COMPONENT_SESSIOND
,
42 HEALTH_COMPONENT_CONSUMERD
,
43 HEALTH_COMPONENT_RELAYD
,
48 struct lttng_health_thread
{
49 struct lttng_health
*p
;
54 enum health_component component
;
56 unsigned int nr_threads
;
57 char health_sock_path
[PATH_MAX
];
58 /* For consumer health only */
59 enum lttng_health_consumerd consumerd_type
;
60 struct lttng_health_thread thread
[];
64 const char *sessiond_thread_name
[NR_HEALTH_SESSIOND_TYPES
] = {
65 [ HEALTH_SESSIOND_TYPE_CMD
] = "Session daemon command",
66 [ HEALTH_SESSIOND_TYPE_APP_MANAGE
] = "Session daemon application manager",
67 [ HEALTH_SESSIOND_TYPE_APP_REG
] = "Session daemon application registration",
68 [ HEALTH_SESSIOND_TYPE_KERNEL
] = "Session daemon kernel",
69 [ HEALTH_SESSIOND_TYPE_CONSUMER
] = "Session daemon consumer manager",
70 [ HEALTH_SESSIOND_TYPE_HT_CLEANUP
] = "Session daemon hash table cleanup",
71 [ HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY
] = "Session daemon application notification manager",
72 [ HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH
] = "Session daemon application registration dispatcher",
73 [ HEALTH_SESSIOND_TYPE_ROTATION
] = "Session daemon rotation manager",
74 [ HEALTH_SESSIOND_TYPE_TIMER
] = "Session daemon timer manager",
78 const char *consumerd_thread_name
[NR_HEALTH_CONSUMERD_TYPES
] = {
79 [ HEALTH_CONSUMERD_TYPE_CHANNEL
] = "Consumer daemon channel",
80 [ HEALTH_CONSUMERD_TYPE_METADATA
] = "Consumer daemon metadata",
81 [ HEALTH_CONSUMERD_TYPE_DATA
] = "Consumer daemon data",
82 [ HEALTH_CONSUMERD_TYPE_SESSIOND
] = "Consumer daemon session daemon command manager",
83 [ HEALTH_CONSUMERD_TYPE_METADATA_TIMER
] = "Consumer daemon metadata timer",
87 const char *relayd_thread_name
[NR_HEALTH_RELAYD_TYPES
] = {
88 [ HEALTH_RELAYD_TYPE_DISPATCHER
] = "Relay daemon dispatcher",
89 [ HEALTH_RELAYD_TYPE_WORKER
] = "Relay daemon worker",
90 [ HEALTH_RELAYD_TYPE_LISTENER
] = "Relay daemon listener",
91 [ HEALTH_RELAYD_TYPE_LIVE_DISPATCHER
] = "Relay daemon live dispatcher",
92 [ HEALTH_RELAYD_TYPE_LIVE_WORKER
] = "Relay daemon live worker",
93 [ HEALTH_RELAYD_TYPE_LIVE_LISTENER
] = "Relay daemon live listener",
97 const char **thread_name
[NR_HEALTH_COMPONENT
] = {
98 [ HEALTH_COMPONENT_SESSIOND
] = sessiond_thread_name
,
99 [ HEALTH_COMPONENT_CONSUMERD
] = consumerd_thread_name
,
100 [ HEALTH_COMPONENT_RELAYD
] = relayd_thread_name
,
104 * Set health socket path.
106 * Returns 0 on success or a negative errno.
109 int set_health_socket_path(struct lttng_health
*lh
,
115 /* Global and home format strings */
116 const char *global_str
, *home_str
;
118 switch (lh
->component
) {
119 case HEALTH_COMPONENT_SESSIOND
:
120 global_str
= DEFAULT_GLOBAL_HEALTH_UNIX_SOCK
;
121 home_str
= DEFAULT_HOME_HEALTH_UNIX_SOCK
;
123 case HEALTH_COMPONENT_CONSUMERD
:
124 switch (lh
->consumerd_type
) {
125 case LTTNG_HEALTH_CONSUMERD_UST_32
:
126 global_str
= DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK
;
127 home_str
= DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK
;
129 case LTTNG_HEALTH_CONSUMERD_UST_64
:
130 global_str
= DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK
;
131 home_str
= DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK
;
133 case LTTNG_HEALTH_CONSUMERD_KERNEL
:
134 global_str
= DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK
;
135 home_str
= DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK
;
141 case HEALTH_COMPONENT_RELAYD
:
142 if (lh
->health_sock_path
[0] == '\0') {
147 break; /* Unreached */
154 if (uid
== 0 || tracing_group
) {
155 ret
= lttng_strncpy(lh
->health_sock_path
,
157 sizeof(lh
->health_sock_path
));
158 return ret
== 0 ? 0 : -EINVAL
;
162 * With GNU C < 2.1, snprintf returns -1 if the target buffer
163 * is too small; With GNU C >= 2.1, snprintf returns the
164 * required size (excluding closing null).
166 home
= utils_get_home_dir();
168 /* Fallback in /tmp */
172 ret
= snprintf(lh
->health_sock_path
, sizeof(lh
->health_sock_path
),
174 if ((ret
< 0) || (ret
>= sizeof(lh
->health_sock_path
))) {
182 struct lttng_health
*lttng_health_create(enum health_component hc
,
183 unsigned int nr_threads
)
185 struct lttng_health
*lh
;
188 lh
= zmalloc(sizeof(*lh
) + sizeof(lh
->thread
[0]) * nr_threads
);
194 lh
->state
= UINT64_MAX
; /* All bits in error initially */
195 lh
->nr_threads
= nr_threads
;
196 for (i
= 0; i
< nr_threads
; i
++) {
197 lh
->thread
[i
].p
= lh
;
202 struct lttng_health
*lttng_health_create_sessiond(void)
204 struct lttng_health
*lh
;
206 lh
= lttng_health_create(HEALTH_COMPONENT_SESSIOND
,
207 NR_HEALTH_SESSIOND_TYPES
);
214 struct lttng_health
*
215 lttng_health_create_consumerd(enum lttng_health_consumerd consumerd
)
217 struct lttng_health
*lh
;
219 lh
= lttng_health_create(HEALTH_COMPONENT_CONSUMERD
,
220 NR_HEALTH_CONSUMERD_TYPES
);
224 lh
->consumerd_type
= consumerd
;
228 struct lttng_health
*lttng_health_create_relayd(const char *path
)
231 struct lttng_health
*lh
= NULL
;
237 lh
= lttng_health_create(HEALTH_COMPONENT_RELAYD
,
238 NR_HEALTH_RELAYD_TYPES
);
243 ret
= lttng_strncpy(lh
->health_sock_path
, path
?: "",
244 sizeof(lh
->health_sock_path
));
256 void lttng_health_destroy(struct lttng_health
*lh
)
261 int lttng_health_query(struct lttng_health
*health
)
263 int sock
, ret
, i
, tracing_group
;
264 struct health_comm_msg msg
;
265 struct health_comm_reply reply
;
271 tracing_group
= lttng_check_tracing_group();
273 ret
= set_health_socket_path(health
, tracing_group
);
277 /* Connect to component */
278 sock
= lttcomm_connect_unix_sock(health
->health_sock_path
);
281 /* For tracing group, fallback to per-user */
289 memset(&msg
, 0, sizeof(msg
));
290 msg
.cmd
= HEALTH_CMD_CHECK
;
292 ret
= lttcomm_send_unix_sock(sock
, (void *)&msg
, sizeof(msg
));
298 ret
= lttcomm_recv_unix_sock(sock
, (void *)&reply
, sizeof(reply
));
304 health
->state
= reply
.ret_code
;
305 for (i
= 0; i
< health
->nr_threads
; i
++) {
306 if (health
->state
& (1ULL << i
)) {
307 health
->thread
[i
].state
= -1;
309 health
->thread
[i
].state
= 0;
317 closeret
= close(sock
);
327 int lttng_health_state(const struct lttng_health
*health
)
333 if (health
->state
== 0) {
340 int lttng_health_get_nr_threads(const struct lttng_health
*health
)
345 return health
->nr_threads
;
348 const struct lttng_health_thread
*
349 lttng_health_get_thread(const struct lttng_health
*health
,
350 unsigned int nth_thread
)
352 if (!health
|| nth_thread
>= health
->nr_threads
) {
355 return &health
->thread
[nth_thread
];
358 int lttng_health_thread_state(const struct lttng_health_thread
*thread
)
363 return thread
->state
;
366 const char *lttng_health_thread_name(const struct lttng_health_thread
*thread
)
373 nr
= thread
- &thread
->p
->thread
[0];
374 return thread_name
[thread
->p
->component
][nr
];