SoW-2019-0002: Dynamic Snapshot
[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
8#include <lttng/condition/condition-internal.h>
9#include <lttng/condition/session-rotation-internal.h>
10#include <lttng/location-internal.h>
11#include <common/macros.h>
12#include <common/error.h>
13#include <assert.h>
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,
1831ae68
FD
22 struct lttng_dynamic_buffer *buf,
23 int *fd_to_send);
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
31static const
32struct lttng_condition rotation_condition_template = {
33 /* .type omitted; shall be set on creation. */
34 .validate = lttng_condition_session_rotation_validate,
35 .serialize = lttng_condition_session_rotation_serialize,
36 .equal = lttng_condition_session_rotation_is_equal,
37 .destroy = lttng_condition_session_rotation_destroy,
38};
39
40static
41int lttng_evaluation_session_rotation_serialize(
42 const struct lttng_evaluation *evaluation,
43 struct lttng_dynamic_buffer *buf);
44static
45void lttng_evaluation_session_rotation_destroy(
46 struct lttng_evaluation *evaluation);
47
48static const
49struct lttng_evaluation rotation_evaluation_template = {
50 /* .type omitted; shall be set on creation. */
51 .serialize = lttng_evaluation_session_rotation_serialize,
52 .destroy = lttng_evaluation_session_rotation_destroy,
53};
54
55static
56bool is_rotation_condition(const struct lttng_condition *condition)
57{
58 enum lttng_condition_type type = lttng_condition_get_type(condition);
59
60 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
61 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
62}
63
64static
65bool is_rotation_evaluation(const struct lttng_evaluation *evaluation)
66{
67 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
68
69 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
70 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
71}
72
73static
74bool lttng_condition_session_rotation_validate(
75 const struct lttng_condition *condition)
76{
77 bool valid = false;
78 struct lttng_condition_session_rotation *rotation;
79
80 if (!condition) {
81 goto end;
82 }
83
84 rotation = container_of(condition,
85 struct lttng_condition_session_rotation, parent);
86 if (!rotation->session_name) {
87 ERR("Invalid session rotation condition: a target session name must be set.");
88 goto end;
89 }
90
91 valid = true;
92end:
93 return valid;
94}
95
96static
97int lttng_condition_session_rotation_serialize(
98 const struct lttng_condition *condition,
1831ae68
FD
99 struct lttng_dynamic_buffer *buf,
100 int *fd_to_send)
c19092cd
JG
101{
102 int ret;
103 size_t session_name_len;
104 struct lttng_condition_session_rotation *rotation;
105 struct lttng_condition_session_rotation_comm rotation_comm;
106
107 if (!condition || !is_rotation_condition(condition)) {
108 ret = -1;
109 goto end;
110 }
111
112 DBG("Serializing session rotation condition");
113 rotation = container_of(condition, struct lttng_condition_session_rotation,
114 parent);
115
116 session_name_len = strlen(rotation->session_name) + 1;
117 if (session_name_len > LTTNG_NAME_MAX) {
118 ret = -1;
119 goto end;
120 }
121
122 rotation_comm.session_name_len = session_name_len;
123 ret = lttng_dynamic_buffer_append(buf, &rotation_comm,
124 sizeof(rotation_comm));
125 if (ret) {
126 goto end;
127 }
128 ret = lttng_dynamic_buffer_append(buf, rotation->session_name,
129 session_name_len);
130 if (ret) {
131 goto end;
132 }
1831ae68
FD
133
134 if (fd_to_send) {
135 /* No fd to send */
136 *fd_to_send = -1;
137 }
c19092cd
JG
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
212ssize_t init_condition_from_buffer(struct lttng_condition *condition,
213 const struct lttng_buffer_view *src_view)
214{
215 ssize_t ret, condition_size;
216 enum lttng_condition_status status;
217 const struct lttng_condition_session_rotation_comm *condition_comm;
218 const char *session_name;
219 struct lttng_buffer_view name_view;
220
221 if (src_view->size < sizeof(*condition_comm)) {
222 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
223 ret = -1;
224 goto end;
225 }
226
227 condition_comm = (const struct lttng_condition_session_rotation_comm *) src_view->data;
228 name_view = lttng_buffer_view_from_view(src_view,
229 sizeof(*condition_comm), -1);
230
231 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
232 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
233 ret = -1;
234 goto end;
235 }
236
237 if (name_view.size < condition_comm->session_name_len) {
238 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
239 ret = -1;
240 goto end;
241 }
242
243 session_name = name_view.data;
244 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
245 ERR("Malformed session name encountered in condition buffer");
246 ret = -1;
247 goto end;
248 }
249
250 status = lttng_condition_session_rotation_set_session_name(condition,
251 session_name);
252 if (status != LTTNG_CONDITION_STATUS_OK) {
253 ERR("Failed to set buffer consumed session name");
254 ret = -1;
255 goto end;
256 }
257
258 if (!lttng_condition_validate(condition)) {
259 ret = -1;
260 goto end;
261 }
262
263 condition_size = sizeof(*condition_comm) +
264 (ssize_t) condition_comm->session_name_len;
265 ret = condition_size;
266end:
267 return ret;
268}
269
270static
271ssize_t lttng_condition_session_rotation_create_from_buffer(
272 const struct lttng_buffer_view *view,
273 struct lttng_condition **_condition,
274 enum lttng_condition_type type)
275{
276 ssize_t ret;
277 struct lttng_condition *condition = NULL;
278
279 switch (type) {
280 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
281 condition = lttng_condition_session_rotation_ongoing_create();
282 break;
283 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
284 condition = lttng_condition_session_rotation_completed_create();
285 break;
286 default:
287 ret = -1;
288 goto error;
289 }
290
291 if (!_condition || !condition) {
292 ret = -1;
293 goto error;
294 }
295
296 ret = init_condition_from_buffer(condition, view);
297 if (ret < 0) {
298 goto error;
299 }
300
301 *_condition = condition;
302 return ret;
303error:
304 lttng_condition_destroy(condition);
305 return ret;
306}
307
308LTTNG_HIDDEN
309ssize_t lttng_condition_session_rotation_ongoing_create_from_buffer(
310 const struct lttng_buffer_view *view,
311 struct lttng_condition **condition)
312{
313 return lttng_condition_session_rotation_create_from_buffer(view,
314 condition,
315 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
316}
317
318LTTNG_HIDDEN
319ssize_t lttng_condition_session_rotation_completed_create_from_buffer(
320 const struct lttng_buffer_view *view,
321 struct lttng_condition **condition)
322{
323 return lttng_condition_session_rotation_create_from_buffer(view,
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;
344 evaluation->location = location;
345 return &evaluation->parent;
346}
347
348static
349ssize_t create_evaluation_from_buffer(
350 enum lttng_condition_type type,
351 const struct lttng_buffer_view *view,
352 struct lttng_evaluation **_evaluation)
353{
354 ssize_t ret, size;
355 struct lttng_evaluation *evaluation = NULL;
356 struct lttng_trace_archive_location *location = NULL;
357 const struct lttng_evaluation_session_rotation_comm *comm =
358 (const struct lttng_evaluation_session_rotation_comm *) view->data;
359 struct lttng_buffer_view location_view;
360
361 if (view->size < sizeof(*comm)) {
362 goto error;
363 }
364
365 size = sizeof(*comm);
366 if (comm->has_location) {
367 location_view = lttng_buffer_view_from_view(view, sizeof(*comm),
368 -1);
369 if (!location_view.data) {
370 goto error;
371 }
372
373 ret = lttng_trace_archive_location_create_from_buffer(
374 &location_view, &location);
375 if (ret < 0) {
376 goto error;
377 }
378 size += ret;
379 }
380
381 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
382 location);
383 if (!evaluation) {
384 goto error;
385 }
386
387 ret = size;
388 *_evaluation = evaluation;
389 return ret;
390error:
391 lttng_trace_archive_location_destroy(location);
392 evaluation = NULL;
393 return -1;
394}
395
396static
397ssize_t lttng_evaluation_session_rotation_create_from_buffer(
398 enum lttng_condition_type type,
399 const struct lttng_buffer_view *view,
400 struct lttng_evaluation **_evaluation)
401{
402 ssize_t ret;
403 struct lttng_evaluation *evaluation = NULL;
404
405 if (!_evaluation) {
406 ret = -1;
407 goto error;
408 }
409
410 ret = create_evaluation_from_buffer(type, view, &evaluation);
411 if (ret < 0) {
412 goto error;
413 }
414
415 *_evaluation = evaluation;
416 return ret;
417error:
418 lttng_evaluation_destroy(evaluation);
419 return ret;
420}
421
422LTTNG_HIDDEN
423ssize_t lttng_evaluation_session_rotation_ongoing_create_from_buffer(
424 const struct lttng_buffer_view *view,
425 struct lttng_evaluation **evaluation)
426{
427 return lttng_evaluation_session_rotation_create_from_buffer(
428 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
429 view, evaluation);
430}
431
432LTTNG_HIDDEN
433ssize_t lttng_evaluation_session_rotation_completed_create_from_buffer(
434 const struct lttng_buffer_view *view,
435 struct lttng_evaluation **evaluation)
436{
437 return lttng_evaluation_session_rotation_create_from_buffer(
438 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
439 view, evaluation);
440}
441
442LTTNG_HIDDEN
443struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
444 uint64_t id)
445{
446 return lttng_evaluation_session_rotation_create(
447 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
448 NULL);
449}
450
451LTTNG_HIDDEN
452struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
453 uint64_t id, struct lttng_trace_archive_location *location)
454{
455 return lttng_evaluation_session_rotation_create(
456 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id,
457 location);
458}
459
460enum lttng_condition_status
461lttng_condition_session_rotation_get_session_name(
462 const struct lttng_condition *condition,
463 const char **session_name)
464{
465 struct lttng_condition_session_rotation *rotation;
466 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
467
468 if (!condition || !is_rotation_condition(condition) || !session_name) {
469 status = LTTNG_CONDITION_STATUS_INVALID;
470 goto end;
471 }
472
473 rotation = container_of(condition, struct lttng_condition_session_rotation,
474 parent);
475 if (!rotation->session_name) {
476 status = LTTNG_CONDITION_STATUS_UNSET;
477 goto end;
478 }
479 *session_name = rotation->session_name;
480end:
481 return status;
482}
483
484enum lttng_condition_status
485lttng_condition_session_rotation_set_session_name(
486 struct lttng_condition *condition, const char *session_name)
487{
488 char *session_name_copy;
489 struct lttng_condition_session_rotation *rotation;
490 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
491
492 if (!condition || !is_rotation_condition(condition) ||
493 !session_name || strlen(session_name) == 0) {
494 status = LTTNG_CONDITION_STATUS_INVALID;
495 goto end;
496 }
497
498 rotation = container_of(condition,
499 struct lttng_condition_session_rotation, parent);
500 session_name_copy = strdup(session_name);
501 if (!session_name_copy) {
502 status = LTTNG_CONDITION_STATUS_ERROR;
503 goto end;
504 }
505
506 free(rotation->session_name);
507 rotation->session_name = session_name_copy;
508end:
509 return status;
510}
511
512static
513int lttng_evaluation_session_rotation_serialize(
514 const struct lttng_evaluation *evaluation,
515 struct lttng_dynamic_buffer *buf)
516{
517 int ret;
518 struct lttng_evaluation_session_rotation *rotation;
519 struct lttng_evaluation_session_rotation_comm comm = { 0 };
520
521 rotation = container_of(evaluation,
522 struct lttng_evaluation_session_rotation, parent);
523 comm.id = rotation->id;
524 comm.has_location = !!rotation->location;
525 ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm));
526 if (ret) {
527 goto end;
528 }
529 if (!rotation->location) {
530 goto end;
531 }
532 ret = lttng_trace_archive_location_serialize(rotation->location,
533 buf);
534end:
535 return ret;
536}
537
538static
539void lttng_evaluation_session_rotation_destroy(
540 struct lttng_evaluation *evaluation)
541{
542 struct lttng_evaluation_session_rotation *rotation;
543
544 rotation = container_of(evaluation,
545 struct lttng_evaluation_session_rotation, parent);
546 lttng_trace_archive_location_destroy(rotation->location);
547 free(rotation);
548}
549
550enum lttng_evaluation_status
551lttng_evaluation_session_rotation_get_id(
552 const struct lttng_evaluation *evaluation, uint64_t *id)
553{
554 const struct lttng_evaluation_session_rotation *rotation;
555 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
556
557 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
558 status = LTTNG_EVALUATION_STATUS_INVALID;
559 goto end;
560 }
561
562 rotation = container_of(evaluation,
563 struct lttng_evaluation_session_rotation, parent);
564 *id = rotation->id;
565end:
566 return status;
567}
568
569enum lttng_evaluation_status
570lttng_evaluation_session_rotation_completed_get_location(
571 const struct lttng_evaluation *evaluation,
572 const struct lttng_trace_archive_location **location)
573{
574 const struct lttng_evaluation_session_rotation *rotation;
575 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
576
577 if (!evaluation || !location ||
578 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
579 status = LTTNG_EVALUATION_STATUS_INVALID;
580 goto end;
581 }
582
583 rotation = container_of(evaluation,
584 struct lttng_evaluation_session_rotation, parent);
585 *location = rotation->location;
586end:
587 return status;
588}
This page took 0.055662 seconds and 5 git commands to generate.