Clean-up: lttng: prepend `the_` to global variables in list.c
[lttng-tools.git] / src / bin / lttng / commands / list.c
CommitLineData
f3ed775e 1/*
ab5be9fa 2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
159b042f 3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
f3ed775e 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
f3ed775e 6 *
f3ed775e
DG
7 */
8
159b042f 9#include <stdint.h>
6c1c0768 10#define _LGPL_SOURCE
9f19cc17 11#include <inttypes.h>
f3ed775e
DG
12#include <popt.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
7a3d1328 16#include <assert.h>
f3ed775e 17
fb14d0d8 18#include <common/mi-lttng.h>
5b89fc92 19#include <common/time.h>
159b042f 20#include <common/tracker.h>
050dd639 21#include <lttng/lttng.h>
fb14d0d8 22
c399183f 23#include "../command.h"
f3ed775e 24
9f19cc17
DG
25static int opt_userspace;
26static int opt_kernel;
3c6a091f 27static int opt_jul;
5cdb6027 28static int opt_log4j;
0e115563 29static int opt_python;
9f19cc17
DG
30static char *opt_channel;
31static int opt_domain;
f37d259d 32static int opt_fields;
834978fd 33static int opt_syscall;
9f19cc17
DG
34
35const char *indent4 = " ";
36const char *indent6 = " ";
37const char *indent8 = " ";
f3ed775e 38
4fc83d94
PP
39#ifdef LTTNG_EMBED_HELP
40static const char help_msg[] =
41#include <lttng-list.1.h>
42;
43#endif
44
f3ed775e
DG
45enum {
46 OPT_HELP = 1,
eeac7d46 47 OPT_USERSPACE,
679b4943 48 OPT_LIST_OPTIONS,
f3ed775e
DG
49};
50
41493f4a
SM
51static struct lttng_handle *the_handle;
52static struct mi_writer *the_writer;
cd80958d 53
e50e81d3 54/* Only set when listing a single session. */
41493f4a 55static struct lttng_session the_listed_session;
e50e81d3 56
f3ed775e
DG
57static struct poptOption long_options[] = {
58 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
2fa605f7
JG
59 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
60 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
61 {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
62 {"log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0},
63 {"python", 'p', POPT_ARG_VAL, &opt_python, 1, 0, 0},
64 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
65 {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0},
66 {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0},
67 {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0},
68 {"syscall", 'S', POPT_ARG_VAL, &opt_syscall, 1, 0, 0},
679b4943 69 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
f3ed775e
DG
70 {0, 0, 0, 0, 0, 0, 0}
71};
72
f3ed775e 73/*
9f19cc17 74 * Get command line from /proc for a specific pid.
f3ed775e 75 *
9f19cc17
DG
76 * On success, return an allocated string pointer to the proc cmdline.
77 * On error, return NULL.
f3ed775e
DG
78 */
79static char *get_cmdline_by_pid(pid_t pid)
80{
81 int ret;
1ad31aec 82 FILE *fp = NULL;
f3ed775e 83 char *cmdline = NULL;
fae9a062
JG
84 /* Can't go bigger than /proc/LTTNG_MAX_PID/cmdline */
85 char path[sizeof("/proc//cmdline") + sizeof(LTTNG_MAX_PID_STR) - 1];
f3ed775e
DG
86
87 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
88 fp = fopen(path, "r");
89 if (fp == NULL) {
90 goto end;
91 }
92
93 /* Caller must free() *cmdline */
63a2c1bd 94 cmdline = zmalloc(PATH_MAX);
f6962219 95 if (!cmdline) {
6f04ed72 96 PERROR("malloc cmdline");
f6962219
JG
97 goto end;
98 }
f3ed775e 99 ret = fread(cmdline, 1, PATH_MAX, fp);
f40799e8 100 if (ret < 0) {
6f04ed72 101 PERROR("fread proc list");
f40799e8 102 }
f3ed775e
DG
103
104end:
1ad31aec
DG
105 if (fp) {
106 fclose(fp);
107 }
f3ed775e
DG
108 return cmdline;
109}
b551a063 110
464dd62d
MD
111static
112const char *active_string(int value)
113{
114 switch (value) {
2cbf8fed
DG
115 case 0: return "inactive";
116 case 1: return "active";
464dd62d
MD
117 case -1: return "";
118 default: return NULL;
119 }
120}
121
2cbf8fed
DG
122static const char *snapshot_string(int value)
123{
124 switch (value) {
125 case 1:
126 return " snapshot";
127 default:
128 return "";
129 }
130}
131
464dd62d
MD
132static
133const char *enabled_string(int value)
134{
135 switch (value) {
b09f0429
MD
136 case 0: return " [disabled]";
137 case 1: return " [enabled]";
464dd62d
MD
138 case -1: return "";
139 default: return NULL;
140 }
141}
142
fceb65df 143static
7b4a95b1 144const char *safe_string(const char *str)
fceb65df 145{
7b4a95b1 146 return str ? str : "";
4634f12e
JI
147}
148
1f0e17de
DG
149static const char *logleveltype_string(enum lttng_loglevel_type value)
150{
151 switch (value) {
af6bce80
DG
152 case LTTNG_EVENT_LOGLEVEL_ALL:
153 return ":";
1f0e17de 154 case LTTNG_EVENT_LOGLEVEL_RANGE:
af6bce80 155 return " <=";
1f0e17de 156 case LTTNG_EVENT_LOGLEVEL_SINGLE:
af6bce80 157 return " ==";
1f0e17de 158 default:
af6bce80 159 return " <<TYPE UNKN>>";
1f0e17de
DG
160 }
161}
162
834978fd
DG
163static const char *bitness_event(enum lttng_event_flag flags)
164{
165 if (flags & LTTNG_EVENT_FLAG_SYSCALL_32) {
166 if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
167 return " [32/64-bit]";
168 } else {
169 return " [32-bit]";
170 }
171 } else if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
172 return " [64-bit]";
173 } else {
174 return "";
175 }
176}
177
7b4a95b1
PP
178/*
179 * Get exclusion names message for a single event.
180 *
181 * Returned pointer must be freed by caller. Returns NULL on error.
182 */
183static char *get_exclusion_names_msg(struct lttng_event *event)
184{
185 int ret;
186 int exclusion_count;
187 char *exclusion_msg = NULL;
188 char *at;
7b4a95b1
PP
189 size_t i;
190 const char * const exclusion_fmt = " [exclusions: ";
19ed7632 191 const size_t exclusion_fmt_len = strlen(exclusion_fmt);
7b4a95b1
PP
192
193 exclusion_count = lttng_event_get_exclusion_name_count(event);
194 if (exclusion_count < 0) {
195 goto end;
196 } else if (exclusion_count == 0) {
197 /*
198 * No exclusions: return copy of empty string so that
199 * it can be freed by caller.
200 */
201 exclusion_msg = strdup("");
202 goto end;
203 }
204
205 /*
206 * exclusion_msg's size is bounded by the exclusion_fmt string,
207 * a comma per entry, the entry count (fixed-size), a closing
208 * bracket, and a trailing \0.
209 */
210 exclusion_msg = malloc(exclusion_count +
211 exclusion_count * LTTNG_SYMBOL_NAME_LEN +
19ed7632 212 exclusion_fmt_len + 1);
7b4a95b1
PP
213 if (!exclusion_msg) {
214 goto end;
215 }
216
19ed7632 217 at = strcpy(exclusion_msg, exclusion_fmt) + exclusion_fmt_len;
7b4a95b1
PP
218 for (i = 0; i < exclusion_count; ++i) {
219 const char *name;
220
221 /* Append comma between exclusion names */
222 if (i > 0) {
223 *at = ',';
224 at++;
225 }
226
227 ret = lttng_event_get_exclusion_name(event, i, &name);
228 if (ret) {
229 /* Prints '?' on local error; should never happen */
230 *at = '?';
231 at++;
232 continue;
233 }
234
235 /* Append exclusion name */
31e40170 236 at += sprintf(at, "%s", name);
7b4a95b1
PP
237 }
238
239 /* This also puts a final '\0' at the end of exclusion_msg */
19ed7632 240 strcpy(at, "]");
7b4a95b1
PP
241
242end:
243 return exclusion_msg;
244}
245
b955b4d4
FD
246static void print_userspace_probe_location(struct lttng_event *event)
247{
87597c2c
JG
248 const struct lttng_userspace_probe_location *location;
249 const struct lttng_userspace_probe_location_lookup_method *lookup_method;
b955b4d4
FD
250 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
251
252 location = lttng_event_get_userspace_probe_location(event);
253 if (!location) {
254 MSG("Event has no userspace probe location");
255 return;
256 }
257
258 lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
259 if (!lookup_method) {
260 MSG("Event has no userspace probe location lookup method");
261 return;
262 }
263
264 MSG("%s%s (type: userspace-probe)%s", indent6, event->name, enabled_string(event->enabled));
265
266 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
267
268 switch (lttng_userspace_probe_location_get_type(location)) {
269 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
270 MSG("%sType: Unknown", indent8);
271 break;
272 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
273 {
274 const char *function_name;
4df1f2d4 275 char *binary_path;
b955b4d4
FD
276
277 MSG("%sType: Function", indent8);
278 function_name = lttng_userspace_probe_location_function_get_function_name(location);
279 binary_path = realpath(lttng_userspace_probe_location_function_get_binary_path(location), NULL);
280
281 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
282 MSG("%sFunction: %s()", indent8, function_name ? function_name : "NULL");
283 switch (lookup_type) {
284 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
285 MSG("%sLookup method: ELF", indent8);
286 break;
287 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
288 MSG("%sLookup method: default", indent8);
289 break;
290 default:
291 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
292 break;
293 }
4df1f2d4
JG
294
295 free(binary_path);
b955b4d4
FD
296 break;
297 }
298 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
299 {
300 const char *probe_name, *provider_name;
4df1f2d4 301 char *binary_path;
b955b4d4
FD
302
303 MSG("%sType: Tracepoint", indent8);
304 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
305 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
306 binary_path = realpath(lttng_userspace_probe_location_tracepoint_get_binary_path(location), NULL);
307 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
308 MSG("%sTracepoint: %s:%s", indent8, provider_name ? provider_name : "NULL", probe_name ? probe_name : "NULL");
309 switch (lookup_type) {
310 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
311 MSG("%sLookup method: SDT", indent8);
312 break;
313 default:
314 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
315 break;
316 }
4df1f2d4
JG
317
318 free(binary_path);
b955b4d4
FD
319 break;
320 }
321 default:
322 ERR("Invalid probe type encountered");
323 }
324}
325
b551a063
DG
326/*
327 * Pretty print single event.
328 */
329static void print_events(struct lttng_event *event)
330{
4adbcc72
PP
331 int ret;
332 const char *filter_str;
333 char *filter_msg = NULL;
7b4a95b1 334 char *exclusion_msg = NULL;
4adbcc72 335
134e72ed 336 ret = lttng_event_get_filter_expression(event, &filter_str);
4adbcc72
PP
337
338 if (ret) {
339 filter_msg = strdup(" [failed to retrieve filter]");
340 } else if (filter_str) {
341 const char * const filter_fmt = " [filter: '%s']";
342
343 filter_msg = malloc(strlen(filter_str) +
344 strlen(filter_fmt) + 1);
345 if (filter_msg) {
346 sprintf(filter_msg, filter_fmt,
347 filter_str);
348 }
349 }
350
7b4a95b1
PP
351 exclusion_msg = get_exclusion_names_msg(event);
352 if (!exclusion_msg) {
353 exclusion_msg = strdup(" [failed to retrieve exclusions]");
354 }
355
b551a063
DG
356 switch (event->type) {
357 case LTTNG_EVENT_TRACEPOINT:
e4baff1e 358 {
8b703175 359 if (event->loglevel != -1) {
af6bce80 360 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
41493f4a
SM
361 indent6, event->name,
362 logleveltype_string(
363 event->loglevel_type),
364 mi_lttng_loglevel_string(
365 event->loglevel,
366 the_handle->domain.type),
367 event->loglevel,
368 enabled_string(event->enabled),
369 safe_string(exclusion_msg),
370 safe_string(filter_msg));
8b703175 371 } else {
4634f12e 372 MSG("%s%s (type: tracepoint)%s%s%s",
8b703175
MD
373 indent6,
374 event->name,
fceb65df 375 enabled_string(event->enabled),
7b4a95b1
PP
376 safe_string(exclusion_msg),
377 safe_string(filter_msg));
8b703175 378 }
b551a063 379 break;
e4baff1e 380 }
1896972b
DG
381 case LTTNG_EVENT_FUNCTION:
382 MSG("%s%s (type: function)%s%s", indent6,
383 event->name, enabled_string(event->enabled),
7b4a95b1 384 safe_string(filter_msg));
1896972b
DG
385 if (event->attr.probe.addr != 0) {
386 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
387 } else {
388 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
389 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
390 }
391 break;
b551a063 392 case LTTNG_EVENT_PROBE:
fceb65df
MD
393 MSG("%s%s (type: probe)%s%s", indent6,
394 event->name, enabled_string(event->enabled),
7b4a95b1 395 safe_string(filter_msg));
b551a063
DG
396 if (event->attr.probe.addr != 0) {
397 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
398 } else {
399 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
400 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
401 }
402 break;
b955b4d4
FD
403 case LTTNG_EVENT_USERSPACE_PROBE:
404 print_userspace_probe_location(event);
405 break;
b551a063 406 case LTTNG_EVENT_FUNCTION_ENTRY:
fceb65df
MD
407 MSG("%s%s (type: function)%s%s", indent6,
408 event->name, enabled_string(event->enabled),
7b4a95b1 409 safe_string(filter_msg));
b551a063
DG
410 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
411 break;
412 case LTTNG_EVENT_SYSCALL:
2199ad66 413 MSG("%s%s%s%s%s%s", indent6, event->name,
834978fd 414 (opt_syscall ? "" : " (type:syscall)"),
fceb65df 415 enabled_string(event->enabled),
2199ad66
JG
416 bitness_event(event->flags),
417 safe_string(filter_msg));
b551a063
DG
418 break;
419 case LTTNG_EVENT_NOOP:
fceb65df
MD
420 MSG("%s (type: noop)%s%s", indent6,
421 enabled_string(event->enabled),
7b4a95b1 422 safe_string(filter_msg));
b551a063
DG
423 break;
424 case LTTNG_EVENT_ALL:
410b78a0
FD
425 /* Fall-through. */
426 default:
b551a063
DG
427 /* We should never have "all" events in list. */
428 assert(0);
429 break;
430 }
4adbcc72
PP
431
432 free(filter_msg);
7b4a95b1 433 free(exclusion_msg);
b551a063
DG
434}
435
f37d259d
MD
436static const char *field_type(struct lttng_event_field *field)
437{
438 switch(field->type) {
439 case LTTNG_EVENT_FIELD_INTEGER:
440 return "integer";
441 case LTTNG_EVENT_FIELD_ENUM:
442 return "enum";
443 case LTTNG_EVENT_FIELD_FLOAT:
444 return "float";
445 case LTTNG_EVENT_FIELD_STRING:
446 return "string";
447 case LTTNG_EVENT_FIELD_OTHER:
448 default: /* fall-through */
449 return "unknown";
450 }
451}
452
453/*
454 * Pretty print single event fields.
455 */
456static void print_event_field(struct lttng_event_field *field)
457{
458 if (!field->field_name[0]) {
459 return;
460 }
d8fbe2a9 461 MSG("%sfield: %s (%s)%s", indent8, field->field_name,
45a32634 462 field_type(field), field->nowrite ? " [no write]" : "");
f37d259d
MD
463}
464
fb14d0d8
JR
465/*
466 * Machine interface
467 * Jul and ust event listing
468 */
5cdb6027 469static int mi_list_agent_ust_events(struct lttng_event *events, int count,
fb14d0d8
JR
470 struct lttng_domain *domain)
471{
472 int ret, i;
473 pid_t cur_pid = 0;
474 char *cmdline = NULL;
475 int pid_element_open = 0;
476
477 /* Open domains element */
41493f4a 478 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
479 if (ret) {
480 goto end;
481 }
482
483 /* Write domain */
41493f4a 484 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
485 if (ret) {
486 goto end;
487 }
488
bf239d4c 489 /* Open pids element element */
41493f4a 490 ret = mi_lttng_pids_open(the_writer);
fb14d0d8
JR
491 if (ret) {
492 goto end;
493 }
494
495 for (i = 0; i < count; i++) {
496 if (cur_pid != events[i].pid) {
497 if (pid_element_open) {
2e9aecb9 498 /* Close the previous events and pid element */
41493f4a
SM
499 ret = mi_lttng_close_multi_element(
500 the_writer, 2);
fb14d0d8
JR
501 if (ret) {
502 goto end;
503 }
504 pid_element_open = 0;
505 }
506
507 cur_pid = events[i].pid;
508 cmdline = get_cmdline_by_pid(cur_pid);
509 if (!cmdline) {
510 ret = CMD_ERROR;
511 goto end;
512 }
513
514 if (!pid_element_open) {
515 /* Open and write a pid element */
41493f4a
SM
516 ret = mi_lttng_pid(the_writer, cur_pid, cmdline,
517 1);
fb14d0d8
JR
518 if (ret) {
519 goto error;
520 }
521
522 /* Open events element */
41493f4a 523 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
524 if (ret) {
525 goto error;
526 }
527
528 pid_element_open = 1;
529 }
530 free(cmdline);
531 }
532
533 /* Write an event */
41493f4a
SM
534 ret = mi_lttng_event(the_writer, &events[i], 0,
535 the_handle->domain.type);
fb14d0d8
JR
536 if (ret) {
537 goto end;
538 }
539 }
540
bf239d4c 541 /* Close pids */
41493f4a 542 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
543 if (ret) {
544 goto end;
545 }
546
547 /* Close domain, domains */
41493f4a 548 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
549end:
550 return ret;
551error:
552 free(cmdline);
553 return ret;
554}
555
5cdb6027 556static int list_agent_events(void)
3c6a091f 557{
fb14d0d8 558 int i, size, ret = CMD_SUCCESS;
3c6a091f 559 struct lttng_domain domain;
26c610c9 560 struct lttng_handle *handle = NULL;
469b972b 561 struct lttng_event *event_list = NULL;
3c6a091f
DG
562 pid_t cur_pid = 0;
563 char *cmdline = NULL;
5cdb6027 564 const char *agent_domain_str;
3c6a091f
DG
565
566 memset(&domain, 0, sizeof(domain));
5cdb6027
DG
567 if (opt_jul) {
568 domain.type = LTTNG_DOMAIN_JUL;
569 } else if (opt_log4j) {
570 domain.type = LTTNG_DOMAIN_LOG4J;
0e115563
DG
571 } else if (opt_python) {
572 domain.type = LTTNG_DOMAIN_PYTHON;
26c610c9
JG
573 } else {
574 ERR("Invalid agent domain selected.");
575 ret = CMD_ERROR;
576 goto error;
5cdb6027
DG
577 }
578
579 agent_domain_str = get_domain_str(domain.type);
580
581 DBG("Getting %s tracing events", agent_domain_str);
3c6a091f
DG
582
583 handle = lttng_create_handle(NULL, &domain);
584 if (handle == NULL) {
fb14d0d8
JR
585 ret = CMD_ERROR;
586 goto end;
3c6a091f
DG
587 }
588
589 size = lttng_list_tracepoints(handle, &event_list);
590 if (size < 0) {
5cdb6027
DG
591 ERR("Unable to list %s events: %s", agent_domain_str,
592 lttng_strerror(size));
fb14d0d8
JR
593 ret = CMD_ERROR;
594 goto end;
3c6a091f
DG
595 }
596
fb14d0d8
JR
597 if (lttng_opt_mi) {
598 /* Mi print */
5cdb6027 599 ret = mi_list_agent_ust_events(event_list, size, &domain);
fb14d0d8
JR
600 if (ret) {
601 ret = CMD_ERROR;
602 goto error;
3c6a091f 603 }
fb14d0d8
JR
604 } else {
605 /* Pretty print */
5cdb6027
DG
606 MSG("%s events (Logger name):\n-------------------------",
607 agent_domain_str);
3c6a091f 608
fb14d0d8
JR
609 if (size == 0) {
610 MSG("None");
611 }
3c6a091f 612
fb14d0d8
JR
613 for (i = 0; i < size; i++) {
614 if (cur_pid != event_list[i].pid) {
615 cur_pid = event_list[i].pid;
616 cmdline = get_cmdline_by_pid(cur_pid);
617 if (cmdline == NULL) {
618 ret = CMD_ERROR;
619 goto error;
620 }
621 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
622 free(cmdline);
623 }
624 MSG("%s- %s", indent6, event_list[i].name);
625 }
3c6a091f 626
fb14d0d8
JR
627 MSG("");
628 }
3c6a091f
DG
629
630error:
fb14d0d8
JR
631 free(event_list);
632end:
3c6a091f 633 lttng_destroy_handle(handle);
fb14d0d8 634 return ret;
3c6a091f
DG
635}
636
b551a063
DG
637/*
638 * Ask session daemon for all user space tracepoints available.
639 */
640static int list_ust_events(void)
641{
fb14d0d8 642 int i, size, ret = CMD_SUCCESS;
b551a063
DG
643 struct lttng_domain domain;
644 struct lttng_handle *handle;
bec97646 645 struct lttng_event *event_list = NULL;
b551a063 646 pid_t cur_pid = 0;
ea5cbc00 647 char *cmdline = NULL;
b551a063 648
441c16a7
MD
649 memset(&domain, 0, sizeof(domain));
650
b551a063
DG
651 DBG("Getting UST tracing events");
652
653 domain.type = LTTNG_DOMAIN_UST;
654
655 handle = lttng_create_handle(NULL, &domain);
656 if (handle == NULL) {
fb14d0d8
JR
657 ret = CMD_ERROR;
658 goto end;
b551a063
DG
659 }
660
661 size = lttng_list_tracepoints(handle, &event_list);
662 if (size < 0) {
60e835ca 663 ERR("Unable to list UST events: %s", lttng_strerror(size));
fb14d0d8
JR
664 ret = CMD_ERROR;
665 goto error;
b551a063
DG
666 }
667
fb14d0d8
JR
668 if (lttng_opt_mi) {
669 /* Mi print */
5cdb6027 670 ret = mi_list_agent_ust_events(event_list, size, &domain);
fb14d0d8
JR
671 } else {
672 /* Pretty print */
673 MSG("UST events:\n-------------");
674
675 if (size == 0) {
676 MSG("None");
677 }
678
679 for (i = 0; i < size; i++) {
680 if (cur_pid != event_list[i].pid) {
681 cur_pid = event_list[i].pid;
682 cmdline = get_cmdline_by_pid(cur_pid);
683 if (cmdline == NULL) {
684 ret = CMD_ERROR;
685 goto error;
686 }
687 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
688 free(cmdline);
689 }
690 print_events(&event_list[i]);
691 }
b551a063 692
fb14d0d8 693 MSG("");
b551a063
DG
694 }
695
fb14d0d8
JR
696error:
697 free(event_list);
698end:
699 lttng_destroy_handle(handle);
700 return ret;
701}
702
703/*
704 * Machine interface
705 * List all ust event with their fields
706 */
707static int mi_list_ust_event_fields(struct lttng_event_field *fields, int count,
708 struct lttng_domain *domain)
709{
710 int ret, i;
711 pid_t cur_pid = 0;
712 char *cmdline = NULL;
713 int pid_element_open = 0;
714 int event_element_open = 0;
715 struct lttng_event cur_event;
716
d113fbc8
JR
717 memset(&cur_event, 0, sizeof(cur_event));
718
fb14d0d8 719 /* Open domains element */
41493f4a 720 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
721 if (ret) {
722 goto end;
723 }
724
725 /* Write domain */
41493f4a 726 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
727 if (ret) {
728 goto end;
729 }
730
bf239d4c 731 /* Open pids element */
41493f4a 732 ret = mi_lttng_pids_open(the_writer);
fb14d0d8
JR
733 if (ret) {
734 goto end;
735 }
736
737 for (i = 0; i < count; i++) {
738 if (cur_pid != fields[i].event.pid) {
739 if (pid_element_open) {
740 if (event_element_open) {
485ca16f 741 /* Close the previous field element and event. */
41493f4a
SM
742 ret = mi_lttng_close_multi_element(
743 the_writer, 2);
fb14d0d8
JR
744 if (ret) {
745 goto end;
746 }
747 event_element_open = 0;
748 }
749 /* Close the previous events, pid element */
41493f4a
SM
750 ret = mi_lttng_close_multi_element(
751 the_writer, 2);
fb14d0d8
JR
752 if (ret) {
753 goto end;
754 }
755 pid_element_open = 0;
756 }
757
758 cur_pid = fields[i].event.pid;
ea5cbc00 759 cmdline = get_cmdline_by_pid(cur_pid);
fb14d0d8 760 if (!pid_element_open) {
bf239d4c 761 /* Open and write a pid element */
41493f4a
SM
762 ret = mi_lttng_pid(the_writer, cur_pid, cmdline,
763 1);
fb14d0d8
JR
764 if (ret) {
765 goto error;
766 }
767
768 /* Open events element */
41493f4a 769 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
770 if (ret) {
771 goto error;
772 }
773 pid_element_open = 1;
774 }
ea5cbc00 775 free(cmdline);
fb14d0d8
JR
776 /* Wipe current event since we are about to print a new PID. */
777 memset(&cur_event, 0, sizeof(cur_event));
b551a063 778 }
b551a063 779
fb14d0d8
JR
780 if (strcmp(cur_event.name, fields[i].event.name) != 0) {
781 if (event_element_open) {
782 /* Close the previous fields element and the previous event */
41493f4a
SM
783 ret = mi_lttng_close_multi_element(
784 the_writer, 2);
fb14d0d8
JR
785 if (ret) {
786 goto end;
787 }
788 event_element_open = 0;
789 }
790
791 memcpy(&cur_event, &fields[i].event,
792 sizeof(cur_event));
b551a063 793
fb14d0d8
JR
794 if (!event_element_open) {
795 /* Open and write the event */
41493f4a
SM
796 ret = mi_lttng_event(the_writer, &cur_event, 1,
797 the_handle->domain.type);
fb14d0d8
JR
798 if (ret) {
799 goto end;
800 }
801
802 /* Open a fields element */
41493f4a 803 ret = mi_lttng_event_fields_open(the_writer);
fb14d0d8
JR
804 if (ret) {
805 goto end;
806 }
807 event_element_open = 1;
808 }
809 }
b551a063 810
fb14d0d8 811 /* Print the event_field */
41493f4a 812 ret = mi_lttng_event_field(the_writer, &fields[i]);
fb14d0d8
JR
813 if (ret) {
814 goto end;
815 }
816 }
b551a063 817
83d6d6c4 818 /* Close pids, domain, domains */
41493f4a 819 ret = mi_lttng_close_multi_element(the_writer, 3);
fb14d0d8
JR
820end:
821 return ret;
b551a063 822error:
fb14d0d8
JR
823 free(cmdline);
824 return ret;
b551a063 825}
f3ed775e 826
f37d259d
MD
827/*
828 * Ask session daemon for all user space tracepoint fields available.
829 */
830static int list_ust_event_fields(void)
831{
fb14d0d8 832 int i, size, ret = CMD_SUCCESS;
f37d259d
MD
833 struct lttng_domain domain;
834 struct lttng_handle *handle;
835 struct lttng_event_field *event_field_list;
836 pid_t cur_pid = 0;
ea5cbc00
CB
837 char *cmdline = NULL;
838
f37d259d
MD
839 struct lttng_event cur_event;
840
841 memset(&domain, 0, sizeof(domain));
842 memset(&cur_event, 0, sizeof(cur_event));
843
844 DBG("Getting UST tracing event fields");
845
846 domain.type = LTTNG_DOMAIN_UST;
847
848 handle = lttng_create_handle(NULL, &domain);
849 if (handle == NULL) {
fb14d0d8
JR
850 ret = CMD_ERROR;
851 goto end;
f37d259d
MD
852 }
853
854 size = lttng_list_tracepoint_fields(handle, &event_field_list);
855 if (size < 0) {
60e835ca 856 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
fb14d0d8
JR
857 ret = CMD_ERROR;
858 goto end;
f37d259d
MD
859 }
860
fb14d0d8
JR
861 if (lttng_opt_mi) {
862 /* Mi print */
863 ret = mi_list_ust_event_fields(event_field_list, size, &domain);
864 if (ret) {
865 ret = CMD_ERROR;
866 goto error;
867 }
868 } else {
869 /* Pretty print */
870 MSG("UST events:\n-------------");
f37d259d 871
fb14d0d8
JR
872 if (size == 0) {
873 MSG("None");
f37d259d 874 }
fb14d0d8
JR
875
876 for (i = 0; i < size; i++) {
877 if (cur_pid != event_field_list[i].event.pid) {
878 cur_pid = event_field_list[i].event.pid;
879 cmdline = get_cmdline_by_pid(cur_pid);
880 if (cmdline == NULL) {
881 ret = CMD_ERROR;
882 goto error;
883 }
884 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
885 free(cmdline);
886 /* Wipe current event since we are about to print a new PID. */
887 memset(&cur_event, 0, sizeof(cur_event));
888 }
889 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
890 print_events(&event_field_list[i].event);
891 memcpy(&cur_event, &event_field_list[i].event,
892 sizeof(cur_event));
893 }
894 print_event_field(&event_field_list[i]);
f37d259d 895 }
f37d259d 896
fb14d0d8
JR
897 MSG("");
898 }
f37d259d 899
fb14d0d8 900error:
f37d259d 901 free(event_field_list);
fb14d0d8 902end:
f37d259d 903 lttng_destroy_handle(handle);
fb14d0d8
JR
904 return ret;
905}
f37d259d 906
fb14d0d8
JR
907/*
908 * Machine interface
909 * Print a list of kernel events
910 */
911static int mi_list_kernel_events(struct lttng_event *events, int count,
912 struct lttng_domain *domain)
913{
914 int ret, i;
f37d259d 915
fb14d0d8 916 /* Open domains element */
41493f4a 917 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
918 if (ret) {
919 goto end;
920 }
921
922 /* Write domain */
41493f4a 923 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
924 if (ret) {
925 goto end;
926 }
927
928 /* Open events */
41493f4a 929 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
930 if (ret) {
931 goto end;
932 }
933
934 for (i = 0; i < count; i++) {
41493f4a
SM
935 ret = mi_lttng_event(the_writer, &events[i], 0,
936 the_handle->domain.type);
fb14d0d8
JR
937 if (ret) {
938 goto end;
939 }
940 }
941
942 /* close events, domain and domains */
41493f4a 943 ret = mi_lttng_close_multi_element(the_writer, 3);
fb14d0d8
JR
944 if (ret) {
945 goto end;
946 }
947
948end:
949 return ret;
f37d259d
MD
950}
951
f3ed775e 952/*
fb14d0d8 953 * Ask for all trace events in the kernel
f3ed775e 954 */
9f19cc17 955static int list_kernel_events(void)
f3ed775e 956{
fb14d0d8 957 int i, size, ret = CMD_SUCCESS;
b551a063
DG
958 struct lttng_domain domain;
959 struct lttng_handle *handle;
9f19cc17 960 struct lttng_event *event_list;
f3ed775e 961
441c16a7
MD
962 memset(&domain, 0, sizeof(domain));
963
b551a063
DG
964 DBG("Getting kernel tracing events");
965
966 domain.type = LTTNG_DOMAIN_KERNEL;
967
968 handle = lttng_create_handle(NULL, &domain);
969 if (handle == NULL) {
fb14d0d8 970 ret = CMD_ERROR;
b551a063
DG
971 goto error;
972 }
f3ed775e 973
cd80958d 974 size = lttng_list_tracepoints(handle, &event_list);
9f19cc17 975 if (size < 0) {
60e835ca 976 ERR("Unable to list kernel events: %s", lttng_strerror(size));
ef021732 977 lttng_destroy_handle(handle);
fb14d0d8 978 return CMD_ERROR;
f3ed775e
DG
979 }
980
fb14d0d8
JR
981 if (lttng_opt_mi) {
982 /* Mi print */
983 ret = mi_list_kernel_events(event_list, size, &domain);
984 if (ret) {
985 ret = CMD_ERROR;
986 goto end;
987 }
988 } else {
989 MSG("Kernel events:\n-------------");
f3ed775e 990
fb14d0d8
JR
991 for (i = 0; i < size; i++) {
992 print_events(&event_list[i]);
993 }
f3ed775e 994
fb14d0d8
JR
995 MSG("");
996 }
b551a063 997
fb14d0d8 998end:
f3ed775e
DG
999 free(event_list);
1000
ef021732 1001 lttng_destroy_handle(handle);
fb14d0d8 1002 return ret;
b551a063
DG
1003
1004error:
ef021732 1005 lttng_destroy_handle(handle);
fb14d0d8
JR
1006 return ret;
1007}
1008
834978fd
DG
1009/*
1010 * Machine interface
1011 * Print a list of system calls.
1012 */
1013static int mi_list_syscalls(struct lttng_event *events, int count)
1014{
1015 int ret, i;
1016
1017 /* Open events */
41493f4a 1018 ret = mi_lttng_events_open(the_writer);
834978fd
DG
1019 if (ret) {
1020 goto end;
1021 }
1022
1023 for (i = 0; i < count; i++) {
41493f4a
SM
1024 ret = mi_lttng_event(the_writer, &events[i], 0,
1025 the_handle->domain.type);
834978fd
DG
1026 if (ret) {
1027 goto end;
1028 }
1029 }
1030
1031 /* Close events. */
41493f4a 1032 ret = mi_lttng_writer_close_element(the_writer);
834978fd
DG
1033 if (ret) {
1034 goto end;
1035 }
1036
1037end:
1038 return ret;
1039}
1040
1041/*
1042 * Ask for kernel system calls.
1043 */
1044static int list_syscalls(void)
1045{
1046 int i, size, ret = CMD_SUCCESS;
1047 struct lttng_event *event_list;
1048
1049 DBG("Getting kernel system call events");
1050
1051 size = lttng_list_syscalls(&event_list);
1052 if (size < 0) {
1053 ERR("Unable to list system calls: %s", lttng_strerror(size));
1054 ret = CMD_ERROR;
1055 goto error;
1056 }
1057
1058 if (lttng_opt_mi) {
1059 /* Mi print */
1060 ret = mi_list_syscalls(event_list, size);
1061 if (ret) {
1062 ret = CMD_ERROR;
1063 goto end;
1064 }
1065 } else {
1066 MSG("System calls:\n-------------");
1067
1068 for (i = 0; i < size; i++) {
1069 print_events(&event_list[i]);
1070 }
1071
1072 MSG("");
1073 }
1074
1075end:
1076 free(event_list);
1077 return ret;
1078
1079error:
1080 return ret;
1081}
1082
fb14d0d8
JR
1083/*
1084 * Machine Interface
5cdb6027 1085 * Print a list of agent events
fb14d0d8 1086 */
5cdb6027 1087static int mi_list_session_agent_events(struct lttng_event *events, int count)
fb14d0d8
JR
1088{
1089 int ret, i;
1090
1091 /* Open events element */
41493f4a 1092 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
1093 if (ret) {
1094 goto end;
1095 }
1096
1097 for (i = 0; i < count; i++) {
41493f4a
SM
1098 ret = mi_lttng_event(the_writer, &events[i], 0,
1099 the_handle->domain.type);
fb14d0d8
JR
1100 if (ret) {
1101 goto end;
1102 }
1103 }
1104
1105 /* Close events element */
41493f4a 1106 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1107
1108end:
1109 return ret;
f3ed775e
DG
1110}
1111
3c6a091f 1112/*
5cdb6027 1113 * List agent events for a specific session using the handle.
3c6a091f
DG
1114 *
1115 * Return CMD_SUCCESS on success else a negative value.
1116 */
5cdb6027 1117static int list_session_agent_events(void)
3c6a091f 1118{
fb14d0d8 1119 int ret = CMD_SUCCESS, count, i;
3c6a091f
DG
1120 struct lttng_event *events = NULL;
1121
41493f4a 1122 count = lttng_list_events(the_handle, "", &events);
3c6a091f 1123 if (count < 0) {
fb14d0d8
JR
1124 ret = CMD_ERROR;
1125 ERR("%s", lttng_strerror(count));
3c6a091f
DG
1126 goto error;
1127 }
1128
fb14d0d8
JR
1129 if (lttng_opt_mi) {
1130 /* Mi print */
5cdb6027 1131 ret = mi_list_session_agent_events(events, count);
fb14d0d8
JR
1132 if (ret) {
1133 ret = CMD_ERROR;
1134 goto end;
1135 }
1136 } else {
1137 /* Pretty print */
1138 MSG("Events (Logger name):\n---------------------");
1139 if (count == 0) {
1140 MSG("%sNone\n", indent6);
1141 goto end;
1142 }
1143
1144 for (i = 0; i < count; i++) {
9a890ce8
JG
1145 const char *filter_str;
1146 char *filter_msg = NULL;
1147 struct lttng_event *event = &events[i];
1148
134e72ed
JG
1149 ret = lttng_event_get_filter_expression(event,
1150 &filter_str);
9a890ce8
JG
1151 if (ret) {
1152 filter_msg = strdup(" [failed to retrieve filter]");
1153 } else if (filter_str) {
1154 const char * const filter_fmt =
1155 " [filter: '%s']";
1156
1157 filter_msg = malloc(strlen(filter_str) +
1158 strlen(filter_fmt) + 1);
1159 if (filter_msg) {
00505bae
JG
1160 sprintf(filter_msg, filter_fmt,
1161 filter_str);
9a890ce8
JG
1162 }
1163 }
1164
1165 if (event->loglevel_type !=
755066c2 1166 LTTNG_EVENT_LOGLEVEL_ALL) {
9a890ce8
JG
1167 MSG("%s- %s%s (loglevel%s %s)%s", indent4,
1168 event->name,
1169 enabled_string(event->enabled),
755066c2 1170 logleveltype_string(
41493f4a 1171 event->loglevel_type),
755066c2 1172 mi_lttng_loglevel_string(
41493f4a
SM
1173 event->loglevel,
1174 the_handle->domain
1175 .type),
7b4a95b1 1176 safe_string(filter_msg));
755066c2 1177 } else {
9a890ce8
JG
1178 MSG("%s- %s%s%s", indent4, event->name,
1179 enabled_string(event->enabled),
7b4a95b1 1180 safe_string(filter_msg));
755066c2 1181 }
9a890ce8 1182 free(filter_msg);
fb14d0d8
JR
1183 }
1184
1185 MSG("");
1186 }
1187
1188end:
1189 free(events);
1190error:
1191 return ret;
1192}
1193
1194/*
1195 * Machine interface
1196 * print a list of event
1197 */
1198static int mi_list_events(struct lttng_event *events, int count)
1199{
1200 int ret, i;
1201
1202 /* Open events element */
41493f4a 1203 ret = mi_lttng_events_open(the_writer);
fb14d0d8 1204 if (ret) {
3c6a091f
DG
1205 goto end;
1206 }
1207
1208 for (i = 0; i < count; i++) {
41493f4a
SM
1209 ret = mi_lttng_event(the_writer, &events[i], 0,
1210 the_handle->domain.type);
fb14d0d8
JR
1211 if (ret) {
1212 goto end;
1213 }
3c6a091f
DG
1214 }
1215
fb14d0d8 1216 /* Close events element */
41493f4a 1217 ret = mi_lttng_writer_close_element(the_writer);
3c6a091f
DG
1218
1219end:
3c6a091f
DG
1220 return ret;
1221}
1222
f3ed775e 1223/*
9f19cc17 1224 * List events of channel of session and domain.
f3ed775e 1225 */
cd80958d 1226static int list_events(const char *channel_name)
f3ed775e 1227{
fb14d0d8 1228 int ret = CMD_SUCCESS, count, i;
9f19cc17 1229 struct lttng_event *events = NULL;
f3ed775e 1230
41493f4a 1231 count = lttng_list_events(the_handle, channel_name, &events);
f3ed775e 1232 if (count < 0) {
fb14d0d8
JR
1233 ret = CMD_ERROR;
1234 ERR("%s", lttng_strerror(count));
f3ed775e
DG
1235 goto error;
1236 }
1237
fb14d0d8
JR
1238 if (lttng_opt_mi) {
1239 /* Mi print */
1240 ret = mi_list_events(events, count);
1241 if (ret) {
1242 ret = CMD_ERROR;
1243 goto end;
1244 }
1245 } else {
1246 /* Pretty print */
f3b3a67b 1247 MSG("\n%sEvent rules:", indent4);
fb14d0d8
JR
1248 if (count == 0) {
1249 MSG("%sNone\n", indent6);
1250 goto end;
1251 }
f3ed775e 1252
fb14d0d8
JR
1253 for (i = 0; i < count; i++) {
1254 print_events(&events[i]);
1255 }
f3ed775e 1256
fb14d0d8
JR
1257 MSG("");
1258 }
9f19cc17 1259end:
0e428499 1260 free(events);
f3ed775e
DG
1261error:
1262 return ret;
1263}
1264
f3b3a67b
JG
1265static
1266void print_timer(const char *timer_name, uint32_t space_count, int64_t value)
1267{
1268 uint32_t i;
1269
1270 _MSG("%s%s:", indent6, timer_name);
1271 for (i = 0; i < space_count; i++) {
1272 _MSG(" ");
1273 }
1274
1275 if (value) {
2a1135fa 1276 MSG("%" PRId64 " %s", value, USEC_UNIT);
f3b3a67b
JG
1277 } else {
1278 MSG("inactive");
1279 }
1280}
1281
f3ed775e 1282/*
9f19cc17
DG
1283 * Pretty print channel
1284 */
1285static void print_channel(struct lttng_channel *channel)
1286{
fb83fe64 1287 int ret;
cf0bcb51 1288 uint64_t discarded_events, lost_packets, monitor_timer_interval;
491d1539 1289 int64_t blocking_timeout;
fb83fe64
JD
1290
1291 ret = lttng_channel_get_discarded_event_count(channel,
1292 &discarded_events);
1293 if (ret) {
1294 ERR("Failed to retrieve discarded event count of channel");
1295 return;
1296 }
1297
1298 ret = lttng_channel_get_lost_packet_count(channel,
1299 &lost_packets);
1300 if (ret) {
1301 ERR("Failed to retrieve lost packet count of channel");
1302 return;
1303 }
1304
cf0bcb51
JG
1305 ret = lttng_channel_get_monitor_timer_interval(channel,
1306 &monitor_timer_interval);
1307 if (ret) {
1308 ERR("Failed to retrieve monitor interval of channel");
1309 return;
1310 }
1311
491d1539
MD
1312 ret = lttng_channel_get_blocking_timeout(channel,
1313 &blocking_timeout);
1314 if (ret) {
1315 ERR("Failed to retrieve blocking timeout of channel");
1316 return;
1317 }
1318
464dd62d 1319 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
9f19cc17 1320 MSG("%sAttributes:", indent4);
f3b3a67b
JG
1321 MSG("%sEvent-loss mode: %s", indent6, channel->attr.overwrite ? "overwrite" : "discard");
1322 MSG("%sSub-buffer size: %" PRIu64 " bytes", indent6, channel->attr.subbuf_size);
1323 MSG("%sSub-buffer count: %" PRIu64, indent6, channel->attr.num_subbuf);
1324
1325 print_timer("Switch timer", 5, channel->attr.switch_timer_interval);
1326 print_timer("Read timer", 7, channel->attr.read_timer_interval);
1327 print_timer("Monitor timer", 4, monitor_timer_interval);
1328
1329 if (!channel->attr.overwrite) {
1330 if (blocking_timeout == -1) {
1331 MSG("%sBlocking timeout: infinite", indent6);
1332 } else {
2a1135fa
JG
1333 MSG("%sBlocking timeout: %" PRId64 " %s", indent6,
1334 blocking_timeout, USEC_UNIT);
f3b3a67b
JG
1335 }
1336 }
1337
1338 MSG("%sTrace file count: %" PRIu64 " per stream", indent6,
1339 channel->attr.tracefile_count == 0 ?
1340 1 : channel->attr.tracefile_count);
1341 if (channel->attr.tracefile_size != 0 ) {
1342 MSG("%sTrace file size: %" PRIu64 " bytes", indent6,
1343 channel->attr.tracefile_size);
1344 } else {
1345 MSG("%sTrace file size: %s", indent6, "unlimited");
1346 }
9f19cc17
DG
1347 switch (channel->attr.output) {
1348 case LTTNG_EVENT_SPLICE:
f3b3a67b 1349 MSG("%sOutput mode: splice", indent6);
9f19cc17
DG
1350 break;
1351 case LTTNG_EVENT_MMAP:
f3b3a67b 1352 MSG("%sOutput mode: mmap", indent6);
9f19cc17
DG
1353 break;
1354 }
e50e81d3 1355
f3b3a67b 1356 MSG("\n%sStatistics:", indent4);
41493f4a 1357 if (the_listed_session.snapshot_mode) {
e50e81d3
JG
1358 /*
1359 * The lost packet count is omitted for sessions in snapshot
1360 * mode as it is misleading: it would indicate the number of
1361 * packets that the consumer could not extract during the
1362 * course of recording the snapshot. It does not have the
1363 * same meaning as the "regular" lost packet count that
1364 * would result from the consumer not keeping up with
1365 * event production in an overwrite-mode channel.
1366 *
1367 * A more interesting statistic would be the number of
1368 * packets lost between the first and last extracted
1369 * packets of a given snapshot (which prevents most analyses).
1370 */
f3b3a67b 1371 MSG("%sNone", indent6);
e50e81d3
JG
1372 goto skip_stats_printing;
1373 }
1374
1375 if (!channel->attr.overwrite) {
f3b3a67b 1376 MSG("%sDiscarded events: %" PRIu64, indent6, discarded_events);
e50e81d3 1377 } else {
f3b3a67b 1378 MSG("%sLost packets: %" PRIu64, indent6, lost_packets);
e50e81d3
JG
1379 }
1380skip_stats_printing:
1381 return;
9f19cc17
DG
1382}
1383
fb14d0d8
JR
1384/*
1385 * Machine interface
1386 * Print a list of channel
1387 *
1388 */
1389static int mi_list_channels(struct lttng_channel *channels, int count,
1390 const char *channel_name)
1391{
1392 int i, ret;
1393 unsigned int chan_found = 0;
1394
1395 /* Open channels element */
41493f4a 1396 ret = mi_lttng_channels_open(the_writer);
fb14d0d8
JR
1397 if (ret) {
1398 goto error;
1399 }
1400
1401 for (i = 0; i < count; i++) {
1402 if (channel_name != NULL) {
1403 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1404 chan_found = 1;
1405 } else {
1406 continue;
1407 }
1408 }
1409
1410 /* Write channel element and leave it open */
41493f4a 1411 ret = mi_lttng_channel(the_writer, &channels[i], 1);
fb14d0d8
JR
1412 if (ret) {
1413 goto error;
1414 }
1415
1416 /* Listing events per channel */
1417 ret = list_events(channels[i].name);
1418 if (ret) {
1419 goto error;
1420 }
1421
1422 /* Closing the channel element we opened earlier */
41493f4a 1423 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1424 if (ret) {
1425 goto error;
1426 }
1427
1428 if (chan_found) {
1429 break;
1430 }
1431 }
1432
1433 /* Close channels element */
41493f4a 1434 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1435 if (ret) {
1436 goto error;
1437 }
1438
1439error:
1440 return ret;
1441}
1442
9f19cc17
DG
1443/*
1444 * List channel(s) of session and domain.
f3ed775e 1445 *
9f19cc17 1446 * If channel_name is NULL, all channels are listed.
f3ed775e 1447 */
cd80958d 1448static int list_channels(const char *channel_name)
f3ed775e 1449{
9f19cc17
DG
1450 int count, i, ret = CMD_SUCCESS;
1451 unsigned int chan_found = 0;
1452 struct lttng_channel *channels = NULL;
f3ed775e 1453
3e25cb20 1454 DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
9f19cc17 1455
41493f4a 1456 count = lttng_list_channels(the_handle, &channels);
f3ed775e 1457 if (count < 0) {
c7d620a2
DG
1458 switch (-count) {
1459 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
fb14d0d8
JR
1460 if (lttng_opt_mi) {
1461 /* When printing mi this is not an error
1462 * but an empty channels element */
1463 count = 0;
1464 } else {
1465 ret = CMD_SUCCESS;
fb14d0d8
JR
1466 goto error_channels;
1467 }
c7d620a2
DG
1468 break;
1469 default:
1470 /* We had a real error */
fb14d0d8
JR
1471 ret = CMD_ERROR;
1472 ERR("%s", lttng_strerror(count));
1473 goto error_channels;
60e835ca 1474 break;
c7d620a2 1475 }
f3ed775e
DG
1476 }
1477
fb14d0d8
JR
1478 if (lttng_opt_mi) {
1479 /* Mi print */
1480 ret = mi_list_channels(channels, count, channel_name);
1481 if (ret) {
1482 ret = CMD_ERROR;
1483 goto error;
1484 }
1485 } else {
1486 /* Pretty print */
ade7ce52 1487 if (count) {
fb14d0d8
JR
1488 MSG("Channels:\n-------------");
1489 }
9f19cc17 1490
fb14d0d8
JR
1491 for (i = 0; i < count; i++) {
1492 if (channel_name != NULL) {
1493 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1494 chan_found = 1;
1495 } else {
1496 continue;
1497 }
1498 }
1499 print_channel(&channels[i]);
1500
1501 /* Listing events per channel */
1502 ret = list_events(channels[i].name);
1503 if (ret) {
1504 goto error;
1505 }
1506
1507 if (chan_found) {
1508 break;
9f19cc17
DG
1509 }
1510 }
9f19cc17 1511
fb14d0d8
JR
1512 if (!chan_found && channel_name != NULL) {
1513 ret = CMD_ERROR;
1514 ERR("Channel %s not found", channel_name);
1515 goto error;
9f19cc17 1516 }
fb14d0d8
JR
1517 }
1518error:
1519 free(channels);
9f19cc17 1520
fb14d0d8
JR
1521error_channels:
1522 return ret;
1523}
1524
159b042f 1525static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr)
83d6d6c4 1526{
159b042f
JG
1527 switch (process_attr) {
1528 case LTTNG_PROCESS_ATTR_PROCESS_ID:
1529 return "Process ID";
1530 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
1531 return "Virtual process ID";
1532 case LTTNG_PROCESS_ATTR_USER_ID:
1533 return "User ID";
1534 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
1535 return "Virtual user ID";
1536 case LTTNG_PROCESS_ATTR_GROUP_ID:
1537 return "Group ID";
1538 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
1539 return "Virtual group ID";
1540 default:
1541 return "Unknown";
83d6d6c4
JR
1542 }
1543 return NULL;
1544}
1545
159b042f
JG
1546static int handle_process_attr_status(enum lttng_process_attr process_attr,
1547 enum lttng_process_attr_tracker_handle_status status)
1548{
1549 int ret = CMD_SUCCESS;
1550
1551 switch (status) {
1552 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
1553 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
1554 /* Carry on. */
1555 break;
1556 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
1557 ERR("Communication occurred while fetching %s tracker",
1558 lttng_process_attr_to_string(process_attr));
1559 ret = CMD_ERROR;
1560 break;
1561 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
1562 ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists",
1563 lttng_process_attr_to_string(process_attr),
41493f4a 1564 the_handle->session_name);
159b042f
JG
1565 ret = CMD_ERROR;
1566 break;
1567 default:
1568 ERR("Unknown error occurred while fetching the inclusion set of the %s tracker",
1569 lttng_process_attr_to_string(process_attr));
1570 ret = CMD_ERROR;
1571 break;
1572 }
1573
1574 return ret;
1575}
1576
1577static int mi_output_empty_tracker(enum lttng_process_attr process_attr)
1578{
1579 int ret;
1580
41493f4a 1581 ret = mi_lttng_process_attribute_tracker_open(the_writer, process_attr);
159b042f
JG
1582 if (ret) {
1583 goto end;
1584 }
1585
41493f4a 1586 ret = mi_lttng_close_multi_element(the_writer, 2);
159b042f
JG
1587end:
1588 return ret;
1589}
1590
1591static inline bool is_value_type_name(
1592 enum lttng_process_attr_value_type value_type)
1593{
1594 return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ||
1595 value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME;
1596}
1597
a5dfbb9d 1598/*
159b042f 1599 * List a process attribute tracker for a session and domain tuple.
a5dfbb9d 1600 */
159b042f 1601static int list_process_attr_tracker(enum lttng_process_attr process_attr)
a5dfbb9d 1602{
ebbf5ab7 1603 int ret = 0;
159b042f
JG
1604 unsigned int count, i;
1605 enum lttng_tracking_policy policy;
1606 enum lttng_error_code ret_code;
1607 enum lttng_process_attr_tracker_handle_status handle_status;
1608 enum lttng_process_attr_values_status values_status;
1609 const struct lttng_process_attr_values *values;
1610 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
1611
41493f4a
SM
1612 ret_code = lttng_session_get_tracker_handle(the_handle->session_name,
1613 the_handle->domain.type, process_attr, &tracker_handle);
159b042f
JG
1614 if (ret_code != LTTNG_OK) {
1615 ERR("Failed to get process attribute tracker handle: %s",
1616 lttng_strerror(ret_code));
1617 ret = CMD_ERROR;
1618 goto end;
1619 }
a5dfbb9d 1620
159b042f
JG
1621 handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
1622 tracker_handle, &values);
1623 ret = handle_process_attr_status(process_attr, handle_status);
1624 if (ret != CMD_SUCCESS) {
1625 goto end;
a5dfbb9d 1626 }
a7a533cd 1627
159b042f
JG
1628 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
1629 tracker_handle, &policy);
1630 ret = handle_process_attr_status(process_attr, handle_status);
1631 if (ret != CMD_SUCCESS) {
e283e4a0
JR
1632 goto end;
1633 }
1634
159b042f
JG
1635 {
1636 char *process_attr_name;
1637 const int print_ret = asprintf(&process_attr_name, "%ss:",
1638 get_capitalized_process_attr_str(process_attr));
1639
1640 if (print_ret == -1) {
1641 ret = CMD_FATAL;
1642 goto end;
a7a533cd 1643 }
159b042f
JG
1644 _MSG(" %-22s", process_attr_name);
1645 free(process_attr_name);
1646 }
1647 switch (policy) {
1648 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
1649 break;
1650 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
41493f4a 1651 if (the_writer) {
159b042f
JG
1652 mi_output_empty_tracker(process_attr);
1653 }
1654 MSG("none");
1655 ret = CMD_SUCCESS;
1656 goto end;
1657 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
1658 MSG("all");
1659 ret = CMD_SUCCESS;
1660 goto end;
1661 default:
1662 ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`",
1663 lttng_process_attr_to_string(process_attr),
41493f4a 1664 the_handle->session_name);
159b042f
JG
1665 ret = CMD_FATAL;
1666 goto end;
83d6d6c4 1667 }
a7a533cd 1668
159b042f
JG
1669 values_status = lttng_process_attr_values_get_count(values, &count);
1670 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1671 ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`",
1672 lttng_process_attr_to_string(process_attr),
41493f4a 1673 the_handle->session_name);
159b042f
JG
1674 ret = CMD_FATAL;
1675 goto end;
1676 }
a5dfbb9d 1677
159b042f
JG
1678 if (count == 0) {
1679 /* Functionally equivalent to the 'exclude all' policy. */
41493f4a 1680 if (the_writer) {
159b042f 1681 mi_output_empty_tracker(process_attr);
ebbf5ab7 1682 }
159b042f
JG
1683 MSG("none");
1684 ret = CMD_SUCCESS;
1685 goto end;
1686 }
ebbf5ab7 1687
159b042f 1688 /* Mi tracker_id element */
41493f4a 1689 if (the_writer) {
159b042f
JG
1690 /* Open tracker_id and targets elements */
1691 ret = mi_lttng_process_attribute_tracker_open(
41493f4a 1692 the_writer, process_attr);
159b042f
JG
1693 if (ret) {
1694 goto end;
1695 }
1696 }
2d97a006 1697
159b042f
JG
1698 for (i = 0; i < count; i++) {
1699 const enum lttng_process_attr_value_type value_type =
1700 lttng_process_attr_values_get_type_at_index(
1701 values, i);
1702 int64_t integral_value = INT64_MAX;
1703 const char *name = "error";
1704
1705 if (i >= 1) {
1706 _MSG(", ");
1707 }
1708 switch (value_type) {
1709 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID:
1710 {
1711 pid_t pid;
1712
1713 values_status = lttng_process_attr_values_get_pid_at_index(
1714 values, i, &pid);
1715 integral_value = (int64_t) pid;
1716 break;
1717 }
1718 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID:
1719 {
1720 uid_t uid;
a7a533cd 1721
159b042f
JG
1722 values_status = lttng_process_attr_values_get_uid_at_index(
1723 values, i, &uid);
1724 integral_value = (int64_t) uid;
1725 break;
1726 }
1727 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID:
1728 {
1729 gid_t gid;
2d97a006 1730
159b042f
JG
1731 values_status = lttng_process_attr_values_get_gid_at_index(
1732 values, i, &gid);
1733 integral_value = (int64_t) gid;
1734 break;
1735 }
1736 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME:
1737 values_status = lttng_process_attr_values_get_user_name_at_index(
1738 values, i, &name);
1739 break;
1740 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME:
1741 values_status = lttng_process_attr_values_get_group_name_at_index(
1742 values, i, &name);
1743 break;
1744 default:
1745 ret = CMD_ERROR;
1746 goto end;
1747 }
83d6d6c4 1748
159b042f
JG
1749 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1750 /*
1751 * Not possible given the current liblttng-ctl
1752 * implementation.
1753 */
1754 ERR("Unknown error occurred while fetching process attribute value in inclusion list");
1755 ret = CMD_FATAL;
1756 goto end;
1757 }
ebbf5ab7 1758
159b042f
JG
1759 if (is_value_type_name(value_type)) {
1760 _MSG("`%s`", name);
1761 } else {
1762 _MSG("%" PRIi64, integral_value);
a5dfbb9d 1763 }
ebbf5ab7 1764
159b042f 1765 /* Mi */
41493f4a 1766 if (the_writer) {
159b042f
JG
1767 ret = is_value_type_name(value_type) ?
1768 mi_lttng_string_process_attribute_value(
41493f4a
SM
1769 the_writer,
1770 process_attr, name,
1771 false) :
159b042f 1772 mi_lttng_integral_process_attribute_value(
41493f4a
SM
1773 the_writer,
1774 process_attr,
1775 integral_value, false);
ebbf5ab7
JR
1776 if (ret) {
1777 goto end;
1778 }
1779 }
a5dfbb9d 1780 }
159b042f
JG
1781 MSG("");
1782
1783 /* Mi close tracker_id and targets */
41493f4a
SM
1784 if (the_writer) {
1785 ret = mi_lttng_close_multi_element(the_writer, 2);
159b042f
JG
1786 if (ret) {
1787 goto end;
1788 }
1789 }
ebbf5ab7 1790end:
159b042f 1791 lttng_process_attr_tracker_handle_destroy(tracker_handle);
ebbf5ab7 1792 return ret;
ebbf5ab7
JR
1793}
1794
1795/*
83d6d6c4 1796 * List all trackers of a domain
ebbf5ab7 1797 */
83d6d6c4 1798static int list_trackers(const struct lttng_domain *domain)
ebbf5ab7 1799{
0dda6728 1800 int ret = 0;
ebbf5ab7 1801
159b042f 1802 MSG("Tracked process attributes");
ebbf5ab7
JR
1803 /* Trackers listing */
1804 if (lttng_opt_mi) {
41493f4a 1805 ret = mi_lttng_trackers_open(the_writer);
ebbf5ab7
JR
1806 if (ret) {
1807 goto end;
1808 }
1809 }
1810
83d6d6c4
JR
1811 switch (domain->type) {
1812 case LTTNG_DOMAIN_KERNEL:
1813 /* pid tracker */
159b042f 1814 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID);
83d6d6c4
JR
1815 if (ret) {
1816 goto end;
1817 }
1818 /* vpid tracker */
159b042f
JG
1819 ret = list_process_attr_tracker(
1820 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
83d6d6c4
JR
1821 if (ret) {
1822 goto end;
1823 }
1824 /* uid tracker */
159b042f 1825 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID);
83d6d6c4
JR
1826 if (ret) {
1827 goto end;
1828 }
1829 /* vuid tracker */
159b042f
JG
1830 ret = list_process_attr_tracker(
1831 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
83d6d6c4
JR
1832 if (ret) {
1833 goto end;
1834 }
1835 /* gid tracker */
159b042f 1836 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID);
83d6d6c4
JR
1837 if (ret) {
1838 goto end;
1839 }
1840 /* vgid tracker */
159b042f
JG
1841 ret = list_process_attr_tracker(
1842 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
83d6d6c4
JR
1843 if (ret) {
1844 goto end;
1845 }
1846 break;
1847 case LTTNG_DOMAIN_UST:
1848 /* vpid tracker */
159b042f
JG
1849 ret = list_process_attr_tracker(
1850 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
83d6d6c4
JR
1851 if (ret) {
1852 goto end;
1853 }
1854 /* vuid tracker */
159b042f
JG
1855 ret = list_process_attr_tracker(
1856 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
83d6d6c4
JR
1857 if (ret) {
1858 goto end;
1859 }
1860 /* vgid tracker */
159b042f
JG
1861 ret = list_process_attr_tracker(
1862 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
83d6d6c4
JR
1863 if (ret) {
1864 goto end;
1865 }
1866 break;
1867 default:
1868 break;
ebbf5ab7 1869 }
159b042f 1870 MSG();
ebbf5ab7
JR
1871 if (lttng_opt_mi) {
1872 /* Close trackers element */
41493f4a 1873 ret = mi_lttng_writer_close_element(the_writer);
ebbf5ab7
JR
1874 if (ret) {
1875 goto end;
1876 }
1877 }
1878
1879end:
1880 return ret;
a5dfbb9d
MD
1881}
1882
66ea93b1
JG
1883static enum cmd_error_code print_periodic_rotation_schedule(
1884 const struct lttng_rotation_schedule *schedule)
1885{
1886 enum cmd_error_code ret;
1887 enum lttng_rotation_status status;
1888 uint64_t value;
1889
1890 status = lttng_rotation_schedule_periodic_get_period(schedule,
1891 &value);
1892 if (status != LTTNG_ROTATION_STATUS_OK) {
1893 ERR("Failed to retrieve period parameter from periodic rotation schedule.");
1894 ret = CMD_ERROR;
1895 goto end;
1896 }
1897
2a1135fa 1898 MSG(" timer period: %" PRIu64" %s", value, USEC_UNIT);
66ea93b1
JG
1899 ret = CMD_SUCCESS;
1900end:
1901 return ret;
1902}
1903
1904static enum cmd_error_code print_size_threshold_rotation_schedule(
1905 const struct lttng_rotation_schedule *schedule)
1906{
1907 enum cmd_error_code ret;
1908 enum lttng_rotation_status status;
1909 uint64_t value;
1910
1911 status = lttng_rotation_schedule_size_threshold_get_threshold(schedule,
1912 &value);
1913 if (status != LTTNG_ROTATION_STATUS_OK) {
1914 ERR("Failed to retrieve size parameter from size-based rotation schedule.");
1915 ret = CMD_ERROR;
1916 goto end;
1917 }
1918
1919 MSG(" size threshold: %" PRIu64" bytes", value);
66ea93b1
JG
1920 ret = CMD_SUCCESS;
1921end:
1922 return ret;
1923}
1924
1925static enum cmd_error_code print_rotation_schedule(
1926 const struct lttng_rotation_schedule *schedule)
1927{
1928 enum cmd_error_code ret;
1929
1930 switch (lttng_rotation_schedule_get_type(schedule)) {
1931 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
1932 ret = print_size_threshold_rotation_schedule(schedule);
1933 break;
1934 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
1935 ret = print_periodic_rotation_schedule(schedule);
1936 break;
1937 default:
1938 ret = CMD_ERROR;
1939 }
1940 return ret;
1941}
1942
329f3443 1943/*
66ea93b1 1944 * List the automatic rotation settings.
329f3443 1945 */
66ea93b1 1946static enum cmd_error_code list_rotate_settings(const char *session_name)
329f3443
JD
1947{
1948 int ret;
66ea93b1
JG
1949 enum cmd_error_code cmd_ret = CMD_SUCCESS;
1950 unsigned int count, i;
1951 struct lttng_rotation_schedules *schedules = NULL;
1952 enum lttng_rotation_status status;
1953
1954 ret = lttng_session_list_rotation_schedules(session_name, &schedules);
1955 if (ret != LTTNG_OK) {
1956 ERR("Failed to list session rotation schedules: %s", lttng_strerror(ret));
1957 cmd_ret = CMD_ERROR;
329f3443
JD
1958 goto end;
1959 }
1960
66ea93b1
JG
1961 status = lttng_rotation_schedules_get_count(schedules, &count);
1962 if (status != LTTNG_ROTATION_STATUS_OK) {
1963 ERR("Failed to retrieve the number of session rotation schedules.");
1964 cmd_ret = CMD_ERROR;
329f3443
JD
1965 goto end;
1966 }
1967
66ea93b1
JG
1968 if (count == 0) {
1969 cmd_ret = CMD_SUCCESS;
329f3443
JD
1970 goto end;
1971 }
1972
66ea93b1
JG
1973 MSG("Automatic rotation schedules:");
1974 if (lttng_opt_mi) {
41493f4a 1975 ret = mi_lttng_writer_open_element(the_writer,
66ea93b1
JG
1976 mi_lttng_element_rotation_schedules);
1977 if (ret) {
1978 cmd_ret = CMD_ERROR;
1979 goto end;
329f3443
JD
1980 }
1981 }
66ea93b1
JG
1982
1983 for (i = 0; i < count; i++) {
1984 enum cmd_error_code tmp_ret = CMD_SUCCESS;
1985 const struct lttng_rotation_schedule *schedule;
1986
1987 schedule = lttng_rotation_schedules_get_at_index(schedules, i);
1988 if (!schedule) {
1989 ERR("Failed to retrieve session rotation schedule.");
1990 cmd_ret = CMD_ERROR;
1991 goto end;
1992 }
1993
329f3443 1994 if (lttng_opt_mi) {
41493f4a 1995 ret = mi_lttng_rotation_schedule(the_writer, schedule);
329f3443 1996 if (ret) {
66ea93b1 1997 tmp_ret = CMD_ERROR;
329f3443 1998 }
66ea93b1
JG
1999 } else {
2000 tmp_ret = print_rotation_schedule(schedule);
329f3443 2001 }
66ea93b1
JG
2002
2003 /*
2004 * Report an error if the serialization of any of the
2005 * descriptors failed.
2006 */
2007 cmd_ret = cmd_ret ? cmd_ret : tmp_ret;
329f3443 2008 }
329f3443 2009
66ea93b1
JG
2010 _MSG("\n");
2011 if (lttng_opt_mi) {
2012 /* Close the rotation_schedules element. */
41493f4a 2013 ret = mi_lttng_writer_close_element(the_writer);
66ea93b1
JG
2014 if (ret) {
2015 cmd_ret = CMD_ERROR;
2016 goto end;
2017 }
2018 }
329f3443 2019end:
66ea93b1
JG
2020 lttng_rotation_schedules_destroy(schedules);
2021 return cmd_ret;
329f3443
JD
2022}
2023
fb14d0d8
JR
2024/*
2025 * Machine interface
2026 * Find the session with session_name as name
2027 * and print his informations.
2028 */
2029static int mi_list_session(const char *session_name,
2030 struct lttng_session *sessions, int count)
2031{
2032 int ret, i;
2033 unsigned int session_found = 0;
2034
2035 if (session_name == NULL) {
2036 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2037 goto end;
2038 }
2039
2040 for (i = 0; i < count; i++) {
2041 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2042 /* We need to leave it open to append other informations
2043 * like domain, channel, events etc.*/
2044 session_found = 1;
41493f4a 2045 ret = mi_lttng_session(the_writer, &sessions[i], 1);
fb14d0d8
JR
2046 if (ret) {
2047 goto end;
2048 }
9f19cc17 2049 break;
f3ed775e 2050 }
f3ed775e
DG
2051 }
2052
fb14d0d8
JR
2053 if (!session_found) {
2054 ERR("Session '%s' not found", session_name);
2055 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2056 goto end;
9f19cc17 2057 }
f3ed775e 2058
fb14d0d8
JR
2059end:
2060 return ret;
2061}
f3ed775e 2062
fb14d0d8
JR
2063/*
2064 * Machine interface
2065 * List all availables session
2066 */
2067static int mi_list_sessions(struct lttng_session *sessions, int count)
2068{
2069 int ret, i;
ae856491 2070
fb14d0d8 2071 /* Opening sessions element */
41493f4a 2072 ret = mi_lttng_sessions_open(the_writer);
fb14d0d8
JR
2073 if (ret) {
2074 goto end;
2075 }
2076
2077 /* Listing sessions */
2078 for (i = 0; i < count; i++) {
41493f4a 2079 ret = mi_lttng_session(the_writer, &sessions[i], 0);
fb14d0d8
JR
2080 if (ret) {
2081 goto end;
2082 }
2083 }
2084
2085 /* Closing sessions element */
41493f4a 2086 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2087 if (ret) {
2088 goto end;
2089 }
2090
2091end:
f3ed775e
DG
2092 return ret;
2093}
2094
2095/*
9f19cc17 2096 * List available tracing session. List only basic information.
f3ed775e 2097 *
9f19cc17 2098 * If session_name is NULL, all sessions are listed.
f3ed775e 2099 */
9f19cc17 2100static int list_sessions(const char *session_name)
f3ed775e 2101{
fb14d0d8
JR
2102 int ret = CMD_SUCCESS;
2103 int count, i;
9f19cc17 2104 unsigned int session_found = 0;
aff0fa72 2105 struct lttng_session *sessions = NULL;
9f19cc17
DG
2106
2107 count = lttng_list_sessions(&sessions);
2108 DBG("Session count %d", count);
2109 if (count < 0) {
fb14d0d8
JR
2110 ret = CMD_ERROR;
2111 ERR("%s", lttng_strerror(count));
d32fb093 2112 goto end;
9f19cc17
DG
2113 }
2114
fb14d0d8
JR
2115 if (lttng_opt_mi) {
2116 /* Mi */
2117 if (session_name == NULL) {
aff0fa72 2118 /* List all sessions */
fb14d0d8
JR
2119 ret = mi_list_sessions(sessions, count);
2120 } else {
2121 /* Note : this return an open session element */
2122 ret = mi_list_session(session_name, sessions, count);
2123 }
2124 if (ret) {
2125 ret = CMD_ERROR;
aff0fa72 2126 goto end;
fb14d0d8
JR
2127 }
2128 } else {
2129 /* Pretty print */
2130 if (count == 0) {
2131 MSG("Currently no available tracing session");
fb14d0d8
JR
2132 goto end;
2133 }
9f19cc17 2134
fb14d0d8
JR
2135 if (session_name == NULL) {
2136 MSG("Available tracing sessions:");
2137 }
2138
fb14d0d8
JR
2139 for (i = 0; i < count; i++) {
2140 if (session_name != NULL) {
2141 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2142 session_found = 1;
2143 MSG("Tracing session %s: [%s%s]", session_name,
2144 active_string(sessions[i].enabled),
2145 snapshot_string(sessions[i].snapshot_mode));
5b89fc92
JG
2146 if (*sessions[i].path) {
2147 MSG("%sTrace output: %s\n", indent4, sessions[i].path);
2148 }
41493f4a
SM
2149 memcpy(&the_listed_session,
2150 &sessions[i],
2151 sizeof(the_listed_session));
fb14d0d8
JR
2152 break;
2153 }
2154 } else {
5b89fc92
JG
2155 MSG(" %d) %s [%s%s]", i + 1,
2156 sessions[i].name,
2cbf8fed
DG
2157 active_string(sessions[i].enabled),
2158 snapshot_string(sessions[i].snapshot_mode));
5b89fc92
JG
2159 if (*sessions[i].path) {
2160 MSG("%sTrace output: %s", indent4, sessions[i].path);
2161 }
fcbc96a2 2162 if (sessions[i].live_timer_interval != 0) {
5b89fc92
JG
2163 MSG("%sLive timer interval: %u %s", indent4,
2164 sessions[i].live_timer_interval,
2165 USEC_UNIT);
fcbc96a2
JG
2166 }
2167 MSG("");
9f19cc17 2168 }
fb14d0d8
JR
2169 }
2170
2171 if (!session_found && session_name != NULL) {
2172 ERR("Session '%s' not found", session_name);
2173 ret = CMD_ERROR;
aff0fa72 2174 goto end;
fb14d0d8
JR
2175 }
2176
2177 if (session_name == NULL) {
2178 MSG("\nUse lttng list <session_name> for more details");
9f19cc17
DG
2179 }
2180 }
2181
fb14d0d8 2182end:
aff0fa72 2183 free(sessions);
fb14d0d8
JR
2184 return ret;
2185}
9f19cc17 2186
fb14d0d8
JR
2187
2188/*
2189 * Machine Interface
2190 * list available domain(s) for a session.
2191 */
2192static int mi_list_domains(struct lttng_domain *domains, int count)
2193{
2194 int i, ret;
2195 /* Open domains element */
41493f4a 2196 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2197 if (ret) {
2198 goto end;
9f19cc17
DG
2199 }
2200
fb14d0d8 2201 for (i = 0; i < count; i++) {
41493f4a 2202 ret = mi_lttng_domain(the_writer, &domains[i], 0);
fb14d0d8
JR
2203 if (ret) {
2204 goto end;
2205 }
9f19cc17 2206 }
f3ed775e 2207
fb14d0d8 2208 /* Closing domains element */
41493f4a 2209 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2210 if (ret) {
2211 goto end;
2212 }
d32fb093 2213end:
f3ed775e
DG
2214 return ret;
2215}
f3ed775e
DG
2216
2217/*
9f19cc17 2218 * List available domain(s) for a session.
f3ed775e 2219 */
330be774 2220static int list_domains(const char *session_name)
f3ed775e 2221{
9f19cc17
DG
2222 int i, count, ret = CMD_SUCCESS;
2223 struct lttng_domain *domains = NULL;
2224
9f19cc17 2225
330be774 2226 count = lttng_list_domains(session_name, &domains);
9f19cc17 2227 if (count < 0) {
fb14d0d8
JR
2228 ret = CMD_ERROR;
2229 ERR("%s", lttng_strerror(count));
9f19cc17
DG
2230 goto end;
2231 }
2232
fb14d0d8
JR
2233 if (lttng_opt_mi) {
2234 /* Mi output */
2235 ret = mi_list_domains(domains, count);
2236 if (ret) {
2237 ret = CMD_ERROR;
2238 goto error;
2239 }
2240 } else {
2241 /* Pretty print */
2242 MSG("Domains:\n-------------");
2243 if (count == 0) {
2244 MSG(" None");
2245 goto end;
2246 }
2247
2248 for (i = 0; i < count; i++) {
2249 switch (domains[i].type) {
2250 case LTTNG_DOMAIN_KERNEL:
2251 MSG(" - Kernel");
2252 break;
2253 case LTTNG_DOMAIN_UST:
2254 MSG(" - UST global");
2255 break;
2256 case LTTNG_DOMAIN_JUL:
2257 MSG(" - JUL (Java Util Logging)");
2258 break;
5cdb6027
DG
2259 case LTTNG_DOMAIN_LOG4J:
2260 MSG(" - LOG4j (Logging for Java)");
2261 break;
0e115563
DG
2262 case LTTNG_DOMAIN_PYTHON:
2263 MSG(" - Python (logging)");
2264 break;
fb14d0d8
JR
2265 default:
2266 break;
2267 }
9f19cc17
DG
2268 }
2269 }
2270
fb14d0d8 2271error:
9f19cc17
DG
2272 free(domains);
2273
fb14d0d8 2274end:
9f19cc17 2275 return ret;
f3ed775e 2276}
f3ed775e
DG
2277
2278/*
9f19cc17 2279 * The 'list <options>' first level command
f3ed775e
DG
2280 */
2281int cmd_list(int argc, const char **argv)
2282{
c617c0c6 2283 int opt, ret = CMD_SUCCESS;
68c7f6e5 2284 const char *session_name, *leftover = NULL;
f3ed775e 2285 static poptContext pc;
9f19cc17
DG
2286 struct lttng_domain domain;
2287 struct lttng_domain *domains = NULL;
f3ed775e 2288
441c16a7
MD
2289 memset(&domain, 0, sizeof(domain));
2290
9f19cc17 2291 if (argc < 1) {
ca1c3607 2292 ret = CMD_ERROR;
f3ed775e
DG
2293 goto end;
2294 }
2295
2296 pc = poptGetContext(NULL, argc, argv, long_options, 0);
2297 poptReadDefaultConfig(pc, 0);
2298
2299 while ((opt = poptGetNextOpt(pc)) != -1) {
2300 switch (opt) {
2301 case OPT_HELP:
4ba92f18 2302 SHOW_HELP();
f3ed775e 2303 goto end;
eeac7d46
MD
2304 case OPT_USERSPACE:
2305 opt_userspace = 1;
eeac7d46 2306 break;
679b4943
SM
2307 case OPT_LIST_OPTIONS:
2308 list_cmd_options(stdout, long_options);
679b4943 2309 goto end;
f3ed775e 2310 default:
f3ed775e
DG
2311 ret = CMD_UNDEFINED;
2312 goto end;
2313 }
2314 }
2315
fb14d0d8
JR
2316 /* Mi check */
2317 if (lttng_opt_mi) {
41493f4a
SM
2318 the_writer = mi_lttng_writer_create(
2319 fileno(stdout), lttng_opt_mi);
2320 if (!the_writer) {
fb14d0d8
JR
2321 ret = CMD_ERROR;
2322 goto end;
2323 }
2324
2325 /* Open command element */
41493f4a
SM
2326 ret = mi_lttng_writer_command_open(
2327 the_writer, mi_lttng_element_command_list);
fb14d0d8
JR
2328 if (ret) {
2329 ret = CMD_ERROR;
2330 goto end;
2331 }
2332
2333 /* Open output element */
41493f4a
SM
2334 ret = mi_lttng_writer_open_element(
2335 the_writer, mi_lttng_element_command_output);
fb14d0d8
JR
2336 if (ret) {
2337 ret = CMD_ERROR;
2338 goto end;
2339 }
2340 }
2341
9f19cc17
DG
2342 /* Get session name (trailing argument) */
2343 session_name = poptGetArg(pc);
b551a063 2344 DBG2("Session name: %s", session_name);
9f19cc17 2345
68c7f6e5
JD
2346 leftover = poptGetArg(pc);
2347 if (leftover) {
2348 ERR("Unknown argument: %s", leftover);
2349 ret = CMD_ERROR;
2350 goto end;
2351 }
2352
cd80958d
DG
2353 if (opt_kernel) {
2354 domain.type = LTTNG_DOMAIN_KERNEL;
b551a063
DG
2355 } else if (opt_userspace) {
2356 DBG2("Listing userspace global domain");
2357 domain.type = LTTNG_DOMAIN_UST;
3c6a091f
DG
2358 } else if (opt_jul) {
2359 DBG2("Listing JUL domain");
2360 domain.type = LTTNG_DOMAIN_JUL;
edf60534 2361 } else if (opt_log4j) {
5cdb6027 2362 domain.type = LTTNG_DOMAIN_LOG4J;
0e115563
DG
2363 } else if (opt_python) {
2364 domain.type = LTTNG_DOMAIN_PYTHON;
cd80958d
DG
2365 }
2366
834978fd
DG
2367 if (!opt_kernel && opt_syscall) {
2368 WARN("--syscall will only work with the Kernel domain (-k)");
2369 ret = CMD_ERROR;
2370 goto end;
2371 }
2372
0e115563 2373 if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) {
41493f4a
SM
2374 the_handle = lttng_create_handle(session_name, &domain);
2375 if (the_handle == NULL) {
aa5de748
MD
2376 ret = CMD_FATAL;
2377 goto end;
2378 }
cd80958d
DG
2379 }
2380
9f19cc17 2381 if (session_name == NULL) {
0e115563
DG
2382 if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j
2383 && !opt_python) {
b551a063 2384 ret = list_sessions(NULL);
fb14d0d8 2385 if (ret) {
b551a063
DG
2386 goto end;
2387 }
2388 }
9f19cc17 2389 if (opt_kernel) {
834978fd
DG
2390 if (opt_syscall) {
2391 ret = list_syscalls();
2392 if (ret) {
2393 goto end;
2394 }
2395 } else {
2396 ret = list_kernel_events();
2397 if (ret) {
2398 goto end;
2399 }
9f19cc17 2400 }
b551a063
DG
2401 }
2402 if (opt_userspace) {
f37d259d
MD
2403 if (opt_fields) {
2404 ret = list_ust_event_fields();
2405 } else {
2406 ret = list_ust_events();
2407 }
fb14d0d8 2408 if (ret) {
9f19cc17
DG
2409 goto end;
2410 }
2411 }
0e115563 2412 if (opt_jul || opt_log4j || opt_python) {
5cdb6027 2413 ret = list_agent_events();
fb14d0d8 2414 if (ret) {
3c6a091f
DG
2415 goto end;
2416 }
2417 }
9f19cc17
DG
2418 } else {
2419 /* List session attributes */
fb14d0d8
JR
2420 if (lttng_opt_mi) {
2421 /* Open element sessions
2422 * Present for xml consistency */
41493f4a 2423 ret = mi_lttng_sessions_open(the_writer);
fb14d0d8
JR
2424 if (ret) {
2425 goto end;
2426 }
2427 }
2428 /* MI: the ouptut of list_sessions is an unclosed session element */
9f19cc17 2429 ret = list_sessions(session_name);
fb14d0d8 2430 if (ret) {
9f19cc17
DG
2431 goto end;
2432 }
2433
329f3443
JD
2434 ret = list_rotate_settings(session_name);
2435 if (ret) {
2436 goto end;
2437 }
2438
9f19cc17
DG
2439 /* Domain listing */
2440 if (opt_domain) {
330be774 2441 ret = list_domains(session_name);
9f19cc17
DG
2442 goto end;
2443 }
2444
fb14d0d8 2445 /* Channel listing */
1c3de747 2446 if (opt_kernel || opt_userspace) {
fb14d0d8
JR
2447 if (lttng_opt_mi) {
2448 /* Add of domains and domain element for xml
2449 * consistency and validation
2450 */
41493f4a 2451 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2452 if (ret) {
2453 goto end;
2454 }
2455
2456 /* Open domain and leave it open for
2457 * nested channels printing */
41493f4a 2458 ret = mi_lttng_domain(the_writer, &domain, 1);
fb14d0d8
JR
2459 if (ret) {
2460 goto end;
2461 }
2462
2463 }
2464
ebbf5ab7
JR
2465
2466 /* Trackers */
83d6d6c4 2467 ret = list_trackers(&domain);
a5dfbb9d
MD
2468 if (ret) {
2469 goto end;
2470 }
2471
ebbf5ab7 2472 /* Channels */
cd80958d 2473 ret = list_channels(opt_channel);
fb14d0d8
JR
2474 if (ret) {
2475 goto end;
2476 }
2477
2478 if (lttng_opt_mi) {
2479 /* Close domain and domain element */
41493f4a
SM
2480 ret = mi_lttng_close_multi_element(
2481 the_writer, 2);
fb14d0d8
JR
2482 }
2483 if (ret) {
9f19cc17
DG
2484 goto end;
2485 }
fb14d0d8
JR
2486
2487
9f19cc17 2488 } else {
c617c0c6
MD
2489 int i, nb_domain;
2490
9f19cc17 2491 /* We want all domain(s) */
330be774 2492 nb_domain = lttng_list_domains(session_name, &domains);
b551a063 2493 if (nb_domain < 0) {
fb14d0d8
JR
2494 ret = CMD_ERROR;
2495 ERR("%s", lttng_strerror(nb_domain));
9f19cc17
DG
2496 goto end;
2497 }
2498
fb14d0d8 2499 if (lttng_opt_mi) {
41493f4a 2500 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2501 if (ret) {
2502 ret = CMD_ERROR;
2503 goto end;
2504 }
2505 }
2506
b551a063 2507 for (i = 0; i < nb_domain; i++) {
9f19cc17
DG
2508 switch (domains[i].type) {
2509 case LTTNG_DOMAIN_KERNEL:
ac41e67e 2510 MSG("=== Domain: Linux kernel ===\n");
9f19cc17 2511 break;
b551a063 2512 case LTTNG_DOMAIN_UST:
ac41e67e 2513 MSG("=== Domain: User space ===\n");
74707e6e 2514 MSG("Buffering scheme: %s\n",
88c5f0d8 2515 domains[i].buf_type ==
74707e6e 2516 LTTNG_BUFFER_PER_PID ? "per-process" : "per-user");
b551a063 2517 break;
3c6a091f 2518 case LTTNG_DOMAIN_JUL:
ac41e67e 2519 MSG("=== Domain: java.util.logging (JUL) ===\n");
3c6a091f 2520 break;
5cdb6027 2521 case LTTNG_DOMAIN_LOG4J:
ac41e67e 2522 MSG("=== Domain: log4j ===\n");
5cdb6027 2523 break;
0e115563 2524 case LTTNG_DOMAIN_PYTHON:
ac41e67e 2525 MSG("=== Domain: Python logging ===\n");
0e115563 2526 break;
9f19cc17
DG
2527 default:
2528 MSG("=== Domain: Unimplemented ===\n");
2529 break;
2530 }
2531
fb14d0d8 2532 if (lttng_opt_mi) {
41493f4a
SM
2533 ret = mi_lttng_domain(the_writer,
2534 &domains[i], 1);
fb14d0d8
JR
2535 if (ret) {
2536 ret = CMD_ERROR;
2537 goto end;
2538 }
2539 }
2540
cd80958d 2541 /* Clean handle before creating a new one */
41493f4a
SM
2542 if (the_handle) {
2543 lttng_destroy_handle(the_handle);
aa5de748 2544 }
cd80958d 2545
41493f4a
SM
2546 the_handle = lttng_create_handle(
2547 session_name, &domains[i]);
2548 if (the_handle == NULL) {
ca1c3607 2549 ret = CMD_FATAL;
cd80958d
DG
2550 goto end;
2551 }
2552
5cdb6027 2553 if (domains[i].type == LTTNG_DOMAIN_JUL ||
0e115563
DG
2554 domains[i].type == LTTNG_DOMAIN_LOG4J ||
2555 domains[i].type == LTTNG_DOMAIN_PYTHON) {
5cdb6027 2556 ret = list_session_agent_events();
fb14d0d8 2557 if (ret) {
3c6a091f
DG
2558 goto end;
2559 }
cd7b2927
PP
2560
2561 goto next_domain;
3c6a091f 2562 }
a5dfbb9d
MD
2563
2564 switch (domains[i].type) {
2565 case LTTNG_DOMAIN_KERNEL:
2566 case LTTNG_DOMAIN_UST:
83d6d6c4 2567 ret = list_trackers(&domains[i]);
a5dfbb9d
MD
2568 if (ret) {
2569 goto end;
2570 }
2571 break;
2572 default:
2573 break;
2574 }
3c6a091f 2575
cd80958d 2576 ret = list_channels(opt_channel);
fb14d0d8
JR
2577 if (ret) {
2578 goto end;
2579 }
2580
cd7b2927 2581next_domain:
fb14d0d8
JR
2582 if (lttng_opt_mi) {
2583 /* Close domain element */
41493f4a
SM
2584 ret = mi_lttng_writer_close_element(
2585 the_writer);
fb14d0d8
JR
2586 if (ret) {
2587 ret = CMD_ERROR;
2588 goto end;
2589 }
2590 }
2591
2592 }
2593 if (lttng_opt_mi) {
2594 /* Close the domains, session and sessions element */
41493f4a
SM
2595 ret = mi_lttng_close_multi_element(
2596 the_writer, 3);
fb14d0d8
JR
2597 if (ret) {
2598 ret = CMD_ERROR;
9f19cc17
DG
2599 goto end;
2600 }
2601 }
2602 }
f3ed775e
DG
2603 }
2604
fb14d0d8
JR
2605 /* Mi closing */
2606 if (lttng_opt_mi) {
2607 /* Close output element */
41493f4a 2608 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2609 if (ret) {
2610 ret = CMD_ERROR;
2611 goto end;
2612 }
2613
2614 /* Command element close */
41493f4a 2615 ret = mi_lttng_writer_command_close(the_writer);
fb14d0d8
JR
2616 if (ret) {
2617 ret = CMD_ERROR;
2618 goto end;
2619 }
2620 }
f3ed775e 2621end:
fb14d0d8 2622 /* Mi clean-up */
41493f4a 2623 if (the_writer && mi_lttng_writer_destroy(the_writer)) {
fb14d0d8
JR
2624 /* Preserve original error code */
2625 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
2626 }
2627
0e428499 2628 free(domains);
41493f4a
SM
2629 if (the_handle) {
2630 lttng_destroy_handle(the_handle);
aa5de748 2631 }
cd80958d 2632
ca1c3607 2633 poptFreeContext(pc);
f3ed775e
DG
2634 return ret;
2635}
This page took 0.192548 seconds and 4 git commands to generate.