2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
17 #include <lttng/condition/event-rule-matches.h>
18 #include <lttng/lttng.h>
22 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(
40 const struct lttng_action
*action_list
)
42 unsigned int i
, count
;
43 enum lttng_action_status status
=
44 lttng_action_list_get_count(action_list
, &count
);
46 if (status
!= LTTNG_ACTION_STATUS_OK
) {
47 printf("Failed to get action count from action list\n");
51 for (i
= 0; i
< count
; i
++) {
52 const struct lttng_action
*action
=
53 lttng_action_list_get_at_index(
55 const enum lttng_action_type action_type
=
56 lttng_action_get_type(action
);
58 if (action_type
== LTTNG_ACTION_TYPE_NOTIFY
) {
65 /* Only expects named triggers. */
66 static bool is_trigger_name(const char *expected_trigger_name
,
67 struct lttng_notification
*notification
)
69 const char *trigger_name
= NULL
;
70 enum lttng_trigger_status trigger_status
;
71 const struct lttng_trigger
*trigger
;
74 trigger
= lttng_notification_get_trigger(notification
);
76 fprintf(stderr
, "Failed to get trigger from notification\n");
81 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
82 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
83 fprintf(stderr
, "Failed to get name from notification's trigger\n");
88 names_match
= strcmp(expected_trigger_name
, trigger_name
) == 0;
90 fprintf(stderr
, "Got an unexpected trigger name: name = '%s', expected name = '%s'\n",
91 trigger_name
, expected_trigger_name
);
97 int main(int argc
, char **argv
)
102 char *expected_trigger_name
= NULL
;
103 char *end_trigger_name
= NULL
;
104 struct lttng_triggers
*triggers
= NULL
;
105 unsigned int count
, i
, subcription_count
= 0;
106 enum lttng_trigger_status trigger_status
;
107 char *after_notif_register_file_path
= NULL
;
108 struct lttng_notification_channel
*notification_channel
= NULL
;
109 int expected_notifications
= 1, notification_count
= 0;
111 while ((option
= getopt_long(argc
, argv
, "a:b:c:t:", long_options
,
112 &option_index
)) != -1) {
115 after_notif_register_file_path
= strdup(optarg
);
118 expected_notifications
= atoi(optarg
);
121 end_trigger_name
= strdup(optarg
);
124 expected_trigger_name
= strdup(optarg
);
127 /* getopt_long already printed an error message. */
134 if (optind
!= argc
) {
140 notification_channel
= lttng_notification_channel_create(
141 lttng_session_daemon_notification_endpoint
);
142 if (!notification_channel
) {
143 fprintf(stderr
, "Failed to create notification channel\n");
148 ret
= lttng_list_triggers(&triggers
);
149 if (ret
!= LTTNG_OK
) {
150 fprintf(stderr
, "Failed to list triggers\n");
155 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
156 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
157 fprintf(stderr
, "Failed to get trigger count\n");
162 /* Look for the trigger we want to subscribe to. */
163 for (i
= 0; i
< count
; i
++) {
164 const struct lttng_trigger
*trigger
=
165 lttng_triggers_get_at_index(triggers
, i
);
166 const struct lttng_condition
*condition
=
167 lttng_trigger_get_const_condition(trigger
);
168 const struct lttng_action
*action
=
169 lttng_trigger_get_const_action(trigger
);
170 const enum lttng_action_type action_type
=
171 lttng_action_get_type(action
);
172 enum lttng_notification_channel_status channel_status
;
173 const char *trigger_name
= NULL
;
175 lttng_trigger_get_name(trigger
, &trigger_name
);
176 if (strcmp(trigger_name
, expected_trigger_name
)) {
177 /* Might match the end event trigger */
178 if (end_trigger_name
!= NULL
&&
184 if (!((action_type
== LTTNG_ACTION_TYPE_GROUP
&&
185 action_list_contains_notify(action
)) ||
186 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
187 /* "The action of trigger is not notify, skipping. */
191 channel_status
= lttng_notification_channel_subscribe(
192 notification_channel
, condition
);
193 if (channel_status
) {
194 fprintf(stderr
, "Failed to subscribe to notifications of trigger \"%s\"\n",
203 if (subcription_count
== 0) {
204 fprintf(stderr
, "No matching trigger with a notify action found.\n");
209 if (end_trigger_name
!= NULL
&& subcription_count
!= 2) {
210 fprintf(stderr
, "No matching end event trigger with a notify action found.\n");
216 * We registered to the notification of our target trigger. We can now
217 * create the sync file to signify that we are ready.
219 ret
= create_file(after_notif_register_file_path
);
225 struct lttng_notification
*notification
;
226 enum lttng_notification_channel_status channel_status
;
229 lttng_notification_channel_get_next_notification(
230 notification_channel
,
232 switch (channel_status
) {
233 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
234 printf("Dropped notification\n");
237 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
240 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
242 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
243 printf("Notification channel was closed by peer.\n");
246 fprintf(stderr
, "A communication error occurred on the notification channel.\n");
251 /* Early exit check. */
252 if (end_trigger_name
!= NULL
&&
253 is_trigger_name(end_trigger_name
,
255 /* Exit the loop immediately. */
256 printf("Received end event notification from trigger %s\n",
258 lttng_notification_destroy(notification
);
259 goto evaluate_success
;
262 ret
= is_trigger_name(expected_trigger_name
, notification
);
263 lttng_notification_destroy(notification
);
269 printf("Received event notification from trigger %s\n",
270 expected_trigger_name
);
271 notification_count
++;
272 if (end_trigger_name
== NULL
&&
273 expected_notifications
== notification_count
) {
275 * Here the loop exit is controlled by the number of
276 * notification and not by the reception of the end
277 * event trigger notification. This represent the
281 goto evaluate_success
;
286 if (expected_notifications
== notification_count
) {
290 fprintf(stderr
, "Expected %d notification got %d\n",
291 expected_notifications
, notification_count
);
296 lttng_triggers_destroy(triggers
);
297 lttng_notification_channel_destroy(notification_channel
);
298 free(after_notif_register_file_path
);
299 free(end_trigger_name
);
300 free(expected_trigger_name
);