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