Build fix: specialization of template in different namespace
[lttng-tools.git] / src / common / session-descriptor.cpp
1 /*
2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 */
6
7 #include <lttng/session-descriptor-internal.hpp>
8 #include <common/macros.hpp>
9 #include <common/uri.hpp>
10 #include <common/defaults.hpp>
11 #include <common/error.hpp>
12 #include <time.h>
13 #include <stdio.h>
14
15 namespace {
16 struct lttng_session_descriptor_network_location {
17 struct lttng_uri *control;
18 struct lttng_uri *data;
19 };
20 } /* namespace */
21
22 struct lttng_session_descriptor {
23 enum lttng_session_descriptor_type type;
24 /*
25 * If an output type that is not OUTPUT_TYPE_NONE is specified,
26 * it means that an output of that type must be generated at
27 * session-creation time.
28 */
29 enum lttng_session_descriptor_output_type output_type;
30 char *name;
31 union {
32 struct lttng_session_descriptor_network_location network;
33 struct lttng_uri *local;
34 } output;
35 };
36
37 namespace {
38 struct lttng_session_descriptor_snapshot {
39 struct lttng_session_descriptor base;
40 /*
41 * Assumes at-most one snapshot output is supported. Uses
42 * the output field of the base class.
43 */
44 };
45
46 struct lttng_session_descriptor_live {
47 struct lttng_session_descriptor base;
48 unsigned long long live_timer_us;
49 };
50
51 struct lttng_session_descriptor_comm {
52 /* enum lttng_session_descriptor_type */
53 uint8_t type;
54 /* enum lttng_session_descriptor_output_type */
55 uint8_t output_type;
56 /* Includes trailing null. */
57 uint32_t name_len;
58 /* Name follows, followed by URIs */
59 uint8_t uri_count;
60 } LTTNG_PACKED;
61
62 struct lttng_session_descriptor_live_comm {
63 struct lttng_session_descriptor_comm base;
64 /* Live-specific parameters. */
65 uint64_t live_timer_us;
66 } LTTNG_PACKED;
67 } /* namespace */
68
69 static
70 struct lttng_uri *uri_copy(const struct lttng_uri *uri)
71 {
72 struct lttng_uri *new_uri = NULL;
73
74 if (!uri) {
75 goto end;
76 }
77
78 new_uri = zmalloc<lttng_uri>();
79 if (!new_uri) {
80 goto end;
81 }
82 memcpy(new_uri, uri, sizeof(*new_uri));
83 end:
84 return new_uri;
85 }
86
87 static
88 struct lttng_uri *uri_from_path(const char *path)
89 {
90 struct lttng_uri *uris = NULL;
91 ssize_t uri_count;
92 char local_protocol_string[LTTNG_PATH_MAX + sizeof("file://")] =
93 "file://";
94
95 if (strlen(path) >= LTTNG_PATH_MAX) {
96 goto end;
97 }
98
99 if (path[0] != '/') {
100 /* Not an absolute path. */
101 goto end;
102 }
103
104 strncat(local_protocol_string, path, LTTNG_PATH_MAX);
105 uri_count = uri_parse(local_protocol_string, &uris);
106 if (uri_count != 1) {
107 goto error;
108 }
109 if (uris[0].dtype != LTTNG_DST_PATH) {
110 goto error;
111 }
112
113 end:
114 return uris;
115 error:
116 free(uris);
117 return NULL;
118 }
119
120 static
121 void network_location_fini(
122 struct lttng_session_descriptor_network_location *location)
123 {
124 free(location->control);
125 free(location->data);
126 }
127
128 /* Assumes ownership of control and data. */
129 static
130 int network_location_set_from_lttng_uris(
131 struct lttng_session_descriptor_network_location *location,
132 struct lttng_uri *control, struct lttng_uri *data)
133 {
134 int ret = 0;
135
136 if (!control && !data) {
137 goto end;
138 }
139
140 if (!(control && data)) {
141 /* None or both must be set. */
142 ret = -1;
143 goto end;
144 }
145
146 if (control->stype != LTTNG_STREAM_CONTROL ||
147 data->stype != LTTNG_STREAM_DATA) {
148 ret = -1;
149 goto end;
150 }
151
152 free(location->control);
153 free(location->data);
154 location->control = control;
155 location->data = data;
156 control = NULL;
157 data = NULL;
158 end:
159 free(control);
160 free(data);
161 return ret;
162 }
163
164 static
165 int network_location_set_from_uri_strings(
166 struct lttng_session_descriptor_network_location *location,
167 const char *control, const char *data)
168 {
169 int ret = 0;
170 ssize_t uri_count;
171 struct lttng_uri *parsed_uris = NULL;
172 struct lttng_uri *control_uri = NULL;
173 struct lttng_uri *data_uri = NULL;
174
175 uri_count = uri_parse_str_urls(control, data, &parsed_uris);
176 if (uri_count != 2 && uri_count != 0) {
177 ret = -1;
178 goto end;
179 }
180
181 /*
182 * uri_parse_str_urls returns a contiguous array of lttng_uris whereas
183 * session descriptors expect individually allocated lttng_uris.
184 */
185 if (uri_count == 2) {
186 control_uri = zmalloc<lttng_uri>();
187 data_uri = zmalloc<lttng_uri>();
188 if (!control_uri || !data_uri) {
189 ret = -1;
190 goto end;
191 }
192 memcpy(control_uri, &parsed_uris[0], sizeof(*control_uri));
193 memcpy(data_uri, &parsed_uris[1], sizeof(*data_uri));
194 }
195
196 /* Ownership of control and data uris is transferred. */
197 ret = network_location_set_from_lttng_uris(
198 location,
199 control_uri,
200 data_uri);
201 control_uri = NULL;
202 data_uri = NULL;
203 end:
204 free(parsed_uris);
205 free(control_uri);
206 free(data_uri);
207 return ret;
208 }
209
210 struct lttng_session_descriptor *
211 lttng_session_descriptor_create(const char *name)
212 {
213 struct lttng_session_descriptor *descriptor;
214
215 descriptor = zmalloc<lttng_session_descriptor>();
216 if (!descriptor) {
217 goto error;
218 }
219
220 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
221 descriptor->output_type =
222 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
223 if (lttng_session_descriptor_set_session_name(descriptor, name)) {
224 goto error;
225 }
226 return descriptor;
227 error:
228 lttng_session_descriptor_destroy(descriptor);
229 return NULL;
230 }
231
232 /* Ownership of uri is transferred. */
233 static
234 struct lttng_session_descriptor *
235 _lttng_session_descriptor_local_create(const char *name,
236 struct lttng_uri *uri)
237 {
238 struct lttng_session_descriptor *descriptor;
239
240 descriptor = lttng_session_descriptor_create(name);
241 if (!descriptor) {
242 goto error;
243 }
244 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
245 descriptor->output_type =
246 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
247 if (uri) {
248 if (uri->dtype != LTTNG_DST_PATH) {
249 goto error;
250 }
251 descriptor->output.local = uri;
252 uri = NULL;
253 }
254 return descriptor;
255 error:
256 free(uri);
257 lttng_session_descriptor_destroy(descriptor);
258 return NULL;
259 }
260
261 struct lttng_session_descriptor *
262 lttng_session_descriptor_local_create(const char *name, const char *path)
263 {
264 struct lttng_uri *uri = NULL;
265 struct lttng_session_descriptor *descriptor;
266
267 if (path) {
268 uri = uri_from_path(path);
269 if (!uri) {
270 goto error;
271 }
272 }
273 descriptor = _lttng_session_descriptor_local_create(name, uri);
274 return descriptor;
275 error:
276 return NULL;
277 }
278
279 /* Assumes the ownership of both uris. */
280 static
281 struct lttng_session_descriptor *
282 _lttng_session_descriptor_network_create(const char *name,
283 struct lttng_uri *control, struct lttng_uri *data)
284 {
285 int ret;
286 struct lttng_session_descriptor *descriptor;
287
288 descriptor = lttng_session_descriptor_create(name);
289 if (!descriptor) {
290 goto error;
291 }
292
293 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
294 descriptor->output_type = LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
295 /* Assumes the ownership of both uris. */
296 ret = network_location_set_from_lttng_uris(&descriptor->output.network,
297 control, data);
298 control = NULL;
299 data = NULL;
300 if (ret) {
301 goto error;
302 }
303 return descriptor;
304 error:
305 lttng_session_descriptor_destroy(descriptor);
306 free(control);
307 free(data);
308 return NULL;
309 }
310
311 struct lttng_session_descriptor *
312 lttng_session_descriptor_network_create(const char *name,
313 const char *control_url, const char *data_url)
314 {
315 int ret;
316 struct lttng_session_descriptor *descriptor;
317
318 descriptor = _lttng_session_descriptor_network_create(name,
319 NULL, NULL);
320 if (!descriptor) {
321 goto error;
322 }
323
324 ret = network_location_set_from_uri_strings(&descriptor->output.network,
325 control_url, data_url);
326 if (ret) {
327 goto error;
328 }
329 return descriptor;
330 error:
331 lttng_session_descriptor_destroy(descriptor);
332 return NULL;
333 }
334
335 static
336 struct lttng_session_descriptor_snapshot *
337 _lttng_session_descriptor_snapshot_create(const char *name)
338 {
339 struct lttng_session_descriptor_snapshot *descriptor;
340
341 descriptor = zmalloc<lttng_session_descriptor_snapshot>();
342 if (!descriptor) {
343 goto error;
344 }
345
346 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT;
347 descriptor->base.output_type =
348 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
349 if (lttng_session_descriptor_set_session_name(&descriptor->base,
350 name)) {
351 goto error;
352 }
353 return descriptor;
354 error:
355 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
356 return NULL;
357 }
358
359 /* Ownership of control and data is transferred. */
360 static
361 struct lttng_session_descriptor_snapshot *
362 _lttng_session_descriptor_snapshot_network_create(const char *name,
363 struct lttng_uri *control, struct lttng_uri *data)
364 {
365 int ret;
366 struct lttng_session_descriptor_snapshot *descriptor;
367
368 descriptor = _lttng_session_descriptor_snapshot_create(name);
369 if (!descriptor) {
370 goto error;
371 }
372
373 descriptor->base.output_type =
374 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
375 /* Ownership of control and data is transferred. */
376 ret = network_location_set_from_lttng_uris(
377 &descriptor->base.output.network,
378 control, data);
379 control = NULL;
380 data = NULL;
381 if (ret) {
382 goto error;
383 }
384 return descriptor;
385 error:
386 free(control);
387 free(data);
388 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
389 return NULL;
390 }
391
392 struct lttng_session_descriptor *
393 lttng_session_descriptor_snapshot_create(const char *name)
394 {
395 struct lttng_session_descriptor_snapshot *descriptor;
396
397 descriptor = _lttng_session_descriptor_snapshot_create(name);
398 return descriptor ? &descriptor->base : NULL;
399 }
400
401 struct lttng_session_descriptor *
402 lttng_session_descriptor_snapshot_network_create(const char *name,
403 const char *control_url, const char *data_url)
404 {
405 int ret;
406 struct lttng_session_descriptor_snapshot *descriptor;
407
408 descriptor = _lttng_session_descriptor_snapshot_network_create(name,
409 NULL, NULL);
410 if (!descriptor) {
411 goto error;
412 }
413
414 ret = network_location_set_from_uri_strings(
415 &descriptor->base.output.network,
416 control_url, data_url);
417 if (ret) {
418 goto error;
419 }
420 return &descriptor->base;
421 error:
422 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
423 return NULL;
424 }
425
426 /* Ownership of uri is transferred. */
427 static
428 struct lttng_session_descriptor_snapshot *
429 _lttng_session_descriptor_snapshot_local_create(const char *name,
430 struct lttng_uri *uri)
431 {
432 struct lttng_session_descriptor_snapshot *descriptor;
433
434 descriptor = _lttng_session_descriptor_snapshot_create(name);
435 if (!descriptor) {
436 goto error;
437 }
438 descriptor->base.output_type =
439 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
440 if (uri) {
441 if (uri->dtype != LTTNG_DST_PATH) {
442 goto error;
443 }
444 descriptor->base.output.local = uri;
445 uri = NULL;
446 }
447 return descriptor;
448 error:
449 free(uri);
450 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
451 return NULL;
452 }
453
454 struct lttng_session_descriptor *
455 lttng_session_descriptor_snapshot_local_create(const char *name,
456 const char *path)
457 {
458 struct lttng_uri *path_uri = NULL;
459 struct lttng_session_descriptor_snapshot *descriptor;
460
461 if (path) {
462 path_uri = uri_from_path(path);
463 if (!path_uri) {
464 goto error;
465 }
466 }
467 descriptor = _lttng_session_descriptor_snapshot_local_create(name,
468 path_uri);
469 return descriptor ? &descriptor->base : NULL;
470 error:
471 return NULL;
472 }
473
474 static
475 struct lttng_session_descriptor_live *
476 _lttng_session_descriptor_live_create(const char *name,
477 unsigned long long live_timer_interval_us)
478 {
479 struct lttng_session_descriptor_live *descriptor = NULL;
480
481 if (live_timer_interval_us == 0) {
482 goto error;
483 }
484 descriptor = zmalloc<lttng_session_descriptor_live>();
485 if (!descriptor) {
486 goto error;
487 }
488
489 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE;
490 descriptor->base.output_type =
491 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
492 descriptor->live_timer_us = live_timer_interval_us;
493 if (lttng_session_descriptor_set_session_name(&descriptor->base,
494 name)) {
495 goto error;
496 }
497
498 return descriptor;
499 error:
500 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
501 return NULL;
502 }
503
504 /* Ownership of control and data is transferred. */
505 static
506 struct lttng_session_descriptor_live *
507 _lttng_session_descriptor_live_network_create(
508 const char *name,
509 struct lttng_uri *control, struct lttng_uri *data,
510 unsigned long long live_timer_interval_us)
511 {
512 int ret;
513 struct lttng_session_descriptor_live *descriptor;
514
515 descriptor = _lttng_session_descriptor_live_create(name,
516 live_timer_interval_us);
517 if (!descriptor) {
518 goto error;
519 }
520
521 descriptor->base.output_type =
522 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
523
524 /* Ownerwhip of control and data is transferred. */
525 ret = network_location_set_from_lttng_uris(
526 &descriptor->base.output.network,
527 control, data);
528 control = NULL;
529 data = NULL;
530 if (ret) {
531 goto error;
532 }
533 return descriptor;
534 error:
535 free(control);
536 free(data);
537 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
538 return NULL;
539 }
540
541 struct lttng_session_descriptor *
542 lttng_session_descriptor_live_create(
543 const char *name,
544 unsigned long long live_timer_us)
545 {
546 struct lttng_session_descriptor_live *descriptor;
547
548 descriptor = _lttng_session_descriptor_live_create(name, live_timer_us);
549
550 return descriptor ? &descriptor->base : NULL;
551 }
552
553 struct lttng_session_descriptor *
554 lttng_session_descriptor_live_network_create(
555 const char *name,
556 const char *control_url, const char *data_url,
557 unsigned long long live_timer_us)
558 {
559 int ret;
560 struct lttng_session_descriptor_live *descriptor;
561
562 descriptor = _lttng_session_descriptor_live_network_create(name,
563 NULL, NULL, live_timer_us);
564 if (!descriptor) {
565 goto error;
566 }
567
568 ret = network_location_set_from_uri_strings(
569 &descriptor->base.output.network,
570 control_url, data_url);
571 if (ret) {
572 goto error;
573 }
574 return &descriptor->base;
575 error:
576 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
577 return NULL;
578 }
579
580 void lttng_session_descriptor_destroy(
581 struct lttng_session_descriptor *descriptor)
582 {
583 if (!descriptor) {
584 return;
585 }
586
587 switch (descriptor->output_type) {
588 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
589 break;
590 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
591 free(descriptor->output.local);
592 break;
593 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
594 network_location_fini(&descriptor->output.network);
595 break;
596 default:
597 abort();
598 }
599
600 free(descriptor->name);
601 free(descriptor);
602 }
603
604 ssize_t lttng_session_descriptor_create_from_buffer(
605 const struct lttng_buffer_view *payload,
606 struct lttng_session_descriptor **descriptor)
607 {
608 int i;
609 ssize_t offset = 0, ret;
610 struct lttng_buffer_view current_view;
611 const char *name = NULL;
612 const struct lttng_session_descriptor_comm *base_header;
613 size_t max_expected_uri_count;
614 uint64_t live_timer_us = 0;
615 struct lttng_uri *uris[2] = {};
616 enum lttng_session_descriptor_type type;
617 enum lttng_session_descriptor_output_type output_type;
618
619 current_view = lttng_buffer_view_from_view(payload, offset,
620 sizeof(*base_header));
621 if (!lttng_buffer_view_is_valid(&current_view)) {
622 ret = -1;
623 goto end;
624 }
625
626 base_header = (typeof(base_header)) current_view.data;
627 switch (base_header->type) {
628 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
629 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
630 break;
631 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
632 {
633 const struct lttng_session_descriptor_live_comm *live_header;
634
635 current_view = lttng_buffer_view_from_view(payload, offset,
636 sizeof(*live_header));
637 if (!lttng_buffer_view_is_valid(&current_view)) {
638 ret = -1;
639 goto end;
640 }
641
642 live_header = (typeof(live_header)) current_view.data;
643 live_timer_us = live_header->live_timer_us;
644 break;
645 }
646 default:
647 ret = -1;
648 goto end;
649 }
650 /* type has been validated. */
651 type = (lttng_session_descriptor_type) base_header->type;
652
653 switch (base_header->output_type) {
654 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
655 max_expected_uri_count = 0;
656 break;
657 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
658 max_expected_uri_count = 1;
659 break;
660 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
661 max_expected_uri_count = 2;
662 break;
663 default:
664 ret = -1;
665 goto end;
666 }
667 /* output_type has been validated. */
668 output_type = (lttng_session_descriptor_output_type) base_header->output_type;
669
670 /* Skip after header. */
671 offset += current_view.size;
672 if (!base_header->name_len) {
673 goto skip_name;
674 }
675
676 /* Map the name. */
677 current_view = lttng_buffer_view_from_view(payload, offset,
678 base_header->name_len);
679 if (!lttng_buffer_view_is_valid(&current_view)) {
680 ret = -1;
681 goto end;
682 }
683
684 name = current_view.data;
685 if (base_header->name_len == 1 ||
686 name[base_header->name_len - 1] ||
687 strlen(name) != base_header->name_len - 1) {
688 /*
689 * Check that the name is not NULL, is NULL-terminated, and
690 * does not contain a NULL before the last byte.
691 */
692 ret = -1;
693 goto end;
694 }
695
696 /* Skip after the name. */
697 offset += base_header->name_len;
698 skip_name:
699 if (base_header->uri_count > max_expected_uri_count) {
700 ret = -1;
701 goto end;
702 }
703
704 for (i = 0; i < base_header->uri_count; i++) {
705 struct lttng_uri *uri;
706
707 /* Map a URI. */
708 current_view = lttng_buffer_view_from_view(payload,
709 offset, sizeof(*uri));
710 if (!lttng_buffer_view_is_valid(&current_view)) {
711 ret = -1;
712 goto end;
713 }
714
715 uri = (typeof(uri)) current_view.data;
716 uris[i] = zmalloc<lttng_uri>();
717 if (!uris[i]) {
718 ret = -1;
719 goto end;
720 }
721 memcpy(uris[i], uri, sizeof(*uri));
722 offset += sizeof(*uri);
723 }
724
725 switch (type) {
726 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
727 switch (output_type) {
728 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
729 *descriptor = lttng_session_descriptor_create(name);
730 break;
731 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
732 *descriptor = _lttng_session_descriptor_local_create(
733 name, uris[0]);
734 break;
735 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
736 *descriptor = _lttng_session_descriptor_network_create(
737 name, uris[0], uris[1]);
738 break;
739 default:
740 /* Already checked. */
741 abort();
742 }
743 break;
744 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
745 {
746 struct lttng_session_descriptor_snapshot *snapshot;
747 switch (output_type) {
748 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
749 snapshot = _lttng_session_descriptor_snapshot_create(
750 name);
751 break;
752 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
753 snapshot = _lttng_session_descriptor_snapshot_local_create(
754 name, uris[0]);
755 break;
756 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
757 snapshot = _lttng_session_descriptor_snapshot_network_create(
758 name, uris[0], uris[1]);
759 break;
760 default:
761 /* Already checked. */
762 abort();
763 }
764 *descriptor = snapshot ? &snapshot->base : NULL;
765 break;
766 }
767 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
768 {
769 struct lttng_session_descriptor_live *live;
770
771 switch (output_type) {
772 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
773 live = _lttng_session_descriptor_live_create(
774 name, live_timer_us);
775 break;
776 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
777 live = _lttng_session_descriptor_live_network_create(
778 name, uris[0], uris[1],
779 live_timer_us);
780 break;
781 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
782 ret = -1;
783 goto end;
784 default:
785 /* Already checked. */
786 abort();
787 }
788 *descriptor = live ? &live->base : NULL;
789 break;
790 }
791 default:
792 /* Already checked. */
793 abort();
794 }
795 memset(uris, 0, sizeof(uris));
796 if (!*descriptor) {
797 ret = -1;
798 goto end;
799 }
800
801 ret = offset;
802 end:
803 free(uris[0]);
804 free(uris[1]);
805 return ret;
806 }
807
808 int lttng_session_descriptor_serialize(
809 const struct lttng_session_descriptor *descriptor,
810 struct lttng_dynamic_buffer *buffer)
811 {
812 int ret, i;
813 /* There are, at most, two URIs to serialize. */
814 struct lttng_uri *uris[2] = {};
815 size_t uri_count = 0;
816 /* The live header is a superset of all headers. */
817 struct lttng_session_descriptor_live_comm header = {
818 .base = {
819 .type = (uint8_t) descriptor->type,
820 .output_type = (uint8_t) descriptor->output_type,
821 .name_len = (uint32_t) (descriptor->name ?
822 strlen(descriptor->name) + 1 : 0),
823 .uri_count = 0,
824 },
825 .live_timer_us = 0,
826
827 };
828 const void *header_ptr = NULL;
829 size_t header_size;
830
831 switch (descriptor->output_type) {
832 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
833 break;
834 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
835 uris[0] = descriptor->output.local;
836 break;
837 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
838 uris[0] = descriptor->output.network.control;
839 uris[1] = descriptor->output.network.data;
840 break;
841 default:
842 ret = -1;
843 goto end;
844 }
845 uri_count += !!uris[0];
846 uri_count += !!uris[1];
847
848 header.base.uri_count = uri_count;
849 if (descriptor->type == LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE) {
850 const struct lttng_session_descriptor_live *live = lttng::utils::container_of(
851 descriptor, &lttng_session_descriptor_live::base);
852
853 header.live_timer_us = live->live_timer_us;
854 header_ptr = &header;
855 header_size = sizeof(header);
856 } else {
857 header_ptr = &header.base;
858 header_size = sizeof(header.base);
859 }
860
861 ret = lttng_dynamic_buffer_append(buffer, header_ptr, header_size);
862 if (ret) {
863 goto end;
864 }
865 if (header.base.name_len) {
866 ret = lttng_dynamic_buffer_append(buffer, descriptor->name,
867 header.base.name_len);
868 if (ret) {
869 goto end;
870 }
871 }
872
873 for (i = 0; i < uri_count; i++) {
874 ret = lttng_dynamic_buffer_append(buffer, uris[i],
875 sizeof(struct lttng_uri));
876 if (ret) {
877 goto end;
878 }
879 }
880 end:
881 return ret;
882 }
883
884 enum lttng_session_descriptor_type
885 lttng_session_descriptor_get_type(
886 const struct lttng_session_descriptor *descriptor)
887 {
888 return descriptor->type;
889 }
890
891 enum lttng_session_descriptor_output_type
892 lttng_session_descriptor_get_output_type(
893 const struct lttng_session_descriptor *descriptor)
894 {
895 return descriptor->output_type;
896 }
897
898 void lttng_session_descriptor_get_local_output_uri(
899 const struct lttng_session_descriptor *descriptor,
900 struct lttng_uri *local_uri)
901 {
902 memcpy(local_uri, descriptor->output.local, sizeof(*local_uri));
903 }
904
905 void lttng_session_descriptor_get_network_output_uris(
906 const struct lttng_session_descriptor *descriptor,
907 struct lttng_uri *control,
908 struct lttng_uri *data)
909 {
910 memcpy(control, descriptor->output.network.control, sizeof(*control));
911 memcpy(data, descriptor->output.network.data, sizeof(*data));
912 }
913
914 unsigned long long
915 lttng_session_descriptor_live_get_timer_interval(
916 const struct lttng_session_descriptor *descriptor)
917 {
918 struct lttng_session_descriptor_live *live;
919
920 live = lttng::utils::container_of(descriptor, &lttng_session_descriptor_live::base);
921 return live->live_timer_us;
922 }
923
924 enum lttng_session_descriptor_status
925 lttng_session_descriptor_get_session_name(
926 const struct lttng_session_descriptor *descriptor,
927 const char **session_name)
928 {
929 enum lttng_session_descriptor_status status;
930
931 if (!descriptor || !session_name) {
932 status = LTTNG_SESSION_DESCRIPTOR_STATUS_INVALID;
933 goto end;
934 }
935
936 *session_name = descriptor->name;
937 status = descriptor->name ?
938 LTTNG_SESSION_DESCRIPTOR_STATUS_OK :
939 LTTNG_SESSION_DESCRIPTOR_STATUS_UNSET;
940 end:
941 return status;
942 }
943
944 int lttng_session_descriptor_set_session_name(
945 struct lttng_session_descriptor *descriptor,
946 const char *name)
947 {
948 int ret = 0;
949 char *new_name;
950
951 if (!name) {
952 goto end;
953 }
954 if (strlen(name) >= LTTNG_NAME_MAX) {
955 ret = -1;
956 goto end;
957 }
958 new_name = strdup(name);
959 if (!new_name) {
960 ret = -1;
961 goto end;
962 }
963 free(descriptor->name);
964 descriptor->name = new_name;
965 end:
966 return ret;
967 }
968
969 bool lttng_session_descriptor_is_output_destination_initialized(
970 const struct lttng_session_descriptor *descriptor)
971 {
972 switch (descriptor->output_type) {
973 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
974 return true;
975 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
976 return descriptor->output.local;
977 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
978 return descriptor->output.network.control;
979 default:
980 abort();
981 }
982 }
983
984 bool lttng_session_descriptor_has_output_directory(
985 const struct lttng_session_descriptor *descriptor)
986 {
987 switch (descriptor->output_type) {
988 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
989 break;
990 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
991 if (descriptor->output.local) {
992 return *descriptor->output.local->dst.path;
993 }
994 break;
995 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
996 if (descriptor->output.network.control) {
997 return *descriptor->output.network.control->subdir;
998 }
999 break;
1000 default:
1001 abort();
1002 }
1003 return false;
1004 }
1005
1006 enum lttng_error_code lttng_session_descriptor_set_default_output(
1007 struct lttng_session_descriptor *descriptor,
1008 time_t *session_creation_time,
1009 const char *absolute_home_path)
1010 {
1011 enum lttng_error_code ret_code = LTTNG_OK;
1012 struct lttng_uri *uris = NULL;
1013
1014 switch (descriptor->output_type) {
1015 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1016 goto end;
1017 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1018 {
1019 int ret;
1020 ssize_t uri_ret;
1021 char local_uri[LTTNG_PATH_MAX];
1022 char creation_datetime_suffix[17] = {};
1023
1024 if (session_creation_time) {
1025 size_t strftime_ret;
1026 struct tm *timeinfo;
1027
1028 timeinfo = localtime(session_creation_time);
1029 if (!timeinfo) {
1030 ret_code = LTTNG_ERR_FATAL;
1031 goto end;
1032 }
1033 strftime_ret = strftime(creation_datetime_suffix,
1034 sizeof(creation_datetime_suffix),
1035 "-%Y%m%d-%H%M%S", timeinfo);
1036 if (strftime_ret == 0) {
1037 ERR("Failed to format session creation timestamp while setting default local output destination");
1038 ret_code = LTTNG_ERR_FATAL;
1039 goto end;
1040 }
1041 }
1042 LTTNG_ASSERT(descriptor->name);
1043 ret = snprintf(local_uri, sizeof(local_uri),
1044 "file://%s/%s/%s%s",
1045 absolute_home_path,
1046 DEFAULT_TRACE_DIR_NAME, descriptor->name,
1047 creation_datetime_suffix);
1048 if (ret >= sizeof(local_uri)) {
1049 ERR("Truncation occurred while setting default local output destination");
1050 ret_code = LTTNG_ERR_SET_URL;
1051 goto end;
1052 } else if (ret < 0) {
1053 PERROR("Failed to format default local output URI");
1054 ret_code = LTTNG_ERR_SET_URL;
1055 goto end;
1056 }
1057
1058 uri_ret = uri_parse(local_uri, &uris);
1059 if (uri_ret != 1) {
1060 ret_code = LTTNG_ERR_SET_URL;
1061 goto end;
1062 }
1063 free(descriptor->output.local);
1064 descriptor->output.local = &uris[0];
1065 uris = NULL;
1066 break;
1067 }
1068 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1069 {
1070 int ret;
1071 ssize_t uri_ret;
1072 struct lttng_uri *control = NULL, *data = NULL;
1073
1074 uri_ret = uri_parse_str_urls("net://127.0.0.1", NULL, &uris);
1075 if (uri_ret != 2) {
1076 ret_code = LTTNG_ERR_SET_URL;
1077 goto end;
1078 }
1079
1080 control = uri_copy(&uris[0]);
1081 data = uri_copy(&uris[1]);
1082 if (!control || !data) {
1083 free(control);
1084 free(data);
1085 ret_code = LTTNG_ERR_SET_URL;
1086 goto end;
1087 }
1088
1089 /* Ownership of uris is transferred. */
1090 ret = network_location_set_from_lttng_uris(
1091 &descriptor->output.network,
1092 control, data);
1093 if (ret) {
1094 abort();
1095 ret_code = LTTNG_ERR_SET_URL;
1096 goto end;
1097 }
1098 break;
1099 }
1100 default:
1101 abort();
1102 }
1103 end:
1104 free(uris);
1105 return ret_code;
1106 }
1107
1108 /*
1109 * Note that only properties that can be populated by the session daemon
1110 * (output destination and name) are assigned.
1111 */
1112 int lttng_session_descriptor_assign(
1113 struct lttng_session_descriptor *dst,
1114 const struct lttng_session_descriptor *src)
1115 {
1116 int ret = 0;
1117
1118 if (dst->type != src->type) {
1119 ret = -1;
1120 goto end;
1121 }
1122 if (dst->output_type != src->output_type) {
1123 ret = -1;
1124 goto end;
1125 }
1126 ret = lttng_session_descriptor_set_session_name(dst, src->name);
1127 if (ret) {
1128 goto end;
1129 }
1130 switch (dst->output_type) {
1131 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1132 free(dst->output.local);
1133 dst->output.local = uri_copy(src->output.local);
1134 if (!dst->output.local) {
1135 ret = -1;
1136 goto end;
1137 }
1138 break;
1139 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1140 {
1141 struct lttng_uri *control_copy = NULL, *data_copy = NULL;
1142
1143 control_copy = uri_copy(dst->output.network.control);
1144 if (!control_copy && dst->output.network.control) {
1145 ret = -1;
1146 goto end;
1147 }
1148 data_copy = uri_copy(dst->output.network.data);
1149 if (!data_copy && dst->output.network.data) {
1150 free(control_copy);
1151 ret = -1;
1152 goto end;
1153 }
1154 ret = network_location_set_from_lttng_uris(&dst->output.network,
1155 control_copy, data_copy);
1156 break;
1157 }
1158 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1159 goto end;
1160 }
1161 end:
1162 return ret;
1163 }
This page took 0.05361 seconds and 4 git commands to generate.