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