Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / src / common / conditions / session-rotation.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 <lttng/condition/condition-internal.h>
12 #include <lttng/condition/session-rotation-internal.h>
13 #include <lttng/location-internal.h>
14 #include <stdbool.h>
15
16 static
17 bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition *condition);
19 static
20 int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition *condition,
22 struct lttng_payload *payload);
23 static
24 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
25 const struct lttng_condition *_b);
26 static
27 void lttng_condition_session_rotation_destroy(
28 struct lttng_condition *condition);
29
30 static
31 enum lttng_error_code lttng_condition_session_rotation_mi_serialize(
32 const struct lttng_condition *condition,
33 struct mi_writer *writer);
34
35 static const
36 struct lttng_condition rotation_condition_template = {
37 /* .type omitted; shall be set on creation. */
38 .validate = lttng_condition_session_rotation_validate,
39 .serialize = lttng_condition_session_rotation_serialize,
40 .equal = lttng_condition_session_rotation_is_equal,
41 .destroy = lttng_condition_session_rotation_destroy,
42 .mi_serialize = lttng_condition_session_rotation_mi_serialize,
43 };
44
45 static
46 int lttng_evaluation_session_rotation_serialize(
47 const struct lttng_evaluation *evaluation,
48 struct lttng_payload *payload);
49 static
50 void lttng_evaluation_session_rotation_destroy(
51 struct lttng_evaluation *evaluation);
52
53 static const
54 struct lttng_evaluation rotation_evaluation_template = {
55 /* .type omitted; shall be set on creation. */
56 .serialize = lttng_evaluation_session_rotation_serialize,
57 .destroy = lttng_evaluation_session_rotation_destroy,
58 };
59
60 static
61 bool is_rotation_condition(const struct lttng_condition *condition)
62 {
63 enum lttng_condition_type type = lttng_condition_get_type(condition);
64
65 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
66 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
67 }
68
69 static
70 bool is_rotation_evaluation(const struct lttng_evaluation *evaluation)
71 {
72 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
73
74 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
75 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
76 }
77
78 static
79 bool lttng_condition_session_rotation_validate(
80 const struct lttng_condition *condition)
81 {
82 bool valid = false;
83 struct lttng_condition_session_rotation *rotation;
84
85 if (!condition) {
86 goto end;
87 }
88
89 rotation = container_of(condition,
90 struct lttng_condition_session_rotation, parent);
91 if (!rotation->session_name) {
92 ERR("Invalid session rotation condition: a target session name must be set.");
93 goto end;
94 }
95
96 valid = true;
97 end:
98 return valid;
99 }
100
101 static
102 int lttng_condition_session_rotation_serialize(
103 const struct lttng_condition *condition,
104 struct lttng_payload *payload)
105 {
106 int ret;
107 size_t session_name_len;
108 struct lttng_condition_session_rotation *rotation;
109 struct lttng_condition_session_rotation_comm rotation_comm;
110
111 if (!condition || !is_rotation_condition(condition)) {
112 ret = -1;
113 goto end;
114 }
115
116 DBG("Serializing session rotation condition");
117 rotation = container_of(condition, struct lttng_condition_session_rotation,
118 parent);
119
120 session_name_len = strlen(rotation->session_name) + 1;
121 if (session_name_len > LTTNG_NAME_MAX) {
122 ret = -1;
123 goto end;
124 }
125
126 rotation_comm.session_name_len = session_name_len;
127 ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm,
128 sizeof(rotation_comm));
129 if (ret) {
130 goto end;
131 }
132 ret = lttng_dynamic_buffer_append(&payload->buffer,
133 rotation->session_name, session_name_len);
134 if (ret) {
135 goto end;
136 }
137 end:
138 return ret;
139 }
140
141 static
142 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
143 const struct lttng_condition *_b)
144 {
145 bool is_equal = false;
146 struct lttng_condition_session_rotation *a, *b;
147
148 a = container_of(_a, struct lttng_condition_session_rotation, parent);
149 b = container_of(_b, struct lttng_condition_session_rotation, parent);
150
151 /* Both session names must be set or both must be unset. */
152 if ((a->session_name && !b->session_name) ||
153 (!a->session_name && b->session_name)) {
154 WARN("Comparing session rotation conditions with uninitialized session names.");
155 goto end;
156 }
157
158 if (a->session_name && b->session_name &&
159 strcmp(a->session_name, b->session_name)) {
160 goto end;
161 }
162
163 is_equal = true;
164 end:
165 return is_equal;
166 }
167
168 static
169 void lttng_condition_session_rotation_destroy(
170 struct lttng_condition *condition)
171 {
172 struct lttng_condition_session_rotation *rotation;
173
174 rotation = container_of(condition,
175 struct lttng_condition_session_rotation, parent);
176
177 free(rotation->session_name);
178 free(rotation);
179 }
180
181 static
182 struct lttng_condition *lttng_condition_session_rotation_create(
183 enum lttng_condition_type type)
184 {
185 struct lttng_condition_session_rotation *condition;
186
187 condition = zmalloc(sizeof(struct lttng_condition_session_rotation));
188 if (!condition) {
189 return NULL;
190 }
191
192 memcpy(&condition->parent, &rotation_condition_template,
193 sizeof(condition->parent));
194 lttng_condition_init(&condition->parent, type);
195 return &condition->parent;
196 }
197
198 struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void)
199 {
200 return lttng_condition_session_rotation_create(
201 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
202 }
203
204 struct lttng_condition *lttng_condition_session_rotation_completed_create(void)
205 {
206 return lttng_condition_session_rotation_create(
207 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
208 }
209
210 static
211 ssize_t init_condition_from_payload(struct lttng_condition *condition,
212 struct lttng_payload_view *src_view)
213 {
214 ssize_t ret, condition_size;
215 enum lttng_condition_status status;
216 const char *session_name;
217 struct lttng_buffer_view name_view;
218 const struct lttng_condition_session_rotation_comm *condition_comm;
219 struct lttng_payload_view condition_comm_view =
220 lttng_payload_view_from_view(
221 src_view, 0, sizeof(*condition_comm));
222
223 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
224 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
225 ret = -1;
226 goto end;
227 }
228
229 condition_comm = (typeof(condition_comm)) src_view->buffer.data;
230 name_view = lttng_buffer_view_from_view(&src_view->buffer,
231 sizeof(*condition_comm), condition_comm->session_name_len);
232
233 if (!lttng_buffer_view_is_valid(&name_view)) {
234 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
235 ret = -1;
236 goto end;
237 }
238
239 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
240 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
241 ret = -1;
242 goto end;
243 }
244
245 session_name = name_view.data;
246 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
247 ERR("Malformed session name encountered in condition buffer");
248 ret = -1;
249 goto end;
250 }
251
252 status = lttng_condition_session_rotation_set_session_name(condition,
253 session_name);
254 if (status != LTTNG_CONDITION_STATUS_OK) {
255 ERR("Failed to set buffer consumed session name");
256 ret = -1;
257 goto end;
258 }
259
260 if (!lttng_condition_validate(condition)) {
261 ret = -1;
262 goto end;
263 }
264
265 condition_size = sizeof(*condition_comm) +
266 (ssize_t) condition_comm->session_name_len;
267 ret = condition_size;
268 end:
269 return ret;
270 }
271
272 static
273 ssize_t lttng_condition_session_rotation_create_from_payload(
274 struct lttng_payload_view *view,
275 struct lttng_condition **_condition,
276 enum lttng_condition_type type)
277 {
278 ssize_t ret;
279 struct lttng_condition *condition = NULL;
280
281 switch (type) {
282 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
283 condition = lttng_condition_session_rotation_ongoing_create();
284 break;
285 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
286 condition = lttng_condition_session_rotation_completed_create();
287 break;
288 default:
289 ret = -1;
290 goto error;
291 }
292
293 if (!_condition || !condition) {
294 ret = -1;
295 goto error;
296 }
297
298 ret = init_condition_from_payload(condition, view);
299 if (ret < 0) {
300 goto error;
301 }
302
303 *_condition = condition;
304 return ret;
305 error:
306 lttng_condition_destroy(condition);
307 return ret;
308 }
309
310 ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
311 struct lttng_payload_view *view,
312 struct lttng_condition **condition)
313 {
314 return lttng_condition_session_rotation_create_from_payload(view,
315 condition,
316 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
317 }
318
319 ssize_t lttng_condition_session_rotation_completed_create_from_payload(
320 struct lttng_payload_view *view,
321 struct lttng_condition **condition)
322 {
323 return lttng_condition_session_rotation_create_from_payload(view,
324 condition,
325 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
326 }
327
328 static
329 struct lttng_evaluation *lttng_evaluation_session_rotation_create(
330 enum lttng_condition_type type, uint64_t id,
331 struct lttng_trace_archive_location *location)
332 {
333 struct lttng_evaluation_session_rotation *evaluation;
334
335 evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation));
336 if (!evaluation) {
337 return NULL;
338 }
339
340 memcpy(&evaluation->parent, &rotation_evaluation_template,
341 sizeof(evaluation->parent));
342 lttng_evaluation_init(&evaluation->parent, type);
343 evaluation->id = id;
344 if (location) {
345 lttng_trace_archive_location_get(location);
346 }
347 evaluation->location = location;
348 return &evaluation->parent;
349 }
350
351 static
352 ssize_t create_evaluation_from_payload(
353 enum lttng_condition_type type,
354 struct lttng_payload_view *view,
355 struct lttng_evaluation **_evaluation)
356 {
357 ssize_t ret, size;
358 struct lttng_evaluation *evaluation = NULL;
359 struct lttng_trace_archive_location *location = NULL;
360 const struct lttng_evaluation_session_rotation_comm *comm;
361 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
362 view, 0, sizeof(*comm));
363
364 if (!lttng_payload_view_is_valid(&comm_view)) {
365 goto error;
366 }
367
368 comm = (typeof(comm)) comm_view.buffer.data;
369 size = sizeof(*comm);
370 if (comm->has_location) {
371 const struct lttng_buffer_view location_view =
372 lttng_buffer_view_from_view(
373 &view->buffer, sizeof(*comm), -1);
374
375 if (!lttng_buffer_view_is_valid(&location_view)) {
376 goto error;
377 }
378
379 ret = lttng_trace_archive_location_create_from_buffer(
380 &location_view, &location);
381 if (ret < 0) {
382 goto error;
383 }
384 size += ret;
385 }
386
387 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
388 location);
389 if (!evaluation) {
390 goto error;
391 }
392
393 lttng_trace_archive_location_put(location);
394 ret = size;
395 *_evaluation = evaluation;
396 return ret;
397 error:
398 lttng_trace_archive_location_put(location);
399 evaluation = NULL;
400 return -1;
401 }
402
403 static
404 ssize_t lttng_evaluation_session_rotation_create_from_payload(
405 enum lttng_condition_type type,
406 struct lttng_payload_view *view,
407 struct lttng_evaluation **_evaluation)
408 {
409 ssize_t ret;
410 struct lttng_evaluation *evaluation = NULL;
411
412 if (!_evaluation) {
413 ret = -1;
414 goto error;
415 }
416
417 ret = create_evaluation_from_payload(type, view, &evaluation);
418 if (ret < 0) {
419 goto error;
420 }
421
422 *_evaluation = evaluation;
423 return ret;
424 error:
425 lttng_evaluation_destroy(evaluation);
426 return ret;
427 }
428
429 ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
430 struct lttng_payload_view *view,
431 struct lttng_evaluation **evaluation)
432 {
433 return lttng_evaluation_session_rotation_create_from_payload(
434 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
435 view, evaluation);
436 }
437
438 ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
439 struct lttng_payload_view *view,
440 struct lttng_evaluation **evaluation)
441 {
442 return lttng_evaluation_session_rotation_create_from_payload(
443 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
444 view, evaluation);
445 }
446
447 struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
448 uint64_t id)
449 {
450 return lttng_evaluation_session_rotation_create(
451 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
452 NULL);
453 }
454
455 struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
456 uint64_t id, struct lttng_trace_archive_location *location)
457 {
458 return lttng_evaluation_session_rotation_create(
459 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id,
460 location);
461 }
462
463 enum lttng_condition_status
464 lttng_condition_session_rotation_get_session_name(
465 const struct lttng_condition *condition,
466 const char **session_name)
467 {
468 struct lttng_condition_session_rotation *rotation;
469 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
470
471 if (!condition || !is_rotation_condition(condition) || !session_name) {
472 status = LTTNG_CONDITION_STATUS_INVALID;
473 goto end;
474 }
475
476 rotation = container_of(condition, struct lttng_condition_session_rotation,
477 parent);
478 if (!rotation->session_name) {
479 status = LTTNG_CONDITION_STATUS_UNSET;
480 goto end;
481 }
482 *session_name = rotation->session_name;
483 end:
484 return status;
485 }
486
487 enum lttng_condition_status
488 lttng_condition_session_rotation_set_session_name(
489 struct lttng_condition *condition, const char *session_name)
490 {
491 char *session_name_copy;
492 struct lttng_condition_session_rotation *rotation;
493 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
494
495 if (!condition || !is_rotation_condition(condition) ||
496 !session_name || strlen(session_name) == 0) {
497 status = LTTNG_CONDITION_STATUS_INVALID;
498 goto end;
499 }
500
501 rotation = container_of(condition,
502 struct lttng_condition_session_rotation, parent);
503 session_name_copy = strdup(session_name);
504 if (!session_name_copy) {
505 status = LTTNG_CONDITION_STATUS_ERROR;
506 goto end;
507 }
508
509 free(rotation->session_name);
510 rotation->session_name = session_name_copy;
511 end:
512 return status;
513 }
514
515 static
516 int lttng_evaluation_session_rotation_serialize(
517 const struct lttng_evaluation *evaluation,
518 struct lttng_payload *payload)
519 {
520 int ret;
521 struct lttng_evaluation_session_rotation *rotation;
522 struct lttng_evaluation_session_rotation_comm comm = { 0 };
523
524 rotation = container_of(evaluation,
525 struct lttng_evaluation_session_rotation, parent);
526 comm.id = rotation->id;
527 comm.has_location = !!rotation->location;
528 ret = lttng_dynamic_buffer_append(
529 &payload->buffer, &comm, sizeof(comm));
530 if (ret) {
531 goto end;
532 }
533 if (!rotation->location) {
534 goto end;
535 }
536 ret = lttng_trace_archive_location_serialize(rotation->location,
537 &payload->buffer);
538 end:
539 return ret;
540 }
541
542 static
543 void lttng_evaluation_session_rotation_destroy(
544 struct lttng_evaluation *evaluation)
545 {
546 struct lttng_evaluation_session_rotation *rotation;
547
548 rotation = container_of(evaluation,
549 struct lttng_evaluation_session_rotation, parent);
550 lttng_trace_archive_location_put(rotation->location);
551 free(rotation);
552 }
553
554 enum lttng_evaluation_status
555 lttng_evaluation_session_rotation_get_id(
556 const struct lttng_evaluation *evaluation, uint64_t *id)
557 {
558 const struct lttng_evaluation_session_rotation *rotation;
559 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
560
561 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
562 status = LTTNG_EVALUATION_STATUS_INVALID;
563 goto end;
564 }
565
566 rotation = container_of(evaluation,
567 struct lttng_evaluation_session_rotation, parent);
568 *id = rotation->id;
569 end:
570 return status;
571 }
572
573 /*
574 * The public API assumes that trace archive locations are always provided as
575 * "constant". This means that the user of liblttng-ctl never has to destroy a
576 * trace archive location. Hence, users of liblttng-ctl have no visibility of
577 * the reference counting of archive locations.
578 */
579 enum lttng_evaluation_status
580 lttng_evaluation_session_rotation_completed_get_location(
581 const struct lttng_evaluation *evaluation,
582 const struct lttng_trace_archive_location **location)
583 {
584 const struct lttng_evaluation_session_rotation *rotation;
585 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
586
587 if (!evaluation || !location ||
588 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
589 status = LTTNG_EVALUATION_STATUS_INVALID;
590 goto end;
591 }
592
593 rotation = container_of(evaluation,
594 struct lttng_evaluation_session_rotation, parent);
595 *location = rotation->location;
596 end:
597 return status;
598 }
599
600 static
601 enum lttng_error_code lttng_condition_session_rotation_mi_serialize(
602 const struct lttng_condition *condition,
603 struct mi_writer *writer)
604 {
605 int ret;
606 enum lttng_error_code ret_code;
607 enum lttng_condition_status status;
608 const char *session_name = NULL;
609 const char *type_element_str = NULL;
610
611 LTTNG_ASSERT(condition);
612 LTTNG_ASSERT(writer);
613 LTTNG_ASSERT(is_rotation_condition(condition));
614
615 switch (lttng_condition_get_type(condition)) {
616 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
617 type_element_str =
618 mi_lttng_element_condition_session_rotation_completed;
619 break;
620 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
621 type_element_str =
622 mi_lttng_element_condition_session_rotation_ongoing;
623 break;
624 default:
625 abort();
626 break;
627 }
628
629 status = lttng_condition_session_rotation_get_session_name(
630 condition, &session_name);
631 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
632 LTTNG_ASSERT(session_name);
633
634 /* Open condition session rotation_* element. */
635 ret = mi_lttng_writer_open_element(writer, type_element_str);
636 if (ret) {
637 goto mi_error;
638 }
639
640 /* Session name. */
641 ret = mi_lttng_writer_write_element_string(
642 writer, mi_lttng_element_session_name, session_name);
643 if (ret) {
644 goto mi_error;
645 }
646
647 /* Close condition session rotation element. */
648 ret = mi_lttng_writer_close_element(writer);
649 if (ret) {
650 goto mi_error;
651 }
652
653 ret_code = LTTNG_OK;
654 goto end;
655
656 mi_error:
657 ret_code = LTTNG_ERR_MI_IO_FAIL;
658 end:
659 return ret_code;
660 }
This page took 0.043153 seconds and 4 git commands to generate.