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 static bool is_trigger_name(const char *expected_trigger_name
,
66 struct lttng_notification
*notification
)
68 const char *trigger_name
= NULL
;
69 enum lttng_trigger_status trigger_status
;
70 const struct lttng_trigger
*trigger
;
73 trigger
= lttng_notification_get_trigger(notification
);
75 fprintf(stderr
, "Failed to get trigger from notification\n");
80 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
81 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
82 fprintf(stderr
, "Failed to get name from notification's trigger\n");
87 names_match
= strcmp(expected_trigger_name
, trigger_name
) == 0;
89 fprintf(stderr
, "Got an unexpected trigger name: name = '%s', expected name = '%s'\n",
90 trigger_name
, expected_trigger_name
);
96 int main(int argc
, char **argv
)
101 char *expected_trigger_name
= NULL
;
102 char *end_trigger_name
= NULL
;
103 struct lttng_triggers
*triggers
= NULL
;
104 unsigned int count
, i
, subcription_count
= 0;
105 enum lttng_trigger_status trigger_status
;
106 char *after_notif_register_file_path
= NULL
;
107 struct lttng_notification_channel
*notification_channel
= NULL
;
108 int expected_notifications
= 1, notification_count
= 0;
110 while ((option
= getopt_long(argc
, argv
, "a:b:c:t:", long_options
,
111 &option_index
)) != -1) {
114 after_notif_register_file_path
= strdup(optarg
);
117 expected_notifications
= atoi(optarg
);
120 end_trigger_name
= strdup(optarg
);
123 expected_trigger_name
= strdup(optarg
);
126 /* getopt_long already printed an error message. */
133 if (optind
!= argc
) {
139 notification_channel
= lttng_notification_channel_create(
140 lttng_session_daemon_notification_endpoint
);
141 if (!notification_channel
) {
142 fprintf(stderr
, "Failed to create notification channel\n");
147 ret
= lttng_list_triggers(&triggers
);
148 if (ret
!= LTTNG_OK
) {
149 fprintf(stderr
, "Failed to list triggers\n");
154 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
155 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
156 fprintf(stderr
, "Failed to get trigger count\n");
161 /* Look for the trigger we want to subscribe to. */
162 for (i
= 0; i
< count
; i
++) {
163 const struct lttng_trigger
*trigger
=
164 lttng_triggers_get_at_index(triggers
, i
);
165 const struct lttng_condition
*condition
=
166 lttng_trigger_get_const_condition(trigger
);
167 const struct lttng_action
*action
=
168 lttng_trigger_get_const_action(trigger
);
169 const enum lttng_action_type action_type
=
170 lttng_action_get_type(action
);
171 enum lttng_notification_channel_status channel_status
;
172 const char *trigger_name
= NULL
;
174 lttng_trigger_get_name(trigger
, &trigger_name
);
175 if (strcmp(trigger_name
, expected_trigger_name
)) {
176 /* Might match the end event trigger */
177 if (end_trigger_name
!= NULL
&&
183 if (!((action_type
== LTTNG_ACTION_TYPE_GROUP
&&
184 action_list_contains_notify(action
)) ||
185 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
186 /* "The action of trigger is not notify, skipping. */
190 channel_status
= lttng_notification_channel_subscribe(
191 notification_channel
, condition
);
192 if (channel_status
) {
193 fprintf(stderr
, "Failed to subscribe to notifications of trigger \"%s\"\n",
202 if (subcription_count
== 0) {
203 fprintf(stderr
, "No matching trigger with a notify action found.\n");
208 if (end_trigger_name
!= NULL
&& subcription_count
!= 2) {
209 fprintf(stderr
, "No matching end event trigger with a notify action found.\n");
215 * We registered to the notification of our target trigger. We can now
216 * create the sync file to signify that we are ready.
218 ret
= create_file(after_notif_register_file_path
);
224 struct lttng_notification
*notification
;
225 enum lttng_notification_channel_status channel_status
;
228 lttng_notification_channel_get_next_notification(
229 notification_channel
,
231 switch (channel_status
) {
232 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
233 printf("Dropped notification\n");
236 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
239 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
241 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
242 printf("Notification channel was closed by peer.\n");
245 fprintf(stderr
, "A communication error occurred on the notification channel.\n");
250 /* Early exit check. */
251 if (end_trigger_name
!= NULL
&&
252 is_trigger_name(end_trigger_name
,
254 /* Exit the loop immediately. */
255 printf("Received end event notification from trigger %s\n",
257 lttng_notification_destroy(notification
);
258 goto evaluate_success
;
261 ret
= is_trigger_name(expected_trigger_name
, notification
);
262 lttng_notification_destroy(notification
);
268 printf("Received event notification from trigger %s\n",
269 expected_trigger_name
);
270 notification_count
++;
271 if (end_trigger_name
== NULL
&&
272 expected_notifications
== notification_count
) {
274 * Here the loop exit is controlled by the number of
275 * notification and not by the reception of the end
276 * event trigger notification. This represent the
280 goto evaluate_success
;
285 if (expected_notifications
== notification_count
) {
289 fprintf(stderr
, "Expected %d notification got %d\n",
290 expected_notifications
, notification_count
);
295 lttng_triggers_destroy(triggers
);
296 lttng_notification_channel_destroy(notification_channel
);
297 free(after_notif_register_file_path
);
298 free(end_trigger_name
);
299 free(expected_trigger_name
);