Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / src / common / conditions / session-consumed-size.c
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.h>
9 #include <common/macros.h>
10 #include <common/mi-lttng.h>
11 #include <float.h>
12 #include <lttng/condition/condition-internal.h>
13 #include <lttng/condition/session-consumed-size-internal.h>
14 #include <lttng/constant.h>
15 #include <math.h>
16 #include <time.h>
17
18 #define IS_CONSUMED_SIZE_CONDITION(condition) ( \
19 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \
20 )
21
22 #define IS_CONSUMED_SIZE_EVALUATION(evaluation) ( \
23 lttng_evaluation_get_type(evaluation) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \
24 )
25
26 static
27 void lttng_condition_session_consumed_size_destroy(struct lttng_condition *condition)
28 {
29 struct lttng_condition_session_consumed_size *consumed_size;
30
31 consumed_size = container_of(condition,
32 struct lttng_condition_session_consumed_size, parent);
33
34 free(consumed_size->session_name);
35 free(consumed_size);
36 }
37
38 static
39 bool lttng_condition_session_consumed_size_validate(
40 const struct lttng_condition *condition)
41 {
42 bool valid = false;
43 struct lttng_condition_session_consumed_size *consumed;
44
45 if (!condition) {
46 goto end;
47 }
48
49 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
50 parent);
51 if (!consumed->session_name) {
52 ERR("Invalid session consumed size condition: a target session name must be set.");
53 goto end;
54 }
55 if (!consumed->consumed_threshold_bytes.set) {
56 ERR("Invalid session consumed size condition: a threshold must be set.");
57 goto end;
58 }
59
60 valid = true;
61 end:
62 return valid;
63 }
64
65 static
66 int lttng_condition_session_consumed_size_serialize(
67 const struct lttng_condition *condition,
68 struct lttng_payload *payload)
69 {
70 int ret;
71 size_t session_name_len;
72 struct lttng_condition_session_consumed_size *consumed;
73 struct lttng_condition_session_consumed_size_comm consumed_comm;
74
75 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) {
76 ret = -1;
77 goto end;
78 }
79
80 DBG("Serializing session consumed size condition");
81 consumed = container_of(condition,
82 struct lttng_condition_session_consumed_size,
83 parent);
84
85 session_name_len = strlen(consumed->session_name) + 1;
86 if (session_name_len > LTTNG_NAME_MAX) {
87 ret = -1;
88 goto end;
89 }
90
91 consumed_comm.consumed_threshold_bytes =
92 consumed->consumed_threshold_bytes.value;
93 consumed_comm.session_name_len = (uint32_t) session_name_len;
94
95 ret = lttng_dynamic_buffer_append(&payload->buffer, &consumed_comm,
96 sizeof(consumed_comm));
97 if (ret) {
98 goto end;
99 }
100
101 ret = lttng_dynamic_buffer_append(&payload->buffer, consumed->session_name,
102 session_name_len);
103 if (ret) {
104 goto end;
105 }
106 end:
107 return ret;
108 }
109
110 static
111 bool lttng_condition_session_consumed_size_is_equal(const struct lttng_condition *_a,
112 const struct lttng_condition *_b)
113 {
114 bool is_equal = false;
115 struct lttng_condition_session_consumed_size *a, *b;
116
117 a = container_of(_a, struct lttng_condition_session_consumed_size, parent);
118 b = container_of(_b, struct lttng_condition_session_consumed_size, parent);
119
120 if (a->consumed_threshold_bytes.set && b->consumed_threshold_bytes.set) {
121 uint64_t a_value, b_value;
122
123 a_value = a->consumed_threshold_bytes.value;
124 b_value = b->consumed_threshold_bytes.value;
125 if (a_value != b_value) {
126 goto end;
127 }
128 }
129
130 LTTNG_ASSERT(a->session_name);
131 LTTNG_ASSERT(b->session_name);
132 if (strcmp(a->session_name, b->session_name)) {
133 goto end;
134 }
135
136 is_equal = true;
137 end:
138 return is_equal;
139 }
140
141 static
142 enum lttng_error_code lttng_condition_session_consumed_size_mi_serialize(
143 const struct lttng_condition *condition,
144 struct mi_writer *writer)
145 {
146 int ret;
147 enum lttng_error_code ret_code;
148 enum lttng_condition_status status;
149 const char *session_name = NULL;
150 uint64_t threshold_bytes;
151
152 LTTNG_ASSERT(condition);
153 LTTNG_ASSERT(writer);
154 LTTNG_ASSERT(IS_CONSUMED_SIZE_CONDITION(condition));
155
156 status = lttng_condition_session_consumed_size_get_session_name(
157 condition, &session_name);
158 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
159 LTTNG_ASSERT(session_name);
160
161 status = lttng_condition_session_consumed_size_get_threshold(
162 condition, &threshold_bytes);
163 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
164
165 /* Open condition session consumed size element. */
166 ret = mi_lttng_writer_open_element(writer,
167 mi_lttng_element_condition_session_consumed_size);
168 if (ret) {
169 goto mi_error;
170 }
171
172 /* Session name. */
173 ret = mi_lttng_writer_write_element_string(
174 writer, mi_lttng_element_session_name, session_name);
175 if (ret) {
176 goto mi_error;
177 }
178
179 /* Threshold in bytes. */
180 ret = mi_lttng_writer_write_element_unsigned_int(writer,
181 mi_lttng_element_condition_threshold_bytes,
182 threshold_bytes);
183 if (ret) {
184 goto mi_error;
185 }
186
187 /* Close condition session consumed size element. */
188 ret = mi_lttng_writer_close_element(writer);
189 if (ret) {
190 goto mi_error;
191 }
192
193 ret_code = LTTNG_OK;
194 goto end;
195
196 mi_error:
197 ret_code = LTTNG_ERR_MI_IO_FAIL;
198 end:
199 return ret_code;
200 }
201
202 struct lttng_condition *lttng_condition_session_consumed_size_create(void)
203 {
204 struct lttng_condition_session_consumed_size *condition;
205
206 condition = zmalloc(sizeof(struct lttng_condition_session_consumed_size));
207 if (!condition) {
208 return NULL;
209 }
210
211 lttng_condition_init(&condition->parent, LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE);
212 condition->parent.validate = lttng_condition_session_consumed_size_validate;
213 condition->parent.serialize = lttng_condition_session_consumed_size_serialize;
214 condition->parent.equal = lttng_condition_session_consumed_size_is_equal;
215 condition->parent.destroy = lttng_condition_session_consumed_size_destroy;
216 condition->parent.mi_serialize = lttng_condition_session_consumed_size_mi_serialize;
217 return &condition->parent;
218 }
219
220 static
221 ssize_t init_condition_from_payload(struct lttng_condition *condition,
222 struct lttng_payload_view *src_view)
223 {
224 ssize_t ret, condition_size;
225 enum lttng_condition_status status;
226 const char *session_name;
227 struct lttng_buffer_view session_name_view;
228 const struct lttng_condition_session_consumed_size_comm *condition_comm;
229 struct lttng_payload_view condition_comm_view = lttng_payload_view_from_view(
230 src_view, 0, sizeof(*condition_comm));
231
232 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
233 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
234 ret = -1;
235 goto end;
236 }
237
238 condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
239 session_name_view = lttng_buffer_view_from_view(&src_view->buffer,
240 sizeof(*condition_comm), condition_comm->session_name_len);
241
242 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
243 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
244 ret = -1;
245 goto end;
246 }
247
248 if (!lttng_buffer_view_is_valid(&session_name_view)) {
249 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
250 ret = -1;
251 goto end;
252 }
253
254 status = lttng_condition_session_consumed_size_set_threshold(condition,
255 condition_comm->consumed_threshold_bytes);
256 if (status != LTTNG_CONDITION_STATUS_OK) {
257 ERR("Failed to initialize session consumed size condition threshold");
258 ret = -1;
259 goto end;
260 }
261
262 session_name = session_name_view.data;
263 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
264 ERR("Malformed session name encountered in condition buffer");
265 ret = -1;
266 goto end;
267 }
268
269 status = lttng_condition_session_consumed_size_set_session_name(condition,
270 session_name);
271 if (status != LTTNG_CONDITION_STATUS_OK) {
272 ERR("Failed to set session consumed size condition's session name");
273 ret = -1;
274 goto end;
275 }
276
277 if (!lttng_condition_validate(condition)) {
278 ret = -1;
279 goto end;
280 }
281
282 condition_size = sizeof(*condition_comm) +
283 (ssize_t) condition_comm->session_name_len;
284 ret = condition_size;
285 end:
286 return ret;
287 }
288
289 ssize_t lttng_condition_session_consumed_size_create_from_payload(
290 struct lttng_payload_view *view,
291 struct lttng_condition **_condition)
292 {
293 ssize_t ret;
294 struct lttng_condition *condition =
295 lttng_condition_session_consumed_size_create();
296
297 if (!_condition || !condition) {
298 ret = -1;
299 goto error;
300 }
301
302 ret = init_condition_from_payload(condition, view);
303 if (ret < 0) {
304 goto error;
305 }
306
307 *_condition = condition;
308 return ret;
309 error:
310 lttng_condition_destroy(condition);
311 return ret;
312 }
313
314 static
315 struct lttng_evaluation *create_evaluation_from_payload(
316 const struct lttng_payload_view *view)
317 {
318 const struct lttng_evaluation_session_consumed_size_comm *comm =
319 (typeof(comm)) view->buffer.data;
320 struct lttng_evaluation *evaluation = NULL;
321
322 if (view->buffer.size < sizeof(*comm)) {
323 goto end;
324 }
325
326 evaluation = lttng_evaluation_session_consumed_size_create(
327 comm->session_consumed);
328 end:
329 return evaluation;
330 }
331
332 ssize_t lttng_evaluation_session_consumed_size_create_from_payload(
333 struct lttng_payload_view *view,
334 struct lttng_evaluation **_evaluation)
335 {
336 ssize_t ret;
337 struct lttng_evaluation *evaluation = NULL;
338
339 if (!_evaluation) {
340 ret = -1;
341 goto error;
342 }
343
344 evaluation = create_evaluation_from_payload(view);
345 if (!evaluation) {
346 ret = -1;
347 goto error;
348 }
349
350 *_evaluation = evaluation;
351 ret = sizeof(struct lttng_evaluation_session_consumed_size_comm);
352 return ret;
353 error:
354 lttng_evaluation_destroy(evaluation);
355 return ret;
356 }
357
358 enum lttng_condition_status
359 lttng_condition_session_consumed_size_get_threshold(
360 const struct lttng_condition *condition,
361 uint64_t *consumed_threshold_bytes)
362 {
363 struct lttng_condition_session_consumed_size *consumed;
364 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
365
366 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !consumed_threshold_bytes) {
367 status = LTTNG_CONDITION_STATUS_INVALID;
368 goto end;
369 }
370
371 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
372 parent);
373 if (!consumed->consumed_threshold_bytes.set) {
374 status = LTTNG_CONDITION_STATUS_UNSET;
375 goto end;
376 }
377 *consumed_threshold_bytes = consumed->consumed_threshold_bytes.value;
378 end:
379 return status;
380 }
381
382 enum lttng_condition_status
383 lttng_condition_session_consumed_size_set_threshold(
384 struct lttng_condition *condition, uint64_t consumed_threshold_bytes)
385 {
386 struct lttng_condition_session_consumed_size *consumed;
387 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
388
389 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) {
390 status = LTTNG_CONDITION_STATUS_INVALID;
391 goto end;
392 }
393
394 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
395 parent);
396 consumed->consumed_threshold_bytes.set = true;
397 consumed->consumed_threshold_bytes.value = consumed_threshold_bytes;
398 end:
399 return status;
400 }
401
402 enum lttng_condition_status
403 lttng_condition_session_consumed_size_get_session_name(
404 const struct lttng_condition *condition,
405 const char **session_name)
406 {
407 struct lttng_condition_session_consumed_size *consumed;
408 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
409
410 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !session_name) {
411 status = LTTNG_CONDITION_STATUS_INVALID;
412 goto end;
413 }
414
415 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
416 parent);
417 if (!consumed->session_name) {
418 status = LTTNG_CONDITION_STATUS_UNSET;
419 goto end;
420 }
421 *session_name = consumed->session_name;
422 end:
423 return status;
424 }
425
426 enum lttng_condition_status
427 lttng_condition_session_consumed_size_set_session_name(
428 struct lttng_condition *condition, const char *session_name)
429 {
430 char *session_name_copy;
431 struct lttng_condition_session_consumed_size *consumed;
432 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
433
434 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) ||
435 !session_name || strlen(session_name) == 0) {
436 status = LTTNG_CONDITION_STATUS_INVALID;
437 goto end;
438 }
439
440 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
441 parent);
442 session_name_copy = strdup(session_name);
443 if (!session_name_copy) {
444 status = LTTNG_CONDITION_STATUS_ERROR;
445 goto end;
446 }
447
448 if (consumed->session_name) {
449 free(consumed->session_name);
450 }
451 consumed->session_name = session_name_copy;
452 end:
453 return status;
454 }
455
456 static
457 int lttng_evaluation_session_consumed_size_serialize(
458 const struct lttng_evaluation *evaluation,
459 struct lttng_payload *payload)
460 {
461 struct lttng_evaluation_session_consumed_size *consumed;
462 struct lttng_evaluation_session_consumed_size_comm comm;
463
464 consumed = container_of(evaluation,
465 struct lttng_evaluation_session_consumed_size, parent);
466 comm.session_consumed = consumed->session_consumed;
467 return lttng_dynamic_buffer_append(
468 &payload->buffer, &comm, sizeof(comm));
469 }
470
471 static
472 void lttng_evaluation_session_consumed_size_destroy(
473 struct lttng_evaluation *evaluation)
474 {
475 struct lttng_evaluation_session_consumed_size *consumed;
476
477 consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size,
478 parent);
479 free(consumed);
480 }
481
482 struct lttng_evaluation *lttng_evaluation_session_consumed_size_create(
483 uint64_t consumed)
484 {
485 struct lttng_evaluation_session_consumed_size *consumed_eval;
486
487 consumed_eval = zmalloc(sizeof(struct lttng_evaluation_session_consumed_size));
488 if (!consumed_eval) {
489 goto end;
490 }
491
492 consumed_eval->parent.type = LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE;
493 consumed_eval->session_consumed = consumed;
494 consumed_eval->parent.serialize = lttng_evaluation_session_consumed_size_serialize;
495 consumed_eval->parent.destroy = lttng_evaluation_session_consumed_size_destroy;
496 end:
497 return &consumed_eval->parent;
498 }
499
500 enum lttng_evaluation_status
501 lttng_evaluation_session_consumed_size_get_consumed_size(
502 const struct lttng_evaluation *evaluation,
503 uint64_t *session_consumed)
504 {
505 struct lttng_evaluation_session_consumed_size *consumed;
506 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
507
508 if (!evaluation || !IS_CONSUMED_SIZE_EVALUATION(evaluation) ||
509 !session_consumed) {
510 status = LTTNG_EVALUATION_STATUS_INVALID;
511 goto end;
512 }
513
514 consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size,
515 parent);
516 *session_consumed = consumed->session_consumed;
517 end:
518 return status;
519 }
This page took 0.039433 seconds and 4 git commands to generate.