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