SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / tests / regression / tools / trigger / utils / notification-client.c
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
17 #include <lttng/condition/event-rule.h>
18 #include <lttng/lttng.h>
19
20 #include "utils.h"
21
22 static struct option long_options[] =
23 {
24 /* These options set a flag. */
25 {"trigger", required_argument, 0, 'i'},
26 {"sync-after-notif-register", required_argument, 0, 'a'},
27 {0, 0, 0, 0}
28 };
29
30 static bool action_group_contains_notify(
31 const struct lttng_action *action_group)
32 {
33 unsigned int i, count;
34 enum lttng_action_status status =
35 lttng_action_group_get_count(action_group, &count);
36
37 if (status != LTTNG_ACTION_STATUS_OK) {
38 printf("Failed to get action count from action group\n");
39 exit(1);
40 }
41
42 for (i = 0; i < count; i++) {
43 const struct lttng_action *action =
44 lttng_action_group_get_at_index(
45 action_group, i);
46 const enum lttng_action_type action_type =
47 lttng_action_get_type(action);
48
49 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
50 return true;
51 }
52 }
53 return false;
54 }
55
56 static bool is_expected_trigger_name(const char *expected_trigger_name,
57 struct lttng_notification *notification)
58 {
59 int ret = false;
60 const struct lttng_evaluation *evaluation =
61 lttng_notification_get_evaluation(notification);
62 const enum lttng_condition_type type =
63 lttng_evaluation_get_type(evaluation);
64
65 switch (type) {
66 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
67 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
68 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
69 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
70 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
71 break;
72 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
73 {
74 const char *trigger_name;
75 enum lttng_evaluation_status evaluation_status;
76
77 evaluation_status =
78 lttng_evaluation_event_rule_get_trigger_name(
79 evaluation, &trigger_name);
80 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
81 fprintf(stderr, "Failed to get trigger name of event rule notification\n");
82 ret = -1;
83 break;
84 }
85
86 ret = true;
87 break;
88 }
89 default:
90 fprintf(stderr, "Unknown notification type (%d)\n", type);
91 }
92
93 return ret;
94 }
95
96 int main(int argc, char **argv)
97 {
98 int ret;
99 int option;
100 int option_index;
101 const char *expected_trigger_name = NULL;
102 struct lttng_triggers *triggers = NULL;
103 unsigned int count, i, subcription_count = 0;
104 enum lttng_trigger_status trigger_status;
105 char *after_notif_register_file_path = NULL;
106 struct lttng_notification_channel *notification_channel = NULL;
107
108 while ((option = getopt_long(argc, argv, "a:t:",
109 long_options, &option_index)) != -1) {
110 switch (option) {
111 case 'a':
112 after_notif_register_file_path = strdup(optarg);
113 break;
114 case 't':
115 expected_trigger_name = strdup(optarg);
116 break;
117 case '?':
118 /* getopt_long already printed an error message. */
119 default:
120 ret = -1;
121 goto end;
122 }
123 }
124
125 if (optind != argc) {
126 ret = -1;
127 goto end;
128 }
129
130
131 notification_channel = lttng_notification_channel_create(
132 lttng_session_daemon_notification_endpoint);
133 if (!notification_channel) {
134 fprintf(stderr, "Failed to create notification channel\n");
135 ret = -1;
136 goto end;
137 }
138
139 ret = lttng_list_triggers(&triggers);
140 if (ret != LTTNG_OK) {
141 fprintf(stderr, "Failed to list triggers\n");
142 goto end;
143 }
144
145 trigger_status = lttng_triggers_get_count(triggers, &count);
146 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
147 fprintf(stderr, "Failed to get trigger count\n");
148 ret = -1;
149 goto end;
150 }
151
152 for (i = 0; i < count; i++) {
153 const struct lttng_trigger *trigger =
154 lttng_triggers_get_at_index(triggers, i);
155 const struct lttng_condition *condition =
156 lttng_trigger_get_const_condition(trigger);
157 const struct lttng_action *action =
158 lttng_trigger_get_const_action(trigger);
159 const enum lttng_action_type action_type =
160 lttng_action_get_type(action);
161 enum lttng_notification_channel_status channel_status;
162 const char *trigger_name = NULL;
163
164 lttng_trigger_get_name(trigger, &trigger_name);
165 if (strcmp(trigger_name, expected_trigger_name)) {
166 continue;
167 }
168
169 if (!((action_type == LTTNG_ACTION_TYPE_GROUP &&
170 action_group_contains_notify(action)) ||
171 action_type == LTTNG_ACTION_TYPE_NOTIFY)) {
172 /* "The action of trigger is not notify, skipping. */
173 continue;
174 }
175
176 channel_status = lttng_notification_channel_subscribe(
177 notification_channel, condition);
178 if (channel_status) {
179 fprintf(stderr, "Failed to subscribe to notifications of trigger \"%s\"\n",
180 trigger_name);
181 ret = -1;
182 goto end;
183 }
184
185 subcription_count++;
186 }
187
188 if (subcription_count == 0) {
189 printf("No matching trigger with a notify action found.\n");
190 ret = 0;
191 goto end;
192 }
193
194
195 /*
196 * We registered to the notification of our target trigger. We can now
197 * create the sync file to signify that we are ready.
198 */
199 ret = create_file(after_notif_register_file_path);
200 if (ret != 0) {
201 goto end;
202 }
203
204 for (;;) {
205 struct lttng_notification *notification;
206 enum lttng_notification_channel_status channel_status;
207
208 channel_status =
209 lttng_notification_channel_get_next_notification(
210 notification_channel,
211 &notification);
212 switch (channel_status) {
213 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
214 printf("Dropped notification\n");
215 break;
216 case LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED:
217 ret = 0;
218 goto end;
219 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
220 break;
221 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
222 printf("Notification channel was closed by peer.\n");
223 break;
224 default:
225 fprintf(stderr, "A communication error occurred on the notification channel.\n");
226 ret = -1;
227 goto end;
228 }
229
230 ret = is_expected_trigger_name(expected_trigger_name,
231 notification);
232 lttng_notification_destroy(notification);
233 if (ret) {
234 ret = 0;
235 goto end;
236 }
237 }
238 end:
239 lttng_triggers_destroy(triggers);
240 lttng_notification_channel_destroy(notification_channel);
241 return !!ret;
242 }
This page took 0.051939 seconds and 5 git commands to generate.