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