Use case-scope error labels handling LTTNG_CONSUMER_ROTATE_CHANNEL
[lttng-tools.git] / src / common / session-rotation.c
CommitLineData
c19092cd
JG
1/*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18#include <lttng/condition/condition-internal.h>
19#include <lttng/condition/session-rotation-internal.h>
20#include <lttng/location-internal.h>
21#include <common/macros.h>
22#include <common/error.h>
23#include <assert.h>
24#include <stdbool.h>
25
26static
27bool lttng_condition_session_rotation_validate(
28 const struct lttng_condition *condition);
29static
30int lttng_condition_session_rotation_serialize(
31 const struct lttng_condition *condition,
32 struct lttng_dynamic_buffer *buf);
33static
34bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
35 const struct lttng_condition *_b);
36static
37void lttng_condition_session_rotation_destroy(
38 struct lttng_condition *condition);
39
40static const
41struct lttng_condition rotation_condition_template = {
42 /* .type omitted; shall be set on creation. */
43 .validate = lttng_condition_session_rotation_validate,
44 .serialize = lttng_condition_session_rotation_serialize,
45 .equal = lttng_condition_session_rotation_is_equal,
46 .destroy = lttng_condition_session_rotation_destroy,
47};
48
49static
50int lttng_evaluation_session_rotation_serialize(
51 const struct lttng_evaluation *evaluation,
52 struct lttng_dynamic_buffer *buf);
53static
54void lttng_evaluation_session_rotation_destroy(
55 struct lttng_evaluation *evaluation);
56
57static const
58struct lttng_evaluation rotation_evaluation_template = {
59 /* .type omitted; shall be set on creation. */
60 .serialize = lttng_evaluation_session_rotation_serialize,
61 .destroy = lttng_evaluation_session_rotation_destroy,
62};
63
64static
65bool is_rotation_condition(const struct lttng_condition *condition)
66{
67 enum lttng_condition_type type = lttng_condition_get_type(condition);
68
69 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
70 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
71}
72
73static
74bool is_rotation_evaluation(const struct lttng_evaluation *evaluation)
75{
76 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
77
78 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
79 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
80}
81
82static
83bool lttng_condition_session_rotation_validate(
84 const struct lttng_condition *condition)
85{
86 bool valid = false;
87 struct lttng_condition_session_rotation *rotation;
88
89 if (!condition) {
90 goto end;
91 }
92
93 rotation = container_of(condition,
94 struct lttng_condition_session_rotation, parent);
95 if (!rotation->session_name) {
96 ERR("Invalid session rotation condition: a target session name must be set.");
97 goto end;
98 }
99
100 valid = true;
101end:
102 return valid;
103}
104
105static
106int lttng_condition_session_rotation_serialize(
107 const struct lttng_condition *condition,
108 struct lttng_dynamic_buffer *buf)
109{
110 int ret;
111 size_t session_name_len;
112 struct lttng_condition_session_rotation *rotation;
113 struct lttng_condition_session_rotation_comm rotation_comm;
114
115 if (!condition || !is_rotation_condition(condition)) {
116 ret = -1;
117 goto end;
118 }
119
120 DBG("Serializing session rotation condition");
121 rotation = container_of(condition, struct lttng_condition_session_rotation,
122 parent);
123
124 session_name_len = strlen(rotation->session_name) + 1;
125 if (session_name_len > LTTNG_NAME_MAX) {
126 ret = -1;
127 goto end;
128 }
129
130 rotation_comm.session_name_len = session_name_len;
131 ret = lttng_dynamic_buffer_append(buf, &rotation_comm,
132 sizeof(rotation_comm));
133 if (ret) {
134 goto end;
135 }
136 ret = lttng_dynamic_buffer_append(buf, rotation->session_name,
137 session_name_len);
138 if (ret) {
139 goto end;
140 }
141end:
142 return ret;
143}
144
145static
146bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
147 const struct lttng_condition *_b)
148{
149 bool is_equal = false;
150 struct lttng_condition_session_rotation *a, *b;
151
152 a = container_of(_a, struct lttng_condition_session_rotation, parent);
153 b = container_of(_b, struct lttng_condition_session_rotation, parent);
154
155 /* Both session names must be set or both must be unset. */
156 if ((a->session_name && !b->session_name) ||
157 (!a->session_name && b->session_name)) {
158 WARN("Comparing session rotation conditions with uninitialized session names.");
159 goto end;
160 }
161
162 if (a->session_name && b->session_name &&
163 strcmp(a->session_name, b->session_name)) {
164 goto end;
165 }
166
167 is_equal = true;
168end:
169 return is_equal;
170}
171
172static
173void lttng_condition_session_rotation_destroy(
174 struct lttng_condition *condition)
175{
176 struct lttng_condition_session_rotation *rotation;
177
178 rotation = container_of(condition,
179 struct lttng_condition_session_rotation, parent);
180
181 free(rotation->session_name);
182 free(rotation);
183}
184
185static
186struct lttng_condition *lttng_condition_session_rotation_create(
187 enum lttng_condition_type type)
188{
189 struct lttng_condition_session_rotation *condition;
190
191 condition = zmalloc(sizeof(struct lttng_condition_session_rotation));
192 if (!condition) {
193 return NULL;
194 }
195
196 memcpy(&condition->parent, &rotation_condition_template,
a38478c9 197 sizeof(condition->parent));
c19092cd
JG
198 lttng_condition_init(&condition->parent, type);
199 return &condition->parent;
200}
201
202struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void)
203{
204 return lttng_condition_session_rotation_create(
205 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
206}
207
208struct lttng_condition *lttng_condition_session_rotation_completed_create(void)
209{
210 return lttng_condition_session_rotation_create(
211 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
212}
213
214static
215ssize_t init_condition_from_buffer(struct lttng_condition *condition,
216 const struct lttng_buffer_view *src_view)
217{
218 ssize_t ret, condition_size;
219 enum lttng_condition_status status;
220 const struct lttng_condition_session_rotation_comm *condition_comm;
221 const char *session_name;
222 struct lttng_buffer_view name_view;
223
224 if (src_view->size < sizeof(*condition_comm)) {
225 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
226 ret = -1;
227 goto end;
228 }
229
230 condition_comm = (const struct lttng_condition_session_rotation_comm *) src_view->data;
231 name_view = lttng_buffer_view_from_view(src_view,
232 sizeof(*condition_comm), -1);
233
234 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
235 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
236 ret = -1;
237 goto end;
238 }
239
240 if (name_view.size < condition_comm->session_name_len) {
241 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
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
274ssize_t lttng_condition_session_rotation_create_from_buffer(
275 const struct lttng_buffer_view *view,
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
299 ret = init_condition_from_buffer(condition, view);
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
312ssize_t lttng_condition_session_rotation_ongoing_create_from_buffer(
313 const struct lttng_buffer_view *view,
314 struct lttng_condition **condition)
315{
316 return lttng_condition_session_rotation_create_from_buffer(view,
317 condition,
318 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
319}
320
321LTTNG_HIDDEN
322ssize_t lttng_condition_session_rotation_completed_create_from_buffer(
323 const struct lttng_buffer_view *view,
324 struct lttng_condition **condition)
325{
326 return lttng_condition_session_rotation_create_from_buffer(view,
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
352ssize_t create_evaluation_from_buffer(
353 enum lttng_condition_type type,
354 const struct lttng_buffer_view *view,
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;
360 const struct lttng_evaluation_session_rotation_comm *comm =
361 (const struct lttng_evaluation_session_rotation_comm *) view->data;
362 struct lttng_buffer_view location_view;
363
364 if (view->size < sizeof(*comm)) {
365 goto error;
366 }
367
368 size = sizeof(*comm);
369 if (comm->has_location) {
370 location_view = lttng_buffer_view_from_view(view, sizeof(*comm),
371 -1);
372 if (!location_view.data) {
373 goto error;
374 }
375
376 ret = lttng_trace_archive_location_create_from_buffer(
377 &location_view, &location);
378 if (ret < 0) {
379 goto error;
380 }
381 size += ret;
382 }
383
384 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
385 location);
386 if (!evaluation) {
387 goto error;
388 }
389
390 ret = size;
391 *_evaluation = evaluation;
392 return ret;
393error:
394 lttng_trace_archive_location_destroy(location);
395 evaluation = NULL;
396 return -1;
397}
398
399static
400ssize_t lttng_evaluation_session_rotation_create_from_buffer(
401 enum lttng_condition_type type,
402 const struct lttng_buffer_view *view,
403 struct lttng_evaluation **_evaluation)
404{
405 ssize_t ret;
406 struct lttng_evaluation *evaluation = NULL;
407
408 if (!_evaluation) {
409 ret = -1;
410 goto error;
411 }
412
413 ret = create_evaluation_from_buffer(type, view, &evaluation);
414 if (ret < 0) {
415 goto error;
416 }
417
418 *_evaluation = evaluation;
419 return ret;
420error:
421 lttng_evaluation_destroy(evaluation);
422 return ret;
423}
424
425LTTNG_HIDDEN
426ssize_t lttng_evaluation_session_rotation_ongoing_create_from_buffer(
427 const struct lttng_buffer_view *view,
428 struct lttng_evaluation **evaluation)
429{
430 return lttng_evaluation_session_rotation_create_from_buffer(
431 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
432 view, evaluation);
433}
434
435LTTNG_HIDDEN
436ssize_t lttng_evaluation_session_rotation_completed_create_from_buffer(
437 const struct lttng_buffer_view *view,
438 struct lttng_evaluation **evaluation)
439{
440 return lttng_evaluation_session_rotation_create_from_buffer(
441 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
442 view, evaluation);
443}
444
445LTTNG_HIDDEN
446struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
447 uint64_t id)
448{
449 return lttng_evaluation_session_rotation_create(
450 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
451 NULL);
452}
453
454LTTNG_HIDDEN
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,
518 struct lttng_dynamic_buffer *buf)
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;
528 ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm));
529 if (ret) {
530 goto end;
531 }
532 if (!rotation->location) {
533 goto end;
534 }
535 ret = lttng_trace_archive_location_serialize(rotation->location,
536 buf);
537end:
538 return ret;
539}
540
541static
542void lttng_evaluation_session_rotation_destroy(
543 struct lttng_evaluation *evaluation)
544{
545 struct lttng_evaluation_session_rotation *rotation;
546
547 rotation = container_of(evaluation,
548 struct lttng_evaluation_session_rotation, parent);
549 lttng_trace_archive_location_destroy(rotation->location);
550 free(rotation);
551}
552
553enum lttng_evaluation_status
554lttng_evaluation_session_rotation_get_id(
555 const struct lttng_evaluation *evaluation, uint64_t *id)
556{
557 const struct lttng_evaluation_session_rotation *rotation;
558 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
559
560 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
561 status = LTTNG_EVALUATION_STATUS_INVALID;
562 goto end;
563 }
564
565 rotation = container_of(evaluation,
566 struct lttng_evaluation_session_rotation, parent);
567 *id = rotation->id;
568end:
569 return status;
570}
571
572enum lttng_evaluation_status
573lttng_evaluation_session_rotation_completed_get_location(
574 const struct lttng_evaluation *evaluation,
575 const struct lttng_trace_archive_location **location)
576{
577 const struct lttng_evaluation_session_rotation *rotation;
578 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
579
580 if (!evaluation || !location ||
581 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
582 status = LTTNG_EVALUATION_STATUS_INVALID;
583 goto end;
584 }
585
586 rotation = container_of(evaluation,
587 struct lttng_evaluation_session_rotation, parent);
588 *location = rotation->location;
589end:
590 return status;
591}
This page took 0.047254 seconds and 4 git commands to generate.