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