SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / tests / regression / tools / notification / base_client.c
CommitLineData
434f8068
JR
1/*
2 * base_client.c
3 *
4 * Base client application for testing of LTTng notification API
5 *
6 * Copyright 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
7 *
9d16b343 8 * SPDX-License-Identifier: MIT
434f8068 9 *
434f8068
JR
10 */
11
12#include <stdio.h>
13#include <stdbool.h>
14#include <string.h>
15#include <unistd.h>
16#include <inttypes.h>
17#include <assert.h>
18
19#include <lttng/action/action.h>
ebdb334b 20#include <lttng/action/group.h>
434f8068
JR
21#include <lttng/action/notify.h>
22#include <lttng/condition/buffer-usage.h>
23#include <lttng/condition/condition.h>
24#include <lttng/condition/evaluation.h>
25#include <lttng/domain.h>
26#include <lttng/endpoint.h>
27#include <lttng/notification/channel.h>
28#include <lttng/notification/notification.h>
29#include <lttng/trigger/trigger.h>
25040abc 30#include <lttng/lttng-error.h>
434f8068
JR
31
32static unsigned int nr_notifications = 0;
33static unsigned int nr_expected_notifications = 0;
34static const char *session_name = NULL;
35static const char *channel_name = NULL;
36static double threshold_ratio = 0.0;
37static uint64_t threshold_bytes = 0;
38static bool is_threshold_ratio = false;
ebdb334b 39static bool use_action_group = false;
434f8068
JR
40static enum lttng_condition_type buffer_usage_type = LTTNG_CONDITION_TYPE_UNKNOWN;
41static enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
42
43int handle_condition(
44 const struct lttng_condition *condition,
45 const struct lttng_evaluation *condition_evaluation);
46
53089c7c
SM
47static
48int parse_arguments(char **argv)
49{
434f8068
JR
50 const char *domain_type_string = NULL;
51 const char *buffer_usage_type_string = NULL;
52 const char *buffer_usage_threshold_type = NULL;
53 const char *buffer_usage_threshold_value = NULL;
54 const char *nr_expected_notifications_string = NULL;
ebdb334b 55 const char *use_action_group_value = NULL;
434f8068
JR
56
57 session_name = argv[1];
58 channel_name = argv[2];
59 domain_type_string = argv[3];
60 buffer_usage_type_string = argv[4];
61 buffer_usage_threshold_type = argv[5];
62 buffer_usage_threshold_value = argv[6];
63 nr_expected_notifications_string = argv[7];
ebdb334b 64 use_action_group_value = argv[8];
434f8068
JR
65
66 /* Parse arguments */
67 /* Domain type */
68 if (!strcasecmp("LTTNG_DOMAIN_UST", domain_type_string)) {
69 domain_type = LTTNG_DOMAIN_UST;
70 }
71 if (!strcasecmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
72 domain_type = LTTNG_DOMAIN_KERNEL;
73 }
74 if (domain_type == LTTNG_DOMAIN_NONE) {
75 printf("error: Unknown domain type\n");
76 goto error;
77 }
78
79 /* Buffer usage condition type */
80 if (!strcasecmp("low", buffer_usage_type_string)) {
81 buffer_usage_type = LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW;
82 }
83 if (!strcasecmp("high", buffer_usage_type_string)) {
84 buffer_usage_type = LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
85 }
86 if (buffer_usage_type == LTTNG_CONDITION_TYPE_UNKNOWN) {
87 printf("error: Unknown condition type\n");
88 goto error;
89 }
90
91 /* Ratio or bytes ? */
92 if (!strcasecmp("bytes", buffer_usage_threshold_type)) {
93 is_threshold_ratio = false;
94 sscanf(buffer_usage_threshold_value, "%" SCNu64, &threshold_bytes);
95 }
96
97 if (!strcasecmp("ratio", buffer_usage_threshold_type)) {
98 is_threshold_ratio = true;
99 sscanf(buffer_usage_threshold_value, "%lf", &threshold_ratio);
100 }
101
102 /* Number of notification to expect */
103 sscanf(nr_expected_notifications_string, "%d", &nr_expected_notifications);
104
ebdb334b
JR
105 /* Put notify action in a group. */
106 if (!strcasecmp("1", use_action_group_value)) {
107 use_action_group = true;
108 }
109
434f8068
JR
110 return 0;
111error:
112 return 1;
113}
114
115int main(int argc, char **argv)
116{
117 int ret = 0;
118 enum lttng_condition_status condition_status;
ebdb334b 119 enum lttng_action_status action_status;
434f8068
JR
120 enum lttng_notification_channel_status nc_status;
121 struct lttng_notification_channel *notification_channel = NULL;
122 struct lttng_condition *condition = NULL;
123 struct lttng_action *action = NULL;
124 struct lttng_trigger *trigger = NULL;
125
126 /*
127 * Disable buffering on stdout.
128 * Safety measure to prevent hang on the validation side since
129 * stdout is used for outside synchronization.
130 */
131 setbuf(stdout, NULL);
132
ebdb334b 133 if (argc < 9) {
434f8068
JR
134 printf("error: Missing arguments for tests\n");
135 ret = 1;
136 goto end;
137 }
138
139 ret = parse_arguments(argv);
140 if (ret) {
141 printf("error: Could not parse arguments\n");
142 goto end;
143 }
144
145 /* Setup */
146 notification_channel = lttng_notification_channel_create(
147 lttng_session_daemon_notification_endpoint);
148 if (!notification_channel) {
149 printf("error: Could not create notification channel\n");
150 ret = 1;
151 goto end;
152 }
153
154 switch (buffer_usage_type) {
155 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
156 condition = lttng_condition_buffer_usage_low_create();
157 break;
158 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
159 condition = lttng_condition_buffer_usage_high_create();
160 break;
161 default:
162 printf("error: Invalid buffer_usage_type\n");
163 ret = 1;
164 goto end;
165 }
166
167 if (!condition) {
168 printf("error: Could not create condition object\n");
169 ret = 1;
170 goto end;
171 }
172
173 if (is_threshold_ratio) {
174 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
175 condition, threshold_ratio);
176 } else {
177 condition_status = lttng_condition_buffer_usage_set_threshold(
178 condition, threshold_bytes);
179 }
180
181 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
182 printf("error: Could not set threshold\n");
183 ret = 1;
184 goto end;
185 }
186
187 condition_status = lttng_condition_buffer_usage_set_session_name(
188 condition, session_name);
189 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
190 printf("error: Could not set session name\n");
191 ret = 1;
192 goto end;
193 }
194 condition_status = lttng_condition_buffer_usage_set_channel_name(
195 condition, channel_name);
196 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
197 printf("error: Could not set channel name\n");
198 ret = 1;
199 goto end;
200 }
201 condition_status = lttng_condition_buffer_usage_set_domain_type(
854382b8 202 condition, domain_type);
434f8068
JR
203 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
204 printf("error: Could not set domain type\n");
205 ret = 1;
206 goto end;
207 }
208
ebdb334b
JR
209 if (use_action_group) {
210 struct lttng_action *notify, *group;
211
212 group = lttng_action_group_create();
213 if (!group) {
214 printf("error: Could not create action group\n");
215 ret = 1;
216 goto end;
217 }
218 notify = lttng_action_notify_create();
219 if (!notify) {
220 lttng_action_destroy(group);
221 printf("error: Could not create action notify\n");
222 ret = 1;
223 goto end;
224 }
225 action_status = lttng_action_group_add_action(group, notify);
226 if (action_status != LTTNG_ACTION_STATUS_OK) {
227 printf("error: Could not add action notify to action group\n");
228 lttng_action_destroy(group);
229 lttng_action_destroy(notify);
230 ret = 1;
231 goto end;
232 }
233
234 action = group;
235 } else {
236 action = lttng_action_notify_create();
237 if (!action) {
238 printf("error: Could not create action notify\n");
239 ret = 1;
240 goto end;
241 }
434f8068
JR
242 }
243
244 trigger = lttng_trigger_create(condition, action);
245 if (!trigger) {
246 printf("error: Could not create trigger\n");
247 ret = 1;
248 goto end;
249 }
250
251 ret = lttng_register_trigger(trigger);
252
253 /*
254 * An equivalent trigger might already be registered if an other app
255 * registered an equivalent trigger.
256 */
257 if (ret < 0 && ret != -LTTNG_ERR_TRIGGER_EXISTS) {
258 printf("error: %s\n", lttng_strerror(ret));
259 ret = 1;
260 goto end;
261 }
262
263 nc_status = lttng_notification_channel_subscribe(notification_channel, condition);
264 if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
265 printf("error: Could not subscribe\n");
266 ret = 1;
267 goto end;
268 }
269
270 /* Tell outside process that the client is ready */
271 printf("sync: ready\n");
272
273 for (;;) {
274 struct lttng_notification *notification;
275 enum lttng_notification_channel_status status;
276 const struct lttng_evaluation *notification_evaluation;
277 const struct lttng_condition *notification_condition;
278
279 if (nr_notifications == nr_expected_notifications) {
280 ret = 0;
281 goto end;
282 }
283 /* Receive the next notification. */
284 status = lttng_notification_channel_get_next_notification(
285 notification_channel,
286 &notification);
287
288 switch (status) {
289 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
290 break;
291 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
292 ret = 1;
293 printf("error: No drop should be observed during this test app\n");
294 goto end;
295 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
296 /*
297 * The notification channel has been closed by the
298 * session daemon. This is typically caused by a session
299 * daemon shutting down (cleanly or because of a crash).
300 */
301 printf("error: Notification channel was closed\n");
302 ret = 1;
303 goto end;
304 default:
305 /* Unhandled conditions / errors. */
ebdb334b 306 printf("error: Unknown notification channel status (%d) \n", status);
434f8068
JR
307 ret = 1;
308 goto end;
309 }
310
311 notification_condition = lttng_notification_get_condition(notification);
312 notification_evaluation = lttng_notification_get_evaluation(notification);
313
314 ret = handle_condition(notification_condition, notification_evaluation);
315 nr_notifications++;
316
317 lttng_notification_destroy(notification);
318 if (ret != 0) {
319 goto end;
320 }
321 }
322end:
323 if (trigger) {
324 lttng_unregister_trigger(trigger);
325 }
eff748d0
JR
326 if (lttng_notification_channel_unsubscribe(notification_channel, condition)) {
327 printf("error: channel unsubscribe error\n");
328 }
434f8068
JR
329 lttng_trigger_destroy(trigger);
330 lttng_condition_destroy(condition);
331 lttng_action_destroy(action);
332 lttng_notification_channel_destroy(notification_channel);
333 printf("exit: %d\n", ret);
334 return ret;
335}
336
337int handle_condition(
338 const struct lttng_condition *condition,
339 const struct lttng_evaluation *evaluation)
340{
341 int ret = 0;
342 const char *string_low = "low";
343 const char *string_high = "high";
344 const char *string_condition_type = NULL;
345 const char *condition_session_name = NULL;
346 const char *condition_channel_name = NULL;
347 enum lttng_condition_type condition_type;
348 enum lttng_domain_type condition_domain_type;
349 double buffer_usage_ratio;
350 uint64_t buffer_usage_bytes;
351
352 condition_type = lttng_condition_get_type(condition);
353
354 if (condition_type != buffer_usage_type) {
355 ret = 1;
356 printf("error: condition type and buffer usage type are not the same\n");
357 goto end;
358 }
359
360 /* Fetch info to test */
eff748d0 361 ret = lttng_condition_buffer_usage_get_session_name(condition,
434f8068 362 &condition_session_name);
eff748d0
JR
363 if (ret) {
364 printf("error: session name could not be fetched\n");
365 ret = 1;
366 goto end;
367 }
368 ret = lttng_condition_buffer_usage_get_channel_name(condition,
434f8068 369 &condition_channel_name);
eff748d0
JR
370 if (ret) {
371 printf("error: channel name could not be fetched\n");
372 ret = 1;
373 goto end;
374 }
375 ret = lttng_condition_buffer_usage_get_domain_type(condition,
434f8068 376 &condition_domain_type);
eff748d0
JR
377 if (ret) {
378 printf("error: domain type could not be fetched\n");
379 ret = 1;
380 goto end;
381 }
434f8068
JR
382
383 if (strcmp(condition_session_name, session_name) != 0) {
384 printf("error: session name differs\n");
385 ret = 1;
386 goto end;
387 }
388
389 if (strcmp(condition_channel_name, channel_name) != 0) {
390 printf("error: channel name differs\n");
391 ret = 1;
392 goto end;
393 }
394
395 if (condition_domain_type != domain_type) {
396 printf("error: domain type differs\n");
397 ret = 1;
398 goto end;
399 }
400
401 if (is_threshold_ratio) {
402 lttng_evaluation_buffer_usage_get_usage_ratio(
403 evaluation, &buffer_usage_ratio);
404 switch (condition_type) {
405 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
406 if (buffer_usage_ratio > threshold_ratio) {
407 printf("error: buffer usage ratio is bigger than set threshold ratio\n");
408 ret = 1;
409 goto end;
410 }
411 break;
412 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
413 if (buffer_usage_ratio < threshold_ratio) {
414 printf("error: buffer usage ratio is lower than set threshold ratio\n");
415 ret = 1;
416 goto end;
417 }
418 break;
419 default:
420 printf("error: Unknown condition type\n");
421 ret = 1;
422 goto end;
423 }
424 } else {
425 lttng_evaluation_buffer_usage_get_usage(
426 evaluation, &buffer_usage_bytes);
427 switch (condition_type) {
428 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
429 if (buffer_usage_bytes > threshold_bytes) {
430 printf("error: buffer usage ratio is bigger than set threshold bytes\n");
431 ret = 1;
432 goto end;
433 }
434 break;
435 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
436 if (buffer_usage_bytes < threshold_bytes) {
437 printf("error: buffer usage ratio is lower than set threshold bytes\n");
438 ret = 1;
439 goto end;
440 }
441 break;
442 default:
443 printf("error: Unknown condition type\n");
444 ret = 1;
445 goto end;
446 }
447 }
448
449 switch (condition_type) {
450 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
451 string_condition_type = string_low;
452 break;
453 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
454 string_condition_type = string_high;
455 break;
456 default:
457 printf("error: Unknown condition type\n");
458 ret = 1;
459 goto end;
460 }
461
462 printf("notification: %s %d\n", string_condition_type, nr_notifications);
463end:
464 return ret;
465}
This page took 0.058882 seconds and 5 git commands to generate.