2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
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>
17 bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition
*condition
);
20 int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition
*condition
,
22 struct lttng_payload
*payload
);
24 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition
*_a
,
25 const struct lttng_condition
*_b
);
27 void lttng_condition_session_rotation_destroy(
28 struct lttng_condition
*condition
);
31 enum lttng_error_code
lttng_condition_session_rotation_mi_serialize(
32 const struct lttng_condition
*condition
,
33 struct mi_writer
*writer
);
36 struct lttng_condition rotation_condition_template
= {
38 LTTNG_CONDITION_TYPE_UNKNOWN
, /* type unset, shall be set on creation. */
39 lttng_condition_session_rotation_validate
,
40 lttng_condition_session_rotation_serialize
,
41 lttng_condition_session_rotation_is_equal
,
42 lttng_condition_session_rotation_destroy
,
43 lttng_condition_session_rotation_mi_serialize
,
47 int lttng_evaluation_session_rotation_serialize(
48 const struct lttng_evaluation
*evaluation
,
49 struct lttng_payload
*payload
);
51 void lttng_evaluation_session_rotation_destroy(
52 struct lttng_evaluation
*evaluation
);
55 struct lttng_evaluation rotation_evaluation_template
= {
56 LTTNG_CONDITION_TYPE_UNKNOWN
, /* type unset, shall be set on creation. */
57 lttng_evaluation_session_rotation_serialize
,
58 lttng_evaluation_session_rotation_destroy
,
62 bool is_rotation_condition(const struct lttng_condition
*condition
)
64 enum lttng_condition_type type
= lttng_condition_get_type(condition
);
66 return type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
||
67 type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
;
71 bool is_rotation_evaluation(const struct lttng_evaluation
*evaluation
)
73 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
75 return type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
||
76 type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
;
80 bool lttng_condition_session_rotation_validate(
81 const struct lttng_condition
*condition
)
84 struct lttng_condition_session_rotation
*rotation
;
90 rotation
= container_of(condition
,
91 struct lttng_condition_session_rotation
, parent
);
92 if (!rotation
->session_name
) {
93 ERR("Invalid session rotation condition: a target session name must be set.");
103 int lttng_condition_session_rotation_serialize(
104 const struct lttng_condition
*condition
,
105 struct lttng_payload
*payload
)
108 size_t session_name_len
;
109 struct lttng_condition_session_rotation
*rotation
;
110 struct lttng_condition_session_rotation_comm rotation_comm
;
112 if (!condition
|| !is_rotation_condition(condition
)) {
117 DBG("Serializing session rotation condition");
118 rotation
= container_of(condition
, struct lttng_condition_session_rotation
,
121 session_name_len
= strlen(rotation
->session_name
) + 1;
122 if (session_name_len
> LTTNG_NAME_MAX
) {
127 rotation_comm
.session_name_len
= session_name_len
;
128 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &rotation_comm
,
129 sizeof(rotation_comm
));
133 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
134 rotation
->session_name
, session_name_len
);
143 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition
*_a
,
144 const struct lttng_condition
*_b
)
146 bool is_equal
= false;
147 struct lttng_condition_session_rotation
*a
, *b
;
149 a
= container_of(_a
, struct lttng_condition_session_rotation
, parent
);
150 b
= container_of(_b
, struct lttng_condition_session_rotation
, parent
);
152 /* Both session names must be set or both must be unset. */
153 if ((a
->session_name
&& !b
->session_name
) ||
154 (!a
->session_name
&& b
->session_name
)) {
155 WARN("Comparing session rotation conditions with uninitialized session names.");
159 if (a
->session_name
&& b
->session_name
&&
160 strcmp(a
->session_name
, b
->session_name
)) {
170 void lttng_condition_session_rotation_destroy(
171 struct lttng_condition
*condition
)
173 struct lttng_condition_session_rotation
*rotation
;
175 rotation
= container_of(condition
,
176 struct lttng_condition_session_rotation
, parent
);
178 free(rotation
->session_name
);
183 struct lttng_condition
*lttng_condition_session_rotation_create(
184 enum lttng_condition_type type
)
186 struct lttng_condition_session_rotation
*condition
;
188 condition
= (lttng_condition_session_rotation
*) zmalloc(sizeof(struct lttng_condition_session_rotation
));
193 memcpy(&condition
->parent
, &rotation_condition_template
,
194 sizeof(condition
->parent
));
195 lttng_condition_init(&condition
->parent
, type
);
196 return &condition
->parent
;
199 struct lttng_condition
*lttng_condition_session_rotation_ongoing_create(void)
201 return lttng_condition_session_rotation_create(
202 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
205 struct lttng_condition
*lttng_condition_session_rotation_completed_create(void)
207 return lttng_condition_session_rotation_create(
208 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
212 ssize_t
init_condition_from_payload(struct lttng_condition
*condition
,
213 struct lttng_payload_view
*src_view
)
215 ssize_t ret
, condition_size
;
216 enum lttng_condition_status status
;
217 const char *session_name
;
218 struct lttng_buffer_view name_view
;
219 const struct lttng_condition_session_rotation_comm
*condition_comm
;
220 struct lttng_payload_view condition_comm_view
=
221 lttng_payload_view_from_view(
222 src_view
, 0, sizeof(*condition_comm
));
224 if (!lttng_payload_view_is_valid(&condition_comm_view
)) {
225 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
230 condition_comm
= (typeof(condition_comm
)) src_view
->buffer
.data
;
231 name_view
= lttng_buffer_view_from_view(&src_view
->buffer
,
232 sizeof(*condition_comm
), condition_comm
->session_name_len
);
234 if (!lttng_buffer_view_is_valid(&name_view
)) {
235 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
240 if (condition_comm
->session_name_len
> LTTNG_NAME_MAX
) {
241 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
246 session_name
= name_view
.data
;
247 if (*(session_name
+ condition_comm
->session_name_len
- 1) != '\0') {
248 ERR("Malformed session name encountered in condition buffer");
253 status
= lttng_condition_session_rotation_set_session_name(condition
,
255 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
256 ERR("Failed to set buffer consumed session name");
261 if (!lttng_condition_validate(condition
)) {
266 condition_size
= sizeof(*condition_comm
) +
267 (ssize_t
) condition_comm
->session_name_len
;
268 ret
= condition_size
;
274 ssize_t
lttng_condition_session_rotation_create_from_payload(
275 struct lttng_payload_view
*view
,
276 struct lttng_condition
**_condition
,
277 enum lttng_condition_type type
)
280 struct lttng_condition
*condition
= NULL
;
283 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
284 condition
= lttng_condition_session_rotation_ongoing_create();
286 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
287 condition
= lttng_condition_session_rotation_completed_create();
294 if (!_condition
|| !condition
) {
299 ret
= init_condition_from_payload(condition
, view
);
304 *_condition
= condition
;
307 lttng_condition_destroy(condition
);
311 ssize_t
lttng_condition_session_rotation_ongoing_create_from_payload(
312 struct lttng_payload_view
*view
,
313 struct lttng_condition
**condition
)
315 return lttng_condition_session_rotation_create_from_payload(view
,
317 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
320 ssize_t
lttng_condition_session_rotation_completed_create_from_payload(
321 struct lttng_payload_view
*view
,
322 struct lttng_condition
**condition
)
324 return lttng_condition_session_rotation_create_from_payload(view
,
326 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
330 struct lttng_evaluation
*lttng_evaluation_session_rotation_create(
331 enum lttng_condition_type type
, uint64_t id
,
332 struct lttng_trace_archive_location
*location
)
334 struct lttng_evaluation_session_rotation
*evaluation
;
336 evaluation
= (lttng_evaluation_session_rotation
*) zmalloc(sizeof(struct lttng_evaluation_session_rotation
));
341 memcpy(&evaluation
->parent
, &rotation_evaluation_template
,
342 sizeof(evaluation
->parent
));
343 lttng_evaluation_init(&evaluation
->parent
, type
);
346 lttng_trace_archive_location_get(location
);
348 evaluation
->location
= location
;
349 return &evaluation
->parent
;
353 ssize_t
create_evaluation_from_payload(
354 enum lttng_condition_type type
,
355 struct lttng_payload_view
*view
,
356 struct lttng_evaluation
**_evaluation
)
359 struct lttng_evaluation
*evaluation
= NULL
;
360 struct lttng_trace_archive_location
*location
= NULL
;
361 const struct lttng_evaluation_session_rotation_comm
*comm
;
362 struct lttng_payload_view comm_view
= lttng_payload_view_from_view(
363 view
, 0, sizeof(*comm
));
365 if (!lttng_payload_view_is_valid(&comm_view
)) {
369 comm
= (typeof(comm
)) comm_view
.buffer
.data
;
370 size
= sizeof(*comm
);
371 if (comm
->has_location
) {
372 const struct lttng_buffer_view location_view
=
373 lttng_buffer_view_from_view(
374 &view
->buffer
, sizeof(*comm
), -1);
376 if (!lttng_buffer_view_is_valid(&location_view
)) {
380 ret
= lttng_trace_archive_location_create_from_buffer(
381 &location_view
, &location
);
388 evaluation
= lttng_evaluation_session_rotation_create(type
, comm
->id
,
394 lttng_trace_archive_location_put(location
);
396 *_evaluation
= evaluation
;
399 lttng_trace_archive_location_put(location
);
405 ssize_t
lttng_evaluation_session_rotation_create_from_payload(
406 enum lttng_condition_type type
,
407 struct lttng_payload_view
*view
,
408 struct lttng_evaluation
**_evaluation
)
411 struct lttng_evaluation
*evaluation
= NULL
;
418 ret
= create_evaluation_from_payload(type
, view
, &evaluation
);
423 *_evaluation
= evaluation
;
426 lttng_evaluation_destroy(evaluation
);
430 ssize_t
lttng_evaluation_session_rotation_ongoing_create_from_payload(
431 struct lttng_payload_view
*view
,
432 struct lttng_evaluation
**evaluation
)
434 return lttng_evaluation_session_rotation_create_from_payload(
435 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
,
439 ssize_t
lttng_evaluation_session_rotation_completed_create_from_payload(
440 struct lttng_payload_view
*view
,
441 struct lttng_evaluation
**evaluation
)
443 return lttng_evaluation_session_rotation_create_from_payload(
444 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
,
448 struct lttng_evaluation
*lttng_evaluation_session_rotation_ongoing_create(
451 return lttng_evaluation_session_rotation_create(
452 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
, id
,
456 struct lttng_evaluation
*lttng_evaluation_session_rotation_completed_create(
457 uint64_t id
, struct lttng_trace_archive_location
*location
)
459 return lttng_evaluation_session_rotation_create(
460 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
, id
,
464 enum lttng_condition_status
465 lttng_condition_session_rotation_get_session_name(
466 const struct lttng_condition
*condition
,
467 const char **session_name
)
469 struct lttng_condition_session_rotation
*rotation
;
470 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
472 if (!condition
|| !is_rotation_condition(condition
) || !session_name
) {
473 status
= LTTNG_CONDITION_STATUS_INVALID
;
477 rotation
= container_of(condition
, struct lttng_condition_session_rotation
,
479 if (!rotation
->session_name
) {
480 status
= LTTNG_CONDITION_STATUS_UNSET
;
483 *session_name
= rotation
->session_name
;
488 enum lttng_condition_status
489 lttng_condition_session_rotation_set_session_name(
490 struct lttng_condition
*condition
, const char *session_name
)
492 char *session_name_copy
;
493 struct lttng_condition_session_rotation
*rotation
;
494 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
496 if (!condition
|| !is_rotation_condition(condition
) ||
497 !session_name
|| strlen(session_name
) == 0) {
498 status
= LTTNG_CONDITION_STATUS_INVALID
;
502 rotation
= container_of(condition
,
503 struct lttng_condition_session_rotation
, parent
);
504 session_name_copy
= strdup(session_name
);
505 if (!session_name_copy
) {
506 status
= LTTNG_CONDITION_STATUS_ERROR
;
510 free(rotation
->session_name
);
511 rotation
->session_name
= session_name_copy
;
517 int lttng_evaluation_session_rotation_serialize(
518 const struct lttng_evaluation
*evaluation
,
519 struct lttng_payload
*payload
)
522 struct lttng_evaluation_session_rotation
*rotation
;
523 struct lttng_evaluation_session_rotation_comm comm
= { 0 };
525 rotation
= container_of(evaluation
,
526 struct lttng_evaluation_session_rotation
, parent
);
527 comm
.id
= rotation
->id
;
528 comm
.has_location
= !!rotation
->location
;
529 ret
= lttng_dynamic_buffer_append(
530 &payload
->buffer
, &comm
, sizeof(comm
));
534 if (!rotation
->location
) {
537 ret
= lttng_trace_archive_location_serialize(rotation
->location
,
544 void lttng_evaluation_session_rotation_destroy(
545 struct lttng_evaluation
*evaluation
)
547 struct lttng_evaluation_session_rotation
*rotation
;
549 rotation
= container_of(evaluation
,
550 struct lttng_evaluation_session_rotation
, parent
);
551 lttng_trace_archive_location_put(rotation
->location
);
555 enum lttng_evaluation_status
556 lttng_evaluation_session_rotation_get_id(
557 const struct lttng_evaluation
*evaluation
, uint64_t *id
)
559 const struct lttng_evaluation_session_rotation
*rotation
;
560 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
562 if (!evaluation
|| !id
|| !is_rotation_evaluation(evaluation
)) {
563 status
= LTTNG_EVALUATION_STATUS_INVALID
;
567 rotation
= container_of(evaluation
,
568 struct lttng_evaluation_session_rotation
, parent
);
575 * The public API assumes that trace archive locations are always provided as
576 * "constant". This means that the user of liblttng-ctl never has to destroy a
577 * trace archive location. Hence, users of liblttng-ctl have no visibility of
578 * the reference counting of archive locations.
580 enum lttng_evaluation_status
581 lttng_evaluation_session_rotation_completed_get_location(
582 const struct lttng_evaluation
*evaluation
,
583 const struct lttng_trace_archive_location
**location
)
585 const struct lttng_evaluation_session_rotation
*rotation
;
586 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
588 if (!evaluation
|| !location
||
589 evaluation
->type
!= LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
) {
590 status
= LTTNG_EVALUATION_STATUS_INVALID
;
594 rotation
= container_of(evaluation
,
595 struct lttng_evaluation_session_rotation
, parent
);
596 *location
= rotation
->location
;
602 enum lttng_error_code
lttng_condition_session_rotation_mi_serialize(
603 const struct lttng_condition
*condition
,
604 struct mi_writer
*writer
)
607 enum lttng_error_code ret_code
;
608 enum lttng_condition_status status
;
609 const char *session_name
= NULL
;
610 const char *type_element_str
= NULL
;
612 LTTNG_ASSERT(condition
);
613 LTTNG_ASSERT(writer
);
614 LTTNG_ASSERT(is_rotation_condition(condition
));
616 switch (lttng_condition_get_type(condition
)) {
617 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
619 mi_lttng_element_condition_session_rotation_completed
;
621 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
623 mi_lttng_element_condition_session_rotation_ongoing
;
630 status
= lttng_condition_session_rotation_get_session_name(
631 condition
, &session_name
);
632 LTTNG_ASSERT(status
== LTTNG_CONDITION_STATUS_OK
);
633 LTTNG_ASSERT(session_name
);
635 /* Open condition session rotation_* element. */
636 ret
= mi_lttng_writer_open_element(writer
, type_element_str
);
642 ret
= mi_lttng_writer_write_element_string(
643 writer
, mi_lttng_element_session_name
, session_name
);
648 /* Close condition session rotation element. */
649 ret
= mi_lttng_writer_close_element(writer
);
658 ret_code
= LTTNG_ERR_MI_IO_FAIL
;