Run clang-format on the whole tree
[lttng-tools.git] / src / common / actions / rate-policy.cpp
1 /*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/buffer-view.hpp>
9 #include <common/dynamic-buffer.hpp>
10 #include <common/error.hpp>
11 #include <common/macros.hpp>
12 #include <common/mi-lttng.hpp>
13 #include <common/payload-view.hpp>
14 #include <common/payload.hpp>
15
16 #include <lttng/action/rate-policy-internal.hpp>
17 #include <lttng/action/rate-policy.h>
18
19 #include <limits.h>
20 #include <stdbool.h>
21 #include <sys/types.h>
22
23 #define IS_EVERY_N_RATE_POLICY(policy) \
24 (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_EVERY_N)
25
26 #define IS_ONCE_AFTER_N_RATE_POLICY(policy) \
27 (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N)
28
29 typedef void (*rate_policy_destroy_cb)(struct lttng_rate_policy *rate_policy);
30 typedef int (*rate_policy_serialize_cb)(struct lttng_rate_policy *rate_policy,
31 struct lttng_payload *payload);
32 typedef bool (*rate_policy_equal_cb)(const struct lttng_rate_policy *a,
33 const struct lttng_rate_policy *b);
34 typedef ssize_t (*rate_policy_create_from_payload_cb)(struct lttng_payload_view *view,
35 struct lttng_rate_policy **rate_policy);
36 typedef struct lttng_rate_policy *(*rate_policy_copy_cb)(const struct lttng_rate_policy *source);
37 typedef enum lttng_error_code (*rate_policy_mi_serialize_cb)(
38 const struct lttng_rate_policy *rate_policy, struct mi_writer *writer);
39
40 struct lttng_rate_policy {
41 enum lttng_rate_policy_type type;
42 rate_policy_serialize_cb serialize;
43 rate_policy_equal_cb equal;
44 rate_policy_destroy_cb destroy;
45 rate_policy_copy_cb copy;
46 rate_policy_mi_serialize_cb mi_serialize;
47 };
48
49 namespace {
50 struct lttng_rate_policy_every_n {
51 struct lttng_rate_policy parent;
52 uint64_t interval;
53 };
54
55 struct lttng_rate_policy_once_after_n {
56 struct lttng_rate_policy parent;
57 uint64_t threshold;
58 };
59
60 struct lttng_rate_policy_comm {
61 /* enum lttng_rate_policy_type */
62 int8_t rate_policy_type;
63 } LTTNG_PACKED;
64
65 struct lttng_rate_policy_once_after_n_comm {
66 uint64_t threshold;
67 } LTTNG_PACKED;
68
69 struct lttng_rate_policy_every_n_comm {
70 uint64_t interval;
71 } LTTNG_PACKED;
72 } /* namespace */
73
74 /* Forward declaration. */
75 static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
76 enum lttng_rate_policy_type type,
77 rate_policy_serialize_cb serialize,
78 rate_policy_equal_cb equal,
79 rate_policy_destroy_cb destroy,
80 rate_policy_copy_cb copy,
81 rate_policy_mi_serialize_cb mi);
82
83 /* Forward declaration. Every n */
84 static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
85 uint64_t counter);
86
87 /* Forward declaration. Once after N */
88 static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
89 uint64_t counter);
90
91 const char *lttng_rate_policy_type_string(enum lttng_rate_policy_type rate_policy_type)
92 {
93 switch (rate_policy_type) {
94 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
95 return "EVERY-N";
96 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
97 return "ONCE-AFTER-N";
98 default:
99 return "???";
100 }
101 }
102
103 enum lttng_rate_policy_type lttng_rate_policy_get_type(const struct lttng_rate_policy *policy)
104 {
105 return policy ? policy->type : LTTNG_RATE_POLICY_TYPE_UNKNOWN;
106 }
107
108 void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy,
109 enum lttng_rate_policy_type type,
110 rate_policy_serialize_cb serialize,
111 rate_policy_equal_cb equal,
112 rate_policy_destroy_cb destroy,
113 rate_policy_copy_cb copy,
114 rate_policy_mi_serialize_cb mi)
115 {
116 rate_policy->type = type;
117 rate_policy->serialize = serialize;
118 rate_policy->equal = equal;
119 rate_policy->destroy = destroy;
120 rate_policy->copy = copy;
121 rate_policy->mi_serialize = mi;
122 }
123
124 void lttng_rate_policy_destroy(struct lttng_rate_policy *rate_policy)
125 {
126 if (!rate_policy) {
127 return;
128 }
129
130 rate_policy->destroy(rate_policy);
131 }
132
133 int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy,
134 struct lttng_payload *payload)
135 {
136 int ret;
137 struct lttng_rate_policy_comm rate_policy_comm = {
138 .rate_policy_type = (int8_t) rate_policy->type,
139 };
140
141 ret = lttng_dynamic_buffer_append(
142 &payload->buffer, &rate_policy_comm, sizeof(rate_policy_comm));
143 if (ret) {
144 goto end;
145 }
146
147 ret = rate_policy->serialize(rate_policy, payload);
148 if (ret) {
149 goto end;
150 }
151 end:
152 return ret;
153 }
154
155 static ssize_t
156 lttng_rate_policy_once_after_n_create_from_payload(struct lttng_payload_view *view,
157 struct lttng_rate_policy **rate_policy)
158 {
159 ssize_t consumed_len = -1;
160 struct lttng_rate_policy *policy = NULL;
161 const struct lttng_rate_policy_once_after_n_comm *comm;
162 const struct lttng_payload_view comm_view =
163 lttng_payload_view_from_view(view, 0, sizeof(*comm));
164
165 if (!view || !rate_policy) {
166 consumed_len = -1;
167 goto end;
168 }
169
170 if (!lttng_payload_view_is_valid(&comm_view)) {
171 /* Payload not large enough to contain the header. */
172 consumed_len = -1;
173 goto end;
174 }
175
176 comm = (const struct lttng_rate_policy_once_after_n_comm *) comm_view.buffer.data;
177
178 policy = lttng_rate_policy_once_after_n_create(comm->threshold);
179 if (policy == NULL) {
180 consumed_len = -1;
181 goto end;
182 }
183
184 *rate_policy = policy;
185 consumed_len = sizeof(*comm);
186
187 end:
188 return consumed_len;
189 }
190
191 static ssize_t lttng_rate_policy_every_n_create_from_payload(struct lttng_payload_view *view,
192 struct lttng_rate_policy **rate_policy)
193 {
194 ssize_t consumed_len = -1;
195 struct lttng_rate_policy *policy = NULL;
196 const struct lttng_rate_policy_every_n_comm *comm;
197 const struct lttng_payload_view comm_view =
198 lttng_payload_view_from_view(view, 0, sizeof(*comm));
199
200 if (!view || !rate_policy) {
201 consumed_len = -1;
202 goto end;
203 }
204
205 if (!lttng_payload_view_is_valid(&comm_view)) {
206 /* Payload not large enough to contain the header. */
207 consumed_len = -1;
208 goto end;
209 }
210
211 comm = (const struct lttng_rate_policy_every_n_comm *) comm_view.buffer.data;
212
213 policy = lttng_rate_policy_every_n_create(comm->interval);
214 if (policy == NULL) {
215 consumed_len = -1;
216 goto end;
217 }
218
219 *rate_policy = policy;
220 consumed_len = sizeof(*comm);
221
222 end:
223 return consumed_len;
224 }
225
226 ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view,
227 struct lttng_rate_policy **rate_policy)
228 {
229 ssize_t consumed_len, specific_rate_policy_consumed_len;
230 rate_policy_create_from_payload_cb create_from_payload_cb;
231 const struct lttng_rate_policy_comm *rate_policy_comm;
232 const struct lttng_payload_view rate_policy_comm_view =
233 lttng_payload_view_from_view(view, 0, sizeof(*rate_policy_comm));
234
235 if (!view || !rate_policy) {
236 consumed_len = -1;
237 goto end;
238 }
239
240 if (!lttng_payload_view_is_valid(&rate_policy_comm_view)) {
241 /* Payload not large enough to contain the header. */
242 consumed_len = -1;
243 goto end;
244 }
245
246 rate_policy_comm =
247 (const struct lttng_rate_policy_comm *) rate_policy_comm_view.buffer.data;
248
249 DBG("Create rate_policy from payload: rate-policy-type=%s",
250 lttng_rate_policy_type_string(
251 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
252
253 switch (rate_policy_comm->rate_policy_type) {
254 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
255 create_from_payload_cb = lttng_rate_policy_every_n_create_from_payload;
256 break;
257 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
258 create_from_payload_cb = lttng_rate_policy_once_after_n_create_from_payload;
259 break;
260 default:
261 ERR("Failed to create rate-policy from payload, unhandled rate-policy type: rate-policy-type=%u (%s)",
262 rate_policy_comm->rate_policy_type,
263 lttng_rate_policy_type_string(
264 (lttng_rate_policy_type) rate_policy_comm->rate_policy_type));
265 consumed_len = -1;
266 goto end;
267 }
268
269 {
270 /* Create buffer view for the rate_policy-type-specific data.
271 */
272 struct lttng_payload_view specific_rate_policy_view = lttng_payload_view_from_view(
273 view, sizeof(struct lttng_rate_policy_comm), -1);
274
275 specific_rate_policy_consumed_len =
276 create_from_payload_cb(&specific_rate_policy_view, rate_policy);
277 }
278 if (specific_rate_policy_consumed_len < 0) {
279 ERR("Failed to create specific rate_policy from buffer.");
280 consumed_len = -1;
281 goto end;
282 }
283
284 LTTNG_ASSERT(*rate_policy);
285
286 consumed_len = sizeof(struct lttng_rate_policy_comm) + specific_rate_policy_consumed_len;
287
288 end:
289 return consumed_len;
290 }
291
292 bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a,
293 const struct lttng_rate_policy *b)
294 {
295 bool is_equal = false;
296
297 if (!a || !b) {
298 goto end;
299 }
300
301 if (a->type != b->type) {
302 goto end;
303 }
304
305 if (a == b) {
306 is_equal = true;
307 goto end;
308 }
309
310 LTTNG_ASSERT(a->equal);
311 is_equal = a->equal(a, b);
312 end:
313 return is_equal;
314 }
315
316 bool lttng_rate_policy_should_execute(const struct lttng_rate_policy *policy, uint64_t counter)
317 {
318 switch (policy->type) {
319 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
320 return lttng_rate_policy_every_n_should_execute(policy, counter);
321 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
322 return lttng_rate_policy_once_after_n_should_execute(policy, counter);
323 default:
324 abort();
325 break;
326 }
327 }
328
329 /* Every N */
330 static struct lttng_rate_policy_every_n *
331 rate_policy_every_n_from_rate_policy(struct lttng_rate_policy *policy)
332 {
333 LTTNG_ASSERT(policy);
334
335 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
336 }
337
338 static const struct lttng_rate_policy_every_n *
339 rate_policy_every_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
340 {
341 LTTNG_ASSERT(policy);
342
343 return lttng::utils::container_of(policy, &lttng_rate_policy_every_n::parent);
344 }
345
346 static int lttng_rate_policy_every_n_serialize(struct lttng_rate_policy *policy,
347 struct lttng_payload *payload)
348 {
349 int ret;
350
351 struct lttng_rate_policy_every_n *every_n_policy;
352 struct lttng_rate_policy_every_n_comm comm = {};
353
354 LTTNG_ASSERT(policy);
355 LTTNG_ASSERT(payload);
356
357 every_n_policy = rate_policy_every_n_from_rate_policy(policy);
358 comm.interval = every_n_policy->interval;
359
360 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
361 return ret;
362 }
363
364 static bool lttng_rate_policy_every_n_is_equal(const struct lttng_rate_policy *_a,
365 const struct lttng_rate_policy *_b)
366 {
367 bool is_equal = false;
368 const struct lttng_rate_policy_every_n *a, *b;
369
370 a = rate_policy_every_n_from_rate_policy_const(_a);
371 b = rate_policy_every_n_from_rate_policy_const(_b);
372
373 if (a->interval != b->interval) {
374 goto end;
375 }
376
377 is_equal = true;
378
379 end:
380 return is_equal;
381 }
382
383 static void lttng_rate_policy_every_n_destroy(struct lttng_rate_policy *policy)
384 {
385 struct lttng_rate_policy_every_n *every_n_policy;
386
387 if (!policy) {
388 goto end;
389 }
390
391 every_n_policy = rate_policy_every_n_from_rate_policy(policy);
392
393 free(every_n_policy);
394
395 end:
396 return;
397 }
398
399 static struct lttng_rate_policy *
400 lttng_rate_policy_every_n_copy(const struct lttng_rate_policy *source)
401 {
402 struct lttng_rate_policy *copy = NULL;
403 const struct lttng_rate_policy_every_n *every_n_policy;
404
405 if (!source) {
406 goto end;
407 }
408
409 every_n_policy = rate_policy_every_n_from_rate_policy_const(source);
410 copy = lttng_rate_policy_every_n_create(every_n_policy->interval);
411
412 end:
413 return copy;
414 }
415
416 static enum lttng_error_code
417 lttng_rate_policy_every_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
418 struct mi_writer *writer)
419 {
420 int ret;
421 enum lttng_error_code ret_code;
422 const struct lttng_rate_policy_every_n *every_n_policy = NULL;
423
424 LTTNG_ASSERT(rate_policy);
425 LTTNG_ASSERT(IS_EVERY_N_RATE_POLICY(rate_policy));
426 LTTNG_ASSERT(writer);
427
428 every_n_policy = rate_policy_every_n_from_rate_policy_const(rate_policy);
429
430 /* Open rate_policy_every_n element. */
431 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_every_n);
432 if (ret) {
433 goto mi_error;
434 }
435
436 /* Interval. */
437 ret = mi_lttng_writer_write_element_unsigned_int(
438 writer, mi_lttng_element_rate_policy_every_n_interval, every_n_policy->interval);
439 if (ret) {
440 goto mi_error;
441 }
442
443 /* Close rate_policy_every_n element. */
444 ret = mi_lttng_writer_close_element(writer);
445 if (ret) {
446 goto mi_error;
447 }
448
449 ret_code = LTTNG_OK;
450 goto end;
451
452 mi_error:
453 ret_code = LTTNG_ERR_MI_IO_FAIL;
454 end:
455 return ret_code;
456 }
457
458 struct lttng_rate_policy *lttng_rate_policy_every_n_create(uint64_t interval)
459 {
460 struct lttng_rate_policy_every_n *policy = NULL;
461 struct lttng_rate_policy *_policy = NULL;
462
463 if (interval == 0) {
464 /*
465 * An interval of 0 is invalid since it would never be fired.
466 */
467 goto end;
468 }
469
470 policy = zmalloc<lttng_rate_policy_every_n>();
471 if (!policy) {
472 goto end;
473 }
474
475 lttng_rate_policy_init(&policy->parent,
476 LTTNG_RATE_POLICY_TYPE_EVERY_N,
477 lttng_rate_policy_every_n_serialize,
478 lttng_rate_policy_every_n_is_equal,
479 lttng_rate_policy_every_n_destroy,
480 lttng_rate_policy_every_n_copy,
481 lttng_rate_policy_every_n_mi_serialize);
482
483 policy->interval = interval;
484
485 _policy = &policy->parent;
486 policy = NULL;
487
488 end:
489 free(policy);
490 return _policy;
491 }
492
493 enum lttng_rate_policy_status
494 lttng_rate_policy_every_n_get_interval(const struct lttng_rate_policy *policy, uint64_t *interval)
495 {
496 const struct lttng_rate_policy_every_n *every_n_policy;
497 enum lttng_rate_policy_status status;
498
499 if (!policy || !IS_EVERY_N_RATE_POLICY(policy) || !interval) {
500 status = LTTNG_RATE_POLICY_STATUS_INVALID;
501 goto end;
502 }
503
504 every_n_policy = rate_policy_every_n_from_rate_policy_const(policy);
505 *interval = every_n_policy->interval;
506 status = LTTNG_RATE_POLICY_STATUS_OK;
507 end:
508
509 return status;
510 }
511
512 static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy,
513 uint64_t counter)
514 {
515 const struct lttng_rate_policy_every_n *every_n_policy;
516 LTTNG_ASSERT(policy);
517 bool execute = false;
518
519 every_n_policy = rate_policy_every_n_from_rate_policy_const(policy);
520
521 if (every_n_policy->interval == 0) {
522 abort();
523 }
524
525 execute = (counter % every_n_policy->interval) == 0;
526
527 DBG("Policy every N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
528 every_n_policy->interval,
529 execute ? "accepted" : "denied",
530 counter);
531
532 return execute;
533 }
534
535 /* Once after N */
536
537 static struct lttng_rate_policy_once_after_n *
538 rate_policy_once_after_n_from_rate_policy(struct lttng_rate_policy *policy)
539 {
540 LTTNG_ASSERT(policy);
541
542 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
543 }
544
545 static const struct lttng_rate_policy_once_after_n *
546 rate_policy_once_after_n_from_rate_policy_const(const struct lttng_rate_policy *policy)
547 {
548 LTTNG_ASSERT(policy);
549
550 return lttng::utils::container_of(policy, &lttng_rate_policy_once_after_n::parent);
551 }
552 static int lttng_rate_policy_once_after_n_serialize(struct lttng_rate_policy *policy,
553 struct lttng_payload *payload)
554 {
555 int ret;
556
557 struct lttng_rate_policy_once_after_n *once_after_n_policy;
558 struct lttng_rate_policy_once_after_n_comm comm = {};
559
560 LTTNG_ASSERT(policy);
561 LTTNG_ASSERT(payload);
562
563 once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy);
564 comm.threshold = once_after_n_policy->threshold;
565
566 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
567 return ret;
568 }
569
570 static bool lttng_rate_policy_once_after_n_is_equal(const struct lttng_rate_policy *_a,
571 const struct lttng_rate_policy *_b)
572 {
573 bool is_equal = false;
574 const struct lttng_rate_policy_once_after_n *a, *b;
575
576 a = rate_policy_once_after_n_from_rate_policy_const(_a);
577 b = rate_policy_once_after_n_from_rate_policy_const(_b);
578
579 if (a->threshold != b->threshold) {
580 goto end;
581 }
582
583 is_equal = true;
584
585 end:
586 return is_equal;
587 }
588
589 static void lttng_rate_policy_once_after_n_destroy(struct lttng_rate_policy *policy)
590 {
591 struct lttng_rate_policy_once_after_n *once_after_n_policy;
592
593 if (!policy) {
594 goto end;
595 }
596
597 once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy);
598
599 free(once_after_n_policy);
600
601 end:
602 return;
603 }
604
605 static struct lttng_rate_policy *
606 lttng_rate_policy_once_after_n_copy(const struct lttng_rate_policy *source)
607 {
608 struct lttng_rate_policy *copy = NULL;
609 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
610
611 if (!source) {
612 goto end;
613 }
614
615 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(source);
616 copy = lttng_rate_policy_once_after_n_create(once_after_n_policy->threshold);
617
618 end:
619 return copy;
620 }
621
622 static enum lttng_error_code
623 lttng_rate_policy_once_after_n_mi_serialize(const struct lttng_rate_policy *rate_policy,
624 struct mi_writer *writer)
625 {
626 int ret;
627 enum lttng_error_code ret_code;
628 const struct lttng_rate_policy_once_after_n *once_after_n_policy = NULL;
629
630 LTTNG_ASSERT(rate_policy);
631 LTTNG_ASSERT(IS_ONCE_AFTER_N_RATE_POLICY(rate_policy));
632 LTTNG_ASSERT(writer);
633
634 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(rate_policy);
635
636 /* Open rate_policy_once_after_n. */
637 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_once_after_n);
638 if (ret) {
639 goto mi_error;
640 }
641
642 /* Threshold. */
643 ret = mi_lttng_writer_write_element_unsigned_int(
644 writer,
645 mi_lttng_element_rate_policy_once_after_n_threshold,
646 once_after_n_policy->threshold);
647 if (ret) {
648 goto mi_error;
649 }
650
651 /* Close rate_policy_once_after_n element. */
652 ret = mi_lttng_writer_close_element(writer);
653 if (ret) {
654 goto mi_error;
655 }
656
657 ret_code = LTTNG_OK;
658 goto end;
659
660 mi_error:
661 ret_code = LTTNG_ERR_MI_IO_FAIL;
662 end:
663 return ret_code;
664 }
665
666 struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(uint64_t threshold)
667 {
668 struct lttng_rate_policy_once_after_n *policy = NULL;
669 struct lttng_rate_policy *_policy = NULL;
670
671 if (threshold == 0) {
672 /* threshold is expected to be > 0 */
673 goto end;
674 }
675
676 policy = zmalloc<lttng_rate_policy_once_after_n>();
677 if (!policy) {
678 goto end;
679 }
680
681 lttng_rate_policy_init(&policy->parent,
682 LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N,
683 lttng_rate_policy_once_after_n_serialize,
684 lttng_rate_policy_once_after_n_is_equal,
685 lttng_rate_policy_once_after_n_destroy,
686 lttng_rate_policy_once_after_n_copy,
687 lttng_rate_policy_once_after_n_mi_serialize);
688
689 policy->threshold = threshold;
690
691 _policy = &policy->parent;
692 policy = NULL;
693
694 end:
695 free(policy);
696 return _policy;
697 }
698
699 enum lttng_rate_policy_status
700 lttng_rate_policy_once_after_n_get_threshold(const struct lttng_rate_policy *policy,
701 uint64_t *threshold)
702 {
703 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
704 enum lttng_rate_policy_status status;
705
706 if (!policy || !IS_ONCE_AFTER_N_RATE_POLICY(policy) || !threshold) {
707 status = LTTNG_RATE_POLICY_STATUS_INVALID;
708 goto end;
709 }
710
711 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
712 *threshold = once_after_n_policy->threshold;
713 status = LTTNG_RATE_POLICY_STATUS_OK;
714 end:
715
716 return status;
717 }
718
719 struct lttng_rate_policy *lttng_rate_policy_copy(const struct lttng_rate_policy *source)
720 {
721 LTTNG_ASSERT(source->copy);
722 return source->copy(source);
723 }
724
725 static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy,
726 uint64_t counter)
727 {
728 const struct lttng_rate_policy_once_after_n *once_after_n_policy;
729 bool execute = false;
730 LTTNG_ASSERT(policy);
731
732 once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy);
733
734 execute = counter == once_after_n_policy->threshold;
735
736 DBG("Policy once after N = %" PRIu64 ": execution %s. Execution count: %" PRIu64,
737 once_after_n_policy->threshold,
738 execute ? "accepted" : "denied",
739 counter);
740
741 return counter == once_after_n_policy->threshold;
742 }
743
744 enum lttng_error_code lttng_rate_policy_mi_serialize(const struct lttng_rate_policy *rate_policy,
745 struct mi_writer *writer)
746 {
747 int ret;
748 enum lttng_error_code ret_code;
749
750 LTTNG_ASSERT(rate_policy);
751 LTTNG_ASSERT(writer);
752 LTTNG_ASSERT(rate_policy->mi_serialize);
753
754 /* Open rate policy element. */
755 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy);
756 if (ret) {
757 goto mi_error;
758 }
759
760 /* Serialize underlying rate policy. */
761 ret_code = rate_policy->mi_serialize(rate_policy, writer);
762 if (ret_code != LTTNG_OK) {
763 goto end;
764 }
765
766 /* Close rate policy element. */
767 ret = mi_lttng_writer_close_element(writer);
768 if (ret) {
769 goto mi_error;
770 }
771
772 ret_code = LTTNG_OK;
773 goto end;
774
775 mi_error:
776 ret_code = LTTNG_ERR_MI_IO_FAIL;
777 end:
778 return ret_code;
779 }
This page took 0.050058 seconds and 4 git commands to generate.