Force usage of assert() condition when NDEBUG is defined
[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 LTTNG_HIDDEN
311 ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
312 struct lttng_payload_view *view,
313 struct lttng_condition **condition)
314 {
315 return lttng_condition_session_rotation_create_from_payload(view,
316 condition,
317 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
318 }
319
320 LTTNG_HIDDEN
321 ssize_t lttng_condition_session_rotation_completed_create_from_payload(
322 struct lttng_payload_view *view,
323 struct lttng_condition **condition)
324 {
325 return lttng_condition_session_rotation_create_from_payload(view,
326 condition,
327 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
328 }
329
330 static
331 struct lttng_evaluation *lttng_evaluation_session_rotation_create(
332 enum lttng_condition_type type, uint64_t id,
333 struct lttng_trace_archive_location *location)
334 {
335 struct lttng_evaluation_session_rotation *evaluation;
336
337 evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation));
338 if (!evaluation) {
339 return NULL;
340 }
341
342 memcpy(&evaluation->parent, &rotation_evaluation_template,
343 sizeof(evaluation->parent));
344 lttng_evaluation_init(&evaluation->parent, type);
345 evaluation->id = id;
346 if (location) {
347 lttng_trace_archive_location_get(location);
348 }
349 evaluation->location = location;
350 return &evaluation->parent;
351 }
352
353 static
354 ssize_t create_evaluation_from_payload(
355 enum lttng_condition_type type,
356 struct lttng_payload_view *view,
357 struct lttng_evaluation **_evaluation)
358 {
359 ssize_t ret, size;
360 struct lttng_evaluation *evaluation = NULL;
361 struct lttng_trace_archive_location *location = NULL;
362 const struct lttng_evaluation_session_rotation_comm *comm;
363 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
364 view, 0, sizeof(*comm));
365
366 if (!lttng_payload_view_is_valid(&comm_view)) {
367 goto error;
368 }
369
370 comm = (typeof(comm)) comm_view.buffer.data;
371 size = sizeof(*comm);
372 if (comm->has_location) {
373 const struct lttng_buffer_view location_view =
374 lttng_buffer_view_from_view(
375 &view->buffer, sizeof(*comm), -1);
376
377 if (!lttng_buffer_view_is_valid(&location_view)) {
378 goto error;
379 }
380
381 ret = lttng_trace_archive_location_create_from_buffer(
382 &location_view, &location);
383 if (ret < 0) {
384 goto error;
385 }
386 size += ret;
387 }
388
389 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
390 location);
391 if (!evaluation) {
392 goto error;
393 }
394
395 lttng_trace_archive_location_put(location);
396 ret = size;
397 *_evaluation = evaluation;
398 return ret;
399 error:
400 lttng_trace_archive_location_put(location);
401 evaluation = NULL;
402 return -1;
403 }
404
405 static
406 ssize_t lttng_evaluation_session_rotation_create_from_payload(
407 enum lttng_condition_type type,
408 struct lttng_payload_view *view,
409 struct lttng_evaluation **_evaluation)
410 {
411 ssize_t ret;
412 struct lttng_evaluation *evaluation = NULL;
413
414 if (!_evaluation) {
415 ret = -1;
416 goto error;
417 }
418
419 ret = create_evaluation_from_payload(type, view, &evaluation);
420 if (ret < 0) {
421 goto error;
422 }
423
424 *_evaluation = evaluation;
425 return ret;
426 error:
427 lttng_evaluation_destroy(evaluation);
428 return ret;
429 }
430
431 LTTNG_HIDDEN
432 ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
433 struct lttng_payload_view *view,
434 struct lttng_evaluation **evaluation)
435 {
436 return lttng_evaluation_session_rotation_create_from_payload(
437 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
438 view, evaluation);
439 }
440
441 LTTNG_HIDDEN
442 ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
443 struct lttng_payload_view *view,
444 struct lttng_evaluation **evaluation)
445 {
446 return lttng_evaluation_session_rotation_create_from_payload(
447 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
448 view, evaluation);
449 }
450
451 LTTNG_HIDDEN
452 struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
453 uint64_t id)
454 {
455 return lttng_evaluation_session_rotation_create(
456 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
457 NULL);
458 }
459
460 LTTNG_HIDDEN
461 struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
462 uint64_t id, struct lttng_trace_archive_location *location)
463 {
464 return lttng_evaluation_session_rotation_create(
465 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id,
466 location);
467 }
468
469 enum lttng_condition_status
470 lttng_condition_session_rotation_get_session_name(
471 const struct lttng_condition *condition,
472 const char **session_name)
473 {
474 struct lttng_condition_session_rotation *rotation;
475 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
476
477 if (!condition || !is_rotation_condition(condition) || !session_name) {
478 status = LTTNG_CONDITION_STATUS_INVALID;
479 goto end;
480 }
481
482 rotation = container_of(condition, struct lttng_condition_session_rotation,
483 parent);
484 if (!rotation->session_name) {
485 status = LTTNG_CONDITION_STATUS_UNSET;
486 goto end;
487 }
488 *session_name = rotation->session_name;
489 end:
490 return status;
491 }
492
493 enum lttng_condition_status
494 lttng_condition_session_rotation_set_session_name(
495 struct lttng_condition *condition, const char *session_name)
496 {
497 char *session_name_copy;
498 struct lttng_condition_session_rotation *rotation;
499 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
500
501 if (!condition || !is_rotation_condition(condition) ||
502 !session_name || strlen(session_name) == 0) {
503 status = LTTNG_CONDITION_STATUS_INVALID;
504 goto end;
505 }
506
507 rotation = container_of(condition,
508 struct lttng_condition_session_rotation, parent);
509 session_name_copy = strdup(session_name);
510 if (!session_name_copy) {
511 status = LTTNG_CONDITION_STATUS_ERROR;
512 goto end;
513 }
514
515 free(rotation->session_name);
516 rotation->session_name = session_name_copy;
517 end:
518 return status;
519 }
520
521 static
522 int lttng_evaluation_session_rotation_serialize(
523 const struct lttng_evaluation *evaluation,
524 struct lttng_payload *payload)
525 {
526 int ret;
527 struct lttng_evaluation_session_rotation *rotation;
528 struct lttng_evaluation_session_rotation_comm comm = { 0 };
529
530 rotation = container_of(evaluation,
531 struct lttng_evaluation_session_rotation, parent);
532 comm.id = rotation->id;
533 comm.has_location = !!rotation->location;
534 ret = lttng_dynamic_buffer_append(
535 &payload->buffer, &comm, sizeof(comm));
536 if (ret) {
537 goto end;
538 }
539 if (!rotation->location) {
540 goto end;
541 }
542 ret = lttng_trace_archive_location_serialize(rotation->location,
543 &payload->buffer);
544 end:
545 return ret;
546 }
547
548 static
549 void lttng_evaluation_session_rotation_destroy(
550 struct lttng_evaluation *evaluation)
551 {
552 struct lttng_evaluation_session_rotation *rotation;
553
554 rotation = container_of(evaluation,
555 struct lttng_evaluation_session_rotation, parent);
556 lttng_trace_archive_location_put(rotation->location);
557 free(rotation);
558 }
559
560 enum lttng_evaluation_status
561 lttng_evaluation_session_rotation_get_id(
562 const struct lttng_evaluation *evaluation, uint64_t *id)
563 {
564 const struct lttng_evaluation_session_rotation *rotation;
565 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
566
567 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
568 status = LTTNG_EVALUATION_STATUS_INVALID;
569 goto end;
570 }
571
572 rotation = container_of(evaluation,
573 struct lttng_evaluation_session_rotation, parent);
574 *id = rotation->id;
575 end:
576 return status;
577 }
578
579 /*
580 * The public API assumes that trace archive locations are always provided as
581 * "constant". This means that the user of liblttng-ctl never has to destroy a
582 * trace archive location. Hence, users of liblttng-ctl have no visibility of
583 * the reference counting of archive locations.
584 */
585 enum lttng_evaluation_status
586 lttng_evaluation_session_rotation_completed_get_location(
587 const struct lttng_evaluation *evaluation,
588 const struct lttng_trace_archive_location **location)
589 {
590 const struct lttng_evaluation_session_rotation *rotation;
591 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
592
593 if (!evaluation || !location ||
594 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
595 status = LTTNG_EVALUATION_STATUS_INVALID;
596 goto end;
597 }
598
599 rotation = container_of(evaluation,
600 struct lttng_evaluation_session_rotation, parent);
601 *location = rotation->location;
602 end:
603 return status;
604 }
605
606 static
607 enum lttng_error_code lttng_condition_session_rotation_mi_serialize(
608 const struct lttng_condition *condition,
609 struct mi_writer *writer)
610 {
611 int ret;
612 enum lttng_error_code ret_code;
613 enum lttng_condition_status status;
614 const char *session_name = NULL;
615 const char *type_element_str = NULL;
616
617 LTTNG_ASSERT(condition);
618 LTTNG_ASSERT(writer);
619 LTTNG_ASSERT(is_rotation_condition(condition));
620
621 switch (lttng_condition_get_type(condition)) {
622 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
623 type_element_str =
624 mi_lttng_element_condition_session_rotation_completed;
625 break;
626 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
627 type_element_str =
628 mi_lttng_element_condition_session_rotation_ongoing;
629 break;
630 default:
631 abort();
632 break;
633 }
634
635 status = lttng_condition_session_rotation_get_session_name(
636 condition, &session_name);
637 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
638 LTTNG_ASSERT(session_name);
639
640 /* Open condition session rotation_* element. */
641 ret = mi_lttng_writer_open_element(writer, type_element_str);
642 if (ret) {
643 goto mi_error;
644 }
645
646 /* Session name. */
647 ret = mi_lttng_writer_write_element_string(
648 writer, mi_lttng_element_session_name, session_name);
649 if (ret) {
650 goto mi_error;
651 }
652
653 /* Close condition session rotation element. */
654 ret = mi_lttng_writer_close_element(writer);
655 if (ret) {
656 goto mi_error;
657 }
658
659 ret_code = LTTNG_OK;
660 goto end;
661
662 mi_error:
663 ret_code = LTTNG_ERR_MI_IO_FAIL;
664 end:
665 return ret_code;
666 }
This page took 0.042404 seconds and 4 git commands to generate.