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