liblttng-ctl: use export list to define exported symbols
[lttng-tools.git] / src / common / conditions / session-rotation.c
CommitLineData
c19092cd 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
c19092cd 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
c19092cd 5 *
c19092cd
JG
6 */
7
6a751b95
JR
8#include <common/error.h>
9#include <common/macros.h>
10#include <common/mi-lttng.h>
c19092cd
JG
11#include <lttng/condition/condition-internal.h>
12#include <lttng/condition/session-rotation-internal.h>
13#include <lttng/location-internal.h>
c19092cd
JG
14#include <stdbool.h>
15
16static
17bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition *condition);
19static
20int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition *condition,
c0a66c84 22 struct lttng_payload *payload);
c19092cd
JG
23static
24bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
25 const struct lttng_condition *_b);
26static
27void lttng_condition_session_rotation_destroy(
28 struct lttng_condition *condition);
29
6a751b95
JR
30static
31enum lttng_error_code lttng_condition_session_rotation_mi_serialize(
32 const struct lttng_condition *condition,
33 struct mi_writer *writer);
34
c19092cd
JG
35static const
36struct 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,
6a751b95 42 .mi_serialize = lttng_condition_session_rotation_mi_serialize,
c19092cd
JG
43};
44
45static
46int lttng_evaluation_session_rotation_serialize(
47 const struct lttng_evaluation *evaluation,
c0a66c84 48 struct lttng_payload *payload);
c19092cd
JG
49static
50void lttng_evaluation_session_rotation_destroy(
51 struct lttng_evaluation *evaluation);
52
53static const
54struct 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
60static
61bool 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
69static
70bool 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
78static
79bool 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;
97end:
98 return valid;
99}
100
101static
102int lttng_condition_session_rotation_serialize(
103 const struct lttng_condition *condition,
c0a66c84 104 struct lttng_payload *payload)
c19092cd
JG
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;
c0a66c84 127 ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm,
c19092cd
JG
128 sizeof(rotation_comm));
129 if (ret) {
130 goto end;
131 }
c0a66c84
JG
132 ret = lttng_dynamic_buffer_append(&payload->buffer,
133 rotation->session_name, session_name_len);
c19092cd
JG
134 if (ret) {
135 goto end;
136 }
137end:
138 return ret;
139}
140
141static
142bool 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;
164end:
165 return is_equal;
166}
167
168static
169void 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
181static
182struct 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,
a38478c9 193 sizeof(condition->parent));
c19092cd
JG
194 lttng_condition_init(&condition->parent, type);
195 return &condition->parent;
196}
197
198struct 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
204struct 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
210static
c0a66c84
JG
211ssize_t init_condition_from_payload(struct lttng_condition *condition,
212 struct lttng_payload_view *src_view)
c19092cd
JG
213{
214 ssize_t ret, condition_size;
215 enum lttng_condition_status status;
c19092cd
JG
216 const char *session_name;
217 struct lttng_buffer_view name_view;
3e6e0df2
JG
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));
c19092cd 222
3e6e0df2 223 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
c19092cd
JG
224 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
225 ret = -1;
226 goto end;
227 }
228
c0a66c84
JG
229 condition_comm = (typeof(condition_comm)) src_view->buffer.data;
230 name_view = lttng_buffer_view_from_view(&src_view->buffer,
3e6e0df2 231 sizeof(*condition_comm), condition_comm->session_name_len);
c19092cd 232
3e6e0df2
JG
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");
c19092cd
JG
235 ret = -1;
236 goto end;
237 }
238
3e6e0df2
JG
239 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
240 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
c19092cd
JG
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;
268end:
269 return ret;
270}
271
272static
c0a66c84
JG
273ssize_t lttng_condition_session_rotation_create_from_payload(
274 struct lttng_payload_view *view,
c19092cd
JG
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
c0a66c84 298 ret = init_condition_from_payload(condition, view);
c19092cd
JG
299 if (ret < 0) {
300 goto error;
301 }
302
303 *_condition = condition;
304 return ret;
305error:
306 lttng_condition_destroy(condition);
307 return ret;
308}
309
c0a66c84
JG
310ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
311 struct lttng_payload_view *view,
c19092cd
JG
312 struct lttng_condition **condition)
313{
c0a66c84 314 return lttng_condition_session_rotation_create_from_payload(view,
c19092cd
JG
315 condition,
316 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
317}
318
c0a66c84
JG
319ssize_t lttng_condition_session_rotation_completed_create_from_payload(
320 struct lttng_payload_view *view,
c19092cd
JG
321 struct lttng_condition **condition)
322{
c0a66c84 323 return lttng_condition_session_rotation_create_from_payload(view,
c19092cd
JG
324 condition,
325 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
326}
327
328static
329struct 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,
a38478c9 341 sizeof(evaluation->parent));
c19092cd
JG
342 lttng_evaluation_init(&evaluation->parent, type);
343 evaluation->id = id;
d3740619
JR
344 if (location) {
345 lttng_trace_archive_location_get(location);
346 }
c19092cd
JG
347 evaluation->location = location;
348 return &evaluation->parent;
349}
350
351static
c0a66c84 352ssize_t create_evaluation_from_payload(
c19092cd 353 enum lttng_condition_type type,
c0a66c84 354 struct lttng_payload_view *view,
c19092cd
JG
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;
3e6e0df2
JG
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));
c19092cd 363
3e6e0df2 364 if (!lttng_payload_view_is_valid(&comm_view)) {
c19092cd
JG
365 goto error;
366 }
367
3e6e0df2 368 comm = (typeof(comm)) comm_view.buffer.data;
c19092cd
JG
369 size = sizeof(*comm);
370 if (comm->has_location) {
3e6e0df2
JG
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)) {
c19092cd
JG
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
d3740619 393 lttng_trace_archive_location_put(location);
c19092cd
JG
394 ret = size;
395 *_evaluation = evaluation;
396 return ret;
397error:
d3740619 398 lttng_trace_archive_location_put(location);
c19092cd
JG
399 evaluation = NULL;
400 return -1;
401}
402
403static
c0a66c84 404ssize_t lttng_evaluation_session_rotation_create_from_payload(
c19092cd 405 enum lttng_condition_type type,
c0a66c84 406 struct lttng_payload_view *view,
c19092cd
JG
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
c0a66c84 417 ret = create_evaluation_from_payload(type, view, &evaluation);
c19092cd
JG
418 if (ret < 0) {
419 goto error;
420 }
421
422 *_evaluation = evaluation;
423 return ret;
424error:
425 lttng_evaluation_destroy(evaluation);
426 return ret;
427}
428
c0a66c84
JG
429ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
430 struct lttng_payload_view *view,
c19092cd
JG
431 struct lttng_evaluation **evaluation)
432{
c0a66c84 433 return lttng_evaluation_session_rotation_create_from_payload(
c19092cd
JG
434 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
435 view, evaluation);
436}
437
c0a66c84
JG
438ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
439 struct lttng_payload_view *view,
c19092cd
JG
440 struct lttng_evaluation **evaluation)
441{
c0a66c84 442 return lttng_evaluation_session_rotation_create_from_payload(
c19092cd
JG
443 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
444 view, evaluation);
445}
446
c19092cd
JG
447struct 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
c19092cd
JG
455struct 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
463enum lttng_condition_status
464lttng_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;
483end:
484 return status;
485}
486
487enum lttng_condition_status
488lttng_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;
511end:
512 return status;
513}
514
515static
516int lttng_evaluation_session_rotation_serialize(
517 const struct lttng_evaluation *evaluation,
c0a66c84 518 struct lttng_payload *payload)
c19092cd
JG
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;
c0a66c84
JG
528 ret = lttng_dynamic_buffer_append(
529 &payload->buffer, &comm, sizeof(comm));
c19092cd
JG
530 if (ret) {
531 goto end;
532 }
533 if (!rotation->location) {
534 goto end;
535 }
536 ret = lttng_trace_archive_location_serialize(rotation->location,
c0a66c84 537 &payload->buffer);
c19092cd
JG
538end:
539 return ret;
540}
541
542static
543void 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);
d3740619 550 lttng_trace_archive_location_put(rotation->location);
c19092cd
JG
551 free(rotation);
552}
553
554enum lttng_evaluation_status
555lttng_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;
569end:
570 return status;
571}
572
d3740619
JR
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 */
c19092cd
JG
579enum lttng_evaluation_status
580lttng_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;
596end:
597 return status;
598}
6a751b95
JR
599
600static
601enum 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
a0377dfe
FD
611 LTTNG_ASSERT(condition);
612 LTTNG_ASSERT(writer);
613 LTTNG_ASSERT(is_rotation_condition(condition));
6a751b95
JR
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);
a0377dfe
FD
631 LTTNG_ASSERT(status == LTTNG_CONDITION_STATUS_OK);
632 LTTNG_ASSERT(session_name);
6a751b95
JR
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
656mi_error:
657 ret_code = LTTNG_ERR_MI_IO_FAIL;
658end:
659 return ret_code;
660}
This page took 0.061017 seconds and 4 git commands to generate.