clang-tidy: add most bugprone warnings
[lttng-tools.git] / tests / regression / tools / trigger / utils / notification-client.c
CommitLineData
6ba31891
FD
1/*
2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8#include <getopt.h>
9#include <stdbool.h>
10#include <stddef.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/time.h>
15#include <time.h>
16
670a26e4 17#include <lttng/condition/event-rule-matches.h>
6ba31891
FD
18#include <lttng/lttng.h>
19
20#include "utils.h"
21
22static struct option long_options[] =
23{
24 /* These options set a flag. */
7d59def2 25 {"trigger", required_argument, 0, 't'},
6ba31891 26 {"sync-after-notif-register", required_argument, 0, 'a'},
6ffce1f5
JR
27 /* Default alue for count is 1 */
28 {"count", required_argument, 0, 'b'},
29 /*
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.
34 */
35 {"end-trigger", required_argument, 0, 'c'},
6ba31891
FD
36 {0, 0, 0, 0}
37};
38
702f26c8
JR
39static bool action_list_contains_notify(
40 const struct lttng_action *action_list)
6ba31891
FD
41{
42 unsigned int i, count;
43 enum lttng_action_status status =
702f26c8 44 lttng_action_list_get_count(action_list, &count);
6ba31891
FD
45
46 if (status != LTTNG_ACTION_STATUS_OK) {
702f26c8 47 printf("Failed to get action count from action list\n");
6ba31891
FD
48 exit(1);
49 }
50
51 for (i = 0; i < count; i++) {
52 const struct lttng_action *action =
702f26c8
JR
53 lttng_action_list_get_at_index(
54 action_list, i);
6ba31891
FD
55 const enum lttng_action_type action_type =
56 lttng_action_get_type(action);
57
58 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
59 return true;
60 }
61 }
62 return false;
63}
64
0efb2ad7 65/* Only expects named triggers. */
7d59def2 66static bool is_trigger_name(const char *expected_trigger_name,
6ba31891
FD
67 struct lttng_notification *notification)
68{
65f64978
JG
69 const char *trigger_name = NULL;
70 enum lttng_trigger_status trigger_status;
71 const struct lttng_trigger *trigger;
72 bool names_match;
6ba31891 73
65f64978
JG
74 trigger = lttng_notification_get_trigger(notification);
75 if (!trigger) {
76 fprintf(stderr, "Failed to get trigger from notification\n");
77 names_match = false;
78 goto end;
6ba31891 79 }
65f64978
JG
80
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");
84 names_match = false;
85 goto end;
6ba31891
FD
86 }
87
65f64978 88 names_match = strcmp(expected_trigger_name, trigger_name) == 0;
7d59def2
JR
89 if (!names_match) {
90 fprintf(stderr, "Got an unexpected trigger name: name = '%s', expected name = '%s'\n",
91 trigger_name, expected_trigger_name);
92 }
65f64978
JG
93end:
94 return names_match;
6ba31891
FD
95}
96
97int main(int argc, char **argv)
98{
99 int ret;
100 int option;
101 int option_index;
3e68c9e8
JG
102 char *expected_trigger_name = NULL;
103 char *end_trigger_name = NULL;
6ba31891
FD
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;
6ffce1f5 109 int expected_notifications = 1, notification_count = 0;
6ba31891 110
6ffce1f5
JR
111 while ((option = getopt_long(argc, argv, "a:b:c:t:", long_options,
112 &option_index)) != -1) {
6ba31891
FD
113 switch (option) {
114 case 'a':
115 after_notif_register_file_path = strdup(optarg);
116 break;
6ffce1f5
JR
117 case 'b':
118 expected_notifications = atoi(optarg);
119 break;
120 case 'c':
121 end_trigger_name = strdup(optarg);
122 break;
6ba31891
FD
123 case 't':
124 expected_trigger_name = strdup(optarg);
125 break;
126 case '?':
127 /* getopt_long already printed an error message. */
128 default:
129 ret = -1;
130 goto end;
131 }
132 }
133
134 if (optind != argc) {
135 ret = -1;
136 goto end;
137 }
138
139
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");
144 ret = -1;
145 goto end;
146 }
147
148 ret = lttng_list_triggers(&triggers);
149 if (ret != LTTNG_OK) {
150 fprintf(stderr, "Failed to list triggers\n");
7d59def2 151 ret = -1;
6ba31891
FD
152 goto end;
153 }
154
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");
158 ret = -1;
159 goto end;
160 }
161
7d59def2 162 /* Look for the trigger we want to subscribe to. */
6ba31891
FD
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;
174
175 lttng_trigger_get_name(trigger, &trigger_name);
5c7248cd 176 if (strcmp(trigger_name, expected_trigger_name) != 0) {
6ffce1f5
JR
177 /* Might match the end event trigger */
178 if (end_trigger_name != NULL &&
179 strcmp(trigger_name,
5c7248cd 180 end_trigger_name) != 0) {
6ffce1f5
JR
181 continue;
182 }
6ba31891 183 }
7c2fae7c 184 if (!((action_type == LTTNG_ACTION_TYPE_LIST &&
702f26c8 185 action_list_contains_notify(action)) ||
6ba31891
FD
186 action_type == LTTNG_ACTION_TYPE_NOTIFY)) {
187 /* "The action of trigger is not notify, skipping. */
188 continue;
189 }
190
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",
195 trigger_name);
196 ret = -1;
197 goto end;
198 }
199
200 subcription_count++;
201 }
202
203 if (subcription_count == 0) {
6ffce1f5
JR
204 fprintf(stderr, "No matching trigger with a notify action found.\n");
205 ret = -1;
6ba31891
FD
206 goto end;
207 }
208
6ffce1f5
JR
209 if (end_trigger_name != NULL && subcription_count != 2) {
210 fprintf(stderr, "No matching end event trigger with a notify action found.\n");
211 ret = -1;
212 goto end;
213 }
6ba31891
FD
214
215 /*
216 * We registered to the notification of our target trigger. We can now
217 * create the sync file to signify that we are ready.
218 */
219 ret = create_file(after_notif_register_file_path);
220 if (ret != 0) {
221 goto end;
222 }
223
224 for (;;) {
225 struct lttng_notification *notification;
226 enum lttng_notification_channel_status channel_status;
227
228 channel_status =
229 lttng_notification_channel_get_next_notification(
230 notification_channel,
231 &notification);
232 switch (channel_status) {
233 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
234 printf("Dropped notification\n");
7d59def2
JR
235 ret = -1;
236 goto end;
6ba31891 237 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED:
7d59def2 238 ret = -1;
6ba31891
FD
239 goto end;
240 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
241 break;
242 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
243 printf("Notification channel was closed by peer.\n");
244 break;
245 default:
246 fprintf(stderr, "A communication error occurred on the notification channel.\n");
247 ret = -1;
248 goto end;
249 }
250
6ffce1f5
JR
251 /* Early exit check. */
252 if (end_trigger_name != NULL &&
253 is_trigger_name(end_trigger_name,
254 notification)) {
255 /* Exit the loop immediately. */
256 printf("Received end event notification from trigger %s\n",
257 end_trigger_name);
258 lttng_notification_destroy(notification);
259 goto evaluate_success;
260 }
261
7d59def2 262 ret = is_trigger_name(expected_trigger_name, notification);
6ba31891 263 lttng_notification_destroy(notification);
7d59def2
JR
264 if (!ret) {
265 ret = -1;
266 goto end;
6ffce1f5
JR
267 }
268
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) {
274 /*
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
278 * default behavior.
279 *
280 */
281 goto evaluate_success;
6ba31891
FD
282 }
283 }
6ffce1f5
JR
284
285evaluate_success:
286 if (expected_notifications == notification_count) {
287 /* Success */
288 ret = 0;
289 } else {
290 fprintf(stderr, "Expected %d notification got %d\n",
291 expected_notifications, notification_count);
292 ret = 1;
293 }
294
6ba31891
FD
295end:
296 lttng_triggers_destroy(triggers);
297 lttng_notification_channel_destroy(notification_channel);
3e68c9e8
JG
298 free(after_notif_register_file_path);
299 free(end_trigger_name);
300 free(expected_trigger_name);
6ba31891
FD
301 return !!ret;
302}
This page took 0.046391 seconds and 4 git commands to generate.