Rename C++ header files to .hpp
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.cpp
CommitLineData
d0b96690 1/*
d0b96690
DG
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
d0b96690 5 *
d0b96690
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
d0b96690
DG
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>
c9e313bc
SM
16#include <common/common.hpp>
17#include <common/time.hpp>
d0b96690 18
c9e313bc
SM
19#include "ust-registry.hpp"
20#include "ust-clock.hpp"
21#include "ust-app.hpp"
d0b96690
DG
22
23#ifndef max_t
24#define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b)))
25#endif
26
8c645bb0
MD
27#define NR_CLOCK_OFFSET_SAMPLES 10
28
29struct offset_sample {
c2636b57 30 int64_t offset; /* correlation offset */
8c645bb0
MD
31 uint64_t measure_delta; /* lower is better */
32};
33
da860cab
MD
34static
35int _lttng_field_statedump(struct ust_registry_session *session,
b623cb6a 36 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
da860cab
MD
37 size_t *iter_field, size_t nesting);
38
d0b96690
DG
39static inline
40int get_count_order(unsigned int count)
41{
42 int order;
43
78ddfe55 44 order = lttng_fls(count) - 1;
46b4dda6 45 if (count & (count - 1)) {
d0b96690 46 order++;
46b4dda6 47 }
a0377dfe 48 LTTNG_ASSERT(order >= 0);
d0b96690
DG
49 return order;
50}
51
52/*
53 * Returns offset where to write in metadata array, or negative error value on error.
54 */
55static
56ssize_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);
7966af57 73 newptr = (char *) realloc(session->metadata, new_alloc_len);
d0b96690
DG
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
d7ba1388
MD
86static
87int 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
d0b96690
DG
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 */
d22ad5f8 109static ATTR_FORMAT_PRINTF(2, 3)
d0b96690
DG
110int 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);
d7ba1388
MD
132 ret = metadata_file_append(session, str, len);
133 if (ret) {
134 PERROR("Error appending to metadata file");
135 goto end;
136 }
d0b96690
DG
137 DBG3("Append to metadata: \"%s\"", str);
138 ret = 0;
139
140end:
141 free(str);
142 return ret;
143}
144
da860cab
MD
145static
146int 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
a1f68b22
MD
161static
162void sanitize_ctf_identifier(char *out, const char *in)
163{
164 size_t i;
165
fc4b93fa 166 for (i = 0; i < LTTNG_UST_ABI_SYM_NAME_LEN; i++) {
a1f68b22
MD
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
8de88061
JR
179static
180int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
181{
35c829f8 182 int ret = 0;
8de88061
JR
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 }
212error:
213 return ret;
214}
215
10b56aef
MD
216/* Called with session registry mutex held. */
217static
218int ust_metadata_enum_statedump(struct ust_registry_session *session,
219 const char *enum_name,
220 uint64_t enum_id,
b623cb6a 221 const struct lttng_ust_ctl_integer_type *container_type,
da860cab 222 const char *field_name, size_t *iter_field, size_t nesting)
10b56aef
MD
223{
224 struct ust_registry_enum *reg_enum;
b623cb6a 225 const struct lttng_ust_ctl_enum_entry *entries;
10b56aef
MD
226 size_t nr_entries;
227 int ret = 0;
228 size_t i;
fc4b93fa 229 char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
10b56aef
MD
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
da860cab
MD
242 ret = print_tabs(session, nesting);
243 if (ret) {
244 goto end;
245 }
10b56aef 246 ret = lttng_metadata_printf(session,
da860cab 247 "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
10b56aef
MD
248 container_type->size,
249 container_type->alignment,
250 container_type->signedness,
b623cb6a 251 (container_type->encoding == lttng_ust_ctl_encode_none)
10b56aef 252 ? "none"
b623cb6a 253 : (container_type->encoding == lttng_ust_ctl_encode_UTF8)
10b56aef
MD
254 ? "UTF8"
255 : "ASCII",
256 container_type->base);
257 if (ret) {
258 goto end;
259 }
1ddb0e8a 260 nesting++;
10b56aef
MD
261 /* Dump all entries */
262 for (i = 0; i < nr_entries; i++) {
b623cb6a 263 const struct lttng_ust_ctl_enum_entry *entry = &entries[i];
10b56aef
MD
264 int j, len;
265
a1f68b22
MD
266 ret = print_tabs(session, nesting);
267 if (ret) {
268 goto end;
269 }
10b56aef 270 ret = lttng_metadata_printf(session,
a1f68b22 271 "\"");
10b56aef
MD
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 }
e85e3723 298 ret = lttng_metadata_printf(session, "\"");
10b56aef
MD
299 if (ret) {
300 goto end;
301 }
3b016e58 302
9d27cec7 303 if (entry->u.extra.options &
b623cb6a 304 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
e85e3723
PP
305 ret = lttng_metadata_printf(session, ",\n");
306 if (ret) {
307 goto end;
308 }
10b56aef
MD
309 } else {
310 ret = lttng_metadata_printf(session,
e85e3723
PP
311 " = ");
312 if (ret) {
313 goto end;
314 }
3b016e58 315
e85e3723 316 if (entry->start.signedness) {
3b016e58 317 ret = lttng_metadata_printf(session,
d22ad5f8 318 "%" PRId64, entry->start.value);
3b016e58
MD
319 } else {
320 ret = lttng_metadata_printf(session,
d22ad5f8 321 "%" PRIu64, entry->start.value);
e85e3723
PP
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,
d22ad5f8
SM
334 " ... %" PRId64 ",\n",
335 entry->end.value);
e85e3723
PP
336 } else {
337 ret = lttng_metadata_printf(session,
d22ad5f8 338 " ... %" PRIu64 ",\n",
e85e3723
PP
339 entry->end.value);
340 }
341 }
342 if (ret) {
343 goto end;
3b016e58 344 }
10b56aef
MD
345 }
346 }
1ddb0e8a 347 nesting--;
a1f68b22
MD
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);
da860cab
MD
355end:
356 (*iter_field)++;
357 return ret;
358}
359
da860cab
MD
360static
361int _lttng_variant_statedump(struct ust_registry_session *session,
0d32d1a9
MD
362 uint32_t nr_choices, const char *tag_name,
363 uint32_t alignment,
b623cb6a 364 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
da860cab
MD
365 size_t *iter_field, size_t nesting)
366{
b623cb6a 367 const struct lttng_ust_ctl_field *variant = &fields[*iter_field];
0d32d1a9 368 uint32_t i;
da860cab 369 int ret;
fc4b93fa 370 char identifier[LTTNG_UST_ABI_SYM_NAME_LEN];
da860cab 371
da860cab 372 (*iter_field)++;
0d32d1a9
MD
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 }
a1f68b22
MD
387 ret = print_tabs(session, nesting);
388 if (ret) {
389 goto end;
390 }
da860cab 391 ret = lttng_metadata_printf(session,
a1f68b22
MD
392 "variant <_%s> {\n",
393 identifier);
da860cab
MD
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);
dc6403f3
JG
406 if (ret) {
407 goto end;
408 }
da860cab 409 }
a1f68b22
MD
410 sanitize_ctf_identifier(identifier, variant->name);
411 ret = print_tabs(session, nesting);
850c5d4a
JR
412 if (ret) {
413 goto end;
414 }
da860cab 415 ret = lttng_metadata_printf(session,
a1f68b22
MD
416 "} _%s;\n",
417 identifier);
da860cab
MD
418 if (ret) {
419 goto end;
420 }
10b56aef
MD
421end:
422 return ret;
423}
424
d0b96690
DG
425static
426int _lttng_field_statedump(struct ust_registry_session *session,
b623cb6a 427 const struct lttng_ust_ctl_field *fields, size_t nr_fields,
da860cab 428 size_t *iter_field, size_t nesting)
d0b96690
DG
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;
b623cb6a 435 const struct lttng_ust_ctl_field *field;
d0b96690 436
da860cab
MD
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) {
d0b96690 444 bo_reverse = bo_le;
da860cab 445 } else {
d0b96690 446 bo_reverse = bo_be;
da860cab 447 }
d0b96690
DG
448
449 switch (field->type.atype) {
b623cb6a 450 case lttng_ust_ctl_atype_integer:
da860cab
MD
451 ret = print_tabs(session, nesting);
452 if (ret) {
453 goto end;
454 }
d0b96690 455 ret = lttng_metadata_printf(session,
da860cab 456 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
0d32d1a9
MD
457 field->type.u.integer.size,
458 field->type.u.integer.alignment,
459 field->type.u.integer.signedness,
b623cb6a 460 (field->type.u.integer.encoding == lttng_ust_ctl_encode_none)
d0b96690 461 ? "none"
b623cb6a 462 : (field->type.u.integer.encoding == lttng_ust_ctl_encode_UTF8)
d0b96690
DG
463 ? "UTF8"
464 : "ASCII",
0d32d1a9
MD
465 field->type.u.integer.base,
466 field->type.u.integer.reverse_byte_order ? bo_reverse : bo_native,
d0b96690 467 field->name);
da860cab 468 (*iter_field)++;
d0b96690 469 break;
b623cb6a 470 case lttng_ust_ctl_atype_enum:
10b56aef 471 ret = ust_metadata_enum_statedump(session,
0d32d1a9
MD
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,
da860cab 475 field->name, iter_field, nesting);
10b56aef 476 break;
b623cb6a 477 case lttng_ust_ctl_atype_float:
da860cab
MD
478 ret = print_tabs(session, nesting);
479 if (ret) {
480 goto end;
481 }
d0b96690 482 ret = lttng_metadata_printf(session,
da860cab 483 "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
0d32d1a9
MD
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,
d0b96690 488 field->name);
da860cab 489 (*iter_field)++;
d0b96690 490 break;
b623cb6a 491 case lttng_ust_ctl_atype_array:
d0b96690 492 {
b623cb6a 493 const struct lttng_ust_ctl_basic_type *elem_type;
d0b96690 494
da860cab
MD
495 ret = print_tabs(session, nesting);
496 if (ret) {
497 goto end;
498 }
0d32d1a9
MD
499 elem_type = &field->type.u.legacy.array.elem_type;
500 /* Only integers are currently supported in arrays. */
b623cb6a 501 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
0d32d1a9
MD
502 ret = -EINVAL;
503 goto end;
504 }
d0b96690 505 ret = lttng_metadata_printf(session,
da860cab 506 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
d0b96690
DG
507 elem_type->u.basic.integer.size,
508 elem_type->u.basic.integer.alignment,
509 elem_type->u.basic.integer.signedness,
b623cb6a 510 (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
d0b96690 511 ? "none"
b623cb6a 512 : (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
d0b96690
DG
513 ? "UTF8"
514 : "ASCII",
515 elem_type->u.basic.integer.base,
516 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
0d32d1a9
MD
517 field->name, field->type.u.legacy.array.length);
518 (*iter_field)++;
519 break;
520 }
b623cb6a 521 case lttng_ust_ctl_atype_array_nestable:
0d32d1a9
MD
522 {
523 uint32_t array_length;
b623cb6a
MJ
524 const struct lttng_ust_ctl_field *array_nestable;
525 const struct lttng_ust_ctl_type *elem_type;
0d32d1a9
MD
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. */
b623cb6a 538 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
0d32d1a9
MD
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,
b623cb6a 566 (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
0d32d1a9 567 ? "none"
b623cb6a 568 : (elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
0d32d1a9
MD
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);
da860cab 574 (*iter_field)++;
d0b96690
DG
575 break;
576 }
b623cb6a 577 case lttng_ust_ctl_atype_sequence:
d0b96690 578 {
b623cb6a
MJ
579 const struct lttng_ust_ctl_basic_type *elem_type;
580 const struct lttng_ust_ctl_basic_type *length_type;
d0b96690 581
0d32d1a9
MD
582 elem_type = &field->type.u.legacy.sequence.elem_type;
583 length_type = &field->type.u.legacy.sequence.length_type;
da860cab
MD
584 ret = print_tabs(session, nesting);
585 if (ret) {
586 goto end;
587 }
0d32d1a9
MD
588
589 /* Only integers are currently supported in sequences. */
b623cb6a 590 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
0d32d1a9
MD
591 ret = -EINVAL;
592 goto end;
593 }
594
d0b96690 595 ret = lttng_metadata_printf(session,
da860cab 596 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
d0b96690
DG
597 length_type->u.basic.integer.size,
598 (unsigned int) length_type->u.basic.integer.alignment,
599 length_type->u.basic.integer.signedness,
b623cb6a 600 (length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
d0b96690 601 ? "none"
b623cb6a 602 : ((length_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
d0b96690
DG
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);
da860cab
MD
608 if (ret) {
609 goto end;
610 }
d0b96690 611
da860cab
MD
612 ret = print_tabs(session, nesting);
613 if (ret) {
614 goto end;
615 }
d0b96690 616 ret = lttng_metadata_printf(session,
da860cab 617 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
d0b96690
DG
618 elem_type->u.basic.integer.size,
619 (unsigned int) elem_type->u.basic.integer.alignment,
620 elem_type->u.basic.integer.signedness,
b623cb6a 621 (elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_none)
d0b96690 622 ? "none"
b623cb6a 623 : ((elem_type->u.basic.integer.encoding == lttng_ust_ctl_encode_UTF8)
d0b96690
DG
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);
da860cab 630 (*iter_field)++;
d0b96690
DG
631 break;
632 }
b623cb6a 633 case lttng_ust_ctl_atype_sequence_nestable:
0d32d1a9 634 {
b623cb6a
MJ
635 const struct lttng_ust_ctl_field *sequence_nestable;
636 const struct lttng_ust_ctl_type *elem_type;
0d32d1a9
MD
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. */
b623cb6a 647 if (elem_type->atype != lttng_ust_ctl_atype_integer) {
0d32d1a9
MD
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 }
d0b96690 665
0d32d1a9
MD
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,
b623cb6a 675 (elem_type->u.integer.encoding == lttng_ust_ctl_encode_none)
0d32d1a9 676 ? "none"
b623cb6a 677 : ((elem_type->u.integer.encoding == lttng_ust_ctl_encode_UTF8)
0d32d1a9
MD
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 }
b623cb6a 687 case lttng_ust_ctl_atype_string:
d0b96690 688 /* Default encoding is UTF8 */
da860cab
MD
689 ret = print_tabs(session, nesting);
690 if (ret) {
691 goto end;
692 }
d0b96690 693 ret = lttng_metadata_printf(session,
da860cab 694 "string%s _%s;\n",
b623cb6a 695 field->type.u.string.encoding == lttng_ust_ctl_encode_ASCII ?
d0b96690
DG
696 " { encoding = ASCII; }" : "",
697 field->name);
da860cab
MD
698 (*iter_field)++;
699 break;
b623cb6a 700 case lttng_ust_ctl_atype_variant:
0d32d1a9
MD
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;
b623cb6a 710 case lttng_ust_ctl_atype_variant_nestable:
0d32d1a9
MD
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);
da860cab
MD
716 if (ret) {
717 goto end;
718 }
719 break;
b623cb6a 720 case lttng_ust_ctl_atype_struct:
0d32d1a9
MD
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 }
da860cab
MD
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)++;
d0b96690 734 break;
b623cb6a 735 case lttng_ust_ctl_atype_struct_nestable:
0d32d1a9
MD
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;
b623cb6a 760 case lttng_ust_ctl_atype_enum_nestable:
0d32d1a9 761 {
b623cb6a
MJ
762 const struct lttng_ust_ctl_field *container_field;
763 const struct lttng_ust_ctl_type *container_type;
0d32d1a9
MD
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. */
b623cb6a 774 if (container_type->atype != lttng_ust_ctl_atype_integer) {
0d32d1a9
MD
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 }
d0b96690 785 default:
da860cab 786 ret = -EINVAL;
d0b96690 787 }
da860cab 788end:
d0b96690
DG
789 return ret;
790}
791
792static
793int _lttng_context_metadata_statedump(struct ust_registry_session *session,
794 size_t nr_ctx_fields,
b623cb6a 795 struct lttng_ust_ctl_field *ctx)
d0b96690
DG
796{
797 int ret = 0;
da860cab 798 size_t i = 0;
d0b96690
DG
799
800 if (!ctx)
801 return 0;
da860cab
MD
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 }
d0b96690
DG
811 }
812 return ret;
813}
814
815static
816int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
817 struct ust_registry_event *event)
818{
819 int ret = 0;
da860cab 820 size_t i = 0;
d0b96690 821
da860cab
MD
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 }
d0b96690
DG
831 }
832 return ret;
833}
834
835/*
836 * Should be called with session registry mutex held.
837 */
838int 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);
0d32d1a9 856 if (ret) {
d0b96690 857 goto end;
0d32d1a9 858 }
d0b96690
DG
859
860 ret = lttng_metadata_printf(session,
861 " loglevel = %d;\n",
2106efa0 862 event->loglevel_value);
0d32d1a9 863 if (ret) {
d0b96690 864 goto end;
0d32d1a9 865 }
d0b96690
DG
866
867 if (event->model_emf_uri) {
868 ret = lttng_metadata_printf(session,
869 " model.emf.uri = \"%s\";\n",
870 event->model_emf_uri);
0d32d1a9 871 if (ret) {
d0b96690 872 goto end;
0d32d1a9 873 }
d0b96690
DG
874 }
875
d0b96690
DG
876 ret = lttng_metadata_printf(session,
877 " fields := struct {\n"
878 );
0d32d1a9 879 if (ret) {
d0b96690 880 goto end;
0d32d1a9 881 }
d0b96690
DG
882
883 ret = _lttng_fields_metadata_statedump(session, event);
0d32d1a9 884 if (ret) {
d0b96690 885 goto end;
0d32d1a9 886 }
d0b96690
DG
887
888 ret = lttng_metadata_printf(session,
889 " };\n"
890 "};\n\n");
0d32d1a9 891 if (ret) {
d0b96690 892 goto end;
0d32d1a9 893 }
7972aab2 894 event->metadata_dumped = 1;
d0b96690
DG
895
896end:
897 return ret;
898}
899
900/*
901 * Should be called with session registry mutex held.
902 */
903int 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,
b623cb6a 921 chan->header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT ?
d0b96690
DG
922 "struct event_header_compact" :
923 "struct event_header_large");
0d32d1a9 924 if (ret) {
d0b96690 925 goto end;
0d32d1a9 926 }
d0b96690
DG
927
928 if (chan->ctx_fields) {
929 ret = lttng_metadata_printf(session,
930 " event.context := struct {\n");
0d32d1a9 931 if (ret) {
d0b96690 932 goto end;
0d32d1a9 933 }
d0b96690
DG
934 }
935 ret = _lttng_context_metadata_statedump(session,
936 chan->nr_ctx_fields,
937 chan->ctx_fields);
0d32d1a9 938 if (ret) {
d0b96690 939 goto end;
0d32d1a9 940 }
d0b96690
DG
941 if (chan->ctx_fields) {
942 ret = lttng_metadata_printf(session,
943 " };\n");
0d32d1a9 944 if (ret) {
d0b96690 945 goto end;
0d32d1a9 946 }
d0b96690
DG
947 }
948
949 ret = lttng_metadata_printf(session,
950 "};\n\n");
7972aab2
DG
951 /* Flag success of metadata dump. */
952 chan->metadata_dumped = 1;
d0b96690
DG
953
954end:
955 return ret;
956}
957
958static
959int _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"
0793bcc6 967 " uint64_t packet_seq_num;\n"
d0b96690
DG
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 */
983static
984int _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
dc113ec7
MD
1017/*
1018 * The offset between monotonic and realtime clock can be negative if
1019 * the system sets the REALTIME clock to 0 after boot.
dc113ec7 1020 */
d0b96690 1021static
8c645bb0 1022int measure_single_clock_offset(struct offset_sample *sample)
d0b96690 1023{
dc113ec7 1024 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
fc0bb9fa 1025 uint64_t tcf = trace_clock_freq();
d0b96690
DG
1026 struct timespec rts = { 0, 0 };
1027 int ret;
1028
1029 monotonic[0] = trace_clock_read64();
389fbf04 1030 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
8c645bb0
MD
1031 if (ret < 0) {
1032 return ret;
1033 }
d0b96690 1034 monotonic[1] = trace_clock_read64();
8c645bb0
MD
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 }
dc113ec7 1043 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
6e1b0543
MD
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;
fc0bb9fa 1049 }
c2636b57 1050 sample->offset = (int64_t) realtime - monotonic_avg;
8c645bb0
MD
1051 sample->measure_delta = measure_delta;
1052 return 0;
d0b96690
DG
1053}
1054
8c645bb0
MD
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.
c2636b57 1059 * May return a negative offset.
8c645bb0
MD
1060 */
1061static
c2636b57 1062int64_t measure_clock_offset(void)
8c645bb0
MD
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}
d0b96690 1077
8de88061
JR
1078static
1079int 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
1132error:
1133 if (session) {
1134 session_put(session);
1135 }
1136 rcu_read_unlock();
1137 return ret;
1138}
1139
1140static
1141int 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
1166end:
1167 return ret;
1168}
1169
d0b96690
DG
1170/*
1171 * Should be called with session registry mutex held.
1172 */
1173int ust_metadata_session_statedump(struct ust_registry_session *session,
af6142cf
MD
1174 struct ust_app *app,
1175 uint32_t major,
1176 uint32_t minor)
d0b96690 1177{
c70636a7
MJ
1178 char uuid_s[LTTNG_UUID_STR_LEN],
1179 clock_uuid_s[LTTNG_UUID_STR_LEN];
d0b96690 1180 int ret = 0;
d0b96690 1181
a0377dfe 1182 LTTNG_ASSERT(session);
7972aab2 1183
c8e0c5f5 1184 lttng_uuid_to_str(session->uuid, uuid_s);
d0b96690 1185
d7ba1388
MD
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
d0b96690
DG
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"
0793bcc6 1213 " uint64_t stream_instance_id;\n"
d0b96690
DG
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 );
0d32d1a9 1227 if (ret) {
d0b96690 1228 goto end;
0d32d1a9 1229 }
d0b96690 1230
d0b96690
DG
1231 ret = lttng_metadata_printf(session,
1232 "env {\n"
d0b96690
DG
1233 " domain = \"ust\";\n"
1234 " tracer_name = \"lttng-ust\";\n"
1235 " tracer_major = %u;\n"
8de88061
JR
1236 " tracer_minor = %u;\n"
1237 " tracer_buffering_scheme = \"%s\";\n"
1238 " tracer_buffering_id = %u;\n"
1239 " architecture_bit_width = %u;\n",
af6142cf 1240 major,
8de88061
JR
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) {
d0b96690 1251 goto end;
8de88061 1252 }
d0b96690
DG
1253
1254 /*
1255 * If per-application registry, we can output extra information
1256 * about the application.
1257 */
8de88061
JR
1258 ret = print_metadata_app_information(session, app);
1259 if (ret) {
1260 goto end;
d0b96690
DG
1261 }
1262
1263 ret = lttng_metadata_printf(session,
1264 "};\n\n"
1265 );
0d32d1a9 1266 if (ret) {
d0b96690 1267 goto end;
0d32d1a9 1268 }
d0b96690
DG
1269
1270 ret = lttng_metadata_printf(session,
1271 "clock {\n"
fc0bb9fa
MD
1272 " name = \"%s\";\n",
1273 trace_clock_name()
d0b96690 1274 );
0d32d1a9 1275 if (ret) {
d0b96690 1276 goto end;
0d32d1a9 1277 }
d0b96690
DG
1278
1279 if (!trace_clock_uuid(clock_uuid_s)) {
1280 ret = lttng_metadata_printf(session,
1281 " uuid = \"%s\";\n",
1282 clock_uuid_s
1283 );
0d32d1a9 1284 if (ret) {
d0b96690 1285 goto end;
0d32d1a9 1286 }
d0b96690
DG
1287 }
1288
1289 ret = lttng_metadata_printf(session,
fc0bb9fa 1290 " description = \"%s\";\n"
d0b96690
DG
1291 " freq = %" PRIu64 "; /* Frequency, in Hz */\n"
1292 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
c2636b57 1293 " offset = %" PRId64 ";\n"
d0b96690 1294 "};\n\n",
fc0bb9fa 1295 trace_clock_description(),
d0b96690
DG
1296 trace_clock_freq(),
1297 measure_clock_offset()
1298 );
0d32d1a9 1299 if (ret) {
d0b96690 1300 goto end;
0d32d1a9 1301 }
d0b96690
DG
1302
1303 ret = lttng_metadata_printf(session,
1304 "typealias integer {\n"
1305 " size = 27; align = 1; signed = false;\n"
fc0bb9fa 1306 " map = clock.%s.value;\n"
d0b96690
DG
1307 "} := uint27_clock_monotonic_t;\n"
1308 "\n"
1309 "typealias integer {\n"
1310 " size = 32; align = %u; signed = false;\n"
fc0bb9fa 1311 " map = clock.%s.value;\n"
d0b96690
DG
1312 "} := uint32_clock_monotonic_t;\n"
1313 "\n"
1314 "typealias integer {\n"
1315 " size = 64; align = %u; signed = false;\n"
fc0bb9fa 1316 " map = clock.%s.value;\n"
d0b96690 1317 "} := uint64_clock_monotonic_t;\n\n",
fc0bb9fa 1318 trace_clock_name(),
d0b96690 1319 session->uint32_t_alignment,
fc0bb9fa
MD
1320 trace_clock_name(),
1321 session->uint64_t_alignment,
1322 trace_clock_name()
d0b96690 1323 );
0d32d1a9 1324 if (ret) {
d0b96690 1325 goto end;
0d32d1a9 1326 }
d0b96690
DG
1327
1328 ret = _lttng_stream_packet_context_declare(session);
0d32d1a9 1329 if (ret) {
d0b96690 1330 goto end;
0d32d1a9 1331 }
d0b96690
DG
1332
1333 ret = _lttng_event_header_declare(session);
0d32d1a9 1334 if (ret) {
d0b96690 1335 goto end;
0d32d1a9 1336 }
d0b96690
DG
1337
1338end:
1339 return ret;
1340}
This page took 0.131229 seconds and 4 git commands to generate.