SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / common / conditions / session-rotation.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
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
16 static
17 bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition *condition);
19 static
20 int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition *condition,
22 struct lttng_dynamic_buffer *buf,
23 int *fd_to_send);
24 static
25 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
26 const struct lttng_condition *_b);
27 static
28 void lttng_condition_session_rotation_destroy(
29 struct lttng_condition *condition);
30
31 static const
32 struct 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
40 static
41 int lttng_evaluation_session_rotation_serialize(
42 const struct lttng_evaluation *evaluation,
43 struct lttng_dynamic_buffer *buf);
44 static
45 void lttng_evaluation_session_rotation_destroy(
46 struct lttng_evaluation *evaluation);
47
48 static const
49 struct 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
55 static
56 bool 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
64 static
65 bool 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
73 static
74 bool 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;
92 end:
93 return valid;
94 }
95
96 static
97 int lttng_condition_session_rotation_serialize(
98 const struct lttng_condition *condition,
99 struct lttng_dynamic_buffer *buf,
100 int *fd_to_send)
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 }
133
134 if (fd_to_send) {
135 /* No fd to send */
136 *fd_to_send = -1;
137 }
138 end:
139 return ret;
140 }
141
142 static
143 bool 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;
165 end:
166 return is_equal;
167 }
168
169 static
170 void 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
182 static
183 struct 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,
194 sizeof(condition->parent));
195 lttng_condition_init(&condition->parent, type);
196 return &condition->parent;
197 }
198
199 struct 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
205 struct 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
211 static
212 ssize_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;
266 end:
267 return ret;
268 }
269
270 static
271 ssize_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;
303 error:
304 lttng_condition_destroy(condition);
305 return ret;
306 }
307
308 LTTNG_HIDDEN
309 ssize_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
318 LTTNG_HIDDEN
319 ssize_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
328 static
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)
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,
341 sizeof(evaluation->parent));
342 lttng_evaluation_init(&evaluation->parent, type);
343 evaluation->id = id;
344 evaluation->location = location;
345 return &evaluation->parent;
346 }
347
348 static
349 ssize_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;
390 error:
391 lttng_trace_archive_location_destroy(location);
392 evaluation = NULL;
393 return -1;
394 }
395
396 static
397 ssize_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;
417 error:
418 lttng_evaluation_destroy(evaluation);
419 return ret;
420 }
421
422 LTTNG_HIDDEN
423 ssize_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
432 LTTNG_HIDDEN
433 ssize_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
442 LTTNG_HIDDEN
443 struct 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
451 LTTNG_HIDDEN
452 struct 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
460 enum lttng_condition_status
461 lttng_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;
480 end:
481 return status;
482 }
483
484 enum lttng_condition_status
485 lttng_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;
508 end:
509 return status;
510 }
511
512 static
513 int 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);
534 end:
535 return ret;
536 }
537
538 static
539 void 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
550 enum lttng_evaluation_status
551 lttng_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;
565 end:
566 return status;
567 }
568
569 enum lttng_evaluation_status
570 lttng_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;
586 end:
587 return status;
588 }
This page took 0.041368 seconds and 5 git commands to generate.