Fix: test_utils_expand_path passes NULL to sprintf
[lttng-tools.git] / src / common / buffer-usage.c
CommitLineData
a58c490f
JG
1/*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
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.
7 *
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
11 * for more details.
12 *
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
16 */
17
18#include <lttng/condition/condition-internal.h>
19#include <lttng/condition/buffer-usage-internal.h>
20#include <common/macros.h>
21#include <common/error.h>
22#include <assert.h>
23#include <math.h>
24#include <float.h>
25#include <time.h>
26
27#define IS_USAGE_CONDITION(condition) ( \
28 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW || \
29 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH \
30 )
31
32static
33double fixed_to_double(uint32_t val)
34{
35 return (double) val / (double) UINT32_MAX;
36}
37
38static
39uint64_t double_to_fixed(double val)
40{
41 return (val * (double) UINT32_MAX);
42}
43
44static
45bool is_usage_evaluation(const struct lttng_evaluation *evaluation)
46{
47 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
48
49 return type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW ||
50 type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
51}
52
53static
54void lttng_condition_buffer_usage_destroy(struct lttng_condition *condition)
55{
56 struct lttng_condition_buffer_usage *usage;
57
58 usage = container_of(condition, struct lttng_condition_buffer_usage,
59 parent);
60
61 free(usage->session_name);
62 free(usage->channel_name);
63 free(usage);
64}
65
66static
67bool lttng_condition_buffer_usage_validate(
68 const struct lttng_condition *condition)
69{
70 bool valid = false;
71 struct lttng_condition_buffer_usage *usage;
72
73 if (!condition) {
74 goto end;
75 }
76
77 usage = container_of(condition, struct lttng_condition_buffer_usage,
78 parent);
79 if (!usage->session_name) {
80 ERR("Invalid buffer condition: a target session name must be set.");
81 goto end;
82 }
83 if (!usage->channel_name) {
84 ERR("Invalid buffer condition: a target channel name must be set.");
85 goto end;
86 }
87 if (!usage->threshold_ratio.set && !usage->threshold_bytes.set) {
88 ERR("Invalid buffer condition: a threshold must be set.");
89 goto end;
90 }
91
92 valid = true;
93end:
94 return valid;
95}
96
97static
98ssize_t lttng_condition_buffer_usage_serialize(
99 const struct lttng_condition *condition, char *buf)
100{
101 struct lttng_condition_buffer_usage *usage;
102 ssize_t ret, size;
103 size_t session_name_len, channel_name_len;
104
105 if (!condition || !IS_USAGE_CONDITION(condition)) {
106 ret = -1;
107 goto end;
108 }
109
110 DBG("Serializing buffer usage condition");
111 usage = container_of(condition, struct lttng_condition_buffer_usage,
112 parent);
113 size = sizeof(struct lttng_condition_buffer_usage_comm);
114 session_name_len = strlen(usage->session_name) + 1;
115 channel_name_len = strlen(usage->channel_name) + 1;
116 if (session_name_len > LTTNG_NAME_MAX ||
117 channel_name_len > LTTNG_NAME_MAX) {
118 ret = -1;
119 goto end;
120 }
121 size += session_name_len + channel_name_len;
122 if (buf) {
123 struct lttng_condition_buffer_usage_comm usage_comm = {
124 .threshold_set_in_bytes = usage->threshold_bytes.set ? 1 : 0,
125 .session_name_len = session_name_len,
126 .channel_name_len = channel_name_len,
127 .domain_type = (int8_t) usage->domain.type,
128 };
129
130 if (usage->threshold_bytes.set) {
131 usage_comm.threshold = usage->threshold_bytes.value;
132 } else {
133 uint64_t val = double_to_fixed(
134 usage->threshold_ratio.value);
135
136 if (val > UINT32_MAX) {
137 /* overflow. */
138 ret = -1;
139 goto end;
140 }
141 usage_comm.threshold = val;
142 }
143
144 memcpy(buf, &usage_comm, sizeof(usage_comm));
145 buf += sizeof(usage_comm);
146 memcpy(buf, usage->session_name, session_name_len);
147 buf += session_name_len;
148 memcpy(buf, usage->channel_name, channel_name_len);
149 buf += channel_name_len;
150 }
151 ret = size;
152end:
153 return ret;
154}
155
156static
157bool lttng_condition_buffer_usage_is_equal(const struct lttng_condition *_a,
158 const struct lttng_condition *_b)
159{
160 bool is_equal = false;
161 struct lttng_condition_buffer_usage *a, *b;
162
163 a = container_of(_a, struct lttng_condition_buffer_usage, parent);
164 b = container_of(_b, struct lttng_condition_buffer_usage, parent);
165
166 if ((a->threshold_ratio.set && !b->threshold_ratio.set) ||
167 (a->threshold_bytes.set && !b->threshold_bytes.set)) {
168 goto end;
169 }
170
171 if (a->threshold_ratio.set && b->threshold_ratio.set) {
172 double a_value, b_value, diff;
173
174 a_value = a->threshold_ratio.value;
175 b_value = b->threshold_ratio.value;
176 diff = fabs(a_value - b_value);
177
178 if (diff > DBL_EPSILON) {
179 goto end;
180 }
181 } else if (a->threshold_bytes.set && b->threshold_bytes.set) {
182 uint64_t a_value, b_value;
183
184 a_value = a->threshold_bytes.value;
185 b_value = b->threshold_bytes.value;
186 if (a_value != b_value) {
187 goto end;
188 }
189 }
190
191 if ((a->session_name && !b->session_name) ||
192 (!a->session_name && b->session_name)) {
193 goto end;
194 }
195
196 if (a->channel_name && b->channel_name) {
197 if (strcmp(a->channel_name, b->channel_name)) {
198 goto end;
199 }
200 } if ((a->channel_name && !b->channel_name) ||
201 (!a->channel_name && b->channel_name)) {
202 goto end;
203 }
204
205 if (a->channel_name && b->channel_name) {
206 if (strcmp(a->channel_name, b->channel_name)) {
207 goto end;
208 }
209 }
210
211 if ((a->domain.set && !b->domain.set) ||
212 (!a->domain.set && b->domain.set)) {
213 goto end;
214 }
215
216 if (a->domain.set && b->domain.set) {
217 if (a->domain.type != b->domain.type) {
218 goto end;
219 }
220 }
221 is_equal = true;
222end:
223 return is_equal;
224}
225
226static
227struct lttng_condition *lttng_condition_buffer_usage_create(
228 enum lttng_condition_type type)
229{
230 struct lttng_condition_buffer_usage *condition;
231
232 condition = zmalloc(sizeof(struct lttng_condition_buffer_usage));
233 if (!condition) {
9a09eef5 234 return NULL;
a58c490f
JG
235 }
236
237 lttng_condition_init(&condition->parent, type);
238 condition->parent.validate = lttng_condition_buffer_usage_validate;
239 condition->parent.serialize = lttng_condition_buffer_usage_serialize;
240 condition->parent.equal = lttng_condition_buffer_usage_is_equal;
241 condition->parent.destroy = lttng_condition_buffer_usage_destroy;
a58c490f
JG
242 return &condition->parent;
243}
244
245struct lttng_condition *lttng_condition_buffer_usage_low_create(void)
246{
247 return lttng_condition_buffer_usage_create(
248 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
249}
250
251struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
252{
253 return lttng_condition_buffer_usage_create(
254 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
255}
256
257static
258ssize_t init_condition_from_buffer(struct lttng_condition *condition,
259 const struct lttng_buffer_view *src_view)
260{
261 ssize_t ret, condition_size;
262 enum lttng_condition_status status;
263 enum lttng_domain_type domain_type;
264 const struct lttng_condition_buffer_usage_comm *condition_comm;
265 const char *session_name, *channel_name;
266 struct lttng_buffer_view names_view;
267
268 if (src_view->size < sizeof(*condition_comm)) {
269 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
270 ret = -1;
271 goto end;
272 }
273
274 condition_comm = (const struct lttng_condition_buffer_usage_comm *) src_view->data;
275 names_view = lttng_buffer_view_from_view(src_view,
276 sizeof(*condition_comm), -1);
277
278 if (condition_comm->session_name_len > LTTNG_NAME_MAX ||
279 condition_comm->channel_name_len > LTTNG_NAME_MAX) {
280 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
281 ret = -1;
282 goto end;
283 }
284
285 if (names_view.size <
286 (condition_comm->session_name_len +
287 condition_comm->channel_name_len)) {
288 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
289 ret = -1;
290 goto end;
291 }
292
293 if (condition_comm->threshold_set_in_bytes) {
294 status = lttng_condition_buffer_usage_set_threshold(condition,
295 condition_comm->threshold);
296 } else {
297 status = lttng_condition_buffer_usage_set_threshold_ratio(
298 condition,
299 fixed_to_double(condition_comm->threshold));
300 }
301 if (status != LTTNG_CONDITION_STATUS_OK) {
302 ERR("Failed to initialize buffer usage condition threshold");
303 ret = -1;
304 goto end;
305 }
306
307 if (condition_comm->domain_type <= LTTNG_DOMAIN_NONE ||
308 condition_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
309 /* Invalid domain value. */
310 ERR("Invalid domain type value (%i) found in condition buffer",
311 (int) condition_comm->domain_type);
312 ret = -1;
313 goto end;
314 }
315
316 domain_type = (enum lttng_domain_type) condition_comm->domain_type;
317 status = lttng_condition_buffer_usage_set_domain_type(condition,
318 domain_type);
319 if (status != LTTNG_CONDITION_STATUS_OK) {
320 ERR("Failed to set buffer usage condition domain");
321 ret = -1;
322 goto end;
323 }
324
325 session_name = names_view.data;
326 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
327 ERR("Malformed session name encountered in condition buffer");
328 ret = -1;
329 goto end;
330 }
331
332 channel_name = session_name + condition_comm->session_name_len;
333 if (*(channel_name + condition_comm->channel_name_len - 1) != '\0') {
334 ERR("Malformed channel name encountered in condition buffer");
335 ret = -1;
336 goto end;
337 }
338
339 status = lttng_condition_buffer_usage_set_session_name(condition,
340 session_name);
341 if (status != LTTNG_CONDITION_STATUS_OK) {
342 ERR("Failed to set buffer usage session name");
343 ret = -1;
344 goto end;
345 }
346
347 status = lttng_condition_buffer_usage_set_channel_name(condition,
348 channel_name);
349 if (status != LTTNG_CONDITION_STATUS_OK) {
350 ERR("Failed to set buffer usage channel name");
351 ret = -1;
352 goto end;
353 }
354
355 if (!lttng_condition_validate(condition)) {
356 ret = -1;
357 goto end;
358 }
359
360 condition_size = sizeof(*condition_comm) +
361 (ssize_t) condition_comm->session_name_len +
362 (ssize_t) condition_comm->channel_name_len;
363 ret = condition_size;
364end:
365 return ret;
366}
367
368LTTNG_HIDDEN
369ssize_t lttng_condition_buffer_usage_low_create_from_buffer(
370 const struct lttng_buffer_view *view,
371 struct lttng_condition **_condition)
372{
373 ssize_t ret;
374 struct lttng_condition *condition =
375 lttng_condition_buffer_usage_low_create();
376
377 if (!_condition || !condition) {
378 ret = -1;
379 goto error;
380 }
381
382 ret = init_condition_from_buffer(condition, view);
383 if (ret < 0) {
384 goto error;
385 }
386
387 *_condition = condition;
388 return ret;
389error:
390 lttng_condition_destroy(condition);
391 return ret;
392}
393
394LTTNG_HIDDEN
395ssize_t lttng_condition_buffer_usage_high_create_from_buffer(
396 const struct lttng_buffer_view *view,
397 struct lttng_condition **_condition)
398{
399 ssize_t ret;
400 struct lttng_condition *condition =
401 lttng_condition_buffer_usage_high_create();
402
403 if (!_condition || !condition) {
404 ret = -1;
405 goto error;
406 }
407
408 ret = init_condition_from_buffer(condition, view);
409 if (ret < 0) {
410 goto error;
411 }
412
413 *_condition = condition;
414 return ret;
415error:
416 lttng_condition_destroy(condition);
417 return ret;
418}
419
420static
421struct lttng_evaluation *create_evaluation_from_buffer(
422 enum lttng_condition_type type,
423 const struct lttng_buffer_view *view)
424{
425 const struct lttng_evaluation_buffer_usage_comm *comm =
426 (const struct lttng_evaluation_buffer_usage_comm *) view->data;
427 struct lttng_evaluation *evaluation = NULL;
428
429 if (view->size < sizeof(*comm)) {
430 goto end;
431 }
432
433 evaluation = lttng_evaluation_buffer_usage_create(type,
434 comm->buffer_use, comm->buffer_capacity);
435end:
436 return evaluation;
437}
438
439LTTNG_HIDDEN
440ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(
441 const struct lttng_buffer_view *view,
442 struct lttng_evaluation **_evaluation)
443{
444 ssize_t ret;
445 struct lttng_evaluation *evaluation = NULL;
446
447 if (!_evaluation) {
448 ret = -1;
449 goto error;
450 }
451
452 evaluation = create_evaluation_from_buffer(
453 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, view);
454 if (!evaluation) {
455 ret = -1;
456 goto error;
457 }
458
459 *_evaluation = evaluation;
460 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
461 return ret;
462error:
463 lttng_evaluation_destroy(evaluation);
464 return ret;
465}
466
467LTTNG_HIDDEN
468ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(
469 const struct lttng_buffer_view *view,
470 struct lttng_evaluation **_evaluation)
471{
472 ssize_t ret;
473 struct lttng_evaluation *evaluation = NULL;
474
475 if (!_evaluation) {
476 ret = -1;
477 goto error;
478 }
479
480 evaluation = create_evaluation_from_buffer(
481 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, view);
482 if (!evaluation) {
483 ret = -1;
484 goto error;
485 }
486
487 *_evaluation = evaluation;
488 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
489 return ret;
490error:
491 lttng_evaluation_destroy(evaluation);
492 return ret;
493}
494
495enum lttng_condition_status
496lttng_condition_buffer_usage_get_threshold_ratio(
497 const struct lttng_condition *condition,
498 double *threshold_ratio)
499{
500 struct lttng_condition_buffer_usage *usage;
501 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
502
503 if (!condition || !IS_USAGE_CONDITION(condition) ||
504 !threshold_ratio) {
505 status = LTTNG_CONDITION_STATUS_INVALID;
506 goto end;
507 }
508
509 usage = container_of(condition, struct lttng_condition_buffer_usage,
510 parent);
511 if (!usage->threshold_ratio.set) {
512 status = LTTNG_CONDITION_STATUS_UNSET;
513 goto end;
514 }
515 *threshold_ratio = usage->threshold_ratio.value;
516end:
517 return status;
518}
519
520/* threshold_ratio expressed as [0.0, 1.0]. */
521enum lttng_condition_status
522lttng_condition_buffer_usage_set_threshold_ratio(
523 struct lttng_condition *condition, double threshold_ratio)
524{
525 struct lttng_condition_buffer_usage *usage;
526 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
527
528 if (!condition || !IS_USAGE_CONDITION(condition) ||
529 threshold_ratio < 0.0 ||
530 threshold_ratio > 1.0) {
531 status = LTTNG_CONDITION_STATUS_INVALID;
532 goto end;
533 }
534
535 usage = container_of(condition, struct lttng_condition_buffer_usage,
536 parent);
537 usage->threshold_ratio.set = true;
538 usage->threshold_bytes.set = false;
539 usage->threshold_ratio.value = threshold_ratio;
540end:
541 return status;
542}
543
544enum lttng_condition_status
545lttng_condition_buffer_usage_get_threshold(
546 const struct lttng_condition *condition,
547 uint64_t *threshold_bytes)
548{
549 struct lttng_condition_buffer_usage *usage;
550 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
551
552 if (!condition || !IS_USAGE_CONDITION(condition) || !threshold_bytes) {
553 status = LTTNG_CONDITION_STATUS_INVALID;
554 goto end;
555 }
556
557 usage = container_of(condition, struct lttng_condition_buffer_usage,
558 parent);
559 if (!usage->threshold_bytes.set) {
560 status = LTTNG_CONDITION_STATUS_UNSET;
561 goto end;
562 }
563 *threshold_bytes = usage->threshold_bytes.value;
564end:
565 return status;
566}
567
568enum lttng_condition_status
569lttng_condition_buffer_usage_set_threshold(
570 struct lttng_condition *condition, uint64_t threshold_bytes)
571{
572 struct lttng_condition_buffer_usage *usage;
573 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
574
575 if (!condition || !IS_USAGE_CONDITION(condition)) {
576 status = LTTNG_CONDITION_STATUS_INVALID;
577 goto end;
578 }
579
580 usage = container_of(condition, struct lttng_condition_buffer_usage,
581 parent);
582 usage->threshold_ratio.set = false;
583 usage->threshold_bytes.set = true;
584 usage->threshold_bytes.value = threshold_bytes;
585end:
586 return status;
587}
588
589enum lttng_condition_status
590lttng_condition_buffer_usage_get_session_name(
591 const struct lttng_condition *condition,
592 const char **session_name)
593{
594 struct lttng_condition_buffer_usage *usage;
595 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
596
597 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name) {
598 status = LTTNG_CONDITION_STATUS_INVALID;
599 goto end;
600 }
601
602 usage = container_of(condition, struct lttng_condition_buffer_usage,
603 parent);
604 if (!usage->session_name) {
605 status = LTTNG_CONDITION_STATUS_UNSET;
606 goto end;
607 }
608 *session_name = usage->session_name;
609end:
610 return status;
611}
612
613enum lttng_condition_status
614lttng_condition_buffer_usage_set_session_name(
615 struct lttng_condition *condition, const char *session_name)
616{
617 char *session_name_copy;
618 struct lttng_condition_buffer_usage *usage;
619 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
620
621 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name ||
622 strlen(session_name) == 0) {
623 status = LTTNG_CONDITION_STATUS_INVALID;
624 goto end;
625 }
626
627 usage = container_of(condition, struct lttng_condition_buffer_usage,
628 parent);
629 session_name_copy = strdup(session_name);
630 if (!session_name_copy) {
631 status = LTTNG_CONDITION_STATUS_ERROR;
632 goto end;
633 }
634
635 if (usage->session_name) {
636 free(usage->session_name);
637 }
638 usage->session_name = session_name_copy;
639end:
640 return status;
641}
642
643enum lttng_condition_status
644lttng_condition_buffer_usage_get_channel_name(
645 const struct lttng_condition *condition,
646 const char **channel_name)
647{
648 struct lttng_condition_buffer_usage *usage;
649 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
650
651 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name) {
652 status = LTTNG_CONDITION_STATUS_INVALID;
653 goto end;
654 }
655
656 usage = container_of(condition, struct lttng_condition_buffer_usage,
657 parent);
658 if (!usage->channel_name) {
659 status = LTTNG_CONDITION_STATUS_UNSET;
660 goto end;
661 }
662 *channel_name = usage->channel_name;
663end:
664 return status;
665}
666
667enum lttng_condition_status
668lttng_condition_buffer_usage_set_channel_name(
669 struct lttng_condition *condition, const char *channel_name)
670{
671 char *channel_name_copy;
672 struct lttng_condition_buffer_usage *usage;
673 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
674
675 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name ||
676 strlen(channel_name) == 0) {
677 status = LTTNG_CONDITION_STATUS_INVALID;
678 goto end;
679 }
680
681 usage = container_of(condition, struct lttng_condition_buffer_usage,
682 parent);
683 channel_name_copy = strdup(channel_name);
684 if (!channel_name_copy) {
685 status = LTTNG_CONDITION_STATUS_ERROR;
686 goto end;
687 }
688
689 if (usage->channel_name) {
690 free(usage->channel_name);
691 }
692 usage->channel_name = channel_name_copy;
693end:
694 return status;
695}
696
697enum lttng_condition_status
698lttng_condition_buffer_usage_get_domain_type(
699 const struct lttng_condition *condition,
700 enum lttng_domain_type *type)
701{
702 struct lttng_condition_buffer_usage *usage;
703 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
704
705 if (!condition || !IS_USAGE_CONDITION(condition) || !type) {
706 status = LTTNG_CONDITION_STATUS_INVALID;
707 goto end;
708 }
709
710 usage = container_of(condition, struct lttng_condition_buffer_usage,
711 parent);
712 if (!usage->domain.set) {
713 status = LTTNG_CONDITION_STATUS_UNSET;
714 goto end;
715 }
716 *type = usage->domain.type;
717end:
718 return status;
719}
720
721enum lttng_condition_status
722lttng_condition_buffer_usage_set_domain_type(
723 struct lttng_condition *condition, enum lttng_domain_type type)
724{
725 struct lttng_condition_buffer_usage *usage;
726 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
727
728 if (!condition || !IS_USAGE_CONDITION(condition) ||
729 type == LTTNG_DOMAIN_NONE) {
730 status = LTTNG_CONDITION_STATUS_INVALID;
731 goto end;
732 }
733
734 usage = container_of(condition, struct lttng_condition_buffer_usage,
735 parent);
736 usage->domain.set = true;
737 usage->domain.type = type;
738end:
739 return status;
740}
741
742static
743ssize_t lttng_evaluation_buffer_usage_serialize(
744 struct lttng_evaluation *evaluation, char *buf)
745{
746 ssize_t ret;
747 struct lttng_evaluation_buffer_usage *usage;
748
749 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
750 parent);
751 if (buf) {
752 struct lttng_evaluation_buffer_usage_comm comm = {
753 .buffer_use = usage->buffer_use,
754 .buffer_capacity = usage->buffer_capacity,
755 };
756
757 memcpy(buf, &comm, sizeof(comm));
758 }
759
760 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
761 return ret;
762}
763
764static
765void lttng_evaluation_buffer_usage_destroy(
766 struct lttng_evaluation *evaluation)
767{
768 struct lttng_evaluation_buffer_usage *usage;
769
770 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
771 parent);
772 free(usage);
773}
774
775LTTNG_HIDDEN
776struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
777 enum lttng_condition_type type, uint64_t use, uint64_t capacity)
778{
779 struct lttng_evaluation_buffer_usage *usage;
780
781 usage = zmalloc(sizeof(struct lttng_evaluation_buffer_usage));
782 if (!usage) {
783 goto end;
784 }
785
786 usage->parent.type = type;
787 usage->buffer_use = use;
788 usage->buffer_capacity = capacity;
789 usage->parent.serialize = lttng_evaluation_buffer_usage_serialize;
790 usage->parent.destroy = lttng_evaluation_buffer_usage_destroy;
791end:
792 return &usage->parent;
793}
794
795/*
796 * Get the sampled buffer usage which caused the associated condition to
797 * evaluate to "true".
798 */
799enum lttng_evaluation_status
800lttng_evaluation_buffer_usage_get_usage_ratio(
801 const struct lttng_evaluation *evaluation, double *usage_ratio)
802{
803 struct lttng_evaluation_buffer_usage *usage;
804 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
805
806 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_ratio) {
807 status = LTTNG_EVALUATION_STATUS_INVALID;
808 goto end;
809 }
810
811 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
812 parent);
813 *usage_ratio = (double) usage->buffer_use /
814 (double) usage->buffer_capacity;
815end:
816 return status;
817}
818
819enum lttng_evaluation_status
820lttng_evaluation_buffer_usage_get_usage(
821 const struct lttng_evaluation *evaluation,
822 uint64_t *usage_bytes)
823{
824 struct lttng_evaluation_buffer_usage *usage;
825 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
826
827 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_bytes) {
828 status = LTTNG_EVALUATION_STATUS_INVALID;
829 goto end;
830 }
831
832 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
833 parent);
834 *usage_bytes = usage->buffer_use;
835end:
836 return status;
837}
This page took 0.052843 seconds and 4 git commands to generate.