sessiond: Move trace_ust_clock to a clock_attributes_sample class
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.cpp
1 /*
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <inttypes.h>
10 #include <limits.h>
11 #include <stdarg.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <vector>
17
18 #include <common/common.hpp>
19 #include <common/exception.hpp>
20 #include <common/time.hpp>
21 #include <common/uuid.hpp>
22
23 #include "ust-app.hpp"
24 #include "ust-clock.hpp"
25 #include "ust-registry.hpp"
26
27 static
28 int _lttng_field_statedump(ust_registry_session *session,
29 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
30 size_t *iter_field, size_t nesting);
31
32 static inline
33 int get_count_order(unsigned int count)
34 {
35 int order;
36
37 order = lttng_fls(count) - 1;
38 if (count & (count - 1)) {
39 order++;
40 }
41 LTTNG_ASSERT(order >= 0);
42 return order;
43 }
44
45 /*
46 * Returns offset where to write in metadata array, or negative error value on error.
47 */
48 static
49 ssize_t metadata_reserve(ust_registry_session *session, size_t len)
50 {
51 size_t new_len = session->_metadata_len + len;
52 size_t new_alloc_len = new_len;
53 size_t old_alloc_len = session->_metadata_alloc_len;
54 ssize_t ret;
55
56 if (new_alloc_len > (UINT32_MAX >> 1))
57 return -EINVAL;
58 if ((old_alloc_len << 1) > (UINT32_MAX >> 1))
59 return -EINVAL;
60
61 if (new_alloc_len > old_alloc_len) {
62 char *newptr;
63
64 new_alloc_len =
65 std::max<size_t>(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
66 newptr = (char *) realloc(session->_metadata, new_alloc_len);
67 if (!newptr)
68 return -ENOMEM;
69 session->_metadata = newptr;
70 /* We zero directly the memory from start of allocation. */
71 memset(&session->_metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
72 session->_metadata_alloc_len = new_alloc_len;
73 }
74 ret = session->_metadata_len;
75 session->_metadata_len += len;
76 return ret;
77 }
78
79 static
80 int metadata_file_append(ust_registry_session *session,
81 const char *str, size_t len)
82 {
83 ssize_t written;
84
85 if (session->_metadata_fd < 0) {
86 return 0;
87 }
88 /* Write to metadata file */
89 written = lttng_write(session->_metadata_fd, str, len);
90 if (written != len) {
91 return -1;
92 }
93 return 0;
94 }
95
96 /*
97 * We have exclusive access to our metadata buffer (protected by the
98 * ust_lock), so we can do racy operations such as looking for
99 * remaining space left in packet and write, since mutual exclusion
100 * protects us from concurrent writes.
101 */
102 static ATTR_FORMAT_PRINTF(2, 3)
103 int lttng_metadata_printf(ust_registry_session *session,
104 const char *fmt, ...)
105 {
106 char *str = NULL;
107 size_t len;
108 va_list ap;
109 ssize_t offset;
110 int ret;
111
112 va_start(ap, fmt);
113 ret = vasprintf(&str, fmt, ap);
114 va_end(ap);
115 if (ret < 0)
116 return -ENOMEM;
117
118 len = strlen(str);
119 offset = metadata_reserve(session, len);
120 if (offset < 0) {
121 ret = offset;
122 goto end;
123 }
124 memcpy(&session->_metadata[offset], str, len);
125 ret = metadata_file_append(session, str, len);
126 if (ret) {
127 PERROR("Error appending to metadata file");
128 goto end;
129 }
130 DBG3("Append to metadata: \"%s\"", str);
131 ret = 0;
132
133 end:
134 free(str);
135 return ret;
136 }
137
138 static
139 int print_tabs(ust_registry_session *session, size_t nesting)
140 {
141 size_t i;
142
143 for (i = 0; i < nesting; i++) {
144 int ret;
145
146 ret = lttng_metadata_printf(session, " ");
147 if (ret) {
148 return ret;
149 }
150 }
151 return 0;
152 }
153
154 static
155 void sanitize_ctf_identifier(char *out, const char *in)
156 {
157 size_t i;
158
159 for (i = 0; i < LTTNG_UST_ABI_SYM_NAME_LEN; i++) {
160 switch (in[i]) {
161 case '.':
162 case '$':
163 case ':':
164 out[i] = '_';
165 break;
166 default:
167 out[i] = in[i];
168 }
169 }
170 }
171
172 static
173 int print_escaped_ctf_string(ust_registry_session *session, const char *string)
174 {
175 int ret = 0;
176 size_t i;
177 char cur;
178
179 i = 0;
180 cur = string[i];
181 while (cur != '\0') {
182 switch (cur) {
183 case '\n':
184 ret = lttng_metadata_printf(session, "%s", "\\n");
185 break;
186 case '\\':
187 case '"':
188 ret = lttng_metadata_printf(session, "%c", '\\');
189 if (ret) {
190 goto error;
191 }
192 /* We still print the current char */
193 /* Fallthrough */
194 default:
195 ret = lttng_metadata_printf(session, "%c", cur);
196 break;
197 }
198
199 if (ret) {
200 goto error;
201 }
202
203 cur = string[++i];
204 }
205 error:
206 return ret;
207 }
208
209 /* Called with session registry mutex held. */
210 static
211 int ust_metadata_enum_statedump(ust_registry_session *session,
212 const char *enum_name,
213 uint64_t enum_id,
214 const struct lttng_ust_ctl_integer_type *container_type,
215 const char *field_name, size_t *iter_field, size_t nesting)
216 {
217 struct ust_registry_enum *reg_enum;
218 const struct lttng_ust_ctl_enum_entry *entries;
219 size_t nr_entries;
220 int ret = 0;
221 size_t i;
222 char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
223
224 rcu_read_lock();
225 reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id);
226 rcu_read_unlock();
227 /* reg_enum can still be used because session registry mutex is held. */
228 if (!reg_enum) {
229 ret = -ENOENT;
230 goto end;
231 }
232 entries = reg_enum->entries;
233 nr_entries = reg_enum->nr_entries;
234
235 ret = print_tabs(session, nesting);
236 if (ret) {
237 goto end;
238 }
239 ret = lttng_metadata_printf(session,
240 "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
241 container_type->size,
242 container_type->alignment,
243 container_type->signedness,
244 (container_type->encoding == lttng_ust_ctl_encode_none)
245 ? "none"
246 : (container_type->encoding == lttng_ust_ctl_encode_UTF8)
247 ? "UTF8"
248 : "ASCII",
249 container_type->base);
250 if (ret) {
251 goto end;
252 }
253 nesting++;
254 /* Dump all entries */
255 for (i = 0; i < nr_entries; i++) {
256 const struct lttng_ust_ctl_enum_entry *entry = &entries[i];
257 int j, len;
258
259 ret = print_tabs(session, nesting);
260 if (ret) {
261 goto end;
262 }
263 ret = lttng_metadata_printf(session,
264 "\"");
265 if (ret) {
266 goto end;
267 }
268 len = strlen(entry->string);
269 /* Escape the character '"' */
270 for (j = 0; j < len; j++) {
271 char c = entry->string[j];
272
273 switch (c) {
274 case '"':
275 ret = lttng_metadata_printf(session,
276 "\\\"");
277 break;
278 case '\\':
279 ret = lttng_metadata_printf(session,
280 "\\\\");
281 break;
282 default:
283 ret = lttng_metadata_printf(session,
284 "%c", c);
285 break;
286 }
287 if (ret) {
288 goto end;
289 }
290 }
291 ret = lttng_metadata_printf(session, "\"");
292 if (ret) {
293 goto end;
294 }
295
296 if (entry->u.extra.options &
297 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
298 ret = lttng_metadata_printf(session, ",\n");
299 if (ret) {
300 goto end;
301 }
302 } else {
303 ret = lttng_metadata_printf(session,
304 " = ");
305 if (ret) {
306 goto end;
307 }
308
309 if (entry->start.signedness) {
310 ret = lttng_metadata_printf(session,
311 "%" PRId64, entry->start.value);
312 } else {
313 ret = lttng_metadata_printf(session,
314 "%" PRIu64, entry->start.value);
315 }
316 if (ret) {
317 goto end;
318 }
319
320 if (entry->start.signedness == entry->end.signedness &&
321 entry->start.value ==
322 entry->end.value) {
323 ret = lttng_metadata_printf(session, ",\n");
324 } else {
325 if (entry->end.signedness) {
326 ret = lttng_metadata_printf(session,
327 " ... %" PRId64 ",\n",
328 entry->end.value);
329 } else {
330 ret = lttng_metadata_printf(session,
331 " ... %" PRIu64 ",\n",
332 entry->end.value);
333 }
334 }
335 if (ret) {
336 goto end;
337 }
338 }
339 }
340 nesting--;
341 sanitize_ctf_identifier(identifier, field_name);
342 ret = print_tabs(session, nesting);
343 if (ret) {
344 goto end;
345 }
346 ret = lttng_metadata_printf(session, "} _%s;\n",
347 identifier);
348 end:
349 (*iter_field)++;
350 return ret;
351 }
352
353 static
354 int _lttng_variant_statedump(ust_registry_session *session,
355 uint32_t nr_choices, const char *tag_name,
356 uint32_t alignment,
357 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
358 size_t *iter_field, size_t nesting)
359 {
360 const struct lttng_ust_ctl_field *variant = &fields[*iter_field];
361 uint32_t i;
362 int ret;
363 char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
364
365 (*iter_field)++;
366 sanitize_ctf_identifier(identifier, tag_name);
367 if (alignment) {
368 ret = print_tabs(session, nesting);
369 if (ret) {
370 goto end;
371 }
372 ret = lttng_metadata_printf(session,
373 "struct { } align(%u) _%s_padding;\n",
374 alignment * CHAR_BIT,
375 variant->name);
376 if (ret) {
377 goto end;
378 }
379 }
380 ret = print_tabs(session, nesting);
381 if (ret) {
382 goto end;
383 }
384 ret = lttng_metadata_printf(session,
385 "variant <_%s> {\n",
386 identifier);
387 if (ret) {
388 goto end;
389 }
390
391 for (i = 0; i < nr_choices; i++) {
392 if (*iter_field >= nr_fields) {
393 ret = -EOVERFLOW;
394 goto end;
395 }
396 ret = _lttng_field_statedump(session,
397 fields, nr_fields,
398 iter_field, nesting + 1);
399 if (ret) {
400 goto end;
401 }
402 }
403 sanitize_ctf_identifier(identifier, variant->name);
404 ret = print_tabs(session, nesting);
405 if (ret) {
406 goto end;
407 }
408 ret = lttng_metadata_printf(session,
409 "} _%s;\n",
410 identifier);
411 if (ret) {
412 goto end;
413 }
414 end:
415 return ret;
416 }
417
418 static
419 int _lttng_field_statedump(ust_registry_session *session,
420 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
421 size_t *iter_field, size_t nesting)
422 {
423 int ret = 0;
424 const char *bo_be = " byte_order = be;";
425 const char *bo_le = " byte_order = le;";
426 const char *bo_native = "";
427 const char *bo_reverse;
428 const struct lttng_ust_ctl_field *field;
429
430 if (*iter_field >= nr_fields) {
431 ret = -EOVERFLOW;
432 goto end;
433 }
434 field = &fields[*iter_field];
435
436 if (session->_byte_order == BIG_ENDIAN) {
437 bo_reverse = bo_le;
438 } else {
439 bo_reverse = bo_be;
440 }
441
442 switch (field->type.atype) {
443 case lttng_ust_ctl_atype_integer:
444 ret = print_tabs(session, nesting);
445 if (ret) {
446 goto end;
447 }
448 ret = lttng_metadata_printf(session,
449 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
450 field->type.u.integer.size,
451 field->type.u.integer.alignment,
452 field->type.u.integer.signedness,
453 (field->type.u.integer.encoding == lttng_ust_ctl_encode_none)
454 ? "none"
455 : (field->type.u.integer.encoding == lttng_ust_ctl_encode_UTF8)
456 ? "UTF8"
457 : "ASCII",
458 field->type.u.integer.base,
459 field->type.u.integer.reverse_byte_order ? bo_reverse : bo_native,
460 field->name);
461 (*iter_field)++;
462 break;
463 case lttng_ust_ctl_atype_enum:
464 ret = ust_metadata_enum_statedump(session,
465 field->type.u.legacy.basic.enumeration.name,
466 field->type.u.legacy.basic.enumeration.id,
467 &field->type.u.legacy.basic.enumeration.container_type,
468 field->name, iter_field, nesting);
469 break;
470 case lttng_ust_ctl_atype_float:
471 ret = print_tabs(session, nesting);
472 if (ret) {
473 goto end;
474 }
475 ret = lttng_metadata_printf(session,
476 "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
477 field->type.u._float.exp_dig,
478 field->type.u._float.mant_dig,
479 field->type.u._float.alignment,
480 field->type.u._float.reverse_byte_order ? bo_reverse : bo_native,
481 field->name);
482 (*iter_field)++;
483 break;
484 case lttng_ust_ctl_atype_array:
485 {
486 const struct lttng_ust_ctl_basic_type *elem_type;
487
488 ret = print_tabs(session, nesting);
489 if (ret) {
490 goto end;
491 }
492 elem_type = &field->type.u.legacy.array.elem_type;
493 /* Only integers are currently supported in arrays. */
494 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
495 ret = -EINVAL;
496 goto end;
497 }
498 ret = lttng_metadata_printf(session,
499 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
500 elem_type->u.basic.integer.size,
501 elem_type->u.basic.integer.alignment,
502 elem_type->u.basic.integer.signedness,
503 (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
504 ? "none"
505 : (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
506 ? "UTF8"
507 : "ASCII",
508 elem_type->u.basic.integer.base,
509 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
510 field->name, field->type.u.legacy.array.length);
511 (*iter_field)++;
512 break;
513 }
514 case lttng_ust_ctl_atype_array_nestable:
515 {
516 uint32_t array_length;
517 const struct lttng_ust_ctl_field *array_nestable;
518 const struct lttng_ust_ctl_type *elem_type;
519
520 array_length = field->type.u.array_nestable.length;
521 (*iter_field)++;
522
523 if (*iter_field >= nr_fields) {
524 ret = -EOVERFLOW;
525 goto end;
526 }
527 array_nestable = &fields[*iter_field];
528 elem_type = &array_nestable->type;
529
530 /* Only integers are currently supported in arrays. */
531 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
532 ret = -EINVAL;
533 goto end;
534 }
535
536 if (field->type.u.array_nestable.alignment) {
537 ret = print_tabs(session, nesting);
538 if (ret) {
539 goto end;
540 }
541 ret = lttng_metadata_printf(session,
542 "struct { } align(%u) _%s_padding;\n",
543 field->type.u.array_nestable.alignment * CHAR_BIT,
544 field->name);
545 if (ret) {
546 goto end;
547 }
548 }
549
550 ret = print_tabs(session, nesting);
551 if (ret) {
552 goto end;
553 }
554 ret = lttng_metadata_printf(session,
555 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
556 elem_type->u.integer.size,
557 elem_type->u.integer.alignment,
558 elem_type->u.integer.signedness,
559 (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
560 ? "none"
561 : (elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
562 ? "UTF8"
563 : "ASCII",
564 elem_type->u.integer.base,
565 elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
566 field->name, array_length);
567 (*iter_field)++;
568 break;
569 }
570 case lttng_ust_ctl_atype_sequence:
571 {
572 const struct lttng_ust_ctl_basic_type *elem_type;
573 const struct lttng_ust_ctl_basic_type *length_type;
574
575 elem_type = &field->type.u.legacy.sequence.elem_type;
576 length_type = &field->type.u.legacy.sequence.length_type;
577 ret = print_tabs(session, nesting);
578 if (ret) {
579 goto end;
580 }
581
582 /* Only integers are currently supported in sequences. */
583 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
584 ret = -EINVAL;
585 goto end;
586 }
587
588 ret = lttng_metadata_printf(session,
589 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
590 length_type->u.basic.integer.size,
591 (unsigned int) length_type->u.basic.integer.alignment,
592 length_type->u.basic.integer.signedness,
593 (length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
594 ? "none"
595 : ((length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
596 ? "UTF8"
597 : "ASCII"),
598 length_type->u.basic.integer.base,
599 length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
600 field->name);
601 if (ret) {
602 goto end;
603 }
604
605 ret = print_tabs(session, nesting);
606 if (ret) {
607 goto end;
608 }
609 ret = lttng_metadata_printf(session,
610 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
611 elem_type->u.basic.integer.size,
612 (unsigned int) elem_type->u.basic.integer.alignment,
613 elem_type->u.basic.integer.signedness,
614 (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
615 ? "none"
616 : ((elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
617 ? "UTF8"
618 : "ASCII"),
619 elem_type->u.basic.integer.base,
620 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
621 field->name,
622 field->name);
623 (*iter_field)++;
624 break;
625 }
626 case lttng_ust_ctl_atype_sequence_nestable:
627 {
628 const struct lttng_ust_ctl_field *sequence_nestable;
629 const struct lttng_ust_ctl_type *elem_type;
630
631 (*iter_field)++;
632 if (*iter_field >= nr_fields) {
633 ret = -EOVERFLOW;
634 goto end;
635 }
636 sequence_nestable = &fields[*iter_field];
637 elem_type = &sequence_nestable->type;
638
639 /* Only integers are currently supported in sequences. */
640 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
641 ret = -EINVAL;
642 goto end;
643 }
644
645 if (field->type.u.sequence_nestable.alignment) {
646 ret = print_tabs(session, nesting);
647 if (ret) {
648 goto end;
649 }
650 ret = lttng_metadata_printf(session,
651 "struct { } align(%u) _%s_padding;\n",
652 field->type.u.sequence_nestable.alignment * CHAR_BIT,
653 field->name);
654 if (ret) {
655 goto end;
656 }
657 }
658
659 ret = print_tabs(session, nesting);
660 if (ret) {
661 goto end;
662 }
663 ret = lttng_metadata_printf(session,
664 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ _%s ];\n",
665 elem_type->u.integer.size,
666 (unsigned int) elem_type->u.integer.alignment,
667 elem_type->u.integer.signedness,
668 (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
669 ? "none"
670 : ((elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
671 ? "UTF8"
672 : "ASCII"),
673 elem_type->u.integer.base,
674 elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
675 field->name,
676 field->type.u.sequence_nestable.length_name);
677 (*iter_field)++;
678 break;
679 }
680 case lttng_ust_ctl_atype_string:
681 /* Default encoding is UTF8 */
682 ret = print_tabs(session, nesting);
683 if (ret) {
684 goto end;
685 }
686 ret = lttng_metadata_printf(session,
687 "string%s _%s;\n",
688 field->type.u.string.encoding == lttng_ust_ctl_encode_ASCII ?
689 " { encoding = ASCII; }" : "",
690 field->name);
691 (*iter_field)++;
692 break;
693 case lttng_ust_ctl_atype_variant:
694 ret = _lttng_variant_statedump(session,
695 field->type.u.legacy.variant.nr_choices,
696 field->type.u.legacy.variant.tag_name,
697 0,
698 fields, nr_fields, iter_field, nesting);
699 if (ret) {
700 goto end;
701 }
702 break;
703 case lttng_ust_ctl_atype_variant_nestable:
704 ret = _lttng_variant_statedump(session,
705 field->type.u.variant_nestable.nr_choices,
706 field->type.u.variant_nestable.tag_name,
707 field->type.u.variant_nestable.alignment,
708 fields, nr_fields, iter_field, nesting);
709 if (ret) {
710 goto end;
711 }
712 break;
713 case lttng_ust_ctl_atype_struct:
714 if (field->type.u.legacy._struct.nr_fields != 0) {
715 /* Currently only 0-length structures are supported. */
716 ret = -EINVAL;
717 goto end;
718 }
719 ret = print_tabs(session, nesting);
720 if (ret) {
721 goto end;
722 }
723 ret = lttng_metadata_printf(session,
724 "struct {} _%s;\n",
725 field->name);
726 (*iter_field)++;
727 break;
728 case lttng_ust_ctl_atype_struct_nestable:
729 if (field->type.u.struct_nestable.nr_fields != 0) {
730 /* Currently only 0-length structures are supported. */
731 ret = -EINVAL;
732 goto end;
733 }
734 ret = print_tabs(session, nesting);
735 if (ret) {
736 goto end;
737 }
738 if (field->type.u.struct_nestable.alignment) {
739 ret = lttng_metadata_printf(session,
740 "struct {} align(%u) _%s;\n",
741 field->type.u.struct_nestable.alignment * CHAR_BIT,
742 field->name);
743 if (ret) {
744 goto end;
745 }
746 } else {
747 ret = lttng_metadata_printf(session,
748 "struct {} _%s;\n",
749 field->name);
750 }
751 (*iter_field)++;
752 break;
753 case lttng_ust_ctl_atype_enum_nestable:
754 {
755 const struct lttng_ust_ctl_field *container_field;
756 const struct lttng_ust_ctl_type *container_type;
757
758 (*iter_field)++;
759 if (*iter_field >= nr_fields) {
760 ret = -EOVERFLOW;
761 goto end;
762 }
763 container_field = &fields[*iter_field];
764 container_type = &container_field->type;
765
766 /* Only integers are supported as container types. */
767 if (container_type->atype != lttng_ust_ctl_atype_integer) {
768 ret = -EINVAL;
769 goto end;
770 }
771 ret = ust_metadata_enum_statedump(session,
772 field->type.u.enum_nestable.name,
773 field->type.u.enum_nestable.id,
774 &container_type->u.integer,
775 field->name, iter_field, nesting);
776 break;
777 }
778 default:
779 ret = -EINVAL;
780 }
781 end:
782 return ret;
783 }
784
785 static
786 int _lttng_context_metadata_statedump(ust_registry_session *session,
787 size_t nr_ctx_fields,
788 struct lttng_ust_ctl_field *ctx)
789 {
790 int ret = 0;
791 size_t i = 0;
792
793 if (!ctx)
794 return 0;
795 for (;;) {
796 if (i >= nr_ctx_fields) {
797 break;
798 }
799 ret = _lttng_field_statedump(session, ctx,
800 nr_ctx_fields, &i, 2);
801 if (ret) {
802 break;
803 }
804 }
805 return ret;
806 }
807
808 static
809 int _lttng_fields_metadata_statedump(ust_registry_session *session,
810 struct ust_registry_event *event)
811 {
812 int ret = 0;
813 size_t i = 0;
814
815 for (;;) {
816 if (i >= event->nr_fields) {
817 break;
818 }
819 ret = _lttng_field_statedump(session, event->fields,
820 event->nr_fields, &i, 2);
821 if (ret) {
822 break;
823 }
824 }
825 return ret;
826 }
827
828 /*
829 * Should be called with session registry mutex held.
830 */
831 int ust_metadata_event_statedump(ust_registry_session *session,
832 struct ust_registry_channel *chan,
833 struct ust_registry_event *event)
834 {
835 int ret = 0;
836
837 /* Don't dump metadata events */
838 if (chan->chan_id == -1U)
839 return 0;
840
841 /*
842 * We don't want to output an event's metadata before its parent
843 * stream's metadata. If the stream's metadata hasn't been output yet,
844 * skip this event. Its metadata will be output when we output the
845 * stream's metadata.
846 */
847 if (!chan->metadata_dumped || event->metadata_dumped) {
848 return 0;
849 }
850
851 ret = lttng_metadata_printf(session,
852 "event {\n"
853 " name = \"%s\";\n"
854 " id = %u;\n"
855 " stream_id = %u;\n",
856 event->name,
857 event->id,
858 chan->chan_id);
859 if (ret) {
860 goto end;
861 }
862
863 ret = lttng_metadata_printf(session,
864 " loglevel = %d;\n",
865 event->loglevel_value);
866 if (ret) {
867 goto end;
868 }
869
870 if (event->model_emf_uri) {
871 ret = lttng_metadata_printf(session,
872 " model.emf.uri = \"%s\";\n",
873 event->model_emf_uri);
874 if (ret) {
875 goto end;
876 }
877 }
878
879 ret = lttng_metadata_printf(session,
880 " fields := struct {\n"
881 );
882 if (ret) {
883 goto end;
884 }
885
886 ret = _lttng_fields_metadata_statedump(session, event);
887 if (ret) {
888 goto end;
889 }
890
891 ret = lttng_metadata_printf(session,
892 " };\n"
893 "};\n\n");
894 if (ret) {
895 goto end;
896 }
897 event->metadata_dumped = 1;
898
899 end:
900 return ret;
901 }
902
903 /*
904 * Should be called with session registry mutex held.
905 *
906 * RCU read lock must be held by the caller.
907 */
908 int ust_metadata_channel_statedump(ust_registry_session *session,
909 struct ust_registry_channel *chan)
910 {
911 int ret;
912
913 ASSERT_RCU_READ_LOCKED();
914
915 /* Don't dump metadata events */
916 if (chan->chan_id == -1U)
917 return 0;
918
919 if (!chan->header_type)
920 return -EINVAL;
921
922 ret = lttng_metadata_printf(session,
923 "stream {\n"
924 " id = %u;\n"
925 " event.header := %s;\n"
926 " packet.context := struct packet_context;\n",
927 chan->chan_id,
928 chan->header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT ?
929 "struct event_header_compact" :
930 "struct event_header_large");
931 if (ret) {
932 return ret;
933 }
934
935 if (chan->ctx_fields) {
936 ret = lttng_metadata_printf(session,
937 " event.context := struct {\n");
938 if (ret) {
939 return ret;
940 }
941 }
942 ret = _lttng_context_metadata_statedump(session,
943 chan->nr_ctx_fields,
944 chan->ctx_fields);
945 if (ret) {
946 return ret;
947 }
948 if (chan->ctx_fields) {
949 ret = lttng_metadata_printf(session,
950 " };\n");
951 if (ret) {
952 return ret;
953 }
954 }
955
956 ret = lttng_metadata_printf(session,
957 "};\n\n");
958 if (ret) {
959 return ret;
960 }
961
962 /* Flag success of metadata dump. */
963 chan->metadata_dumped = 1;
964
965 /*
966 * Output the metadata of any existing event.
967 *
968 * Sort the events by id. This is not necessary, but it's nice to have
969 * a more predictable order in the metadata file.
970 */
971 std::vector<ust_registry_event *> events;
972 {
973 cds_lfht_iter event_iter;
974 ust_registry_event *event;
975 cds_lfht_for_each_entry(chan->events->ht, &event_iter, event,
976 node.node) {
977 events.push_back(event);
978 }
979 }
980
981 std::sort(events.begin(), events.end(),
982 [] (ust_registry_event *a, ust_registry_event *b) {
983 return a->id < b->id;
984 });
985
986 for (ust_registry_event *event : events) {
987 ust_metadata_event_statedump(session, chan, event);
988 }
989
990 return 0;
991 }
992
993 static
994 int _lttng_stream_packet_context_declare(ust_registry_session *session)
995 {
996 return lttng_metadata_printf(session,
997 "struct packet_context {\n"
998 " uint64_clock_monotonic_t timestamp_begin;\n"
999 " uint64_clock_monotonic_t timestamp_end;\n"
1000 " uint64_t content_size;\n"
1001 " uint64_t packet_size;\n"
1002 " uint64_t packet_seq_num;\n"
1003 " unsigned long events_discarded;\n"
1004 " uint32_t cpu_id;\n"
1005 "};\n\n"
1006 );
1007 }
1008
1009 /*
1010 * Compact header:
1011 * id: range: 0 - 30.
1012 * id 31 is reserved to indicate an extended header.
1013 *
1014 * Large header:
1015 * id: range: 0 - 65534.
1016 * id 65535 is reserved to indicate an extended header.
1017 */
1018 static
1019 int _lttng_event_header_declare(ust_registry_session *session)
1020 {
1021 return lttng_metadata_printf(session,
1022 "struct event_header_compact {\n"
1023 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
1024 " variant <id> {\n"
1025 " struct {\n"
1026 " uint27_clock_monotonic_t timestamp;\n"
1027 " } compact;\n"
1028 " struct {\n"
1029 " uint32_t id;\n"
1030 " uint64_clock_monotonic_t timestamp;\n"
1031 " } extended;\n"
1032 " } v;\n"
1033 "} align(%u);\n"
1034 "\n"
1035 "struct event_header_large {\n"
1036 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
1037 " variant <id> {\n"
1038 " struct {\n"
1039 " uint32_clock_monotonic_t timestamp;\n"
1040 " } compact;\n"
1041 " struct {\n"
1042 " uint32_t id;\n"
1043 " uint64_clock_monotonic_t timestamp;\n"
1044 " } extended;\n"
1045 " } v;\n"
1046 "} align(%u);\n\n",
1047 session->_uint32_t_alignment,
1048 session->_uint16_t_alignment
1049 );
1050 }
1051
1052 static
1053 int print_metadata_session_information(ust_registry_session *registry)
1054 {
1055 int ret;
1056 struct ltt_session *session = NULL;
1057 char creation_datetime[ISO8601_STR_LEN];
1058
1059 rcu_read_lock();
1060 session = session_find_by_id(registry->_tracing_id);
1061 if (!session) {
1062 ret = -1;
1063 goto error;
1064 }
1065
1066 /* Print the trace name */
1067 ret = lttng_metadata_printf(registry, " trace_name = \"");
1068 if (ret) {
1069 goto error;
1070 }
1071
1072 /*
1073 * This is necessary since the creation time is present in the session
1074 * name when it is generated.
1075 */
1076 if (session->has_auto_generated_name) {
1077 ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME);
1078 } else {
1079 ret = print_escaped_ctf_string(registry, session->name);
1080 }
1081 if (ret) {
1082 goto error;
1083 }
1084
1085 ret = lttng_metadata_printf(registry, "\";\n");
1086 if (ret) {
1087 goto error;
1088 }
1089
1090 /* Prepare creation time */
1091 ret = time_to_iso8601_str(session->creation_time, creation_datetime,
1092 sizeof(creation_datetime));
1093 if (ret) {
1094 goto error;
1095 }
1096
1097 /* Output the reste of the information */
1098 ret = lttng_metadata_printf(registry,
1099 " trace_creation_datetime = \"%s\";\n"
1100 " hostname = \"%s\";\n",
1101 creation_datetime, session->hostname);
1102 if (ret) {
1103 goto error;
1104 }
1105
1106 error:
1107 if (session) {
1108 session_put(session);
1109 }
1110 rcu_read_unlock();
1111 return ret;
1112 }
1113
1114 static
1115 int print_metadata_app_information(ust_registry_session *registry)
1116 {
1117 if (registry->get_buffering_scheme() != LTTNG_BUFFER_PER_PID) {
1118 return 0;
1119 }
1120
1121 const auto *per_pid_session = static_cast<const ust_registry_session_per_pid *>(registry);
1122
1123 char datetime[ISO8601_STR_LEN];
1124 int ret = time_to_iso8601_str(
1125 per_pid_session->_app_creation_time, datetime, sizeof(datetime));
1126 if (ret) {
1127 return ret;
1128 }
1129
1130 ret = lttng_metadata_printf(registry,
1131 " tracer_patchlevel = %u;\n"
1132 " vpid = %d;\n"
1133 " procname = \"%s\";\n"
1134 " vpid_datetime = \"%s\";\n",
1135 per_pid_session->_tracer_patch_level_version, (int) per_pid_session->_vpid,
1136 per_pid_session->_procname.c_str(), datetime);
1137 return ret;
1138 }
1139
1140 /*
1141 * Should be called with session registry mutex held.
1142 */
1143 int ust_metadata_session_statedump(ust_registry_session *session)
1144 {
1145 int ret = 0;
1146 char trace_uuid_str[LTTNG_UUID_STR_LEN];
1147
1148 LTTNG_ASSERT(session);
1149
1150 lttng_uuid_to_str(session->_uuid, trace_uuid_str);
1151
1152 /* For crash ABI */
1153 ret = lttng_metadata_printf(session,
1154 "/* CTF %u.%u */\n\n",
1155 CTF_SPEC_MAJOR,
1156 CTF_SPEC_MINOR);
1157 if (ret) {
1158 goto end;
1159 }
1160
1161 ret = lttng_metadata_printf(session,
1162 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
1163 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
1164 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
1165 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
1166 "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n"
1167 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
1168 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
1169 "\n"
1170 "trace {\n"
1171 " major = %u;\n"
1172 " minor = %u;\n"
1173 " uuid = \"%s\";\n"
1174 " byte_order = %s;\n"
1175 " packet.header := struct {\n"
1176 " uint32_t magic;\n"
1177 " uint8_t uuid[16];\n"
1178 " uint32_t stream_id;\n"
1179 " uint64_t stream_instance_id;\n"
1180 " };\n"
1181 "};\n\n",
1182 session->_uint8_t_alignment,
1183 session->_uint16_t_alignment,
1184 session->_uint32_t_alignment,
1185 session->_uint64_t_alignment,
1186 session->_bits_per_long,
1187 session->_long_alignment,
1188 CTF_SPEC_MAJOR,
1189 CTF_SPEC_MINOR,
1190 trace_uuid_str,
1191 session->_byte_order == BIG_ENDIAN ? "be" : "le"
1192 );
1193 if (ret) {
1194 goto end;
1195 }
1196
1197 ret = lttng_metadata_printf(session,
1198 "env {\n"
1199 " domain = \"ust\";\n"
1200 " tracer_name = \"lttng-ust\";\n"
1201 " tracer_major = %u;\n"
1202 " tracer_minor = %u;\n"
1203 " tracer_buffering_scheme = \"%s\";\n"
1204 " tracer_buffering_id = %u;\n"
1205 " architecture_bit_width = %u;\n",
1206 session->_app_tracer_version_major, session->_app_tracer_version_minor,
1207 session->get_buffering_scheme() == LTTNG_BUFFER_PER_PID ? "pid" : "uid",
1208 session->get_buffering_scheme() == LTTNG_BUFFER_PER_PID ?
1209 (int) static_cast<ust_registry_session_per_pid *>(session)->_vpid :
1210 (int) static_cast<ust_registry_session_per_uid *>(session)->_tracing_uid,
1211 session->_bits_per_long);
1212 if (ret) {
1213 goto end;
1214 }
1215
1216 ret = print_metadata_session_information(session);
1217 if (ret) {
1218 goto end;
1219 }
1220
1221 /*
1222 * If per-application registry, we can output extra information
1223 * about the application.
1224 */
1225 ret = print_metadata_app_information(session);
1226 if (ret) {
1227 goto end;
1228 }
1229
1230 ret = lttng_metadata_printf(session,
1231 "};\n\n"
1232 );
1233 if (ret) {
1234 goto end;
1235 }
1236
1237 try {
1238 const lttng::ust::clock_attributes_sample clock;
1239
1240 ret = lttng_metadata_printf(session,
1241 "clock {\n"
1242 " name = \"%s\";\n",
1243 clock._name.c_str());
1244 if (ret) {
1245 goto end;
1246 }
1247
1248 if (clock._uuid) {
1249 char clock_uuid_str[LTTNG_UUID_STR_LEN];
1250
1251 lttng_uuid_to_str(*clock._uuid, clock_uuid_str);
1252 ret = lttng_metadata_printf(
1253 session, " uuid = \"%s\";\n", clock_uuid_str);
1254 if (ret) {
1255 goto end;
1256 }
1257 }
1258
1259 ret = lttng_metadata_printf(session,
1260 " description = \"%s\";\n"
1261 " freq = %" PRIu64 "; /* Frequency, in Hz */\n"
1262 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
1263 " offset = %" PRId64 ";\n"
1264 "};\n\n",
1265 clock._description.c_str(), clock._frequency, clock._offset);
1266 if (ret) {
1267 goto end;
1268 }
1269
1270 ret = lttng_metadata_printf(session,
1271 "typealias integer {\n"
1272 " size = 27; align = 1; signed = false;\n"
1273 " map = clock.%s.value;\n"
1274 "} := uint27_clock_monotonic_t;\n"
1275 "\n"
1276 "typealias integer {\n"
1277 " size = 32; align = %u; signed = false;\n"
1278 " map = clock.%s.value;\n"
1279 "} := uint32_clock_monotonic_t;\n"
1280 "\n"
1281 "typealias integer {\n"
1282 " size = 64; align = %u; signed = false;\n"
1283 " map = clock.%s.value;\n"
1284 "} := uint64_clock_monotonic_t;\n\n",
1285 clock._name.c_str(), session->_uint32_t_alignment,
1286 clock._name.c_str(), session->_uint64_t_alignment,
1287 clock._name.c_str());
1288 if (ret) {
1289 goto end;
1290 }
1291 } catch (const std::exception &ex) {
1292 ERR("Failed to serialize clock description: %s", ex.what());
1293 ret = -1;
1294 goto end;
1295 }
1296
1297 ret = _lttng_stream_packet_context_declare(session);
1298 if (ret) {
1299 goto end;
1300 }
1301
1302 ret = _lttng_event_header_declare(session);
1303 if (ret) {
1304 goto end;
1305 }
1306
1307 end:
1308 return ret;
1309 }
This page took 0.087955 seconds and 4 git commands to generate.