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