4 * Base client application for testing of LTTng notification API
6 * Copyright 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <lttng/action/action.h>
35 #include <lttng/action/notify.h>
36 #include <lttng/condition/buffer-usage.h>
37 #include <lttng/condition/condition.h>
38 #include <lttng/condition/evaluation.h>
39 #include <lttng/domain.h>
40 #include <lttng/endpoint.h>
41 #include <lttng/notification/channel.h>
42 #include <lttng/notification/notification.h>
43 #include <lttng/trigger/trigger.h>
44 #include <lttng/lttng-error.h>
46 static unsigned int nr_notifications
= 0;
47 static unsigned int nr_expected_notifications
= 0;
48 static const char *session_name
= NULL
;
49 static const char *channel_name
= NULL
;
50 static double threshold_ratio
= 0.0;
51 static uint64_t threshold_bytes
= 0;
52 static bool is_threshold_ratio
= false;
53 static enum lttng_condition_type buffer_usage_type
= LTTNG_CONDITION_TYPE_UNKNOWN
;
54 static enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
57 const struct lttng_condition
*condition
,
58 const struct lttng_evaluation
*condition_evaluation
);
60 int parse_arguments(char **argv
) {
61 const char *domain_type_string
= NULL
;
62 const char *buffer_usage_type_string
= NULL
;
63 const char *buffer_usage_threshold_type
= NULL
;
64 const char *buffer_usage_threshold_value
= NULL
;
65 const char *nr_expected_notifications_string
= NULL
;
67 session_name
= argv
[1];
68 channel_name
= argv
[2];
69 domain_type_string
= argv
[3];
70 buffer_usage_type_string
= argv
[4];
71 buffer_usage_threshold_type
= argv
[5];
72 buffer_usage_threshold_value
= argv
[6];
73 nr_expected_notifications_string
= argv
[7];
77 if (!strcasecmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
78 domain_type
= LTTNG_DOMAIN_UST
;
80 if (!strcasecmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
81 domain_type
= LTTNG_DOMAIN_KERNEL
;
83 if (domain_type
== LTTNG_DOMAIN_NONE
) {
84 printf("error: Unknown domain type\n");
88 /* Buffer usage condition type */
89 if (!strcasecmp("low", buffer_usage_type_string
)) {
90 buffer_usage_type
= LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
;
92 if (!strcasecmp("high", buffer_usage_type_string
)) {
93 buffer_usage_type
= LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
;
95 if (buffer_usage_type
== LTTNG_CONDITION_TYPE_UNKNOWN
) {
96 printf("error: Unknown condition type\n");
100 /* Ratio or bytes ? */
101 if (!strcasecmp("bytes", buffer_usage_threshold_type
)) {
102 is_threshold_ratio
= false;
103 sscanf(buffer_usage_threshold_value
, "%" SCNu64
, &threshold_bytes
);
106 if (!strcasecmp("ratio", buffer_usage_threshold_type
)) {
107 is_threshold_ratio
= true;
108 sscanf(buffer_usage_threshold_value
, "%lf", &threshold_ratio
);
111 /* Number of notification to expect */
112 sscanf(nr_expected_notifications_string
, "%d", &nr_expected_notifications
);
119 int main(int argc
, char **argv
)
122 enum lttng_condition_status condition_status
;
123 enum lttng_notification_channel_status nc_status
;
124 struct lttng_notification_channel
*notification_channel
= NULL
;
125 struct lttng_condition
*condition
= NULL
;
126 struct lttng_action
*action
= NULL
;
127 struct lttng_trigger
*trigger
= NULL
;
130 * Disable buffering on stdout.
131 * Safety measure to prevent hang on the validation side since
132 * stdout is used for outside synchronization.
134 setbuf(stdout
, NULL
);
137 printf("error: Missing arguments for tests\n");
142 ret
= parse_arguments(argv
);
144 printf("error: Could not parse arguments\n");
149 notification_channel
= lttng_notification_channel_create(
150 lttng_session_daemon_notification_endpoint
);
151 if (!notification_channel
) {
152 printf("error: Could not create notification channel\n");
157 switch (buffer_usage_type
) {
158 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
159 condition
= lttng_condition_buffer_usage_low_create();
161 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
162 condition
= lttng_condition_buffer_usage_high_create();
165 printf("error: Invalid buffer_usage_type\n");
171 printf("error: Could not create condition object\n");
176 if (is_threshold_ratio
) {
177 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
178 condition
, threshold_ratio
);
180 condition_status
= lttng_condition_buffer_usage_set_threshold(
181 condition
, threshold_bytes
);
184 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
185 printf("error: Could not set threshold\n");
190 condition_status
= lttng_condition_buffer_usage_set_session_name(
191 condition
, session_name
);
192 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
193 printf("error: Could not set session name\n");
197 condition_status
= lttng_condition_buffer_usage_set_channel_name(
198 condition
, channel_name
);
199 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
200 printf("error: Could not set channel name\n");
204 condition_status
= lttng_condition_buffer_usage_set_domain_type(
205 condition
, domain_type
);
206 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
207 printf("error: Could not set domain type\n");
212 action
= lttng_action_notify_create();
214 printf("error: Could not create action notify\n");
219 trigger
= lttng_trigger_create(condition
, action
);
221 printf("error: Could not create trigger\n");
226 ret
= lttng_register_trigger(trigger
);
229 * An equivalent trigger might already be registered if an other app
230 * registered an equivalent trigger.
232 if (ret
< 0 && ret
!= -LTTNG_ERR_TRIGGER_EXISTS
) {
233 printf("error: %s\n", lttng_strerror(ret
));
238 nc_status
= lttng_notification_channel_subscribe(notification_channel
, condition
);
239 if (nc_status
!= LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
) {
240 printf("error: Could not subscribe\n");
245 /* Tell outside process that the client is ready */
246 printf("sync: ready\n");
249 struct lttng_notification
*notification
;
250 enum lttng_notification_channel_status status
;
251 const struct lttng_evaluation
*notification_evaluation
;
252 const struct lttng_condition
*notification_condition
;
254 if (nr_notifications
== nr_expected_notifications
) {
258 /* Receive the next notification. */
259 status
= lttng_notification_channel_get_next_notification(
260 notification_channel
,
264 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
266 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED
:
268 printf("error: No drop should be observed during this test app\n");
270 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED
:
272 * The notification channel has been closed by the
273 * session daemon. This is typically caused by a session
274 * daemon shutting down (cleanly or because of a crash).
276 printf("error: Notification channel was closed\n");
280 /* Unhandled conditions / errors. */
281 printf("error: Unknown notification channel status\n");
286 notification_condition
= lttng_notification_get_condition(notification
);
287 notification_evaluation
= lttng_notification_get_evaluation(notification
);
289 ret
= handle_condition(notification_condition
, notification_evaluation
);
292 lttng_notification_destroy(notification
);
299 lttng_unregister_trigger(trigger
);
301 if (lttng_notification_channel_unsubscribe(notification_channel
, condition
)) {
302 printf("error: channel unsubscribe error\n");
304 lttng_trigger_destroy(trigger
);
305 lttng_condition_destroy(condition
);
306 lttng_action_destroy(action
);
307 lttng_notification_channel_destroy(notification_channel
);
308 printf("exit: %d\n", ret
);
312 int handle_condition(
313 const struct lttng_condition
*condition
,
314 const struct lttng_evaluation
*evaluation
)
317 const char *string_low
= "low";
318 const char *string_high
= "high";
319 const char *string_condition_type
= NULL
;
320 const char *condition_session_name
= NULL
;
321 const char *condition_channel_name
= NULL
;
322 enum lttng_condition_type condition_type
;
323 enum lttng_domain_type condition_domain_type
;
324 double buffer_usage_ratio
;
325 uint64_t buffer_usage_bytes
;
327 condition_type
= lttng_condition_get_type(condition
);
329 if (condition_type
!= buffer_usage_type
) {
331 printf("error: condition type and buffer usage type are not the same\n");
335 /* Fetch info to test */
336 ret
= lttng_condition_buffer_usage_get_session_name(condition
,
337 &condition_session_name
);
339 printf("error: session name could not be fetched\n");
343 ret
= lttng_condition_buffer_usage_get_channel_name(condition
,
344 &condition_channel_name
);
346 printf("error: channel name could not be fetched\n");
350 ret
= lttng_condition_buffer_usage_get_domain_type(condition
,
351 &condition_domain_type
);
353 printf("error: domain type could not be fetched\n");
358 if (strcmp(condition_session_name
, session_name
) != 0) {
359 printf("error: session name differs\n");
364 if (strcmp(condition_channel_name
, channel_name
) != 0) {
365 printf("error: channel name differs\n");
370 if (condition_domain_type
!= domain_type
) {
371 printf("error: domain type differs\n");
376 if (is_threshold_ratio
) {
377 lttng_evaluation_buffer_usage_get_usage_ratio(
378 evaluation
, &buffer_usage_ratio
);
379 switch (condition_type
) {
380 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
381 if (buffer_usage_ratio
> threshold_ratio
) {
382 printf("error: buffer usage ratio is bigger than set threshold ratio\n");
387 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
388 if (buffer_usage_ratio
< threshold_ratio
) {
389 printf("error: buffer usage ratio is lower than set threshold ratio\n");
395 printf("error: Unknown condition type\n");
400 lttng_evaluation_buffer_usage_get_usage(
401 evaluation
, &buffer_usage_bytes
);
402 switch (condition_type
) {
403 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
404 if (buffer_usage_bytes
> threshold_bytes
) {
405 printf("error: buffer usage ratio is bigger than set threshold bytes\n");
410 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
411 if (buffer_usage_bytes
< threshold_bytes
) {
412 printf("error: buffer usage ratio is lower than set threshold bytes\n");
418 printf("error: Unknown condition type\n");
424 switch (condition_type
) {
425 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
426 string_condition_type
= string_low
;
428 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
429 string_condition_type
= string_high
;
432 printf("error: Unknown condition type\n");
437 printf("notification: %s %d\n", string_condition_type
, nr_notifications
);