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
= {
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
,
46 int lttng_evaluation_session_rotation_serialize(
47 const struct lttng_evaluation
*evaluation
,
48 struct lttng_payload
*payload
);
50 void lttng_evaluation_session_rotation_destroy(
51 struct lttng_evaluation
*evaluation
);
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
,
61 bool is_rotation_condition(const struct lttng_condition
*condition
)
63 enum lttng_condition_type type
= lttng_condition_get_type(condition
);
65 return type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
||
66 type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
;
70 bool is_rotation_evaluation(const struct lttng_evaluation
*evaluation
)
72 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
74 return type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
||
75 type
== LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
;
79 bool lttng_condition_session_rotation_validate(
80 const struct lttng_condition
*condition
)
83 struct lttng_condition_session_rotation
*rotation
;
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.");
102 int lttng_condition_session_rotation_serialize(
103 const struct lttng_condition
*condition
,
104 struct lttng_payload
*payload
)
107 size_t session_name_len
;
108 struct lttng_condition_session_rotation
*rotation
;
109 struct lttng_condition_session_rotation_comm rotation_comm
;
111 if (!condition
|| !is_rotation_condition(condition
)) {
116 DBG("Serializing session rotation condition");
117 rotation
= container_of(condition
, struct lttng_condition_session_rotation
,
120 session_name_len
= strlen(rotation
->session_name
) + 1;
121 if (session_name_len
> LTTNG_NAME_MAX
) {
126 rotation_comm
.session_name_len
= session_name_len
;
127 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &rotation_comm
,
128 sizeof(rotation_comm
));
132 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
133 rotation
->session_name
, session_name_len
);
142 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition
*_a
,
143 const struct lttng_condition
*_b
)
145 bool is_equal
= false;
146 struct lttng_condition_session_rotation
*a
, *b
;
148 a
= container_of(_a
, struct lttng_condition_session_rotation
, parent
);
149 b
= container_of(_b
, struct lttng_condition_session_rotation
, parent
);
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.");
158 if (a
->session_name
&& b
->session_name
&&
159 strcmp(a
->session_name
, b
->session_name
)) {
169 void lttng_condition_session_rotation_destroy(
170 struct lttng_condition
*condition
)
172 struct lttng_condition_session_rotation
*rotation
;
174 rotation
= container_of(condition
,
175 struct lttng_condition_session_rotation
, parent
);
177 free(rotation
->session_name
);
182 struct lttng_condition
*lttng_condition_session_rotation_create(
183 enum lttng_condition_type type
)
185 struct lttng_condition_session_rotation
*condition
;
187 condition
= zmalloc(sizeof(struct lttng_condition_session_rotation
));
192 memcpy(&condition
->parent
, &rotation_condition_template
,
193 sizeof(condition
->parent
));
194 lttng_condition_init(&condition
->parent
, type
);
195 return &condition
->parent
;
198 struct lttng_condition
*lttng_condition_session_rotation_ongoing_create(void)
200 return lttng_condition_session_rotation_create(
201 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
204 struct lttng_condition
*lttng_condition_session_rotation_completed_create(void)
206 return lttng_condition_session_rotation_create(
207 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
211 ssize_t
init_condition_from_payload(struct lttng_condition
*condition
,
212 struct lttng_payload_view
*src_view
)
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
));
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");
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
);
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");
239 if (condition_comm
->session_name_len
> LTTNG_NAME_MAX
) {
240 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
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");
252 status
= lttng_condition_session_rotation_set_session_name(condition
,
254 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
255 ERR("Failed to set buffer consumed session name");
260 if (!lttng_condition_validate(condition
)) {
265 condition_size
= sizeof(*condition_comm
) +
266 (ssize_t
) condition_comm
->session_name_len
;
267 ret
= condition_size
;
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
)
279 struct lttng_condition
*condition
= NULL
;
282 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
283 condition
= lttng_condition_session_rotation_ongoing_create();
285 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
286 condition
= lttng_condition_session_rotation_completed_create();
293 if (!_condition
|| !condition
) {
298 ret
= init_condition_from_payload(condition
, view
);
303 *_condition
= condition
;
306 lttng_condition_destroy(condition
);
310 ssize_t
lttng_condition_session_rotation_ongoing_create_from_payload(
311 struct lttng_payload_view
*view
,
312 struct lttng_condition
**condition
)
314 return lttng_condition_session_rotation_create_from_payload(view
,
316 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
319 ssize_t
lttng_condition_session_rotation_completed_create_from_payload(
320 struct lttng_payload_view
*view
,
321 struct lttng_condition
**condition
)
323 return lttng_condition_session_rotation_create_from_payload(view
,
325 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
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
)
333 struct lttng_evaluation_session_rotation
*evaluation
;
335 evaluation
= zmalloc(sizeof(struct lttng_evaluation_session_rotation
));
340 memcpy(&evaluation
->parent
, &rotation_evaluation_template
,
341 sizeof(evaluation
->parent
));
342 lttng_evaluation_init(&evaluation
->parent
, type
);
345 lttng_trace_archive_location_get(location
);
347 evaluation
->location
= location
;
348 return &evaluation
->parent
;
352 ssize_t
create_evaluation_from_payload(
353 enum lttng_condition_type type
,
354 struct lttng_payload_view
*view
,
355 struct lttng_evaluation
**_evaluation
)
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
));
364 if (!lttng_payload_view_is_valid(&comm_view
)) {
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);
375 if (!lttng_buffer_view_is_valid(&location_view
)) {
379 ret
= lttng_trace_archive_location_create_from_buffer(
380 &location_view
, &location
);
387 evaluation
= lttng_evaluation_session_rotation_create(type
, comm
->id
,
393 lttng_trace_archive_location_put(location
);
395 *_evaluation
= evaluation
;
398 lttng_trace_archive_location_put(location
);
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
)
410 struct lttng_evaluation
*evaluation
= NULL
;
417 ret
= create_evaluation_from_payload(type
, view
, &evaluation
);
422 *_evaluation
= evaluation
;
425 lttng_evaluation_destroy(evaluation
);
429 ssize_t
lttng_evaluation_session_rotation_ongoing_create_from_payload(
430 struct lttng_payload_view
*view
,
431 struct lttng_evaluation
**evaluation
)
433 return lttng_evaluation_session_rotation_create_from_payload(
434 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
,
438 ssize_t
lttng_evaluation_session_rotation_completed_create_from_payload(
439 struct lttng_payload_view
*view
,
440 struct lttng_evaluation
**evaluation
)
442 return lttng_evaluation_session_rotation_create_from_payload(
443 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
,
447 struct lttng_evaluation
*lttng_evaluation_session_rotation_ongoing_create(
450 return lttng_evaluation_session_rotation_create(
451 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
, id
,
455 struct lttng_evaluation
*lttng_evaluation_session_rotation_completed_create(
456 uint64_t id
, struct lttng_trace_archive_location
*location
)
458 return lttng_evaluation_session_rotation_create(
459 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
, id
,
463 enum lttng_condition_status
464 lttng_condition_session_rotation_get_session_name(
465 const struct lttng_condition
*condition
,
466 const char **session_name
)
468 struct lttng_condition_session_rotation
*rotation
;
469 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
471 if (!condition
|| !is_rotation_condition(condition
) || !session_name
) {
472 status
= LTTNG_CONDITION_STATUS_INVALID
;
476 rotation
= container_of(condition
, struct lttng_condition_session_rotation
,
478 if (!rotation
->session_name
) {
479 status
= LTTNG_CONDITION_STATUS_UNSET
;
482 *session_name
= rotation
->session_name
;
487 enum lttng_condition_status
488 lttng_condition_session_rotation_set_session_name(
489 struct lttng_condition
*condition
, const char *session_name
)
491 char *session_name_copy
;
492 struct lttng_condition_session_rotation
*rotation
;
493 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
495 if (!condition
|| !is_rotation_condition(condition
) ||
496 !session_name
|| strlen(session_name
) == 0) {
497 status
= LTTNG_CONDITION_STATUS_INVALID
;
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
;
509 free(rotation
->session_name
);
510 rotation
->session_name
= session_name_copy
;
516 int lttng_evaluation_session_rotation_serialize(
517 const struct lttng_evaluation
*evaluation
,
518 struct lttng_payload
*payload
)
521 struct lttng_evaluation_session_rotation
*rotation
;
522 struct lttng_evaluation_session_rotation_comm comm
= { 0 };
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
));
533 if (!rotation
->location
) {
536 ret
= lttng_trace_archive_location_serialize(rotation
->location
,
543 void lttng_evaluation_session_rotation_destroy(
544 struct lttng_evaluation
*evaluation
)
546 struct lttng_evaluation_session_rotation
*rotation
;
548 rotation
= container_of(evaluation
,
549 struct lttng_evaluation_session_rotation
, parent
);
550 lttng_trace_archive_location_put(rotation
->location
);
554 enum lttng_evaluation_status
555 lttng_evaluation_session_rotation_get_id(
556 const struct lttng_evaluation
*evaluation
, uint64_t *id
)
558 const struct lttng_evaluation_session_rotation
*rotation
;
559 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
561 if (!evaluation
|| !id
|| !is_rotation_evaluation(evaluation
)) {
562 status
= LTTNG_EVALUATION_STATUS_INVALID
;
566 rotation
= container_of(evaluation
,
567 struct lttng_evaluation_session_rotation
, parent
);
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.
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
)
584 const struct lttng_evaluation_session_rotation
*rotation
;
585 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
587 if (!evaluation
|| !location
||
588 evaluation
->type
!= LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
) {
589 status
= LTTNG_EVALUATION_STATUS_INVALID
;
593 rotation
= container_of(evaluation
,
594 struct lttng_evaluation_session_rotation
, parent
);
595 *location
= rotation
->location
;
601 enum lttng_error_code
lttng_condition_session_rotation_mi_serialize(
602 const struct lttng_condition
*condition
,
603 struct mi_writer
*writer
)
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
;
611 LTTNG_ASSERT(condition
);
612 LTTNG_ASSERT(writer
);
613 LTTNG_ASSERT(is_rotation_condition(condition
));
615 switch (lttng_condition_get_type(condition
)) {
616 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
618 mi_lttng_element_condition_session_rotation_completed
;
620 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
622 mi_lttng_element_condition_session_rotation_ongoing
;
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
);
634 /* Open condition session rotation_* element. */
635 ret
= mi_lttng_writer_open_element(writer
, type_element_str
);
641 ret
= mi_lttng_writer_write_element_string(
642 writer
, mi_lttng_element_session_name
, session_name
);
647 /* Close condition session rotation element. */
648 ret
= mi_lttng_writer_close_element(writer
);
657 ret_code
= LTTNG_ERR_MI_IO_FAIL
;