4 * Base client application for testing of LTTng notification API
6 * Copyright 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
8 * SPDX-License-Identifier: MIT
19 #include <lttng/action/action.h>
20 #include <lttng/action/notify.h>
21 #include <lttng/condition/buffer-usage.h>
22 #include <lttng/condition/condition.h>
23 #include <lttng/condition/evaluation.h>
24 #include <lttng/domain.h>
25 #include <lttng/endpoint.h>
26 #include <lttng/notification/channel.h>
27 #include <lttng/notification/notification.h>
28 #include <lttng/trigger/trigger.h>
29 #include <lttng/lttng-error.h>
31 static unsigned int nr_notifications
= 0;
32 static unsigned int nr_expected_notifications
= 0;
33 static const char *session_name
= NULL
;
34 static const char *channel_name
= NULL
;
35 static double threshold_ratio
= 0.0;
36 static uint64_t threshold_bytes
= 0;
37 static bool is_threshold_ratio
= false;
38 static enum lttng_condition_type buffer_usage_type
= LTTNG_CONDITION_TYPE_UNKNOWN
;
39 static enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
42 const struct lttng_condition
*condition
,
43 const struct lttng_evaluation
*condition_evaluation
);
45 int parse_arguments(char **argv
) {
46 const char *domain_type_string
= NULL
;
47 const char *buffer_usage_type_string
= NULL
;
48 const char *buffer_usage_threshold_type
= NULL
;
49 const char *buffer_usage_threshold_value
= NULL
;
50 const char *nr_expected_notifications_string
= NULL
;
52 session_name
= argv
[1];
53 channel_name
= argv
[2];
54 domain_type_string
= argv
[3];
55 buffer_usage_type_string
= argv
[4];
56 buffer_usage_threshold_type
= argv
[5];
57 buffer_usage_threshold_value
= argv
[6];
58 nr_expected_notifications_string
= argv
[7];
62 if (!strcasecmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
63 domain_type
= LTTNG_DOMAIN_UST
;
65 if (!strcasecmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
66 domain_type
= LTTNG_DOMAIN_KERNEL
;
68 if (domain_type
== LTTNG_DOMAIN_NONE
) {
69 printf("error: Unknown domain type\n");
73 /* Buffer usage condition type */
74 if (!strcasecmp("low", buffer_usage_type_string
)) {
75 buffer_usage_type
= LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
;
77 if (!strcasecmp("high", buffer_usage_type_string
)) {
78 buffer_usage_type
= LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
;
80 if (buffer_usage_type
== LTTNG_CONDITION_TYPE_UNKNOWN
) {
81 printf("error: Unknown condition type\n");
85 /* Ratio or bytes ? */
86 if (!strcasecmp("bytes", buffer_usage_threshold_type
)) {
87 is_threshold_ratio
= false;
88 sscanf(buffer_usage_threshold_value
, "%" SCNu64
, &threshold_bytes
);
91 if (!strcasecmp("ratio", buffer_usage_threshold_type
)) {
92 is_threshold_ratio
= true;
93 sscanf(buffer_usage_threshold_value
, "%lf", &threshold_ratio
);
96 /* Number of notification to expect */
97 sscanf(nr_expected_notifications_string
, "%d", &nr_expected_notifications
);
104 int main(int argc
, char **argv
)
107 enum lttng_condition_status condition_status
;
108 enum lttng_notification_channel_status nc_status
;
109 struct lttng_notification_channel
*notification_channel
= NULL
;
110 struct lttng_condition
*condition
= NULL
;
111 struct lttng_action
*action
= NULL
;
112 struct lttng_trigger
*trigger
= NULL
;
115 * Disable buffering on stdout.
116 * Safety measure to prevent hang on the validation side since
117 * stdout is used for outside synchronization.
119 setbuf(stdout
, NULL
);
122 printf("error: Missing arguments for tests\n");
127 ret
= parse_arguments(argv
);
129 printf("error: Could not parse arguments\n");
134 notification_channel
= lttng_notification_channel_create(
135 lttng_session_daemon_notification_endpoint
);
136 if (!notification_channel
) {
137 printf("error: Could not create notification channel\n");
142 switch (buffer_usage_type
) {
143 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
144 condition
= lttng_condition_buffer_usage_low_create();
146 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
147 condition
= lttng_condition_buffer_usage_high_create();
150 printf("error: Invalid buffer_usage_type\n");
156 printf("error: Could not create condition object\n");
161 if (is_threshold_ratio
) {
162 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
163 condition
, threshold_ratio
);
165 condition_status
= lttng_condition_buffer_usage_set_threshold(
166 condition
, threshold_bytes
);
169 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
170 printf("error: Could not set threshold\n");
175 condition_status
= lttng_condition_buffer_usage_set_session_name(
176 condition
, session_name
);
177 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
178 printf("error: Could not set session name\n");
182 condition_status
= lttng_condition_buffer_usage_set_channel_name(
183 condition
, channel_name
);
184 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
185 printf("error: Could not set channel name\n");
189 condition_status
= lttng_condition_buffer_usage_set_domain_type(
190 condition
, domain_type
);
191 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
192 printf("error: Could not set domain type\n");
197 action
= lttng_action_notify_create();
199 printf("error: Could not create action notify\n");
204 trigger
= lttng_trigger_create(condition
, action
);
206 printf("error: Could not create trigger\n");
211 ret
= lttng_register_trigger(trigger
);
214 * An equivalent trigger might already be registered if an other app
215 * registered an equivalent trigger.
217 if (ret
< 0 && ret
!= -LTTNG_ERR_TRIGGER_EXISTS
) {
218 printf("error: %s\n", lttng_strerror(ret
));
223 nc_status
= lttng_notification_channel_subscribe(notification_channel
, condition
);
224 if (nc_status
!= LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
) {
225 printf("error: Could not subscribe\n");
230 /* Tell outside process that the client is ready */
231 printf("sync: ready\n");
234 struct lttng_notification
*notification
;
235 enum lttng_notification_channel_status status
;
236 const struct lttng_evaluation
*notification_evaluation
;
237 const struct lttng_condition
*notification_condition
;
239 if (nr_notifications
== nr_expected_notifications
) {
243 /* Receive the next notification. */
244 status
= lttng_notification_channel_get_next_notification(
245 notification_channel
,
249 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
251 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
253 printf("error: No drop should be observed during this test app\n");
255 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
257 * The notification channel has been closed by the
258 * session daemon. This is typically caused by a session
259 * daemon shutting down (cleanly or because of a crash).
261 printf("error: Notification channel was closed\n");
265 /* Unhandled conditions / errors. */
266 printf("error: Unknown notification channel status\n");
271 notification_condition
= lttng_notification_get_condition(notification
);
272 notification_evaluation
= lttng_notification_get_evaluation(notification
);
274 ret
= handle_condition(notification_condition
, notification_evaluation
);
277 lttng_notification_destroy(notification
);
284 lttng_unregister_trigger(trigger
);
286 if (lttng_notification_channel_unsubscribe(notification_channel
, condition
)) {
287 printf("error: channel unsubscribe error\n");
289 lttng_trigger_destroy(trigger
);
290 lttng_condition_destroy(condition
);
291 lttng_action_destroy(action
);
292 lttng_notification_channel_destroy(notification_channel
);
293 printf("exit: %d\n", ret
);
297 int handle_condition(
298 const struct lttng_condition
*condition
,
299 const struct lttng_evaluation
*evaluation
)
302 const char *string_low
= "low";
303 const char *string_high
= "high";
304 const char *string_condition_type
= NULL
;
305 const char *condition_session_name
= NULL
;
306 const char *condition_channel_name
= NULL
;
307 enum lttng_condition_type condition_type
;
308 enum lttng_domain_type condition_domain_type
;
309 double buffer_usage_ratio
;
310 uint64_t buffer_usage_bytes
;
312 condition_type
= lttng_condition_get_type(condition
);
314 if (condition_type
!= buffer_usage_type
) {
316 printf("error: condition type and buffer usage type are not the same\n");
320 /* Fetch info to test */
321 ret
= lttng_condition_buffer_usage_get_session_name(condition
,
322 &condition_session_name
);
324 printf("error: session name could not be fetched\n");
328 ret
= lttng_condition_buffer_usage_get_channel_name(condition
,
329 &condition_channel_name
);
331 printf("error: channel name could not be fetched\n");
335 ret
= lttng_condition_buffer_usage_get_domain_type(condition
,
336 &condition_domain_type
);
338 printf("error: domain type could not be fetched\n");
343 if (strcmp(condition_session_name
, session_name
) != 0) {
344 printf("error: session name differs\n");
349 if (strcmp(condition_channel_name
, channel_name
) != 0) {
350 printf("error: channel name differs\n");
355 if (condition_domain_type
!= domain_type
) {
356 printf("error: domain type differs\n");
361 if (is_threshold_ratio
) {
362 lttng_evaluation_buffer_usage_get_usage_ratio(
363 evaluation
, &buffer_usage_ratio
);
364 switch (condition_type
) {
365 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
366 if (buffer_usage_ratio
> threshold_ratio
) {
367 printf("error: buffer usage ratio is bigger than set threshold ratio\n");
372 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
373 if (buffer_usage_ratio
< threshold_ratio
) {
374 printf("error: buffer usage ratio is lower than set threshold ratio\n");
380 printf("error: Unknown condition type\n");
385 lttng_evaluation_buffer_usage_get_usage(
386 evaluation
, &buffer_usage_bytes
);
387 switch (condition_type
) {
388 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
389 if (buffer_usage_bytes
> threshold_bytes
) {
390 printf("error: buffer usage ratio is bigger than set threshold bytes\n");
395 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
396 if (buffer_usage_bytes
< threshold_bytes
) {
397 printf("error: buffer usage ratio is lower than set threshold bytes\n");
403 printf("error: Unknown condition type\n");
409 switch (condition_type
) {
410 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
411 string_condition_type
= string_low
;
413 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
414 string_condition_type
= string_high
;
417 printf("error: Unknown condition type\n");
422 printf("notification: %s %d\n", string_condition_type
, nr_notifications
);