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