Add client notification API
[lttng-tools.git] / src / common / buffer-usage.c
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
32 static
33 double fixed_to_double(uint32_t val)
34 {
35 return (double) val / (double) UINT32_MAX;
36 }
37
38 static
39 uint64_t double_to_fixed(double val)
40 {
41 return (val * (double) UINT32_MAX);
42 }
43
44 static
45 bool 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
53 static
54 void 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
66 static
67 bool 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;
93 end:
94 return valid;
95 }
96
97 static
98 ssize_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;
152 end:
153 return ret;
154 }
155
156 static
157 bool 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;
222 end:
223 return is_equal;
224 }
225
226 static
227 struct 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) {
234 goto end;
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;
242 end:
243 return &condition->parent;
244 }
245
246 struct lttng_condition *lttng_condition_buffer_usage_low_create(void)
247 {
248 return lttng_condition_buffer_usage_create(
249 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
250 }
251
252 struct lttng_condition *lttng_condition_buffer_usage_high_create(void)
253 {
254 return lttng_condition_buffer_usage_create(
255 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
256 }
257
258 static
259 ssize_t init_condition_from_buffer(struct lttng_condition *condition,
260 const struct lttng_buffer_view *src_view)
261 {
262 ssize_t ret, condition_size;
263 enum lttng_condition_status status;
264 enum lttng_domain_type domain_type;
265 const struct lttng_condition_buffer_usage_comm *condition_comm;
266 const char *session_name, *channel_name;
267 struct lttng_buffer_view names_view;
268
269 if (src_view->size < sizeof(*condition_comm)) {
270 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
271 ret = -1;
272 goto end;
273 }
274
275 condition_comm = (const struct lttng_condition_buffer_usage_comm *) src_view->data;
276 names_view = lttng_buffer_view_from_view(src_view,
277 sizeof(*condition_comm), -1);
278
279 if (condition_comm->session_name_len > LTTNG_NAME_MAX ||
280 condition_comm->channel_name_len > LTTNG_NAME_MAX) {
281 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
282 ret = -1;
283 goto end;
284 }
285
286 if (names_view.size <
287 (condition_comm->session_name_len +
288 condition_comm->channel_name_len)) {
289 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
290 ret = -1;
291 goto end;
292 }
293
294 if (condition_comm->threshold_set_in_bytes) {
295 status = lttng_condition_buffer_usage_set_threshold(condition,
296 condition_comm->threshold);
297 } else {
298 status = lttng_condition_buffer_usage_set_threshold_ratio(
299 condition,
300 fixed_to_double(condition_comm->threshold));
301 }
302 if (status != LTTNG_CONDITION_STATUS_OK) {
303 ERR("Failed to initialize buffer usage condition threshold");
304 ret = -1;
305 goto end;
306 }
307
308 if (condition_comm->domain_type <= LTTNG_DOMAIN_NONE ||
309 condition_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
310 /* Invalid domain value. */
311 ERR("Invalid domain type value (%i) found in condition buffer",
312 (int) condition_comm->domain_type);
313 ret = -1;
314 goto end;
315 }
316
317 domain_type = (enum lttng_domain_type) condition_comm->domain_type;
318 status = lttng_condition_buffer_usage_set_domain_type(condition,
319 domain_type);
320 if (status != LTTNG_CONDITION_STATUS_OK) {
321 ERR("Failed to set buffer usage condition domain");
322 ret = -1;
323 goto end;
324 }
325
326 session_name = names_view.data;
327 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
328 ERR("Malformed session name encountered in condition buffer");
329 ret = -1;
330 goto end;
331 }
332
333 channel_name = session_name + condition_comm->session_name_len;
334 if (*(channel_name + condition_comm->channel_name_len - 1) != '\0') {
335 ERR("Malformed channel name encountered in condition buffer");
336 ret = -1;
337 goto end;
338 }
339
340 status = lttng_condition_buffer_usage_set_session_name(condition,
341 session_name);
342 if (status != LTTNG_CONDITION_STATUS_OK) {
343 ERR("Failed to set buffer usage session name");
344 ret = -1;
345 goto end;
346 }
347
348 status = lttng_condition_buffer_usage_set_channel_name(condition,
349 channel_name);
350 if (status != LTTNG_CONDITION_STATUS_OK) {
351 ERR("Failed to set buffer usage channel name");
352 ret = -1;
353 goto end;
354 }
355
356 if (!lttng_condition_validate(condition)) {
357 ret = -1;
358 goto end;
359 }
360
361 condition_size = sizeof(*condition_comm) +
362 (ssize_t) condition_comm->session_name_len +
363 (ssize_t) condition_comm->channel_name_len;
364 ret = condition_size;
365 end:
366 return ret;
367 }
368
369 LTTNG_HIDDEN
370 ssize_t lttng_condition_buffer_usage_low_create_from_buffer(
371 const struct lttng_buffer_view *view,
372 struct lttng_condition **_condition)
373 {
374 ssize_t ret;
375 struct lttng_condition *condition =
376 lttng_condition_buffer_usage_low_create();
377
378 if (!_condition || !condition) {
379 ret = -1;
380 goto error;
381 }
382
383 ret = init_condition_from_buffer(condition, view);
384 if (ret < 0) {
385 goto error;
386 }
387
388 *_condition = condition;
389 return ret;
390 error:
391 lttng_condition_destroy(condition);
392 return ret;
393 }
394
395 LTTNG_HIDDEN
396 ssize_t lttng_condition_buffer_usage_high_create_from_buffer(
397 const struct lttng_buffer_view *view,
398 struct lttng_condition **_condition)
399 {
400 ssize_t ret;
401 struct lttng_condition *condition =
402 lttng_condition_buffer_usage_high_create();
403
404 if (!_condition || !condition) {
405 ret = -1;
406 goto error;
407 }
408
409 ret = init_condition_from_buffer(condition, view);
410 if (ret < 0) {
411 goto error;
412 }
413
414 *_condition = condition;
415 return ret;
416 error:
417 lttng_condition_destroy(condition);
418 return ret;
419 }
420
421 static
422 struct lttng_evaluation *create_evaluation_from_buffer(
423 enum lttng_condition_type type,
424 const struct lttng_buffer_view *view)
425 {
426 const struct lttng_evaluation_buffer_usage_comm *comm =
427 (const struct lttng_evaluation_buffer_usage_comm *) view->data;
428 struct lttng_evaluation *evaluation = NULL;
429
430 if (view->size < sizeof(*comm)) {
431 goto end;
432 }
433
434 evaluation = lttng_evaluation_buffer_usage_create(type,
435 comm->buffer_use, comm->buffer_capacity);
436 end:
437 return evaluation;
438 }
439
440 LTTNG_HIDDEN
441 ssize_t lttng_evaluation_buffer_usage_low_create_from_buffer(
442 const struct lttng_buffer_view *view,
443 struct lttng_evaluation **_evaluation)
444 {
445 ssize_t ret;
446 struct lttng_evaluation *evaluation = NULL;
447
448 if (!_evaluation) {
449 ret = -1;
450 goto error;
451 }
452
453 evaluation = create_evaluation_from_buffer(
454 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW, view);
455 if (!evaluation) {
456 ret = -1;
457 goto error;
458 }
459
460 *_evaluation = evaluation;
461 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
462 return ret;
463 error:
464 lttng_evaluation_destroy(evaluation);
465 return ret;
466 }
467
468 LTTNG_HIDDEN
469 ssize_t lttng_evaluation_buffer_usage_high_create_from_buffer(
470 const struct lttng_buffer_view *view,
471 struct lttng_evaluation **_evaluation)
472 {
473 ssize_t ret;
474 struct lttng_evaluation *evaluation = NULL;
475
476 if (!_evaluation) {
477 ret = -1;
478 goto error;
479 }
480
481 evaluation = create_evaluation_from_buffer(
482 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH, view);
483 if (!evaluation) {
484 ret = -1;
485 goto error;
486 }
487
488 *_evaluation = evaluation;
489 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
490 return ret;
491 error:
492 lttng_evaluation_destroy(evaluation);
493 return ret;
494 }
495
496 enum lttng_condition_status
497 lttng_condition_buffer_usage_get_threshold_ratio(
498 const struct lttng_condition *condition,
499 double *threshold_ratio)
500 {
501 struct lttng_condition_buffer_usage *usage;
502 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
503
504 if (!condition || !IS_USAGE_CONDITION(condition) ||
505 !threshold_ratio) {
506 status = LTTNG_CONDITION_STATUS_INVALID;
507 goto end;
508 }
509
510 usage = container_of(condition, struct lttng_condition_buffer_usage,
511 parent);
512 if (!usage->threshold_ratio.set) {
513 status = LTTNG_CONDITION_STATUS_UNSET;
514 goto end;
515 }
516 *threshold_ratio = usage->threshold_ratio.value;
517 end:
518 return status;
519 }
520
521 /* threshold_ratio expressed as [0.0, 1.0]. */
522 enum lttng_condition_status
523 lttng_condition_buffer_usage_set_threshold_ratio(
524 struct lttng_condition *condition, double threshold_ratio)
525 {
526 struct lttng_condition_buffer_usage *usage;
527 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
528
529 if (!condition || !IS_USAGE_CONDITION(condition) ||
530 threshold_ratio < 0.0 ||
531 threshold_ratio > 1.0) {
532 status = LTTNG_CONDITION_STATUS_INVALID;
533 goto end;
534 }
535
536 usage = container_of(condition, struct lttng_condition_buffer_usage,
537 parent);
538 usage->threshold_ratio.set = true;
539 usage->threshold_bytes.set = false;
540 usage->threshold_ratio.value = threshold_ratio;
541 end:
542 return status;
543 }
544
545 enum lttng_condition_status
546 lttng_condition_buffer_usage_get_threshold(
547 const struct lttng_condition *condition,
548 uint64_t *threshold_bytes)
549 {
550 struct lttng_condition_buffer_usage *usage;
551 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
552
553 if (!condition || !IS_USAGE_CONDITION(condition) || !threshold_bytes) {
554 status = LTTNG_CONDITION_STATUS_INVALID;
555 goto end;
556 }
557
558 usage = container_of(condition, struct lttng_condition_buffer_usage,
559 parent);
560 if (!usage->threshold_bytes.set) {
561 status = LTTNG_CONDITION_STATUS_UNSET;
562 goto end;
563 }
564 *threshold_bytes = usage->threshold_bytes.value;
565 end:
566 return status;
567 }
568
569 enum lttng_condition_status
570 lttng_condition_buffer_usage_set_threshold(
571 struct lttng_condition *condition, uint64_t threshold_bytes)
572 {
573 struct lttng_condition_buffer_usage *usage;
574 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
575
576 if (!condition || !IS_USAGE_CONDITION(condition)) {
577 status = LTTNG_CONDITION_STATUS_INVALID;
578 goto end;
579 }
580
581 usage = container_of(condition, struct lttng_condition_buffer_usage,
582 parent);
583 usage->threshold_ratio.set = false;
584 usage->threshold_bytes.set = true;
585 usage->threshold_bytes.value = threshold_bytes;
586 end:
587 return status;
588 }
589
590 enum lttng_condition_status
591 lttng_condition_buffer_usage_get_session_name(
592 const struct lttng_condition *condition,
593 const char **session_name)
594 {
595 struct lttng_condition_buffer_usage *usage;
596 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
597
598 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name) {
599 status = LTTNG_CONDITION_STATUS_INVALID;
600 goto end;
601 }
602
603 usage = container_of(condition, struct lttng_condition_buffer_usage,
604 parent);
605 if (!usage->session_name) {
606 status = LTTNG_CONDITION_STATUS_UNSET;
607 goto end;
608 }
609 *session_name = usage->session_name;
610 end:
611 return status;
612 }
613
614 enum lttng_condition_status
615 lttng_condition_buffer_usage_set_session_name(
616 struct lttng_condition *condition, const char *session_name)
617 {
618 char *session_name_copy;
619 struct lttng_condition_buffer_usage *usage;
620 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
621
622 if (!condition || !IS_USAGE_CONDITION(condition) || !session_name ||
623 strlen(session_name) == 0) {
624 status = LTTNG_CONDITION_STATUS_INVALID;
625 goto end;
626 }
627
628 usage = container_of(condition, struct lttng_condition_buffer_usage,
629 parent);
630 session_name_copy = strdup(session_name);
631 if (!session_name_copy) {
632 status = LTTNG_CONDITION_STATUS_ERROR;
633 goto end;
634 }
635
636 if (usage->session_name) {
637 free(usage->session_name);
638 }
639 usage->session_name = session_name_copy;
640 end:
641 return status;
642 }
643
644 enum lttng_condition_status
645 lttng_condition_buffer_usage_get_channel_name(
646 const struct lttng_condition *condition,
647 const char **channel_name)
648 {
649 struct lttng_condition_buffer_usage *usage;
650 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
651
652 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name) {
653 status = LTTNG_CONDITION_STATUS_INVALID;
654 goto end;
655 }
656
657 usage = container_of(condition, struct lttng_condition_buffer_usage,
658 parent);
659 if (!usage->channel_name) {
660 status = LTTNG_CONDITION_STATUS_UNSET;
661 goto end;
662 }
663 *channel_name = usage->channel_name;
664 end:
665 return status;
666 }
667
668 enum lttng_condition_status
669 lttng_condition_buffer_usage_set_channel_name(
670 struct lttng_condition *condition, const char *channel_name)
671 {
672 char *channel_name_copy;
673 struct lttng_condition_buffer_usage *usage;
674 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
675
676 if (!condition || !IS_USAGE_CONDITION(condition) || !channel_name ||
677 strlen(channel_name) == 0) {
678 status = LTTNG_CONDITION_STATUS_INVALID;
679 goto end;
680 }
681
682 usage = container_of(condition, struct lttng_condition_buffer_usage,
683 parent);
684 channel_name_copy = strdup(channel_name);
685 if (!channel_name_copy) {
686 status = LTTNG_CONDITION_STATUS_ERROR;
687 goto end;
688 }
689
690 if (usage->channel_name) {
691 free(usage->channel_name);
692 }
693 usage->channel_name = channel_name_copy;
694 end:
695 return status;
696 }
697
698 enum lttng_condition_status
699 lttng_condition_buffer_usage_get_domain_type(
700 const struct lttng_condition *condition,
701 enum lttng_domain_type *type)
702 {
703 struct lttng_condition_buffer_usage *usage;
704 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
705
706 if (!condition || !IS_USAGE_CONDITION(condition) || !type) {
707 status = LTTNG_CONDITION_STATUS_INVALID;
708 goto end;
709 }
710
711 usage = container_of(condition, struct lttng_condition_buffer_usage,
712 parent);
713 if (!usage->domain.set) {
714 status = LTTNG_CONDITION_STATUS_UNSET;
715 goto end;
716 }
717 *type = usage->domain.type;
718 end:
719 return status;
720 }
721
722 enum lttng_condition_status
723 lttng_condition_buffer_usage_set_domain_type(
724 struct lttng_condition *condition, enum lttng_domain_type type)
725 {
726 struct lttng_condition_buffer_usage *usage;
727 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
728
729 if (!condition || !IS_USAGE_CONDITION(condition) ||
730 type == LTTNG_DOMAIN_NONE) {
731 status = LTTNG_CONDITION_STATUS_INVALID;
732 goto end;
733 }
734
735 usage = container_of(condition, struct lttng_condition_buffer_usage,
736 parent);
737 usage->domain.set = true;
738 usage->domain.type = type;
739 end:
740 return status;
741 }
742
743 static
744 ssize_t lttng_evaluation_buffer_usage_serialize(
745 struct lttng_evaluation *evaluation, char *buf)
746 {
747 ssize_t ret;
748 struct lttng_evaluation_buffer_usage *usage;
749
750 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
751 parent);
752 if (buf) {
753 struct lttng_evaluation_buffer_usage_comm comm = {
754 .buffer_use = usage->buffer_use,
755 .buffer_capacity = usage->buffer_capacity,
756 };
757
758 memcpy(buf, &comm, sizeof(comm));
759 }
760
761 ret = sizeof(struct lttng_evaluation_buffer_usage_comm);
762 return ret;
763 }
764
765 static
766 void lttng_evaluation_buffer_usage_destroy(
767 struct lttng_evaluation *evaluation)
768 {
769 struct lttng_evaluation_buffer_usage *usage;
770
771 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
772 parent);
773 free(usage);
774 }
775
776 LTTNG_HIDDEN
777 struct lttng_evaluation *lttng_evaluation_buffer_usage_create(
778 enum lttng_condition_type type, uint64_t use, uint64_t capacity)
779 {
780 struct lttng_evaluation_buffer_usage *usage;
781
782 usage = zmalloc(sizeof(struct lttng_evaluation_buffer_usage));
783 if (!usage) {
784 goto end;
785 }
786
787 usage->parent.type = type;
788 usage->buffer_use = use;
789 usage->buffer_capacity = capacity;
790 usage->parent.serialize = lttng_evaluation_buffer_usage_serialize;
791 usage->parent.destroy = lttng_evaluation_buffer_usage_destroy;
792 end:
793 return &usage->parent;
794 }
795
796 /*
797 * Get the sampled buffer usage which caused the associated condition to
798 * evaluate to "true".
799 */
800 enum lttng_evaluation_status
801 lttng_evaluation_buffer_usage_get_usage_ratio(
802 const struct lttng_evaluation *evaluation, double *usage_ratio)
803 {
804 struct lttng_evaluation_buffer_usage *usage;
805 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
806
807 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_ratio) {
808 status = LTTNG_EVALUATION_STATUS_INVALID;
809 goto end;
810 }
811
812 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
813 parent);
814 *usage_ratio = (double) usage->buffer_use /
815 (double) usage->buffer_capacity;
816 end:
817 return status;
818 }
819
820 enum lttng_evaluation_status
821 lttng_evaluation_buffer_usage_get_usage(
822 const struct lttng_evaluation *evaluation,
823 uint64_t *usage_bytes)
824 {
825 struct lttng_evaluation_buffer_usage *usage;
826 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
827
828 if (!evaluation || !is_usage_evaluation(evaluation) || !usage_bytes) {
829 status = LTTNG_EVALUATION_STATUS_INVALID;
830 goto end;
831 }
832
833 usage = container_of(evaluation, struct lttng_evaluation_buffer_usage,
834 parent);
835 *usage_bytes = usage->buffer_use;
836 end:
837 return status;
838 }
This page took 0.045763 seconds and 4 git commands to generate.