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