2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
10 #include <lttng/action/list-internal.hpp>
11 #include <lttng/condition/event-rule-matches.h>
12 #include <lttng/lttng.h>
23 static struct option long_options
[] = {
24 /* These options set a flag. */
25 { "trigger", required_argument
, 0, 't' },
26 { "sync-after-notif-register", required_argument
, 0, 'a' },
27 /* Default alue for count is 1 */
28 { "count", required_argument
, 0, 'b' },
30 * When end-trigger is present the reception loop is exited only when a
31 * notification matching the end trigger is received.
32 * Otherwise the loop is exited when the count of notification received
33 * for `trigger` math the `count` argument.
35 { "end-trigger", required_argument
, 0, 'c' },
39 static bool action_list_contains_notify(const struct lttng_action
*action_list
)
41 for (auto sub_action
: lttng::ctl::const_action_list_view(action_list
)) {
42 if (lttng_action_get_type(sub_action
) == LTTNG_ACTION_TYPE_NOTIFY
) {
50 /* Only expects named triggers. */
51 static bool is_trigger_name(const char *expected_trigger_name
,
52 struct lttng_notification
*notification
)
54 const char *trigger_name
= NULL
;
55 enum lttng_trigger_status trigger_status
;
56 const struct lttng_trigger
*trigger
;
59 trigger
= lttng_notification_get_trigger(notification
);
61 fprintf(stderr
, "Failed to get trigger from notification\n");
66 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
67 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
68 fprintf(stderr
, "Failed to get name from notification's trigger\n");
73 names_match
= strcmp(expected_trigger_name
, trigger_name
) == 0;
76 "Got an unexpected trigger name: name = '%s', expected name = '%s'\n",
78 expected_trigger_name
);
84 int main(int argc
, char **argv
)
89 char *expected_trigger_name
= NULL
;
90 char *end_trigger_name
= NULL
;
91 struct lttng_triggers
*triggers
= NULL
;
92 unsigned int count
, i
, subcription_count
= 0;
93 enum lttng_trigger_status trigger_status
;
94 char *after_notif_register_file_path
= NULL
;
95 struct lttng_notification_channel
*notification_channel
= NULL
;
96 int expected_notifications
= 1, notification_count
= 0;
98 while ((option
= getopt_long(argc
, argv
, "a:b:c:t:", long_options
, &option_index
)) != -1) {
101 after_notif_register_file_path
= strdup(optarg
);
104 expected_notifications
= atoi(optarg
);
107 end_trigger_name
= strdup(optarg
);
110 expected_trigger_name
= strdup(optarg
);
113 /* getopt_long already printed an error message. */
120 if (optind
!= argc
) {
125 notification_channel
=
126 lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
127 if (!notification_channel
) {
128 fprintf(stderr
, "Failed to create notification channel\n");
133 ret
= lttng_list_triggers(&triggers
);
134 if (ret
!= LTTNG_OK
) {
135 fprintf(stderr
, "Failed to list triggers\n");
140 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
141 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
142 fprintf(stderr
, "Failed to get trigger count\n");
147 /* Look for the trigger we want to subscribe to. */
148 for (i
= 0; i
< count
; i
++) {
149 const struct lttng_trigger
*trigger
= lttng_triggers_get_at_index(triggers
, i
);
150 const struct lttng_condition
*condition
=
151 lttng_trigger_get_const_condition(trigger
);
152 const struct lttng_action
*action
= lttng_trigger_get_const_action(trigger
);
153 const enum lttng_action_type action_type
= lttng_action_get_type(action
);
154 enum lttng_notification_channel_status channel_status
;
155 const char *trigger_name
= NULL
;
157 lttng_trigger_get_name(trigger
, &trigger_name
);
158 if (strcmp(trigger_name
, expected_trigger_name
) != 0) {
159 /* Might match the end event trigger */
160 if (end_trigger_name
!= NULL
&&
161 strcmp(trigger_name
, end_trigger_name
) != 0) {
165 if (!((action_type
== LTTNG_ACTION_TYPE_LIST
&&
166 action_list_contains_notify(action
)) ||
167 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
168 /* "The action of trigger is not notify, skipping. */
173 lttng_notification_channel_subscribe(notification_channel
, condition
);
174 if (channel_status
) {
176 "Failed to subscribe to notifications of trigger \"%s\"\n",
185 if (subcription_count
== 0) {
186 fprintf(stderr
, "No matching trigger with a notify action found.\n");
191 if (end_trigger_name
!= NULL
&& subcription_count
!= 2) {
192 fprintf(stderr
, "No matching end event trigger with a notify action found.\n");
198 * We registered to the notification of our target trigger. We can now
199 * create the sync file to signify that we are ready.
201 ret
= create_file(after_notif_register_file_path
);
207 struct lttng_notification
*notification
;
208 enum lttng_notification_channel_status channel_status
;
210 channel_status
= lttng_notification_channel_get_next_notification(
211 notification_channel
, ¬ification
);
212 switch (channel_status
) {
213 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
214 printf("Dropped notification\n");
217 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
220 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
222 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
223 printf("Notification channel was closed by peer.\n");
227 "A communication error occurred on the notification channel.\n");
232 /* Early exit check. */
233 if (end_trigger_name
!= NULL
&& is_trigger_name(end_trigger_name
, notification
)) {
234 /* Exit the loop immediately. */
235 printf("Received end event notification from trigger %s\n",
237 lttng_notification_destroy(notification
);
238 goto evaluate_success
;
241 ret
= is_trigger_name(expected_trigger_name
, notification
);
242 lttng_notification_destroy(notification
);
248 printf("Received event notification from trigger %s\n", expected_trigger_name
);
249 notification_count
++;
250 if (end_trigger_name
== NULL
&& expected_notifications
== notification_count
) {
252 * Here the loop exit is controlled by the number of
253 * notification and not by the reception of the end
254 * event trigger notification. This represent the
258 goto evaluate_success
;
263 if (expected_notifications
== notification_count
) {
268 "Expected %d notification got %d\n",
269 expected_notifications
,
275 lttng_triggers_destroy(triggers
);
276 lttng_notification_channel_destroy(notification_channel
);
277 free(after_notif_register_file_path
);
278 free(end_trigger_name
);
279 free(expected_trigger_name
);