Commit | Line | Data |
---|---|---|
7f4d5b07 JR |
1 | /* |
2 | * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
c9e313bc SM |
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> | |
28ab034a | 15 | |
c9e313bc | 16 | #include <lttng/action/rate-policy-internal.hpp> |
7f4d5b07 | 17 | #include <lttng/action/rate-policy.h> |
28ab034a JG |
18 | |
19 | #include <limits.h> | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
26 | #define IS_ONCE_AFTER_N_RATE_POLICY(policy) \ |
27 | (lttng_rate_policy_get_type(policy) == LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N) | |
7f4d5b07 JR |
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, | |
28ab034a | 31 | struct lttng_payload *payload); |
7f4d5b07 | 32 | typedef bool (*rate_policy_equal_cb)(const struct lttng_rate_policy *a, |
28ab034a JG |
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); | |
6a751b95 | 37 | typedef enum lttng_error_code (*rate_policy_mi_serialize_cb)( |
28ab034a | 38 | const struct lttng_rate_policy *rate_policy, struct mi_writer *writer); |
7f4d5b07 JR |
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; | |
6a751b95 | 46 | rate_policy_mi_serialize_cb mi_serialize; |
7f4d5b07 JR |
47 | }; |
48 | ||
f1494934 | 49 | namespace { |
7f4d5b07 JR |
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; | |
f1494934 | 72 | } /* namespace */ |
7f4d5b07 JR |
73 | |
74 | /* Forward declaration. */ | |
75 | static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy, | |
28ab034a JG |
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); | |
7f4d5b07 JR |
82 | |
83 | /* Forward declaration. Every n */ | |
28ab034a JG |
84 | static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy, |
85 | uint64_t counter); | |
7f4d5b07 JR |
86 | |
87 | /* Forward declaration. Once after N */ | |
28ab034a JG |
88 | static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy, |
89 | uint64_t counter); | |
7f4d5b07 | 90 | |
28ab034a | 91 | const char *lttng_rate_policy_type_string(enum lttng_rate_policy_type rate_policy_type) |
7f4d5b07 JR |
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 | ||
28ab034a | 103 | enum lttng_rate_policy_type lttng_rate_policy_get_type(const struct lttng_rate_policy *policy) |
7f4d5b07 JR |
104 | { |
105 | return policy ? policy->type : LTTNG_RATE_POLICY_TYPE_UNKNOWN; | |
106 | } | |
107 | ||
7f4d5b07 | 108 | void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy, |
28ab034a JG |
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) | |
7f4d5b07 JR |
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; | |
6a751b95 | 121 | rate_policy->mi_serialize = mi; |
7f4d5b07 JR |
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 | ||
7f4d5b07 | 133 | int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy, |
28ab034a | 134 | struct lttng_payload *payload) |
7f4d5b07 JR |
135 | { |
136 | int ret; | |
137 | struct lttng_rate_policy_comm rate_policy_comm = { | |
28ab034a | 138 | .rate_policy_type = (int8_t) rate_policy->type, |
7f4d5b07 JR |
139 | }; |
140 | ||
28ab034a JG |
141 | ret = lttng_dynamic_buffer_append( |
142 | &payload->buffer, &rate_policy_comm, sizeof(rate_policy_comm)); | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
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) | |
7f4d5b07 JR |
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 = | |
28ab034a | 163 | lttng_payload_view_from_view(view, 0, sizeof(*comm)); |
7f4d5b07 JR |
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 | ||
28ab034a | 176 | comm = (const struct lttng_rate_policy_once_after_n_comm *) comm_view.buffer.data; |
7f4d5b07 JR |
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 | ||
28ab034a JG |
191 | static ssize_t lttng_rate_policy_every_n_create_from_payload(struct lttng_payload_view *view, |
192 | struct lttng_rate_policy **rate_policy) | |
7f4d5b07 JR |
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 = | |
28ab034a | 198 | lttng_payload_view_from_view(view, 0, sizeof(*comm)); |
7f4d5b07 JR |
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 | ||
28ab034a | 211 | comm = (const struct lttng_rate_policy_every_n_comm *) comm_view.buffer.data; |
7f4d5b07 JR |
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 | ||
7f4d5b07 | 226 | ssize_t lttng_rate_policy_create_from_payload(struct lttng_payload_view *view, |
28ab034a | 227 | struct lttng_rate_policy **rate_policy) |
7f4d5b07 JR |
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 = | |
28ab034a | 233 | lttng_payload_view_from_view(view, 0, sizeof(*rate_policy_comm)); |
7f4d5b07 JR |
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 | ||
28ab034a JG |
246 | rate_policy_comm = |
247 | (const struct lttng_rate_policy_comm *) rate_policy_comm_view.buffer.data; | |
7f4d5b07 JR |
248 | |
249 | DBG("Create rate_policy from payload: rate-policy-type=%s", | |
28ab034a JG |
250 | lttng_rate_policy_type_string( |
251 | (lttng_rate_policy_type) rate_policy_comm->rate_policy_type)); | |
7f4d5b07 JR |
252 | |
253 | switch (rate_policy_comm->rate_policy_type) { | |
254 | case LTTNG_RATE_POLICY_TYPE_EVERY_N: | |
28ab034a | 255 | create_from_payload_cb = lttng_rate_policy_every_n_create_from_payload; |
7f4d5b07 JR |
256 | break; |
257 | case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N: | |
28ab034a | 258 | create_from_payload_cb = lttng_rate_policy_once_after_n_create_from_payload; |
7f4d5b07 JR |
259 | break; |
260 | default: | |
261 | ERR("Failed to create rate-policy from payload, unhandled rate-policy type: rate-policy-type=%u (%s)", | |
28ab034a JG |
262 | rate_policy_comm->rate_policy_type, |
263 | lttng_rate_policy_type_string( | |
264 | (lttng_rate_policy_type) rate_policy_comm->rate_policy_type)); | |
7f4d5b07 JR |
265 | consumed_len = -1; |
266 | goto end; | |
267 | } | |
268 | ||
269 | { | |
270 | /* Create buffer view for the rate_policy-type-specific data. | |
271 | */ | |
28ab034a JG |
272 | struct lttng_payload_view specific_rate_policy_view = lttng_payload_view_from_view( |
273 | view, sizeof(struct lttng_rate_policy_comm), -1); | |
7f4d5b07 | 274 | |
28ab034a JG |
275 | specific_rate_policy_consumed_len = |
276 | create_from_payload_cb(&specific_rate_policy_view, rate_policy); | |
7f4d5b07 JR |
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 | ||
a0377dfe | 284 | LTTNG_ASSERT(*rate_policy); |
7f4d5b07 | 285 | |
28ab034a | 286 | consumed_len = sizeof(struct lttng_rate_policy_comm) + specific_rate_policy_consumed_len; |
7f4d5b07 JR |
287 | |
288 | end: | |
289 | return consumed_len; | |
290 | } | |
291 | ||
7f4d5b07 | 292 | bool lttng_rate_policy_is_equal(const struct lttng_rate_policy *a, |
28ab034a | 293 | const struct lttng_rate_policy *b) |
7f4d5b07 JR |
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 | ||
a0377dfe | 310 | LTTNG_ASSERT(a->equal); |
7f4d5b07 JR |
311 | is_equal = a->equal(a, b); |
312 | end: | |
313 | return is_equal; | |
314 | } | |
315 | ||
28ab034a | 316 | bool lttng_rate_policy_should_execute(const struct lttng_rate_policy *policy, uint64_t counter) |
7f4d5b07 JR |
317 | { |
318 | switch (policy->type) { | |
319 | case LTTNG_RATE_POLICY_TYPE_EVERY_N: | |
28ab034a | 320 | return lttng_rate_policy_every_n_should_execute(policy, counter); |
7f4d5b07 | 321 | case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N: |
28ab034a | 322 | return lttng_rate_policy_once_after_n_should_execute(policy, counter); |
7f4d5b07 JR |
323 | default: |
324 | abort(); | |
325 | break; | |
326 | } | |
327 | } | |
328 | ||
329 | /* Every N */ | |
28ab034a JG |
330 | static struct lttng_rate_policy_every_n * |
331 | rate_policy_every_n_from_rate_policy(struct lttng_rate_policy *policy) | |
7f4d5b07 | 332 | { |
a0377dfe | 333 | LTTNG_ASSERT(policy); |
7f4d5b07 | 334 | |
0114db0e | 335 | return lttng::utils::container_of(policy, <tng_rate_policy_every_n::parent); |
7f4d5b07 JR |
336 | } |
337 | ||
338 | static const struct lttng_rate_policy_every_n * | |
28ab034a | 339 | rate_policy_every_n_from_rate_policy_const(const struct lttng_rate_policy *policy) |
7f4d5b07 | 340 | { |
a0377dfe | 341 | LTTNG_ASSERT(policy); |
7f4d5b07 | 342 | |
0114db0e | 343 | return lttng::utils::container_of(policy, <tng_rate_policy_every_n::parent); |
7f4d5b07 JR |
344 | } |
345 | ||
28ab034a JG |
346 | static int lttng_rate_policy_every_n_serialize(struct lttng_rate_policy *policy, |
347 | struct lttng_payload *payload) | |
7f4d5b07 JR |
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 | ||
a0377dfe FD |
354 | LTTNG_ASSERT(policy); |
355 | LTTNG_ASSERT(payload); | |
7f4d5b07 JR |
356 | |
357 | every_n_policy = rate_policy_every_n_from_rate_policy(policy); | |
358 | comm.interval = every_n_policy->interval; | |
359 | ||
28ab034a | 360 | ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm)); |
7f4d5b07 JR |
361 | return ret; |
362 | } | |
363 | ||
28ab034a JG |
364 | static bool lttng_rate_policy_every_n_is_equal(const struct lttng_rate_policy *_a, |
365 | const struct lttng_rate_policy *_b) | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
399 | static struct lttng_rate_policy * |
400 | lttng_rate_policy_every_n_copy(const struct lttng_rate_policy *source) | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
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) | |
6a751b95 JR |
419 | { |
420 | int ret; | |
421 | enum lttng_error_code ret_code; | |
422 | const struct lttng_rate_policy_every_n *every_n_policy = NULL; | |
423 | ||
a0377dfe FD |
424 | LTTNG_ASSERT(rate_policy); |
425 | LTTNG_ASSERT(IS_EVERY_N_RATE_POLICY(rate_policy)); | |
426 | LTTNG_ASSERT(writer); | |
6a751b95 | 427 | |
28ab034a | 428 | every_n_policy = rate_policy_every_n_from_rate_policy_const(rate_policy); |
6a751b95 JR |
429 | |
430 | /* Open rate_policy_every_n element. */ | |
28ab034a | 431 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_every_n); |
6a751b95 JR |
432 | if (ret) { |
433 | goto mi_error; | |
434 | } | |
435 | ||
436 | /* Interval. */ | |
28ab034a JG |
437 | ret = mi_lttng_writer_write_element_unsigned_int( |
438 | writer, mi_lttng_element_rate_policy_every_n_interval, every_n_policy->interval); | |
6a751b95 JR |
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 | ||
7f4d5b07 JR |
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 | ||
64803277 | 470 | policy = zmalloc<lttng_rate_policy_every_n>(); |
7f4d5b07 JR |
471 | if (!policy) { |
472 | goto end; | |
473 | } | |
474 | ||
28ab034a JG |
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); | |
7f4d5b07 JR |
482 | |
483 | policy->interval = interval; | |
484 | ||
485 | _policy = &policy->parent; | |
486 | policy = NULL; | |
487 | ||
488 | end: | |
489 | free(policy); | |
490 | return _policy; | |
491 | } | |
492 | ||
28ab034a JG |
493 | enum lttng_rate_policy_status |
494 | lttng_rate_policy_every_n_get_interval(const struct lttng_rate_policy *policy, uint64_t *interval) | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
512 | static bool lttng_rate_policy_every_n_should_execute(const struct lttng_rate_policy *policy, |
513 | uint64_t counter) | |
7f4d5b07 JR |
514 | { |
515 | const struct lttng_rate_policy_every_n *every_n_policy; | |
a0377dfe | 516 | LTTNG_ASSERT(policy); |
7f4d5b07 JR |
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 | ||
28ab034a JG |
527 | DBG("Policy every N = %" PRIu64 ": execution %s. Execution count: %" PRIu64, |
528 | every_n_policy->interval, | |
529 | execute ? "accepted" : "denied", | |
530 | counter); | |
7f4d5b07 JR |
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 | { | |
a0377dfe | 540 | LTTNG_ASSERT(policy); |
7f4d5b07 | 541 | |
28ab034a | 542 | return lttng::utils::container_of(policy, <tng_rate_policy_once_after_n::parent); |
7f4d5b07 JR |
543 | } |
544 | ||
545 | static const struct lttng_rate_policy_once_after_n * | |
28ab034a | 546 | rate_policy_once_after_n_from_rate_policy_const(const struct lttng_rate_policy *policy) |
7f4d5b07 | 547 | { |
a0377dfe | 548 | LTTNG_ASSERT(policy); |
7f4d5b07 | 549 | |
28ab034a | 550 | return lttng::utils::container_of(policy, <tng_rate_policy_once_after_n::parent); |
7f4d5b07 | 551 | } |
28ab034a JG |
552 | static int lttng_rate_policy_once_after_n_serialize(struct lttng_rate_policy *policy, |
553 | struct lttng_payload *payload) | |
7f4d5b07 JR |
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 | ||
a0377dfe FD |
560 | LTTNG_ASSERT(policy); |
561 | LTTNG_ASSERT(payload); | |
7f4d5b07 JR |
562 | |
563 | once_after_n_policy = rate_policy_once_after_n_from_rate_policy(policy); | |
564 | comm.threshold = once_after_n_policy->threshold; | |
565 | ||
28ab034a | 566 | ret = lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm)); |
7f4d5b07 JR |
567 | return ret; |
568 | } | |
569 | ||
28ab034a JG |
570 | static bool lttng_rate_policy_once_after_n_is_equal(const struct lttng_rate_policy *_a, |
571 | const struct lttng_rate_policy *_b) | |
7f4d5b07 JR |
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 | ||
28ab034a | 589 | static void lttng_rate_policy_once_after_n_destroy(struct lttng_rate_policy *policy) |
7f4d5b07 JR |
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 | ||
28ab034a JG |
605 | static struct lttng_rate_policy * |
606 | lttng_rate_policy_once_after_n_copy(const struct lttng_rate_policy *source) | |
7f4d5b07 JR |
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 | ||
28ab034a JG |
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); | |
7f4d5b07 JR |
617 | |
618 | end: | |
619 | return copy; | |
620 | } | |
621 | ||
28ab034a JG |
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) | |
6a751b95 JR |
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 | ||
a0377dfe FD |
630 | LTTNG_ASSERT(rate_policy); |
631 | LTTNG_ASSERT(IS_ONCE_AFTER_N_RATE_POLICY(rate_policy)); | |
632 | LTTNG_ASSERT(writer); | |
6a751b95 | 633 | |
28ab034a | 634 | once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(rate_policy); |
6a751b95 JR |
635 | |
636 | /* Open rate_policy_once_after_n. */ | |
28ab034a | 637 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy_once_after_n); |
6a751b95 JR |
638 | if (ret) { |
639 | goto mi_error; | |
640 | } | |
641 | ||
642 | /* Threshold. */ | |
28ab034a JG |
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); | |
6a751b95 JR |
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 | ||
28ab034a | 666 | struct lttng_rate_policy *lttng_rate_policy_once_after_n_create(uint64_t threshold) |
7f4d5b07 JR |
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 | ||
64803277 | 676 | policy = zmalloc<lttng_rate_policy_once_after_n>(); |
7f4d5b07 JR |
677 | if (!policy) { |
678 | goto end; | |
679 | } | |
680 | ||
681 | lttng_rate_policy_init(&policy->parent, | |
28ab034a JG |
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); | |
7f4d5b07 JR |
688 | |
689 | policy->threshold = threshold; | |
690 | ||
691 | _policy = &policy->parent; | |
692 | policy = NULL; | |
693 | ||
694 | end: | |
695 | free(policy); | |
696 | return _policy; | |
697 | } | |
698 | ||
28ab034a JG |
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) | |
7f4d5b07 JR |
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 | ||
28ab034a | 711 | once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy); |
7f4d5b07 JR |
712 | *threshold = once_after_n_policy->threshold; |
713 | status = LTTNG_RATE_POLICY_STATUS_OK; | |
714 | end: | |
715 | ||
716 | return status; | |
717 | } | |
718 | ||
28ab034a | 719 | struct lttng_rate_policy *lttng_rate_policy_copy(const struct lttng_rate_policy *source) |
7f4d5b07 | 720 | { |
a0377dfe | 721 | LTTNG_ASSERT(source->copy); |
7f4d5b07 JR |
722 | return source->copy(source); |
723 | } | |
724 | ||
28ab034a JG |
725 | static bool lttng_rate_policy_once_after_n_should_execute(const struct lttng_rate_policy *policy, |
726 | uint64_t counter) | |
7f4d5b07 JR |
727 | { |
728 | const struct lttng_rate_policy_once_after_n *once_after_n_policy; | |
729 | bool execute = false; | |
a0377dfe | 730 | LTTNG_ASSERT(policy); |
7f4d5b07 | 731 | |
28ab034a | 732 | once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const(policy); |
7f4d5b07 JR |
733 | |
734 | execute = counter == once_after_n_policy->threshold; | |
735 | ||
28ab034a JG |
736 | DBG("Policy once after N = %" PRIu64 ": execution %s. Execution count: %" PRIu64, |
737 | once_after_n_policy->threshold, | |
738 | execute ? "accepted" : "denied", | |
739 | counter); | |
7f4d5b07 JR |
740 | |
741 | return counter == once_after_n_policy->threshold; | |
742 | } | |
6a751b95 | 743 | |
28ab034a JG |
744 | enum lttng_error_code lttng_rate_policy_mi_serialize(const struct lttng_rate_policy *rate_policy, |
745 | struct mi_writer *writer) | |
6a751b95 JR |
746 | { |
747 | int ret; | |
748 | enum lttng_error_code ret_code; | |
749 | ||
a0377dfe FD |
750 | LTTNG_ASSERT(rate_policy); |
751 | LTTNG_ASSERT(writer); | |
752 | LTTNG_ASSERT(rate_policy->mi_serialize); | |
6a751b95 JR |
753 | |
754 | /* Open rate policy element. */ | |
28ab034a | 755 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_rate_policy); |
6a751b95 JR |
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 | } |