f8d4439de06056296e1a2bc269bc37b6b0385c22
[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_dynamic_buffer *buf);
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_dynamic_buffer *buf);
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_dynamic_buffer *buf)
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(buf, &rotation_comm,
122 sizeof(rotation_comm));
123 if (ret) {
124 goto end;
125 }
126 ret = lttng_dynamic_buffer_append(buf, rotation->session_name,
127 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_buffer(struct lttng_condition *condition,
206 const struct lttng_buffer_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->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 = (const struct lttng_condition_session_rotation_comm *) src_view->data;
221 name_view = lttng_buffer_view_from_view(src_view,
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_buffer(
265 const struct lttng_buffer_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_buffer(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_buffer(
303 const struct lttng_buffer_view *view,
304 struct lttng_condition **condition)
305 {
306 return lttng_condition_session_rotation_create_from_buffer(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_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_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_buffer(
343 enum lttng_condition_type type,
344 const struct lttng_buffer_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 (const struct lttng_evaluation_session_rotation_comm *) view->data;
352 struct lttng_buffer_view location_view;
353
354 if (view->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(view, sizeof(*comm),
361 -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_buffer(
391 enum lttng_condition_type type,
392 const struct lttng_buffer_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_buffer(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_buffer(
417 const struct lttng_buffer_view *view,
418 struct lttng_evaluation **evaluation)
419 {
420 return lttng_evaluation_session_rotation_create_from_buffer(
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_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_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_dynamic_buffer *buf)
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(buf, &comm, sizeof(comm));
519 if (ret) {
520 goto end;
521 }
522 if (!rotation->location) {
523 goto end;
524 }
525 ret = lttng_trace_archive_location_serialize(rotation->location,
526 buf);
527 end:
528 return ret;
529 }
530
531 static
532 void lttng_evaluation_session_rotation_destroy(
533 struct lttng_evaluation *evaluation)
534 {
535 struct lttng_evaluation_session_rotation *rotation;
536
537 rotation = container_of(evaluation,
538 struct lttng_evaluation_session_rotation, parent);
539 lttng_trace_archive_location_destroy(rotation->location);
540 free(rotation);
541 }
542
543 enum lttng_evaluation_status
544 lttng_evaluation_session_rotation_get_id(
545 const struct lttng_evaluation *evaluation, uint64_t *id)
546 {
547 const struct lttng_evaluation_session_rotation *rotation;
548 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
549
550 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
551 status = LTTNG_EVALUATION_STATUS_INVALID;
552 goto end;
553 }
554
555 rotation = container_of(evaluation,
556 struct lttng_evaluation_session_rotation, parent);
557 *id = rotation->id;
558 end:
559 return status;
560 }
561
562 enum lttng_evaluation_status
563 lttng_evaluation_session_rotation_completed_get_location(
564 const struct lttng_evaluation *evaluation,
565 const struct lttng_trace_archive_location **location)
566 {
567 const struct lttng_evaluation_session_rotation *rotation;
568 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
569
570 if (!evaluation || !location ||
571 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
572 status = LTTNG_EVALUATION_STATUS_INVALID;
573 goto end;
574 }
575
576 rotation = container_of(evaluation,
577 struct lttng_evaluation_session_rotation, parent);
578 *location = rotation->location;
579 end:
580 return status;
581 }
This page took 0.060214 seconds and 3 git commands to generate.