2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/condition/condition-internal.h>
19 #include <lttng/condition/buffer-usage-internal.h>
20 #include <common/macros.h>
24 bool is_usage_condition(struct lttng_condition
*condition
)
26 enum lttng_condition_type type
= lttng_condition_get_type(condition
);
28 return type
== LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
||
29 type
== LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
;
33 bool is_usage_evaluation(struct lttng_evaluation
*evaluation
)
35 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
37 return type
== LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
||
38 type
== LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
;
42 void lttng_condition_buffer_usage_destroy(struct lttng_condition
*condition
)
44 struct lttng_condition_buffer_usage
*usage
;
46 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
49 free(usage
->session_name
);
50 free(usage
->channel_name
);
55 bool lttng_condition_buffer_usage_validate(struct lttng_condition
*condition
)
58 struct lttng_condition_buffer_usage
*usage
;
64 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
66 if (!usage
->session_name
) {
69 if (!usage
->channel_name
) {
72 if (!usage
->threshold_percent
.set
&& !usage
->threshold_bytes
.set
) {
82 ssize_t
lttng_condition_buffer_usage_serialize(struct lttng_condition
*condition
,
85 struct lttng_condition_buffer_usage
*usage
;
87 size_t session_name_len
, channel_name_len
;
89 if (!condition
|| !is_usage_condition(condition
)) {
94 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
96 size
= sizeof(struct lttng_condition_buffer_usage_comm
);
97 session_name_len
= strlen(usage
->session_name
) + 1;
98 channel_name_len
= strlen(usage
->channel_name
) + 1;
99 size
+= session_name_len
+ channel_name_len
;
101 struct lttng_condition_buffer_usage_comm usage_comm
= {
102 .threshold_set_in_bytes
= usage
->threshold_bytes
.set
? 1 : 0,
103 .session_name_len
= session_name_len
,
104 .channel_name_len
= channel_name_len
,
105 .domain_type
= (int8_t) usage
->domain
.type
,
108 if (usage
->threshold_bytes
.set
) {
109 usage_comm
.threshold
.bytes
=
110 usage
->threshold_bytes
.value
;
112 usage_comm
.threshold
.percent
=
113 usage
->threshold_percent
.value
;
116 memcpy(buf
, &usage_comm
, sizeof(usage_comm
));
117 buf
+= sizeof(usage_comm
);
118 memcpy(buf
, usage
->session_name
, session_name_len
);
119 buf
+= session_name_len
;
120 memcpy(buf
, usage
->channel_name
, channel_name_len
);
121 buf
+= channel_name_len
;
128 struct lttng_condition
*lttng_condition_buffer_usage_create(
129 enum lttng_condition_type type
)
131 struct lttng_condition_buffer_usage
*condition
;
133 condition
= zmalloc(sizeof(struct lttng_condition_buffer_usage
));
138 condition
->parent
.type
= type
;
139 condition
->parent
.validate
= lttng_condition_buffer_usage_validate
;
140 condition
->parent
.serialize
= lttng_condition_buffer_usage_serialize
;
141 condition
->parent
.destroy
= lttng_condition_buffer_usage_destroy
;
143 return &condition
->parent
;
146 struct lttng_condition
*lttng_condition_buffer_usage_low_create(void)
148 return lttng_condition_buffer_usage_create(
149 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
);
152 struct lttng_condition
*lttng_condition_buffer_usage_high_create(void)
154 return lttng_condition_buffer_usage_create(
155 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
);
159 ssize_t
init_from_buffer(struct lttng_condition
*condition
, const char *buf
)
161 ssize_t ret
, condition_size
;
162 enum lttng_condition_status status
;
163 enum lttng_domain_type domain_type
;
164 struct lttng_condition_buffer_usage_comm
*condition_comm
=
165 (struct lttng_condition_buffer_usage_comm
*) buf
;
166 const char *session_name
, *channel_name
;
168 if (condition_comm
->threshold_set_in_bytes
) {
169 status
= lttng_condition_buffer_usage_set_threshold(condition
,
170 condition_comm
->threshold
.bytes
);
172 status
= lttng_condition_buffer_usage_set_threshold_percentage(
173 condition
, condition_comm
->threshold
.percent
);
175 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
180 if (condition_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
181 condition_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
182 /* Invalid domain value. */
187 domain_type
= (enum lttng_domain_type
) condition_comm
->domain_type
;
188 status
= lttng_condition_buffer_usage_set_domain_type(condition
,
190 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
195 session_name
= buf
+ sizeof(struct lttng_condition_buffer_usage_comm
);
196 channel_name
= session_name
+ condition_comm
->session_name_len
;
198 status
= lttng_condition_buffer_usage_set_session_name(condition
,
200 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
205 status
= lttng_condition_buffer_usage_set_channel_name(condition
,
207 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
212 if (!lttng_condition_validate(condition
)) {
217 condition_size
= sizeof(*condition_comm
);
218 condition_size
+= (ssize_t
) condition_comm
->session_name_len
;
219 condition_size
+= (ssize_t
) condition_comm
->channel_name_len
;
220 ret
= condition_size
;
226 ssize_t
lttng_condition_buffer_usage_low_create_from_buffer(const char *buf
,
227 struct lttng_condition
**_condition
)
230 struct lttng_condition
*condition
=
231 lttng_condition_buffer_usage_low_create();
233 if (!_condition
|| !condition
) {
238 ret
= init_from_buffer(condition
, buf
);
243 *_condition
= condition
;
246 lttng_condition_destroy(condition
);
251 ssize_t
lttng_condition_buffer_usage_high_create_from_buffer(const char *buf
,
252 struct lttng_condition
**_condition
)
255 struct lttng_condition
*condition
=
256 lttng_condition_buffer_usage_high_create();
258 if (!_condition
|| !condition
) {
263 ret
= init_from_buffer(condition
, buf
);
268 *_condition
= condition
;
271 lttng_condition_destroy(condition
);
275 enum lttng_condition_status
276 lttng_condition_buffer_usage_get_threshold_percentage(
277 struct lttng_condition
*condition
, double *threshold_percent
)
279 struct lttng_condition_buffer_usage
*usage
;
280 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
282 if (!condition
|| !is_usage_condition(condition
) ||
283 !threshold_percent
) {
284 status
= LTTNG_CONDITION_STATUS_INVALID
;
288 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
290 if (!usage
->threshold_percent
.set
) {
291 status
= LTTNG_CONDITION_STATUS_UNSET
;
294 *threshold_percent
= usage
->threshold_percent
.value
;
299 /* threshold_percent expressed as [0.0, 1.0]. */
300 enum lttng_condition_status
301 lttng_condition_buffer_usage_set_threshold_percentage(
302 struct lttng_condition
*condition
, double threshold_percent
)
304 struct lttng_condition_buffer_usage
*usage
;
305 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
307 if (!condition
|| !is_usage_condition(condition
) ||
308 threshold_percent
< 0.0 || threshold_percent
> 1.0) {
309 status
= LTTNG_CONDITION_STATUS_INVALID
;
313 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
315 usage
->threshold_percent
.set
= true;
316 usage
->threshold_bytes
.set
= false;
317 usage
->threshold_percent
.value
= threshold_percent
;
322 enum lttng_condition_status
323 lttng_condition_buffer_usage_get_threshold(
324 struct lttng_condition
*condition
, uint64_t *threshold_bytes
)
326 struct lttng_condition_buffer_usage
*usage
;
327 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
329 if (!condition
|| !is_usage_condition(condition
) || !threshold_bytes
) {
330 status
= LTTNG_CONDITION_STATUS_INVALID
;
334 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
336 if (!usage
->threshold_bytes
.set
) {
337 status
= LTTNG_CONDITION_STATUS_UNSET
;
340 *threshold_bytes
= usage
->threshold_bytes
.value
;
345 enum lttng_condition_status
346 lttng_condition_buffer_usage_set_threshold(
347 struct lttng_condition
*condition
, uint64_t threshold_bytes
)
349 struct lttng_condition_buffer_usage
*usage
;
350 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
352 if (!condition
|| !is_usage_condition(condition
)) {
353 status
= LTTNG_CONDITION_STATUS_INVALID
;
357 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
359 usage
->threshold_percent
.set
= false;
360 usage
->threshold_bytes
.set
= true;
361 usage
->threshold_bytes
.value
= threshold_bytes
;
366 enum lttng_condition_status
367 lttng_condition_buffer_usage_get_session_name(
368 struct lttng_condition
*condition
, const char **session_name
)
370 struct lttng_condition_buffer_usage
*usage
;
371 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
373 if (!condition
|| !is_usage_condition(condition
) || !session_name
) {
374 status
= LTTNG_CONDITION_STATUS_INVALID
;
378 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
380 if (!usage
->session_name
) {
381 status
= LTTNG_CONDITION_STATUS_UNSET
;
384 *session_name
= usage
->session_name
;
389 extern enum lttng_condition_status
390 lttng_condition_buffer_usage_set_session_name(
391 struct lttng_condition
*condition
, const char *session_name
)
393 struct lttng_condition_buffer_usage
*usage
;
394 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
396 if (!condition
|| !is_usage_condition(condition
) || !session_name
||
397 strlen(session_name
) == 0) {
398 status
= LTTNG_CONDITION_STATUS_INVALID
;
402 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
404 usage
->session_name
= strdup(session_name
);
405 if (!usage
->session_name
) {
406 status
= LTTNG_CONDITION_STATUS_ERROR
;
413 enum lttng_condition_status
414 lttng_condition_buffer_usage_get_channel_name(
415 struct lttng_condition
*condition
, const char **channel_name
)
417 struct lttng_condition_buffer_usage
*usage
;
418 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
420 if (!condition
|| !is_usage_condition(condition
) || !channel_name
) {
421 status
= LTTNG_CONDITION_STATUS_INVALID
;
425 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
427 if (!usage
->channel_name
) {
428 status
= LTTNG_CONDITION_STATUS_UNSET
;
431 *channel_name
= usage
->channel_name
;
436 extern enum lttng_condition_status
437 lttng_condition_buffer_usage_set_channel_name(
438 struct lttng_condition
*condition
, const char *channel_name
)
440 struct lttng_condition_buffer_usage
*usage
;
441 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
443 if (!condition
|| !is_usage_condition(condition
) || !channel_name
||
444 strlen(channel_name
) == 0) {
445 status
= LTTNG_CONDITION_STATUS_INVALID
;
449 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
451 usage
->channel_name
= strdup(channel_name
);
452 if (!usage
->channel_name
) {
453 status
= LTTNG_CONDITION_STATUS_ERROR
;
460 extern enum lttng_condition_status
461 lttng_condition_buffer_usage_get_domain_type(
462 struct lttng_condition
*condition
, enum lttng_domain_type
*type
)
464 struct lttng_condition_buffer_usage
*usage
;
465 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
467 if (!condition
|| !is_usage_condition(condition
) || !type
) {
468 status
= LTTNG_CONDITION_STATUS_INVALID
;
472 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
474 if (!usage
->domain
.set
) {
475 status
= LTTNG_CONDITION_STATUS_UNSET
;
478 *type
= usage
->domain
.type
;
483 extern enum lttng_condition_status
484 lttng_condition_buffer_usage_set_domain_type(
485 struct lttng_condition
*condition
, enum lttng_domain_type type
)
487 struct lttng_condition_buffer_usage
*usage
;
488 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
490 if (!condition
|| !is_usage_condition(condition
) ||
491 type
== LTTNG_DOMAIN_NONE
) {
492 status
= LTTNG_CONDITION_STATUS_INVALID
;
496 usage
= container_of(condition
, struct lttng_condition_buffer_usage
,
498 usage
->domain
.set
= true;
499 usage
->domain
.type
= type
;
505 void lttng_evaluation_buffer_usage_destroy(
506 struct lttng_evaluation
*evaluation
)
508 struct lttng_evaluation_buffer_usage
*usage
;
510 usage
= container_of(evaluation
, struct lttng_evaluation_buffer_usage
,
516 struct lttng_evaluation
*lttng_evaluation_buffer_usage_create(uint64_t use
,
519 struct lttng_evaluation_buffer_usage
*usage
;
521 usage
= zmalloc(sizeof(struct lttng_evaluation_buffer_usage
));
526 usage
->buffer_use
= use
;
527 usage
->buffer_capacity
= capacity
;
528 usage
->parent
.destroy
= lttng_evaluation_buffer_usage_destroy
;
530 return &usage
->parent
;
534 * Get the sampled buffer usage which caused the associated condition to
535 * evaluate to "true".
537 enum lttng_evaluation_status
538 lttng_evaluation_buffer_usage_get_usage_percentage(
539 struct lttng_evaluation
*evaluation
, double *usage_percent
)
541 struct lttng_evaluation_buffer_usage
*usage
;
542 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
544 if (!evaluation
|| !is_usage_evaluation(evaluation
) || !usage_percent
) {
545 status
= LTTNG_EVALUATION_STATUS_INVALID
;
549 usage
= container_of(evaluation
, struct lttng_evaluation_buffer_usage
,
551 *usage_percent
= (double) usage
->buffer_use
/
552 (double) usage
->buffer_capacity
;
557 enum lttng_evaluation_status
558 lttng_evaluation_buffer_usage_get_usage(struct lttng_evaluation
*evaluation
,
559 uint64_t *usage_bytes
)
561 struct lttng_evaluation_buffer_usage
*usage
;
562 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
564 if (!evaluation
|| !is_usage_evaluation(evaluation
) || !usage_bytes
) {
565 status
= LTTNG_EVALUATION_STATUS_INVALID
;
569 usage
= container_of(evaluation
, struct lttng_evaluation_buffer_usage
,
571 *usage_bytes
= usage
->buffer_use
;