Move firing policy from lttng_trigger to lttng_action
[lttng-tools.git] / src / bin / lttng / commands / list_triggers.c
CommitLineData
0de2479d
SM
1/*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#include <stdio.h>
9
10#include "../command.h"
11
12#include "common/argpar/argpar.h"
13#include "common/dynamic-array.h"
14#include "common/mi-lttng.h"
15/* For lttng_condition_type_str(). */
16#include "lttng/condition/condition-internal.h"
90aa04a1
FD
17#include "lttng/condition/on-event.h"
18#include "lttng/condition/on-event-internal.h"
0de2479d
SM
19/* For lttng_domain_type_str(). */
20#include "lttng/domain-internal.h"
85b05318 21#include "../loglevel.h"
0de2479d
SM
22
23#ifdef LTTNG_EMBED_HELP
24static const char help_msg[] =
279eb769 25#include <lttng-list-triggers.1.h>
0de2479d
SM
26;
27#endif
28
29enum {
30 OPT_HELP,
31 OPT_LIST_OPTIONS,
32};
33
34static const
35struct argpar_opt_descr list_trigger_options[] = {
36 { OPT_HELP, 'h', "help", false },
37 { OPT_LIST_OPTIONS, '\0', "list-options", false },
38 ARGPAR_OPT_DESCR_SENTINEL,
39};
40
85b05318
JR
41/*
42 * Returns the human-readable log level name associated with a numerical value
43 * if there is one. The Log4j and JUL domains have discontinuous log level
44 * values (a value can fall between two labels). In those cases, NULL is
45 * returned.
46 */
47static const char *get_pretty_loglevel_name(
48 enum lttng_domain_type domain, int loglevel)
49{
50 const char *name = NULL;
51
52 switch (domain) {
53 case LTTNG_DOMAIN_UST:
54 name = loglevel_value_to_name(loglevel);
55 break;
56 case LTTNG_DOMAIN_LOG4J:
57 name = loglevel_log4j_value_to_name(loglevel);
58 break;
59 case LTTNG_DOMAIN_JUL:
60 name = loglevel_jul_value_to_name(loglevel);
61 break;
62 case LTTNG_DOMAIN_PYTHON:
63 name = loglevel_python_value_to_name(loglevel);
64 break;
65 default:
66 break;
67 }
68
69 return name;
70}
71
0de2479d
SM
72static
73void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule)
74{
75 enum lttng_event_rule_status event_rule_status;
76 enum lttng_domain_type domain_type;
77 const char *pattern;
78 const char *filter;
79 int log_level;
85b05318 80 const struct lttng_log_level_rule *log_level_rule = NULL;
0de2479d
SM
81 unsigned int exclusions_count;
82 int i;
83
84 event_rule_status = lttng_event_rule_tracepoint_get_pattern(
85 event_rule, &pattern);
86 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
87
88 event_rule_status = lttng_event_rule_tracepoint_get_domain_type(
89 event_rule, &domain_type);
90 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
91
92 _MSG(" rule: %s (type: tracepoint, domain: %s", pattern,
93 lttng_domain_type_str(domain_type));
94
95 event_rule_status = lttng_event_rule_tracepoint_get_filter(
96 event_rule, &filter);
97 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
98 _MSG(", filter: %s", filter);
99 } else {
100 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
101 }
102
85b05318
JR
103 event_rule_status = lttng_event_rule_tracepoint_get_log_level_rule(
104 event_rule, &log_level_rule);
0de2479d 105 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
85b05318 106 enum lttng_log_level_rule_status llr_status;
0de2479d 107 const char *log_level_op;
85b05318
JR
108 const char *pretty_loglevel_name;
109
110 switch (lttng_log_level_rule_get_type(log_level_rule)) {
111 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
112 log_level_op = "is";
113 llr_status = lttng_log_level_rule_exactly_get_level(
114 log_level_rule, &log_level);
115 break;
116 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
117 log_level_op = "at least";
118 llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
119 log_level_rule, &log_level);
120 break;
121 default:
122 abort();
123 }
124
125 assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
126
127 pretty_loglevel_name = get_pretty_loglevel_name(
128 domain_type, log_level);
129 if (pretty_loglevel_name) {
130 _MSG(", log level %s %s", log_level_op,
131 pretty_loglevel_name);
132 } else {
133 _MSG(", log level %s %d", log_level_op, log_level);
134 }
0de2479d
SM
135 } else {
136 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
137 }
138
139 event_rule_status = lttng_event_rule_tracepoint_get_exclusions_count(
140 event_rule, &exclusions_count);
141 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
142 if (exclusions_count > 0) {
143 _MSG(", exclusions: ");
144 for (i = 0; i < exclusions_count; i++) {
145 const char *exclusion;
146
147 event_rule_status = lttng_event_rule_tracepoint_get_exclusion_at_index(
148 event_rule, i, &exclusion);
149 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
150
151 _MSG("%s%s", i > 0 ? "," : "", exclusion);
152 }
153 }
154
155 MSG(")");
156}
157
158static void print_kernel_probe_location(
159 const struct lttng_kernel_probe_location *location)
160{
161 enum lttng_kernel_probe_location_status status;
162 switch (lttng_kernel_probe_location_get_type(location)) {
163 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
164 {
165 uint64_t address;
166
167 status = lttng_kernel_probe_location_address_get_address(
168 location, &address);
169 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
170 ERR("Getting kernel probe location address failed.");
171 goto end;
172 }
173
174 _MSG("0x%" PRIx64, address);
175
176 break;
177 }
178 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
179 {
180 uint64_t offset;
181 const char *symbol_name;
182
183 symbol_name = lttng_kernel_probe_location_symbol_get_name(
184 location);
185 if (!symbol_name) {
186 ERR("Getting kernel probe location symbol name failed.");
187 goto end;
188 }
189
190 status = lttng_kernel_probe_location_symbol_get_offset(
191 location, &offset);
192 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
193 ERR("Getting kernel probe location address failed.");
194 goto end;
195 }
196
197 if (offset == 0) {
198 _MSG("%s", symbol_name);
199 } else {
200 _MSG("%s+0x%" PRIx64, symbol_name, offset);
201 }
202
203 break;
204 }
205 default:
206 abort();
207 };
208end:
209 return;
210}
211
212static
f2791161 213void print_event_rule_kernel_probe(const struct lttng_event_rule *event_rule)
0de2479d
SM
214{
215 enum lttng_event_rule_status event_rule_status;
216 const char *name;
217 const struct lttng_kernel_probe_location *location;
218
f2791161 219 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE);
0de2479d 220
d891bb52 221 event_rule_status = lttng_event_rule_kernel_probe_get_event_name(event_rule, &name);
0de2479d
SM
222 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
223 ERR("Failed to get kprobe event rule's name.");
224 goto end;
225 }
226
f2791161 227 event_rule_status = lttng_event_rule_kernel_probe_get_location(
0de2479d
SM
228 event_rule, &location);
229 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
230 ERR("Failed to get kprobe event rule's location.");
231 goto end;
232 }
233
234 _MSG(" rule: %s (type: probe, location: ", name);
235
236 print_kernel_probe_location(location);
237
238 MSG(")");
239
240end:
241 return;
242}
243
244static
1f1567a5 245void print_event_rule_userspace_probe(const struct lttng_event_rule *event_rule)
0de2479d
SM
246{
247 enum lttng_event_rule_status event_rule_status;
248 const char *name;
249 const struct lttng_userspace_probe_location *location;
250 enum lttng_userspace_probe_location_type userspace_probe_location_type;
251
1f1567a5 252 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE);
0de2479d 253
405f9e7d
JR
254 event_rule_status = lttng_event_rule_userspace_probe_get_event_name(
255 event_rule, &name);
0de2479d
SM
256 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
257 ERR("Failed to get uprobe event rule's name.");
258 goto end;
259 }
260
1f1567a5 261 event_rule_status = lttng_event_rule_userspace_probe_get_location(
0de2479d
SM
262 event_rule, &location);
263 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
264 ERR("Failed to get uprobe event rule's location.");
265 goto end;
266 }
267
268 _MSG(" rule: %s (type: userspace probe, location: ", name);
269
270 userspace_probe_location_type =
271 lttng_userspace_probe_location_get_type(location);
272
273 switch (userspace_probe_location_type) {
274 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
275 {
276 const char *binary_path, *function_name;
277
278 binary_path = lttng_userspace_probe_location_function_get_binary_path(
279 location);
280 function_name = lttng_userspace_probe_location_function_get_function_name(
281 location);
282
283 _MSG("%s:%s", binary_path, function_name);
284 break;
285 }
286 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
287 _MSG("SDT not implemented yet");
288 break;
289 default:
290 abort();
291 }
292
293 MSG(")");
294
295end:
296 return;
297}
298
299static
300void print_event_rule_syscall(const struct lttng_event_rule *event_rule)
301{
302 const char *pattern, *filter;
303 enum lttng_event_rule_status event_rule_status;
304
305 assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL);
306
307 event_rule_status = lttng_event_rule_syscall_get_pattern(
308 event_rule, &pattern);
309 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
310
311 _MSG(" rule: %s (type: syscall", pattern);
312
313 event_rule_status = lttng_event_rule_syscall_get_filter(
314 event_rule, &filter);
315 if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) {
316 _MSG(", filter: %s", filter);
317 } else {
318 assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET);
319 }
320
321 MSG(")");
322}
323
324static
325void print_event_rule(const struct lttng_event_rule *event_rule)
326{
327 const enum lttng_event_rule_type event_rule_type =
328 lttng_event_rule_get_type(event_rule);
329
330 switch (event_rule_type) {
331 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
332 print_event_rule_tracepoint(event_rule);
333 break;
f2791161
JR
334 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
335 print_event_rule_kernel_probe(event_rule);
0de2479d 336 break;
1f1567a5
JR
337 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
338 print_event_rule_userspace_probe(event_rule);
0de2479d
SM
339 break;
340 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
341 print_event_rule_syscall(event_rule);
342 break;
343 default:
344 abort();
345 }
346}
347
b203b4b0
SM
348static
349void print_one_event_expr(const struct lttng_event_expr *event_expr)
350{
351 enum lttng_event_expr_type type;
352
353 type = lttng_event_expr_get_type(event_expr);
354
355 switch (type) {
356 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
357 {
358 const char *name;
359
360 name = lttng_event_expr_event_payload_field_get_name(
361 event_expr);
362 _MSG("%s", name);
363
364 break;
365 }
366 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
367 {
368 const char *name;
369
370 name = lttng_event_expr_channel_context_field_get_name(
371 event_expr);
372 _MSG("$ctx.%s", name);
373
374 break;
375 }
376 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
377 {
378 const char *provider_name;
379 const char *type_name;
380
381 provider_name = lttng_event_expr_app_specific_context_field_get_provider_name(
382 event_expr);
383 type_name = lttng_event_expr_app_specific_context_field_get_type_name(
384 event_expr);
385
386 _MSG("$app.%s:%s", provider_name, type_name);
387
388 break;
389 }
390 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
391 {
392 unsigned int index;
393 const struct lttng_event_expr *parent_expr;
394 enum lttng_event_expr_status status;
395
396 parent_expr = lttng_event_expr_array_field_element_get_parent_expr(
397 event_expr);
398 assert(parent_expr != NULL);
399
400 print_one_event_expr(parent_expr);
401
402 status = lttng_event_expr_array_field_element_get_index(
403 event_expr, &index);
404 assert(status == LTTNG_EVENT_EXPR_STATUS_OK);
405
406 _MSG("[%u]", index);
407
408 break;
409 }
410 default:
411 abort();
412 }
413}
414
0de2479d 415static
d602bd6a 416void print_condition_on_event(const struct lttng_condition *condition)
0de2479d
SM
417{
418 const struct lttng_event_rule *event_rule;
419 enum lttng_condition_status condition_status;
b203b4b0 420 unsigned int cap_desc_count, i;
90aa04a1 421 uint64_t error_count;
0de2479d
SM
422
423 condition_status =
d602bd6a 424 lttng_condition_on_event_get_rule(condition, &event_rule);
0de2479d
SM
425 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
426
427 print_event_rule(event_rule);
b203b4b0
SM
428
429 condition_status =
d602bd6a 430 lttng_condition_on_event_get_capture_descriptor_count(
b203b4b0
SM
431 condition, &cap_desc_count);
432 assert(condition_status == LTTNG_CONDITION_STATUS_OK);
433
90aa04a1 434 error_count = lttng_condition_on_event_get_error_count(condition);
71f3b9c7 435 MSG(" tracer notifications discarded: %" PRIu64, error_count);
90aa04a1 436
b203b4b0
SM
437 if (cap_desc_count > 0) {
438 MSG(" captures:");
439
440 for (i = 0; i < cap_desc_count; i++) {
441 const struct lttng_event_expr *cap_desc =
d602bd6a 442 lttng_condition_on_event_get_capture_descriptor_at_index(
b203b4b0
SM
443 condition, i);
444
445 _MSG(" - ");
446 print_one_event_expr(cap_desc);
447 MSG("");
448 }
449 }
0de2479d
SM
450}
451
452static
453void print_one_action(const struct lttng_action *action)
454{
455 enum lttng_action_type action_type;
456 enum lttng_action_status action_status;
e45dd625 457 const struct lttng_firing_policy *policy = NULL;
0de2479d
SM
458 const char *value;
459
460 action_type = lttng_action_get_type(action);
461 assert(action_type != LTTNG_ACTION_TYPE_GROUP);
462
463 switch (action_type) {
464 case LTTNG_ACTION_TYPE_NOTIFY:
e45dd625
JR
465 _MSG("notify");
466
467 action_status = lttng_action_notify_get_firing_policy(
468 action, &policy);
469 if (action_status != LTTNG_ACTION_STATUS_OK) {
470 ERR("Failed to retrieve firing policy.");
471 goto end;
472 }
0de2479d
SM
473 break;
474 case LTTNG_ACTION_TYPE_START_SESSION:
475 action_status = lttng_action_start_session_get_session_name(
476 action, &value);
477 assert(action_status == LTTNG_ACTION_STATUS_OK);
e45dd625
JR
478 _MSG("start session `%s`", value);
479
480 action_status = lttng_action_start_session_get_firing_policy(
481 action, &policy);
482 if (action_status != LTTNG_ACTION_STATUS_OK) {
483 ERR("Failed to retrieve firing policy.");
484 goto end;
485 }
0de2479d
SM
486 break;
487 case LTTNG_ACTION_TYPE_STOP_SESSION:
488 action_status = lttng_action_stop_session_get_session_name(
489 action, &value);
490 assert(action_status == LTTNG_ACTION_STATUS_OK);
e45dd625
JR
491 _MSG("stop session `%s`", value);
492
493 action_status = lttng_action_stop_session_get_firing_policy(
494 action, &policy);
495 if (action_status != LTTNG_ACTION_STATUS_OK) {
496 ERR("Failed to retrieve firing policy.");
497 goto end;
498 }
0de2479d
SM
499 break;
500 case LTTNG_ACTION_TYPE_ROTATE_SESSION:
501 action_status = lttng_action_rotate_session_get_session_name(
502 action, &value);
503 assert(action_status == LTTNG_ACTION_STATUS_OK);
e45dd625
JR
504 _MSG("rotate session `%s`", value);
505
506 action_status = lttng_action_rotate_session_get_firing_policy(
507 action, &policy);
508 if (action_status != LTTNG_ACTION_STATUS_OK) {
509 ERR("Failed to retrieve firing policy.");
510 goto end;
511 }
0de2479d
SM
512 break;
513 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
514 {
515 const struct lttng_snapshot_output *output;
516
517 action_status = lttng_action_snapshot_session_get_session_name(
518 action, &value);
519 assert(action_status == LTTNG_ACTION_STATUS_OK);
520 _MSG("snapshot session `%s`", value);
521
522 action_status = lttng_action_snapshot_session_get_output(
523 action, &output);
524 if (action_status == LTTNG_ACTION_STATUS_OK) {
525 const char *name;
526 uint64_t max_size;
527 const char *ctrl_url, *data_url;
528 bool starts_with_file, starts_with_net, starts_with_net6;
529
530 ctrl_url = lttng_snapshot_output_get_ctrl_url(output);
531 assert(ctrl_url && strlen(ctrl_url) > 0);
532
533 data_url = lttng_snapshot_output_get_data_url(output);
534 assert(data_url);
535
536 starts_with_file = strncmp(ctrl_url, "file://", strlen("file://")) == 0;
537 starts_with_net = strncmp(ctrl_url, "net://", strlen("net://")) == 0;
538 starts_with_net6 = strncmp(ctrl_url, "net6://", strlen("net6://")) == 0;
539
540 if (ctrl_url[0] == '/' || starts_with_file) {
541 if (starts_with_file) {
542 ctrl_url += strlen("file://");
543 }
544
545 _MSG(", path: %s", ctrl_url);
546 } else if (starts_with_net || starts_with_net6) {
547 _MSG(", url: %s", ctrl_url);
548 } else {
549 assert(strlen(data_url) > 0);
550
551 _MSG(", control url: %s, data url: %s", ctrl_url, data_url);
552 }
553
554 name = lttng_snapshot_output_get_name(output);
555 assert(name);
556 if (strlen(name) > 0) {
557 _MSG(", name: %s", name);
558 }
559
560 max_size = lttng_snapshot_output_get_maxsize(output);
561 if (max_size != -1ULL) {
562 _MSG(", max size: %" PRIu64, max_size);
563 }
564 }
565
e45dd625
JR
566 action_status = lttng_action_snapshot_session_get_firing_policy(
567 action, &policy);
568 if (action_status != LTTNG_ACTION_STATUS_OK) {
569 ERR("Failed to retrieve firing policy.");
570 goto end;
571 }
0de2479d
SM
572 break;
573 }
0de2479d
SM
574 default:
575 abort();
576 }
e45dd625
JR
577
578 if (policy) {
579 enum lttng_firing_policy_type policy_type;
580 enum lttng_firing_policy_status policy_status;
581 uint64_t policy_value = 0;
582
583 policy_type = lttng_firing_policy_get_type(policy);
584
585 switch (policy_type) {
586 case LTTNG_FIRING_POLICY_TYPE_EVERY_N:
587 policy_status = lttng_firing_policy_every_n_get_interval(
588 policy, &policy_value);
589 if (policy_status != LTTNG_FIRING_POLICY_STATUS_OK) {
590 ERR("Failed to get action firing policy interval");
591 goto end;
592 }
593 if (policy_value > 1) {
594 /* The default is 1 so print only when it is a
595 * special case.
596 */
597 _MSG(", firing policy: after every %" PRIu64
598 " occurrences",
599 policy_value);
600 }
601 break;
602 case LTTNG_FIRING_POLICY_TYPE_ONCE_AFTER_N:
603 policy_status = lttng_firing_policy_once_after_n_get_threshold(
604 policy, &policy_value);
605 if (policy_status != LTTNG_FIRING_POLICY_STATUS_OK) {
606 ERR("Failed to get action firing policy interval");
607 goto end;
608 }
609 _MSG(", firing policy: once after %" PRIu64
610 " occurrences",
611 policy_value);
612 break;
613 default:
614 abort();
615 }
616 }
617
618 MSG("");
619end:
620 return;
0de2479d
SM
621}
622
623static
624void print_one_trigger(const struct lttng_trigger *trigger)
625{
626 const struct lttng_condition *condition;
627 enum lttng_condition_type condition_type;
628 const struct lttng_action *action;
629 enum lttng_action_type action_type;
630 enum lttng_trigger_status trigger_status;
631 const char *name;
0de2479d
SM
632 uid_t trigger_uid;
633
634 trigger_status = lttng_trigger_get_name(trigger, &name);
635 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
636
637 trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_uid);
638 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
639
640 MSG("- id: %s", name);
641 MSG(" user id: %d", trigger_uid);
642
0de2479d
SM
643 condition = lttng_trigger_get_const_condition(trigger);
644 condition_type = lttng_condition_get_type(condition);
645 MSG(" condition: %s", lttng_condition_type_str(condition_type));
646 switch (condition_type) {
d602bd6a
JR
647 case LTTNG_CONDITION_TYPE_ON_EVENT:
648 print_condition_on_event(condition);
0de2479d
SM
649 break;
650 default:
651 MSG(" (condition type not handled in %s)", __func__);
652 break;
653 }
654
655 action = lttng_trigger_get_const_action(trigger);
656 action_type = lttng_action_get_type(action);
657 if (action_type == LTTNG_ACTION_TYPE_GROUP) {
658 unsigned int count, i;
659 enum lttng_action_status action_status;
660
661 MSG(" actions:");
662
663 action_status = lttng_action_group_get_count(action, &count);
664 assert(action_status == LTTNG_ACTION_STATUS_OK);
665
666 for (i = 0; i < count; i++) {
667 const struct lttng_action *subaction =
668 lttng_action_group_get_at_index(
669 action, i);
670
671 _MSG(" ");
672 print_one_action(subaction);
673 }
674 } else {
675 _MSG(" action:");
676 print_one_action(action);
677 }
678
0de2479d
SM
679}
680
681static
682int compare_triggers_by_name(const void *a, const void *b)
683{
684 const struct lttng_trigger *trigger_a = *((const struct lttng_trigger **) a);
685 const struct lttng_trigger *trigger_b = *((const struct lttng_trigger **) b);
686 const char *name_a, *name_b;
687 enum lttng_trigger_status trigger_status;
688
689 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
690 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
691
692 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
693 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
694
695 return strcmp(name_a, name_b);
696}
697
698int cmd_list_triggers(int argc, const char **argv)
699{
700 int ret;
701 struct argpar_parse_ret argpar_parse_ret = {};
702 struct lttng_triggers *triggers = NULL;
703 int i;
704 struct lttng_dynamic_pointer_array sorted_triggers;
705 enum lttng_trigger_status trigger_status;
706 unsigned int num_triggers;
707
708 lttng_dynamic_pointer_array_init(&sorted_triggers, NULL);
709
710 argpar_parse_ret = argpar_parse(
711 argc - 1, argv + 1, list_trigger_options, true);
712 if (!argpar_parse_ret.items) {
713 ERR("%s", argpar_parse_ret.error);
714 goto error;
715 }
716
717 for (i = 0; i < argpar_parse_ret.items->n_items; i++) {
718 const struct argpar_item *item =
719 argpar_parse_ret.items->items[i];
720
721 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
722 const struct argpar_item_opt *item_opt =
723 (const struct argpar_item_opt *) item;
724
725 switch (item_opt->descr->id) {
726 case OPT_HELP:
727 SHOW_HELP();
728 ret = 0;
729 goto end;
730
731 case OPT_LIST_OPTIONS:
732 list_cmd_options_argpar(stdout,
733 list_trigger_options);
734 ret = 0;
735 goto end;
736
737 default:
738 abort();
739 }
740
741 } else {
742 const struct argpar_item_non_opt *item_non_opt =
743 (const struct argpar_item_non_opt *) item;
744
745 ERR("Unexpected argument: %s", item_non_opt->arg);
746 }
747 }
748
749 ret = lttng_list_triggers(&triggers);
750 if (ret != LTTNG_OK) {
751 ERR("Error listing triggers: %s.", lttng_strerror(-ret));
752 goto error;
753 }
754
755 trigger_status = lttng_triggers_get_count(triggers, &num_triggers);
756 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
757 ERR("Failed to get trigger count.");
758 goto error;
759 }
760
761 for (i = 0; i < num_triggers; i++) {
762 const int add_ret = lttng_dynamic_pointer_array_add_pointer(
763 &sorted_triggers,
764 (void *) lttng_triggers_get_at_index(triggers, i));
765
766 if (add_ret) {
767 ERR("Failed to allocate array of struct lttng_trigger *.");
768 goto error;
769 }
770 }
771
772 qsort(sorted_triggers.array.buffer.data, num_triggers,
773 sizeof(struct lttng_trigger *),
774 compare_triggers_by_name);
775
776 for (i = 0; i < num_triggers; i++) {
777 const struct lttng_trigger *trigger_to_print =
778 (const struct lttng_trigger *)
779 lttng_dynamic_pointer_array_get_pointer(
780 &sorted_triggers, i);
781
782 print_one_trigger(trigger_to_print);
783 }
784
785 ret = 0;
786 goto end;
787
788error:
789 ret = 1;
790
791end:
792 argpar_parse_ret_fini(&argpar_parse_ret);
793 lttng_triggers_destroy(triggers);
794 lttng_dynamic_pointer_array_reset(&sorted_triggers);
795
796 return ret;
797}
This page took 0.05449 seconds and 4 git commands to generate.