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