sessiond: make functions static in ust-registry.c
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.c
CommitLineData
d0b96690
DG
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
6c1c0768 22#define _LGPL_SOURCE
d0b96690
DG
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>
395d6b02 31#include <common/time.h>
d0b96690
DG
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
8c645bb0
MD
41#define NR_CLOCK_OFFSET_SAMPLES 10
42
43struct offset_sample {
c2636b57 44 int64_t offset; /* correlation offset */
8c645bb0
MD
45 uint64_t measure_delta; /* lower is better */
46};
47
da860cab
MD
48static
49int _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
d0b96690
DG
53static inline
54int 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)) {
d0b96690
DG
77 r -= 1;
78 }
79 return r;
80}
81
82static inline
83int get_count_order(unsigned int count)
84{
85 int order;
86
87 order = fls(count) - 1;
46b4dda6 88 if (count & (count - 1)) {
d0b96690 89 order++;
46b4dda6
JG
90 }
91 assert(order >= 0);
d0b96690
DG
92 return order;
93}
94
95/*
96 * Returns offset where to write in metadata array, or negative error value on error.
97 */
98static
99ssize_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
d7ba1388
MD
129static
130int 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
d0b96690
DG
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 */
152static
153int 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);
d7ba1388
MD
175 ret = metadata_file_append(session, str, len);
176 if (ret) {
177 PERROR("Error appending to metadata file");
178 goto end;
179 }
d0b96690
DG
180 DBG3("Append to metadata: \"%s\"", str);
181 ret = 0;
182
183end:
184 free(str);
185 return ret;
186}
187
da860cab
MD
188static
189int 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
a1f68b22
MD
204static
205void 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
8de88061
JR
222static
223int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
224{
35c829f8 225 int ret = 0;
8de88061
JR
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 }
255error:
256 return ret;
257}
258
10b56aef
MD
259/* Called with session registry mutex held. */
260static
261int 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,
da860cab 265 const char *field_name, size_t *iter_field, size_t nesting)
10b56aef
MD
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;
a1f68b22 272 char identifier[LTTNG_UST_SYM_NAME_LEN];
10b56aef
MD
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
da860cab
MD
285 ret = print_tabs(session, nesting);
286 if (ret) {
287 goto end;
288 }
10b56aef 289 ret = lttng_metadata_printf(session,
da860cab 290 "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
10b56aef
MD
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 }
1ddb0e8a 303 nesting++;
10b56aef
MD
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
a1f68b22
MD
309 ret = print_tabs(session, nesting);
310 if (ret) {
311 goto end;
312 }
10b56aef 313 ret = lttng_metadata_printf(session,
a1f68b22 314 "\"");
10b56aef
MD
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 }
e85e3723 341 ret = lttng_metadata_printf(session, "\"");
10b56aef
MD
342 if (ret) {
343 goto end;
344 }
3b016e58 345
9d27cec7
PP
346 if (entry->u.extra.options &
347 USTCTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
e85e3723
PP
348 ret = lttng_metadata_printf(session, ",\n");
349 if (ret) {
350 goto end;
351 }
10b56aef
MD
352 } else {
353 ret = lttng_metadata_printf(session,
e85e3723
PP
354 " = ");
355 if (ret) {
356 goto end;
357 }
3b016e58 358
e85e3723 359 if (entry->start.signedness) {
3b016e58 360 ret = lttng_metadata_printf(session,
e85e3723 361 "%lld", (long long) entry->start.value);
3b016e58
MD
362 } else {
363 ret = lttng_metadata_printf(session,
e85e3723
PP
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;
3b016e58 387 }
10b56aef
MD
388 }
389 }
1ddb0e8a 390 nesting--;
a1f68b22
MD
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);
da860cab
MD
398end:
399 (*iter_field)++;
400 return ret;
401}
402
da860cab
MD
403static
404int _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;
a1f68b22 411 char identifier[LTTNG_UST_SYM_NAME_LEN];
da860cab
MD
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)++;
a1f68b22
MD
419 sanitize_ctf_identifier(identifier, variant->type.u.variant.tag_name);
420 ret = print_tabs(session, nesting);
421 if (ret) {
422 goto end;
423 }
da860cab 424 ret = lttng_metadata_printf(session,
a1f68b22
MD
425 "variant <_%s> {\n",
426 identifier);
da860cab
MD
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);
dc6403f3
JG
439 if (ret) {
440 goto end;
441 }
da860cab 442 }
a1f68b22
MD
443 sanitize_ctf_identifier(identifier, variant->name);
444 ret = print_tabs(session, nesting);
850c5d4a
JR
445 if (ret) {
446 goto end;
447 }
da860cab 448 ret = lttng_metadata_printf(session,
a1f68b22
MD
449 "} _%s;\n",
450 identifier);
da860cab
MD
451 if (ret) {
452 goto end;
453 }
10b56aef
MD
454end:
455 return ret;
456}
457
d0b96690
DG
458static
459int _lttng_field_statedump(struct ust_registry_session *session,
da860cab
MD
460 const struct ustctl_field *fields, size_t nr_fields,
461 size_t *iter_field, size_t nesting)
d0b96690
DG
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;
da860cab 468 const struct ustctl_field *field;
d0b96690 469
da860cab
MD
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) {
d0b96690 477 bo_reverse = bo_le;
da860cab 478 } else {
d0b96690 479 bo_reverse = bo_be;
da860cab 480 }
d0b96690
DG
481
482 switch (field->type.atype) {
483 case ustctl_atype_integer:
da860cab
MD
484 ret = print_tabs(session, nesting);
485 if (ret) {
486 goto end;
487 }
d0b96690 488 ret = lttng_metadata_printf(session,
da860cab 489 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
d0b96690
DG
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);
da860cab 501 (*iter_field)++;
d0b96690 502 break;
10b56aef
MD
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,
da860cab 508 field->name, iter_field, nesting);
10b56aef 509 break;
d0b96690 510 case ustctl_atype_float:
da860cab
MD
511 ret = print_tabs(session, nesting);
512 if (ret) {
513 goto end;
514 }
d0b96690 515 ret = lttng_metadata_printf(session,
da860cab 516 "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
d0b96690
DG
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);
da860cab 522 (*iter_field)++;
d0b96690 523 break;
d0b96690
DG
524 case ustctl_atype_array:
525 {
526 const struct ustctl_basic_type *elem_type;
527
da860cab
MD
528 ret = print_tabs(session, nesting);
529 if (ret) {
530 goto end;
531 }
d0b96690
DG
532 elem_type = &field->type.u.array.elem_type;
533 ret = lttng_metadata_printf(session,
da860cab 534 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
d0b96690
DG
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);
da860cab 546 (*iter_field)++;
d0b96690
DG
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;
da860cab
MD
556 ret = print_tabs(session, nesting);
557 if (ret) {
558 goto end;
559 }
d0b96690 560 ret = lttng_metadata_printf(session,
da860cab 561 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
d0b96690
DG
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);
da860cab
MD
573 if (ret) {
574 goto end;
575 }
d0b96690 576
da860cab
MD
577 ret = print_tabs(session, nesting);
578 if (ret) {
579 goto end;
580 }
d0b96690 581 ret = lttng_metadata_printf(session,
da860cab 582 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
d0b96690
DG
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);
da860cab 595 (*iter_field)++;
d0b96690
DG
596 break;
597 }
598
599 case ustctl_atype_string:
600 /* Default encoding is UTF8 */
da860cab
MD
601 ret = print_tabs(session, nesting);
602 if (ret) {
603 goto end;
604 }
d0b96690 605 ret = lttng_metadata_printf(session,
da860cab 606 "string%s _%s;\n",
d0b96690
DG
607 field->type.u.basic.string.encoding == ustctl_encode_ASCII ?
608 " { encoding = ASCII; }" : "",
609 field->name);
da860cab
MD
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)++;
d0b96690
DG
627 break;
628 default:
da860cab 629 ret = -EINVAL;
d0b96690 630 }
da860cab 631end:
d0b96690
DG
632 return ret;
633}
634
635static
636int _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;
da860cab 641 size_t i = 0;
d0b96690
DG
642
643 if (!ctx)
644 return 0;
da860cab
MD
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 }
d0b96690
DG
654 }
655 return ret;
656}
657
658static
659int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
660 struct ust_registry_event *event)
661{
662 int ret = 0;
da860cab 663 size_t i = 0;
d0b96690 664
da860cab
MD
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 }
d0b96690
DG
674 }
675 return ret;
676}
677
678/*
679 * Should be called with session registry mutex held.
680 */
681int 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",
2106efa0 704 event->loglevel_value);
d0b96690
DG
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
d0b96690
DG
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;
7972aab2 731 event->metadata_dumped = 1;
d0b96690
DG
732
733end:
734 return ret;
735}
736
737/*
738 * Should be called with session registry mutex held.
739 */
740int 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");
7972aab2
DG
784 /* Flag success of metadata dump. */
785 chan->metadata_dumped = 1;
d0b96690
DG
786
787end:
788 return ret;
789}
790
791static
792int _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"
0793bcc6 800 " uint64_t packet_seq_num;\n"
d0b96690
DG
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 */
816static
817int _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
dc113ec7
MD
850/*
851 * The offset between monotonic and realtime clock can be negative if
852 * the system sets the REALTIME clock to 0 after boot.
dc113ec7 853 */
d0b96690 854static
8c645bb0 855int measure_single_clock_offset(struct offset_sample *sample)
d0b96690 856{
dc113ec7 857 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
fc0bb9fa 858 uint64_t tcf = trace_clock_freq();
d0b96690
DG
859 struct timespec rts = { 0, 0 };
860 int ret;
861
862 monotonic[0] = trace_clock_read64();
389fbf04 863 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
8c645bb0
MD
864 if (ret < 0) {
865 return ret;
866 }
d0b96690 867 monotonic[1] = trace_clock_read64();
8c645bb0
MD
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 }
dc113ec7 876 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
6e1b0543
MD
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;
fc0bb9fa 882 }
c2636b57 883 sample->offset = (int64_t) realtime - monotonic_avg;
8c645bb0
MD
884 sample->measure_delta = measure_delta;
885 return 0;
d0b96690
DG
886}
887
8c645bb0
MD
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.
c2636b57 892 * May return a negative offset.
8c645bb0
MD
893 */
894static
c2636b57 895int64_t measure_clock_offset(void)
8c645bb0
MD
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}
d0b96690 910
8de88061
JR
911static
912int 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
965error:
966 if (session) {
967 session_put(session);
968 }
969 rcu_read_unlock();
970 return ret;
971}
972
973static
974int 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
999end:
1000 return ret;
1001}
1002
d0b96690
DG
1003/*
1004 * Should be called with session registry mutex held.
1005 */
1006int ust_metadata_session_statedump(struct ust_registry_session *session,
af6142cf
MD
1007 struct ust_app *app,
1008 uint32_t major,
1009 uint32_t minor)
d0b96690 1010{
c70636a7
MJ
1011 char uuid_s[LTTNG_UUID_STR_LEN],
1012 clock_uuid_s[LTTNG_UUID_STR_LEN];
d0b96690 1013 int ret = 0;
d0b96690 1014
7972aab2 1015 assert(session);
7972aab2 1016
c8e0c5f5 1017 lttng_uuid_to_str(session->uuid, uuid_s);
d0b96690 1018
d7ba1388
MD
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
d0b96690
DG
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"
0793bcc6 1046 " uint64_t stream_instance_id;\n"
d0b96690
DG
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
d0b96690
DG
1063 ret = lttng_metadata_printf(session,
1064 "env {\n"
d0b96690
DG
1065 " domain = \"ust\";\n"
1066 " tracer_name = \"lttng-ust\";\n"
1067 " tracer_major = %u;\n"
8de88061
JR
1068 " tracer_minor = %u;\n"
1069 " tracer_buffering_scheme = \"%s\";\n"
1070 " tracer_buffering_id = %u;\n"
1071 " architecture_bit_width = %u;\n",
af6142cf 1072 major,
8de88061
JR
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) {
d0b96690 1083 goto end;
8de88061 1084 }
d0b96690
DG
1085
1086 /*
1087 * If per-application registry, we can output extra information
1088 * about the application.
1089 */
8de88061
JR
1090 ret = print_metadata_app_information(session, app);
1091 if (ret) {
1092 goto end;
d0b96690
DG
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"
fc0bb9fa
MD
1104 " name = \"%s\";\n",
1105 trace_clock_name()
d0b96690
DG
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,
fc0bb9fa 1120 " description = \"%s\";\n"
d0b96690
DG
1121 " freq = %" PRIu64 "; /* Frequency, in Hz */\n"
1122 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
c2636b57 1123 " offset = %" PRId64 ";\n"
d0b96690 1124 "};\n\n",
fc0bb9fa 1125 trace_clock_description(),
d0b96690
DG
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"
fc0bb9fa 1135 " map = clock.%s.value;\n"
d0b96690
DG
1136 "} := uint27_clock_monotonic_t;\n"
1137 "\n"
1138 "typealias integer {\n"
1139 " size = 32; align = %u; signed = false;\n"
fc0bb9fa 1140 " map = clock.%s.value;\n"
d0b96690
DG
1141 "} := uint32_clock_monotonic_t;\n"
1142 "\n"
1143 "typealias integer {\n"
1144 " size = 64; align = %u; signed = false;\n"
fc0bb9fa 1145 " map = clock.%s.value;\n"
d0b96690 1146 "} := uint64_clock_monotonic_t;\n\n",
fc0bb9fa 1147 trace_clock_name(),
d0b96690 1148 session->uint32_t_alignment,
fc0bb9fa
MD
1149 trace_clock_name(),
1150 session->uint64_t_alignment,
1151 trace_clock_name()
d0b96690
DG
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
1164end:
1165 return ret;
1166}
This page took 0.124895 seconds and 4 git commands to generate.