Fix: relayd control socket mutex is not destroyed
[lttng-tools.git] / src / common / session-rotation.c
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
26 static
27 bool lttng_condition_session_rotation_validate(
28 const struct lttng_condition *condition);
29 static
30 int lttng_condition_session_rotation_serialize(
31 const struct lttng_condition *condition,
32 struct lttng_dynamic_buffer *buf);
33 static
34 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
35 const struct lttng_condition *_b);
36 static
37 void lttng_condition_session_rotation_destroy(
38 struct lttng_condition *condition);
39
40 static const
41 struct 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
49 static
50 int lttng_evaluation_session_rotation_serialize(
51 const struct lttng_evaluation *evaluation,
52 struct lttng_dynamic_buffer *buf);
53 static
54 void lttng_evaluation_session_rotation_destroy(
55 struct lttng_evaluation *evaluation);
56
57 static const
58 struct 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
64 static
65 bool 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
73 static
74 bool 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
82 static
83 bool 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;
101 end:
102 return valid;
103 }
104
105 static
106 int 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 }
141 end:
142 return ret;
143 }
144
145 static
146 bool 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;
168 end:
169 return is_equal;
170 }
171
172 static
173 void 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
185 static
186 struct 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,
197 sizeof(condition->parent));
198 lttng_condition_init(&condition->parent, type);
199 return &condition->parent;
200 }
201
202 struct 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
208 struct 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
214 static
215 ssize_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;
269 end:
270 return ret;
271 }
272
273 static
274 ssize_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;
306 error:
307 lttng_condition_destroy(condition);
308 return ret;
309 }
310
311 LTTNG_HIDDEN
312 ssize_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
321 LTTNG_HIDDEN
322 ssize_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
331 static
332 struct 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,
344 sizeof(evaluation->parent));
345 lttng_evaluation_init(&evaluation->parent, type);
346 evaluation->id = id;
347 evaluation->location = location;
348 return &evaluation->parent;
349 }
350
351 static
352 ssize_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;
393 error:
394 lttng_trace_archive_location_destroy(location);
395 evaluation = NULL;
396 return -1;
397 }
398
399 static
400 ssize_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;
420 error:
421 lttng_evaluation_destroy(evaluation);
422 return ret;
423 }
424
425 LTTNG_HIDDEN
426 ssize_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
435 LTTNG_HIDDEN
436 ssize_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
445 LTTNG_HIDDEN
446 struct 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
454 LTTNG_HIDDEN
455 struct 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
463 enum lttng_condition_status
464 lttng_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;
483 end:
484 return status;
485 }
486
487 enum lttng_condition_status
488 lttng_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;
511 end:
512 return status;
513 }
514
515 static
516 int 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);
537 end:
538 return ret;
539 }
540
541 static
542 void 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
553 enum lttng_evaluation_status
554 lttng_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;
568 end:
569 return status;
570 }
571
572 enum lttng_evaluation_status
573 lttng_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;
589 end:
590 return status;
591 }
This page took 0.042875 seconds and 4 git commands to generate.