2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: MIT
10 #include <lttng/condition/event-rule-matches.h>
11 #include <lttng/lttng.h>
22 static struct option long_options
[] = {
23 /* These options set a flag. */
24 { "trigger", required_argument
, 0, 't' },
25 { "sync-after-notif-register", required_argument
, 0, 'a' },
26 /* Default alue for count is 1 */
27 { "count", required_argument
, 0, 'b' },
29 * When end-trigger is present the reception loop is exited only when a
30 * notification matching the end trigger is received.
31 * Otherwise the loop is exited when the count of notification received
32 * for `trigger` math the `count` argument.
34 { "end-trigger", required_argument
, 0, 'c' },
38 static bool action_list_contains_notify(const struct lttng_action
*action_list
)
40 unsigned int i
, count
;
41 enum lttng_action_status status
= lttng_action_list_get_count(action_list
, &count
);
43 if (status
!= LTTNG_ACTION_STATUS_OK
) {
44 printf("Failed to get action count from action list\n");
48 for (i
= 0; i
< count
; i
++) {
49 const struct lttng_action
*action
= lttng_action_list_get_at_index(action_list
, i
);
50 const enum lttng_action_type action_type
= lttng_action_get_type(action
);
52 if (action_type
== LTTNG_ACTION_TYPE_NOTIFY
) {
59 /* Only expects named triggers. */
60 static bool is_trigger_name(const char *expected_trigger_name
,
61 struct lttng_notification
*notification
)
63 const char *trigger_name
= NULL
;
64 enum lttng_trigger_status trigger_status
;
65 const struct lttng_trigger
*trigger
;
68 trigger
= lttng_notification_get_trigger(notification
);
70 fprintf(stderr
, "Failed to get trigger from notification\n");
75 trigger_status
= lttng_trigger_get_name(trigger
, &trigger_name
);
76 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
77 fprintf(stderr
, "Failed to get name from notification's trigger\n");
82 names_match
= strcmp(expected_trigger_name
, trigger_name
) == 0;
85 "Got an unexpected trigger name: name = '%s', expected name = '%s'\n",
87 expected_trigger_name
);
93 int main(int argc
, char **argv
)
98 char *expected_trigger_name
= NULL
;
99 char *end_trigger_name
= NULL
;
100 struct lttng_triggers
*triggers
= NULL
;
101 unsigned int count
, i
, subcription_count
= 0;
102 enum lttng_trigger_status trigger_status
;
103 char *after_notif_register_file_path
= NULL
;
104 struct lttng_notification_channel
*notification_channel
= NULL
;
105 int expected_notifications
= 1, notification_count
= 0;
107 while ((option
= getopt_long(argc
, argv
, "a:b:c:t:", long_options
, &option_index
)) != -1) {
110 after_notif_register_file_path
= strdup(optarg
);
113 expected_notifications
= atoi(optarg
);
116 end_trigger_name
= strdup(optarg
);
119 expected_trigger_name
= strdup(optarg
);
122 /* getopt_long already printed an error message. */
129 if (optind
!= argc
) {
134 notification_channel
=
135 lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
136 if (!notification_channel
) {
137 fprintf(stderr
, "Failed to create notification channel\n");
142 ret
= lttng_list_triggers(&triggers
);
143 if (ret
!= LTTNG_OK
) {
144 fprintf(stderr
, "Failed to list triggers\n");
149 trigger_status
= lttng_triggers_get_count(triggers
, &count
);
150 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
151 fprintf(stderr
, "Failed to get trigger count\n");
156 /* Look for the trigger we want to subscribe to. */
157 for (i
= 0; i
< count
; i
++) {
158 const struct lttng_trigger
*trigger
= lttng_triggers_get_at_index(triggers
, i
);
159 const struct lttng_condition
*condition
=
160 lttng_trigger_get_const_condition(trigger
);
161 const struct lttng_action
*action
= lttng_trigger_get_const_action(trigger
);
162 const enum lttng_action_type action_type
= lttng_action_get_type(action
);
163 enum lttng_notification_channel_status channel_status
;
164 const char *trigger_name
= NULL
;
166 lttng_trigger_get_name(trigger
, &trigger_name
);
167 if (strcmp(trigger_name
, expected_trigger_name
) != 0) {
168 /* Might match the end event trigger */
169 if (end_trigger_name
!= NULL
&&
170 strcmp(trigger_name
, end_trigger_name
) != 0) {
174 if (!((action_type
== LTTNG_ACTION_TYPE_LIST
&&
175 action_list_contains_notify(action
)) ||
176 action_type
== LTTNG_ACTION_TYPE_NOTIFY
)) {
177 /* "The action of trigger is not notify, skipping. */
182 lttng_notification_channel_subscribe(notification_channel
, condition
);
183 if (channel_status
) {
185 "Failed to subscribe to notifications of trigger \"%s\"\n",
194 if (subcription_count
== 0) {
195 fprintf(stderr
, "No matching trigger with a notify action found.\n");
200 if (end_trigger_name
!= NULL
&& subcription_count
!= 2) {
201 fprintf(stderr
, "No matching end event trigger with a notify action found.\n");
207 * We registered to the notification of our target trigger. We can now
208 * create the sync file to signify that we are ready.
210 ret
= create_file(after_notif_register_file_path
);
216 struct lttng_notification
*notification
;
217 enum lttng_notification_channel_status channel_status
;
219 channel_status
= lttng_notification_channel_get_next_notification(
220 notification_channel
, ¬ification
);
221 switch (channel_status
) {
222 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
223 printf("Dropped notification\n");
226 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
:
229 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
231 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
232 printf("Notification channel was closed by peer.\n");
236 "A communication error occurred on the notification channel.\n");
241 /* Early exit check. */
242 if (end_trigger_name
!= NULL
&& is_trigger_name(end_trigger_name
, notification
)) {
243 /* Exit the loop immediately. */
244 printf("Received end event notification from trigger %s\n",
246 lttng_notification_destroy(notification
);
247 goto evaluate_success
;
250 ret
= is_trigger_name(expected_trigger_name
, notification
);
251 lttng_notification_destroy(notification
);
257 printf("Received event notification from trigger %s\n", expected_trigger_name
);
258 notification_count
++;
259 if (end_trigger_name
== NULL
&& expected_notifications
== notification_count
) {
261 * Here the loop exit is controlled by the number of
262 * notification and not by the reception of the end
263 * event trigger notification. This represent the
267 goto evaluate_success
;
272 if (expected_notifications
== notification_count
) {
277 "Expected %d notification got %d\n",
278 expected_notifications
,
284 lttng_triggers_destroy(triggers
);
285 lttng_notification_channel_destroy(notification_channel
);
286 free(after_notif_register_file_path
);
287 free(end_trigger_name
);
288 free(expected_trigger_name
);