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