Fix: kconsumer: missing wait for metadata thread in do_sync_metadata
[lttng-tools.git] / src / common / 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_payload *payload);
23 static
24 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
25 const struct lttng_condition *_b);
26 static
27 void lttng_condition_session_rotation_destroy(
28 struct lttng_condition *condition);
29
30 static const
31 struct lttng_condition rotation_condition_template = {
32 /* .type omitted; shall be set on creation. */
33 .validate = lttng_condition_session_rotation_validate,
34 .serialize = lttng_condition_session_rotation_serialize,
35 .equal = lttng_condition_session_rotation_is_equal,
36 .destroy = lttng_condition_session_rotation_destroy,
37 };
38
39 static
40 int lttng_evaluation_session_rotation_serialize(
41 const struct lttng_evaluation *evaluation,
42 struct lttng_payload *payload);
43 static
44 void lttng_evaluation_session_rotation_destroy(
45 struct lttng_evaluation *evaluation);
46
47 static const
48 struct lttng_evaluation rotation_evaluation_template = {
49 /* .type omitted; shall be set on creation. */
50 .serialize = lttng_evaluation_session_rotation_serialize,
51 .destroy = lttng_evaluation_session_rotation_destroy,
52 };
53
54 static
55 bool is_rotation_condition(const struct lttng_condition *condition)
56 {
57 enum lttng_condition_type type = lttng_condition_get_type(condition);
58
59 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
60 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
61 }
62
63 static
64 bool is_rotation_evaluation(const struct lttng_evaluation *evaluation)
65 {
66 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
67
68 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
69 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
70 }
71
72 static
73 bool lttng_condition_session_rotation_validate(
74 const struct lttng_condition *condition)
75 {
76 bool valid = false;
77 struct lttng_condition_session_rotation *rotation;
78
79 if (!condition) {
80 goto end;
81 }
82
83 rotation = container_of(condition,
84 struct lttng_condition_session_rotation, parent);
85 if (!rotation->session_name) {
86 ERR("Invalid session rotation condition: a target session name must be set.");
87 goto end;
88 }
89
90 valid = true;
91 end:
92 return valid;
93 }
94
95 static
96 int lttng_condition_session_rotation_serialize(
97 const struct lttng_condition *condition,
98 struct lttng_payload *payload)
99 {
100 int ret;
101 size_t session_name_len;
102 struct lttng_condition_session_rotation *rotation;
103 struct lttng_condition_session_rotation_comm rotation_comm;
104
105 if (!condition || !is_rotation_condition(condition)) {
106 ret = -1;
107 goto end;
108 }
109
110 DBG("Serializing session rotation condition");
111 rotation = container_of(condition, struct lttng_condition_session_rotation,
112 parent);
113
114 session_name_len = strlen(rotation->session_name) + 1;
115 if (session_name_len > LTTNG_NAME_MAX) {
116 ret = -1;
117 goto end;
118 }
119
120 rotation_comm.session_name_len = session_name_len;
121 ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm,
122 sizeof(rotation_comm));
123 if (ret) {
124 goto end;
125 }
126 ret = lttng_dynamic_buffer_append(&payload->buffer,
127 rotation->session_name, session_name_len);
128 if (ret) {
129 goto end;
130 }
131 end:
132 return ret;
133 }
134
135 static
136 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
137 const struct lttng_condition *_b)
138 {
139 bool is_equal = false;
140 struct lttng_condition_session_rotation *a, *b;
141
142 a = container_of(_a, struct lttng_condition_session_rotation, parent);
143 b = container_of(_b, struct lttng_condition_session_rotation, parent);
144
145 /* Both session names must be set or both must be unset. */
146 if ((a->session_name && !b->session_name) ||
147 (!a->session_name && b->session_name)) {
148 WARN("Comparing session rotation conditions with uninitialized session names.");
149 goto end;
150 }
151
152 if (a->session_name && b->session_name &&
153 strcmp(a->session_name, b->session_name)) {
154 goto end;
155 }
156
157 is_equal = true;
158 end:
159 return is_equal;
160 }
161
162 static
163 void lttng_condition_session_rotation_destroy(
164 struct lttng_condition *condition)
165 {
166 struct lttng_condition_session_rotation *rotation;
167
168 rotation = container_of(condition,
169 struct lttng_condition_session_rotation, parent);
170
171 free(rotation->session_name);
172 free(rotation);
173 }
174
175 static
176 struct lttng_condition *lttng_condition_session_rotation_create(
177 enum lttng_condition_type type)
178 {
179 struct lttng_condition_session_rotation *condition;
180
181 condition = zmalloc(sizeof(struct lttng_condition_session_rotation));
182 if (!condition) {
183 return NULL;
184 }
185
186 memcpy(&condition->parent, &rotation_condition_template,
187 sizeof(condition->parent));
188 lttng_condition_init(&condition->parent, type);
189 return &condition->parent;
190 }
191
192 struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void)
193 {
194 return lttng_condition_session_rotation_create(
195 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
196 }
197
198 struct lttng_condition *lttng_condition_session_rotation_completed_create(void)
199 {
200 return lttng_condition_session_rotation_create(
201 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
202 }
203
204 static
205 ssize_t init_condition_from_payload(struct lttng_condition *condition,
206 struct lttng_payload_view *src_view)
207 {
208 ssize_t ret, condition_size;
209 enum lttng_condition_status status;
210 const struct lttng_condition_session_rotation_comm *condition_comm;
211 const char *session_name;
212 struct lttng_buffer_view name_view;
213
214 if (src_view->buffer.size < sizeof(*condition_comm)) {
215 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
216 ret = -1;
217 goto end;
218 }
219
220 condition_comm = (typeof(condition_comm)) src_view->buffer.data;
221 name_view = lttng_buffer_view_from_view(&src_view->buffer,
222 sizeof(*condition_comm), -1);
223
224 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
225 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
226 ret = -1;
227 goto end;
228 }
229
230 if (name_view.size < condition_comm->session_name_len) {
231 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
232 ret = -1;
233 goto end;
234 }
235
236 session_name = name_view.data;
237 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
238 ERR("Malformed session name encountered in condition buffer");
239 ret = -1;
240 goto end;
241 }
242
243 status = lttng_condition_session_rotation_set_session_name(condition,
244 session_name);
245 if (status != LTTNG_CONDITION_STATUS_OK) {
246 ERR("Failed to set buffer consumed session name");
247 ret = -1;
248 goto end;
249 }
250
251 if (!lttng_condition_validate(condition)) {
252 ret = -1;
253 goto end;
254 }
255
256 condition_size = sizeof(*condition_comm) +
257 (ssize_t) condition_comm->session_name_len;
258 ret = condition_size;
259 end:
260 return ret;
261 }
262
263 static
264 ssize_t lttng_condition_session_rotation_create_from_payload(
265 struct lttng_payload_view *view,
266 struct lttng_condition **_condition,
267 enum lttng_condition_type type)
268 {
269 ssize_t ret;
270 struct lttng_condition *condition = NULL;
271
272 switch (type) {
273 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
274 condition = lttng_condition_session_rotation_ongoing_create();
275 break;
276 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
277 condition = lttng_condition_session_rotation_completed_create();
278 break;
279 default:
280 ret = -1;
281 goto error;
282 }
283
284 if (!_condition || !condition) {
285 ret = -1;
286 goto error;
287 }
288
289 ret = init_condition_from_payload(condition, view);
290 if (ret < 0) {
291 goto error;
292 }
293
294 *_condition = condition;
295 return ret;
296 error:
297 lttng_condition_destroy(condition);
298 return ret;
299 }
300
301 LTTNG_HIDDEN
302 ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
303 struct lttng_payload_view *view,
304 struct lttng_condition **condition)
305 {
306 return lttng_condition_session_rotation_create_from_payload(view,
307 condition,
308 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
309 }
310
311 LTTNG_HIDDEN
312 ssize_t lttng_condition_session_rotation_completed_create_from_payload(
313 struct lttng_payload_view *view,
314 struct lttng_condition **condition)
315 {
316 return lttng_condition_session_rotation_create_from_payload(view,
317 condition,
318 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
319 }
320
321 static
322 struct lttng_evaluation *lttng_evaluation_session_rotation_create(
323 enum lttng_condition_type type, uint64_t id,
324 struct lttng_trace_archive_location *location)
325 {
326 struct lttng_evaluation_session_rotation *evaluation;
327
328 evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation));
329 if (!evaluation) {
330 return NULL;
331 }
332
333 memcpy(&evaluation->parent, &rotation_evaluation_template,
334 sizeof(evaluation->parent));
335 lttng_evaluation_init(&evaluation->parent, type);
336 evaluation->id = id;
337 evaluation->location = location;
338 return &evaluation->parent;
339 }
340
341 static
342 ssize_t create_evaluation_from_payload(
343 enum lttng_condition_type type,
344 struct lttng_payload_view *view,
345 struct lttng_evaluation **_evaluation)
346 {
347 ssize_t ret, size;
348 struct lttng_evaluation *evaluation = NULL;
349 struct lttng_trace_archive_location *location = NULL;
350 const struct lttng_evaluation_session_rotation_comm *comm =
351 (typeof(comm)) view->buffer.data;
352 struct lttng_buffer_view location_view;
353
354 if (view->buffer.size < sizeof(*comm)) {
355 goto error;
356 }
357
358 size = sizeof(*comm);
359 if (comm->has_location) {
360 location_view = lttng_buffer_view_from_view(
361 &view->buffer, sizeof(*comm), -1);
362 if (!location_view.data) {
363 goto error;
364 }
365
366 ret = lttng_trace_archive_location_create_from_buffer(
367 &location_view, &location);
368 if (ret < 0) {
369 goto error;
370 }
371 size += ret;
372 }
373
374 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
375 location);
376 if (!evaluation) {
377 goto error;
378 }
379
380 ret = size;
381 *_evaluation = evaluation;
382 return ret;
383 error:
384 lttng_trace_archive_location_destroy(location);
385 evaluation = NULL;
386 return -1;
387 }
388
389 static
390 ssize_t lttng_evaluation_session_rotation_create_from_payload(
391 enum lttng_condition_type type,
392 struct lttng_payload_view *view,
393 struct lttng_evaluation **_evaluation)
394 {
395 ssize_t ret;
396 struct lttng_evaluation *evaluation = NULL;
397
398 if (!_evaluation) {
399 ret = -1;
400 goto error;
401 }
402
403 ret = create_evaluation_from_payload(type, view, &evaluation);
404 if (ret < 0) {
405 goto error;
406 }
407
408 *_evaluation = evaluation;
409 return ret;
410 error:
411 lttng_evaluation_destroy(evaluation);
412 return ret;
413 }
414
415 LTTNG_HIDDEN
416 ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
417 struct lttng_payload_view *view,
418 struct lttng_evaluation **evaluation)
419 {
420 return lttng_evaluation_session_rotation_create_from_payload(
421 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
422 view, evaluation);
423 }
424
425 LTTNG_HIDDEN
426 ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
427 struct lttng_payload_view *view,
428 struct lttng_evaluation **evaluation)
429 {
430 return lttng_evaluation_session_rotation_create_from_payload(
431 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
432 view, evaluation);
433 }
434
435 LTTNG_HIDDEN
436 struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
437 uint64_t id)
438 {
439 return lttng_evaluation_session_rotation_create(
440 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
441 NULL);
442 }
443
444 LTTNG_HIDDEN
445 struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
446 uint64_t id, struct lttng_trace_archive_location *location)
447 {
448 return lttng_evaluation_session_rotation_create(
449 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id,
450 location);
451 }
452
453 enum lttng_condition_status
454 lttng_condition_session_rotation_get_session_name(
455 const struct lttng_condition *condition,
456 const char **session_name)
457 {
458 struct lttng_condition_session_rotation *rotation;
459 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
460
461 if (!condition || !is_rotation_condition(condition) || !session_name) {
462 status = LTTNG_CONDITION_STATUS_INVALID;
463 goto end;
464 }
465
466 rotation = container_of(condition, struct lttng_condition_session_rotation,
467 parent);
468 if (!rotation->session_name) {
469 status = LTTNG_CONDITION_STATUS_UNSET;
470 goto end;
471 }
472 *session_name = rotation->session_name;
473 end:
474 return status;
475 }
476
477 enum lttng_condition_status
478 lttng_condition_session_rotation_set_session_name(
479 struct lttng_condition *condition, const char *session_name)
480 {
481 char *session_name_copy;
482 struct lttng_condition_session_rotation *rotation;
483 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
484
485 if (!condition || !is_rotation_condition(condition) ||
486 !session_name || strlen(session_name) == 0) {
487 status = LTTNG_CONDITION_STATUS_INVALID;
488 goto end;
489 }
490
491 rotation = container_of(condition,
492 struct lttng_condition_session_rotation, parent);
493 session_name_copy = strdup(session_name);
494 if (!session_name_copy) {
495 status = LTTNG_CONDITION_STATUS_ERROR;
496 goto end;
497 }
498
499 free(rotation->session_name);
500 rotation->session_name = session_name_copy;
501 end:
502 return status;
503 }
504
505 static
506 int lttng_evaluation_session_rotation_serialize(
507 const struct lttng_evaluation *evaluation,
508 struct lttng_payload *payload)
509 {
510 int ret;
511 struct lttng_evaluation_session_rotation *rotation;
512 struct lttng_evaluation_session_rotation_comm comm = { 0 };
513
514 rotation = container_of(evaluation,
515 struct lttng_evaluation_session_rotation, parent);
516 comm.id = rotation->id;
517 comm.has_location = !!rotation->location;
518 ret = lttng_dynamic_buffer_append(
519 &payload->buffer, &comm, sizeof(comm));
520 if (ret) {
521 goto end;
522 }
523 if (!rotation->location) {
524 goto end;
525 }
526 ret = lttng_trace_archive_location_serialize(rotation->location,
527 &payload->buffer);
528 end:
529 return ret;
530 }
531
532 static
533 void lttng_evaluation_session_rotation_destroy(
534 struct lttng_evaluation *evaluation)
535 {
536 struct lttng_evaluation_session_rotation *rotation;
537
538 rotation = container_of(evaluation,
539 struct lttng_evaluation_session_rotation, parent);
540 lttng_trace_archive_location_destroy(rotation->location);
541 free(rotation);
542 }
543
544 enum lttng_evaluation_status
545 lttng_evaluation_session_rotation_get_id(
546 const struct lttng_evaluation *evaluation, uint64_t *id)
547 {
548 const struct lttng_evaluation_session_rotation *rotation;
549 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
550
551 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
552 status = LTTNG_EVALUATION_STATUS_INVALID;
553 goto end;
554 }
555
556 rotation = container_of(evaluation,
557 struct lttng_evaluation_session_rotation, parent);
558 *id = rotation->id;
559 end:
560 return status;
561 }
562
563 enum lttng_evaluation_status
564 lttng_evaluation_session_rotation_completed_get_location(
565 const struct lttng_evaluation *evaluation,
566 const struct lttng_trace_archive_location **location)
567 {
568 const struct lttng_evaluation_session_rotation *rotation;
569 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
570
571 if (!evaluation || !location ||
572 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
573 status = LTTNG_EVALUATION_STATUS_INVALID;
574 goto end;
575 }
576
577 rotation = container_of(evaluation,
578 struct lttng_evaluation_session_rotation, parent);
579 *location = rotation->location;
580 end:
581 return status;
582 }
This page took 0.043177 seconds and 4 git commands to generate.