lib/ctf-ir/clock-class.c: only serialize UUID if it is set
[babeltrace.git] / lib / ctf-ir / clock-class.c
1 /*
2 * clock-class.c
3 *
4 * Babeltrace CTF IR - Clock class
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #define BT_LOG_TAG "CLOCK-CLASS"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/compat/uuid-internal.h>
33 #include <babeltrace/ctf-ir/clock-class-internal.h>
34 #include <babeltrace/ctf-ir/utils.h>
35 #include <babeltrace/ref.h>
36 #include <babeltrace/compiler-internal.h>
37 #include <babeltrace/types.h>
38 #include <babeltrace/compat/string-internal.h>
39 #include <inttypes.h>
40 #include <babeltrace/object-internal.h>
41
42 static
43 void bt_ctf_clock_class_destroy(struct bt_object *obj);
44
45 BT_HIDDEN
46 bt_bool bt_ctf_clock_class_is_valid(struct bt_ctf_clock_class *clock_class)
47 {
48 return clock_class && clock_class->name;
49 }
50
51 int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
52 const char *name)
53 {
54 int ret = 0;
55
56 if (!clock_class) {
57 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
58 ret = -1;
59 goto end;
60 }
61
62 if (clock_class->frozen) {
63 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
64 clock_class, bt_ctf_clock_class_get_name(clock_class));
65 ret = -1;
66 goto end;
67 }
68
69 if (bt_ctf_validate_identifier(name)) {
70 BT_LOGE("Clock class's name is not a valid CTF identifier: "
71 "addr=%p, name=\"%s\"",
72 clock_class, name);
73 ret = -1;
74 goto end;
75 }
76
77 if (clock_class->name) {
78 g_string_assign(clock_class->name, name);
79 } else {
80 clock_class->name = g_string_new(name);
81 if (!clock_class->name) {
82 BT_LOGE_STR("Failed to allocate a GString.");
83 ret = -1;
84 goto end;
85 }
86 }
87
88 BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
89 clock_class, name);
90
91 end:
92 return ret;
93 }
94
95 static
96 bool validate_freq(struct bt_ctf_clock_class *clock_class,
97 const char *name, uint64_t freq)
98 {
99 bool is_valid = true;
100
101 if (freq == -1ULL || freq == 0) {
102 BT_LOGW("Invalid parameter: frequency is invalid: "
103 "addr=%p, name=\"%s\", freq=%" PRIu64,
104 clock_class, name, freq);
105 is_valid = false;
106 goto end;
107 }
108
109 end:
110 return is_valid;
111 }
112
113 struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
114 uint64_t freq)
115 {
116 int ret;
117 struct bt_ctf_clock_class *clock_class = NULL;
118
119 BT_LOGD("Creating default clock class object: name=\"%s\"",
120 name);
121
122 if (!validate_freq(NULL, name, freq)) {
123 /* validate_freq() logs errors */
124 goto error;
125 }
126
127 clock_class = g_new0(struct bt_ctf_clock_class, 1);
128 if (!clock_class) {
129 BT_LOGE_STR("Failed to allocate one clock class.");
130 goto error;
131 }
132
133 clock_class->precision = 1;
134 clock_class->frequency = freq;
135 bt_object_init(clock_class, bt_ctf_clock_class_destroy);
136
137 if (name) {
138 ret = bt_ctf_clock_class_set_name(clock_class, name);
139 if (ret) {
140 BT_LOGE("Cannot set clock class's name: "
141 "addr=%p, name=\"%s\"",
142 clock_class, name);
143 goto error;
144 }
145 }
146
147 BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
148 clock_class, name);
149 return clock_class;
150 error:
151 BT_PUT(clock_class);
152 return clock_class;
153 }
154
155 const char *bt_ctf_clock_class_get_name(struct bt_ctf_clock_class *clock_class)
156 {
157 const char *ret = NULL;
158
159 if (!clock_class) {
160 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
161 goto end;
162 }
163
164 if (clock_class->name) {
165 ret = clock_class->name->str;
166 }
167
168 end:
169 return ret;
170 }
171
172 const char *bt_ctf_clock_class_get_description(
173 struct bt_ctf_clock_class *clock_class)
174 {
175 const char *ret = NULL;
176
177 if (!clock_class) {
178 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
179 goto end;
180 }
181
182 if (clock_class->description) {
183 ret = clock_class->description->str;
184 }
185 end:
186 return ret;
187 }
188
189 int bt_ctf_clock_class_set_description(struct bt_ctf_clock_class *clock_class,
190 const char *desc)
191 {
192 int ret = 0;
193
194 if (!clock_class || !desc) {
195 BT_LOGW("Invalid parameter: clock class or description is NULL: "
196 "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
197 clock_class, bt_ctf_clock_class_get_name(clock_class),
198 desc);
199 ret = -1;
200 goto end;
201 }
202
203 if (clock_class->frozen) {
204 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
205 clock_class, bt_ctf_clock_class_get_name(clock_class));
206 ret = -1;
207 goto end;
208 }
209
210 clock_class->description = g_string_new(desc);
211 ret = clock_class->description ? 0 : -1;
212 BT_LOGV("Set clock class's description: addr=%p, "
213 "name=\"%s\", desc=\"%s\"",
214 clock_class, bt_ctf_clock_class_get_name(clock_class), desc);
215 end:
216 return ret;
217 }
218
219 uint64_t bt_ctf_clock_class_get_frequency(
220 struct bt_ctf_clock_class *clock_class)
221 {
222 uint64_t ret = -1ULL;
223
224 if (!clock_class) {
225 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
226 goto end;
227 }
228
229 ret = clock_class->frequency;
230 end:
231 return ret;
232 }
233
234 int bt_ctf_clock_class_set_frequency(struct bt_ctf_clock_class *clock_class,
235 uint64_t freq)
236 {
237 int ret = 0;
238
239 if (!clock_class) {
240 BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
241 "addr=%p, name=\"%s\"",
242 clock_class, bt_ctf_clock_class_get_name(clock_class));
243 ret = -1;
244 goto end;
245 }
246
247 if (!validate_freq(clock_class, bt_ctf_clock_class_get_name(clock_class),
248 freq)) {
249 /* validate_freq() logs errors */
250 goto end;
251 }
252
253 if (clock_class->frozen) {
254 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
255 clock_class, bt_ctf_clock_class_get_name(clock_class));
256 ret = -1;
257 goto end;
258 }
259
260 clock_class->frequency = freq;
261 BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
262 clock_class, bt_ctf_clock_class_get_name(clock_class), freq);
263 end:
264 return ret;
265 }
266
267 uint64_t bt_ctf_clock_class_get_precision(struct bt_ctf_clock_class *clock_class)
268 {
269 uint64_t ret = -1ULL;
270
271 if (!clock_class) {
272 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
273 goto end;
274 }
275
276 ret = clock_class->precision;
277 end:
278 return ret;
279 }
280
281 int bt_ctf_clock_class_set_precision(struct bt_ctf_clock_class *clock_class,
282 uint64_t precision)
283 {
284 int ret = 0;
285
286 if (!clock_class || precision == -1ULL) {
287 BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
288 "addr=%p, name=\"%s\", precision=%" PRIu64,
289 clock_class, bt_ctf_clock_class_get_name(clock_class),
290 precision);
291 ret = -1;
292 goto end;
293 }
294
295 if (clock_class->frozen) {
296 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
297 clock_class, bt_ctf_clock_class_get_name(clock_class));
298 ret = -1;
299 goto end;
300 }
301
302 clock_class->precision = precision;
303 BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
304 clock_class, bt_ctf_clock_class_get_name(clock_class),
305 precision);
306 end:
307 return ret;
308 }
309
310 int bt_ctf_clock_class_get_offset_s(struct bt_ctf_clock_class *clock_class,
311 int64_t *offset_s)
312 {
313 int ret = 0;
314
315 if (!clock_class || !offset_s) {
316 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
317 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
318 clock_class, bt_ctf_clock_class_get_name(clock_class),
319 offset_s);
320 ret = -1;
321 goto end;
322 }
323
324 *offset_s = clock_class->offset_s;
325 end:
326 return ret;
327 }
328
329 int bt_ctf_clock_class_set_offset_s(struct bt_ctf_clock_class *clock_class,
330 int64_t offset_s)
331 {
332 int ret = 0;
333
334 if (!clock_class) {
335 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
336 ret = -1;
337 goto end;
338 }
339
340 if (clock_class->frozen) {
341 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
342 clock_class, bt_ctf_clock_class_get_name(clock_class));
343 ret = -1;
344 goto end;
345 }
346
347 clock_class->offset_s = offset_s;
348 BT_LOGV("Set clock class's offset (seconds): "
349 "addr=%p, name=\"%s\", offset-s=%" PRId64,
350 clock_class, bt_ctf_clock_class_get_name(clock_class),
351 offset_s);
352 end:
353 return ret;
354 }
355
356 int bt_ctf_clock_class_get_offset_cycles(struct bt_ctf_clock_class *clock_class,
357 int64_t *offset)
358 {
359 int ret = 0;
360
361 if (!clock_class || !offset) {
362 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
363 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
364 clock_class, bt_ctf_clock_class_get_name(clock_class),
365 offset);
366 ret = -1;
367 goto end;
368 }
369
370 *offset = clock_class->offset;
371 end:
372 return ret;
373 }
374
375 int bt_ctf_clock_class_set_offset_cycles(struct bt_ctf_clock_class *clock_class,
376 int64_t offset)
377 {
378 int ret = 0;
379
380 if (!clock_class) {
381 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
382 ret = -1;
383 goto end;
384 }
385
386 if (clock_class->frozen) {
387 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
388 clock_class, bt_ctf_clock_class_get_name(clock_class));
389 ret = -1;
390 goto end;
391 }
392
393 clock_class->offset = offset;
394 BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
395 clock_class, bt_ctf_clock_class_get_name(clock_class), offset);
396 end:
397 return ret;
398 }
399
400 bt_bool bt_ctf_clock_class_is_absolute(struct bt_ctf_clock_class *clock_class)
401 {
402 int ret = -1;
403
404 if (!clock_class) {
405 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
406 goto end;
407 }
408
409 ret = clock_class->absolute;
410 end:
411 return ret;
412 }
413
414 int bt_ctf_clock_class_set_is_absolute(struct bt_ctf_clock_class *clock_class,
415 bt_bool is_absolute)
416 {
417 int ret = 0;
418
419 if (!clock_class) {
420 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
421 ret = -1;
422 goto end;
423 }
424
425 if (clock_class->frozen) {
426 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
427 clock_class, bt_ctf_clock_class_get_name(clock_class));
428 ret = -1;
429 goto end;
430 }
431
432 clock_class->absolute = !!is_absolute;
433 BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
434 clock_class, bt_ctf_clock_class_get_name(clock_class),
435 is_absolute);
436 end:
437 return ret;
438 }
439
440 const unsigned char *bt_ctf_clock_class_get_uuid(
441 struct bt_ctf_clock_class *clock_class)
442 {
443 const unsigned char *ret;
444
445 if (!clock_class) {
446 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
447 ret = NULL;
448 goto end;
449 }
450
451 if (!clock_class->uuid_set) {
452 BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
453 clock_class, bt_ctf_clock_class_get_name(clock_class));
454 ret = NULL;
455 goto end;
456 }
457
458 ret = clock_class->uuid;
459 end:
460 return ret;
461 }
462
463 int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
464 const unsigned char *uuid)
465 {
466 int ret = 0;
467
468 if (!clock_class || !uuid) {
469 BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
470 "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
471 clock_class, bt_ctf_clock_class_get_name(clock_class),
472 uuid);
473 ret = -1;
474 goto end;
475 }
476
477 if (clock_class->frozen) {
478 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
479 clock_class, bt_ctf_clock_class_get_name(clock_class));
480 ret = -1;
481 goto end;
482 }
483
484 memcpy(clock_class->uuid, uuid, BABELTRACE_UUID_LEN);
485 clock_class->uuid_set = 1;
486 BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
487 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
488 clock_class, bt_ctf_clock_class_get_name(clock_class),
489 (unsigned int) uuid[0],
490 (unsigned int) uuid[1],
491 (unsigned int) uuid[2],
492 (unsigned int) uuid[3],
493 (unsigned int) uuid[4],
494 (unsigned int) uuid[5],
495 (unsigned int) uuid[6],
496 (unsigned int) uuid[7],
497 (unsigned int) uuid[8],
498 (unsigned int) uuid[9],
499 (unsigned int) uuid[10],
500 (unsigned int) uuid[11],
501 (unsigned int) uuid[12],
502 (unsigned int) uuid[13],
503 (unsigned int) uuid[14],
504 (unsigned int) uuid[15]);
505 end:
506 return ret;
507 }
508
509 static uint64_t ns_from_value(uint64_t frequency, uint64_t value)
510 {
511 uint64_t ns;
512
513 if (frequency == 1000000000) {
514 ns = value;
515 } else {
516 ns = (uint64_t) ((1e9 * (double) value) / (double) frequency);
517 }
518
519 return ns;
520 }
521
522 BT_HIDDEN
523 void bt_ctf_clock_class_freeze(struct bt_ctf_clock_class *clock_class)
524 {
525 if (!clock_class) {
526 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
527 return;
528 }
529
530 if (!clock_class->frozen) {
531 BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
532 clock_class, bt_ctf_clock_class_get_name(clock_class));
533 clock_class->frozen = 1;
534 }
535 }
536
537 BT_HIDDEN
538 void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
539 struct metadata_context *context)
540 {
541 unsigned char *uuid;
542
543 BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
544 "name=\"%s\", metadata-context-addr=%p", clock_class,
545 bt_ctf_clock_class_get_name(clock_class), context);
546
547 if (!clock_class || !context) {
548 BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
549 "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
550 clock_class, bt_ctf_clock_class_get_name(clock_class),
551 context);
552 return;
553 }
554
555 uuid = clock_class->uuid;
556 g_string_append(context->string, "clock {\n");
557 g_string_append_printf(context->string, "\tname = %s;\n",
558 clock_class->name->str);
559
560 if (clock_class->uuid_set) {
561 g_string_append_printf(context->string,
562 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
563 uuid[0], uuid[1], uuid[2], uuid[3],
564 uuid[4], uuid[5], uuid[6], uuid[7],
565 uuid[8], uuid[9], uuid[10], uuid[11],
566 uuid[12], uuid[13], uuid[14], uuid[15]);
567 }
568
569 if (clock_class->description) {
570 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
571 clock_class->description->str);
572 }
573
574 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
575 clock_class->frequency);
576 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
577 clock_class->precision);
578 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
579 clock_class->offset_s);
580 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
581 clock_class->offset);
582 g_string_append_printf(context->string, "\tabsolute = %s;\n",
583 clock_class->absolute ? "TRUE" : "FALSE");
584 g_string_append(context->string, "};\n\n");
585 }
586
587 static
588 void bt_ctf_clock_class_destroy(struct bt_object *obj)
589 {
590 struct bt_ctf_clock_class *clock_class;
591
592 clock_class = container_of(obj, struct bt_ctf_clock_class, base);
593 BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
594 obj, bt_ctf_clock_class_get_name(clock_class));
595 if (clock_class->name) {
596 g_string_free(clock_class->name, TRUE);
597 }
598 if (clock_class->description) {
599 g_string_free(clock_class->description, TRUE);
600 }
601
602 g_free(clock_class);
603 }
604
605 static
606 void bt_ctf_clock_value_destroy(struct bt_object *obj)
607 {
608 struct bt_ctf_clock_value *value;
609
610 if (!obj) {
611 return;
612 }
613
614 value = container_of(obj, struct bt_ctf_clock_value, base);
615 BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
616 "clock-class-name=\"%s\"", obj, value->clock_class,
617 bt_ctf_clock_class_get_name(value->clock_class));
618 bt_put(value->clock_class);
619 g_free(value);
620 }
621
622 struct bt_ctf_clock_value *bt_ctf_clock_value_create(
623 struct bt_ctf_clock_class *clock_class, uint64_t value)
624 {
625 struct bt_ctf_clock_value *ret = NULL;
626
627 BT_LOGD("Creating clock value object: clock-class-addr=%p, "
628 "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
629 bt_ctf_clock_class_get_name(clock_class), value);
630
631 if (!clock_class) {
632 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
633 goto end;
634 }
635
636 ret = g_new0(struct bt_ctf_clock_value, 1);
637 if (!ret) {
638 BT_LOGE_STR("Failed to allocate one clock value.");
639 goto end;
640 }
641
642 bt_object_init(ret, bt_ctf_clock_value_destroy);
643 ret->clock_class = bt_get(clock_class);
644 ret->value = value;
645 BT_LOGD("Created clock value object: clock-value-addr=%p, "
646 "clock-class-addr=%p, clock-class-name=\"%s\"",
647 ret, clock_class, bt_ctf_clock_class_get_name(clock_class));
648 end:
649 return ret;
650 }
651
652 int bt_ctf_clock_value_get_value(
653 struct bt_ctf_clock_value *clock_value, uint64_t *raw_value)
654 {
655 int ret = 0;
656
657 if (!clock_value || !raw_value) {
658 BT_LOGW("Invalid parameter: clock value or raw value is NULL: "
659 "clock-value-addr=%p, raw-value-addr=%p",
660 clock_value, raw_value);
661 ret = -1;
662 goto end;
663 }
664
665 *raw_value = clock_value->value;
666 end:
667 return ret;
668 }
669
670 int bt_ctf_clock_value_get_value_ns_from_epoch(struct bt_ctf_clock_value *value,
671 int64_t *ret_value_ns)
672 {
673 int ret = 0;
674 int64_t ns;
675
676 if (!value || !ret_value_ns) {
677 BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
678 "clock-value-addr=%p, ret-value-addr=%p",
679 value, ret_value_ns);
680 ret = -1;
681 goto end;
682 }
683
684 /* Initialize nanosecond timestamp to clock's offset in seconds. */
685 ns = value->clock_class->offset_s * (int64_t) 1000000000;
686
687 /* Add offset in cycles, converted to nanoseconds. */
688 ns += ns_from_value(value->clock_class->frequency,
689 value->clock_class->offset);
690
691 /* Add given value, converter to nanoseconds. */
692 ns += ns_from_value(value->clock_class->frequency, value->value);
693
694 *ret_value_ns = ns;
695 end:
696 return ret;
697 }
698
699 struct bt_ctf_clock_class *bt_ctf_clock_value_get_class(
700 struct bt_ctf_clock_value *clock_value)
701 {
702 struct bt_ctf_clock_class *clock_class = NULL;
703
704 if (!clock_value) {
705 BT_LOGW_STR("Invalid parameter: clock value is NULL.");
706 goto end;
707 }
708
709 clock_class = bt_get(clock_value->clock_class);
710
711 end:
712 return clock_class;
713 }
This page took 0.042672 seconds and 5 git commands to generate.