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