lib: rename include dir to babeltrace2
[babeltrace.git] / lib / trace-ir / trace.c
CommitLineData
bc37ae52 1/*
e2f7325d 2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
bc37ae52
JG
3 * Copyright 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
bc37ae52
JG
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
e011d2c1 24#define BT_LOG_TAG "TRACE"
3fadfbc0 25#include <babeltrace2/lib-logging-internal.h>
e011d2c1 26
3fadfbc0
MJ
27#include <babeltrace2/assert-pre-internal.h>
28#include <babeltrace2/trace-ir/trace.h>
29#include <babeltrace2/trace-ir/trace-class-internal.h>
30#include <babeltrace2/trace-ir/trace-const.h>
31#include <babeltrace2/trace-ir/trace-internal.h>
32#include <babeltrace2/trace-ir/clock-class-internal.h>
33#include <babeltrace2/trace-ir/stream-internal.h>
34#include <babeltrace2/trace-ir/stream-class-internal.h>
35#include <babeltrace2/trace-ir/event-internal.h>
36#include <babeltrace2/trace-ir/event-class.h>
37#include <babeltrace2/trace-ir/event-class-internal.h>
38#include <babeltrace2/ctf-writer/functor-internal.h>
39#include <babeltrace2/ctf-writer/clock-internal.h>
40#include <babeltrace2/trace-ir/field-wrapper-internal.h>
41#include <babeltrace2/trace-ir/field-class-internal.h>
42#include <babeltrace2/trace-ir/attributes-internal.h>
43#include <babeltrace2/trace-ir/utils-internal.h>
44#include <babeltrace2/trace-ir/resolve-field-path-internal.h>
45#include <babeltrace2/compiler-internal.h>
46#include <babeltrace2/value.h>
47#include <babeltrace2/value-const.h>
48#include <babeltrace2/value-internal.h>
49#include <babeltrace2/types.h>
50#include <babeltrace2/endian-internal.h>
51#include <babeltrace2/assert-internal.h>
52#include <babeltrace2/compat/glib-internal.h>
dc3fffef 53#include <inttypes.h>
544d0515 54#include <stdint.h>
4a32fda0 55#include <string.h>
0fbb9a9f 56#include <stdlib.h>
bc37ae52 57
ad5268b5
FD
58struct bt_trace_destruction_listener_elem {
59 bt_trace_destruction_listener_func func;
3602afb0
PP
60 void *data;
61};
62
44c440bc
PP
63#define BT_ASSERT_PRE_TRACE_HOT(_trace) \
64 BT_ASSERT_PRE_HOT((_trace), "Trace", ": %!+t", (_trace))
cb6f1f7d 65
bc37ae52 66static
44c440bc 67void destroy_trace(struct bt_object *obj)
3dca2276
PP
68{
69 struct bt_trace *trace = (void *) obj;
bc37ae52 70
44c440bc 71 BT_LIB_LOGD("Destroying trace object: %!+t", trace);
bc37ae52 72
3dca2276 73 /*
ad5268b5
FD
74 * Call destruction listener functions so that everything else
75 * still exists in the trace.
3dca2276 76 */
ad5268b5
FD
77 if (trace->destruction_listeners) {
78 uint64_t i;
79 BT_LIB_LOGV("Calling trace destruction listener(s): %!+t", trace);
c47a6bec
SM
80
81 /*
82 * The trace's reference count is 0 if we're here. Increment
83 * it to avoid a double-destroy (possibly infinitely recursive).
84 * This could happen for example if a destruction listener did
85 * bt_object_get_ref() (or anything that causes
86 * bt_object_get_ref() to be called) on the trace (ref.
87 * count goes from 0 to 1), and then bt_object_put_ref(): the
88 * reference count would go from 1 to 0 again and this function
89 * would be called again.
90 */
91 trace->base.ref_count++;
92
ad5268b5
FD
93 /* Call all the trace destruction listeners */
94 for (i = 0; i < trace->destruction_listeners->len; i++) {
95 struct bt_trace_destruction_listener_elem elem =
96 g_array_index(trace->destruction_listeners,
97 struct bt_trace_destruction_listener_elem, i);
98
99 if (elem.func) {
100 elem.func(trace, elem.data);
3dca2276 101 }
c47a6bec
SM
102
103 /*
104 * The destruction listener should not have kept a
105 * reference to the trace.
106 */
107 BT_ASSERT_PRE(trace->base.ref_count == 1, "Destruction listener kept a reference to the trace being destroyed: %![trace-]+t", trace);
3dca2276 108 }
ad5268b5
FD
109 g_array_free(trace->destruction_listeners, TRUE);
110 trace->destruction_listeners = NULL;
bc37ae52
JG
111 }
112
44c440bc
PP
113 if (trace->name.str) {
114 g_string_free(trace->name.str, TRUE);
238b7404
PP
115 trace->name.str = NULL;
116 trace->name.value = NULL;
95c09b3a
PP
117 }
118
44c440bc
PP
119 if (trace->streams) {
120 BT_LOGD_STR("Destroying streams.");
121 g_ptr_array_free(trace->streams, TRUE);
238b7404 122 trace->streams = NULL;
bc37ae52
JG
123 }
124
44c440bc
PP
125 if (trace->stream_classes_stream_count) {
126 g_hash_table_destroy(trace->stream_classes_stream_count);
238b7404 127 trace->stream_classes_stream_count = NULL;
44c440bc 128 }
3dca2276 129
862ca4ed
PP
130 BT_LOGD_STR("Putting trace's class.");
131 bt_object_put_ref(trace->class);
132 trace->class = NULL;
44c440bc 133 g_free(trace);
3dca2276
PP
134}
135
862ca4ed 136struct bt_trace *bt_trace_create(struct bt_trace_class *tc)
3dca2276
PP
137{
138 struct bt_trace *trace = NULL;
3dca2276 139
862ca4ed 140 BT_LIB_LOGD("Creating trace object: %![tc-]+T", tc);
3dca2276
PP
141 trace = g_new0(struct bt_trace, 1);
142 if (!trace) {
143 BT_LOGE_STR("Failed to allocate one trace.");
144 goto error;
145 }
146
862ca4ed 147 bt_object_init_shared(&trace->base, destroy_trace);
44c440bc
PP
148 trace->streams = g_ptr_array_new_with_free_func(
149 (GDestroyNotify) bt_object_try_spec_release);
150 if (!trace->streams) {
151 BT_LOGE_STR("Failed to allocate one GPtrArray.");
3dca2276
PP
152 goto error;
153 }
154
44c440bc
PP
155 trace->stream_classes_stream_count = g_hash_table_new(g_direct_hash,
156 g_direct_equal);
157 if (!trace->stream_classes_stream_count) {
158 BT_LOGE_STR("Failed to allocate one GHashTable.");
159 goto error;
160 }
161
162 trace->name.str = g_string_new(NULL);
163 if (!trace->name.str) {
164 BT_LOGE_STR("Failed to allocate one GString.");
165 goto error;
166 }
167
ad5268b5
FD
168 trace->destruction_listeners = g_array_new(FALSE, TRUE,
169 sizeof(struct bt_trace_destruction_listener_elem));
170 if (!trace->destruction_listeners) {
3602afb0
PP
171 BT_LOGE_STR("Failed to allocate one GArray.");
172 goto error;
173 }
174
862ca4ed
PP
175 trace->class = tc;
176 bt_object_get_no_null_check(trace->class);
44c440bc
PP
177 BT_LIB_LOGD("Created trace object: %!+t", trace);
178 goto end;
bc37ae52 179
bc37ae52 180error:
65300d60 181 BT_OBJECT_PUT_REF_AND_RESET(trace);
44c440bc
PP
182
183end:
862ca4ed 184 return trace;
bc37ae52
JG
185}
186
40f4ba76 187const char *bt_trace_get_name(const struct bt_trace *trace)
e96045d4 188{
cb6f1f7d 189 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
44c440bc 190 return trace->name.value;
e96045d4
JG
191}
192
23578e82 193enum bt_trace_status bt_trace_set_name(struct bt_trace *trace, const char *name)
e96045d4 194{
44c440bc
PP
195 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
196 BT_ASSERT_PRE_NON_NULL(name, "Name");
197 BT_ASSERT_PRE_TRACE_HOT(trace);
198 g_string_assign(trace->name.str, name);
199 trace->name.value = trace->name.str->str;
200 BT_LIB_LOGV("Set trace's name: %!+t", trace);
23578e82 201 return BT_TRACE_STATUS_OK;
e96045d4
JG
202}
203
40f4ba76 204uint64_t bt_trace_get_stream_count(const struct bt_trace *trace)
bc37ae52 205{
44c440bc
PP
206 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
207 return (uint64_t) trace->streams->len;
208}
95c09b3a 209
44c440bc
PP
210struct bt_stream *bt_trace_borrow_stream_by_index(
211 struct bt_trace *trace, uint64_t index)
212{
213 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
214 BT_ASSERT_PRE_VALID_INDEX(index, trace->streams->len);
215 return g_ptr_array_index(trace->streams, index);
216}
cb6f1f7d 217
40f4ba76
PP
218const struct bt_stream *bt_trace_borrow_stream_by_index_const(
219 const struct bt_trace *trace, uint64_t index)
e5be10ef 220{
40f4ba76 221 return bt_trace_borrow_stream_by_index((void *) trace, index);
e5be10ef
PP
222}
223
40f4ba76
PP
224struct bt_stream *bt_trace_borrow_stream_by_id(struct bt_trace *trace,
225 uint64_t id)
44c440bc
PP
226{
227 struct bt_stream *stream = NULL;
228 uint64_t i;
bc37ae52 229
44c440bc 230 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
bc37ae52 231
44c440bc
PP
232 for (i = 0; i < trace->streams->len; i++) {
233 struct bt_stream *stream_candidate =
234 g_ptr_array_index(trace->streams, i);
cfeb617e 235
44c440bc
PP
236 if (stream_candidate->id == id) {
237 stream = stream_candidate;
238 goto end;
239 }
6474e016 240 }
95c09b3a 241
bc37ae52 242end:
44c440bc 243 return stream;
bc37ae52
JG
244}
245
40f4ba76
PP
246const struct bt_stream *bt_trace_borrow_stream_by_id_const(
247 const struct bt_trace *trace, uint64_t id)
e5be10ef 248{
40f4ba76 249 return bt_trace_borrow_stream_by_id((void *) trace, id);
e5be10ef
PP
250}
251
ad5268b5 252enum bt_trace_status bt_trace_add_destruction_listener(
40f4ba76 253 const struct bt_trace *c_trace,
ad5268b5
FD
254 bt_trace_destruction_listener_func listener,
255 void *data, uint64_t *listener_id)
3602afb0 256{
40f4ba76 257 struct bt_trace *trace = (void *) c_trace;
44c440bc 258 uint64_t i;
ad5268b5 259 struct bt_trace_destruction_listener_elem new_elem = {
3602afb0
PP
260 .func = listener,
261 .data = data,
262 };
263
44c440bc
PP
264 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
265 BT_ASSERT_PRE_NON_NULL(listener, "Listener");
8480c8cc 266
3602afb0 267 /* Find the next available spot */
ad5268b5
FD
268 for (i = 0; i < trace->destruction_listeners->len; i++) {
269 struct bt_trace_destruction_listener_elem elem =
270 g_array_index(trace->destruction_listeners,
271 struct bt_trace_destruction_listener_elem, i);
3602afb0
PP
272
273 if (!elem.func) {
274 break;
275 }
276 }
277
ad5268b5
FD
278 if (i == trace->destruction_listeners->len) {
279 g_array_append_val(trace->destruction_listeners, new_elem);
3602afb0 280 } else {
ad5268b5 281 g_array_insert_val(trace->destruction_listeners, i, new_elem);
3602afb0
PP
282 }
283
44c440bc
PP
284 if (listener_id) {
285 *listener_id = i;
286 }
3602afb0 287
ad5268b5
FD
288 BT_LIB_LOGV("Added destruction listener: " "%![trace-]+t, "
289 "listener-id=%" PRIu64, trace, i);
23578e82 290 return BT_TRACE_STATUS_OK;
44c440bc
PP
291}
292
293BT_ASSERT_PRE_FUNC
294static
40f4ba76 295bool has_listener_id(const struct bt_trace *trace, uint64_t listener_id)
44c440bc 296{
ad5268b5
FD
297 BT_ASSERT(listener_id < trace->destruction_listeners->len);
298 return (&g_array_index(trace->destruction_listeners,
299 struct bt_trace_destruction_listener_elem,
44c440bc 300 listener_id))->func != NULL;
3602afb0
PP
301}
302
ad5268b5 303enum bt_trace_status bt_trace_remove_destruction_listener(
23578e82 304 const struct bt_trace *c_trace, uint64_t listener_id)
3602afb0 305{
40f4ba76 306 struct bt_trace *trace = (void *) c_trace;
ad5268b5 307 struct bt_trace_destruction_listener_elem *elem;
3602afb0 308
44c440bc 309 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
44c440bc 310 BT_ASSERT_PRE(has_listener_id(trace, listener_id),
ad5268b5 311 "Trace has no such trace destruction listener ID: "
44c440bc 312 "%![trace-]+t, %" PRIu64, trace, listener_id);
ad5268b5
FD
313 elem = &g_array_index(trace->destruction_listeners,
314 struct bt_trace_destruction_listener_elem,
3602afb0 315 listener_id);
44c440bc 316 BT_ASSERT(elem->func);
3602afb0
PP
317
318 elem->func = NULL;
319 elem->data = NULL;
ad5268b5 320 BT_LIB_LOGV("Removed \"trace destruction listener: "
44c440bc
PP
321 "%![trace-]+t, listener-id=%" PRIu64,
322 trace, listener_id);
23578e82 323 return BT_TRACE_STATUS_OK;
44c440bc 324}
3602afb0 325
44c440bc 326BT_HIDDEN
40f4ba76 327void _bt_trace_freeze(const struct bt_trace *trace)
44c440bc 328{
44c440bc 329 BT_ASSERT(trace);
862ca4ed
PP
330 BT_LIB_LOGD("Freezing trace's class: %!+T", trace->class);
331 bt_trace_class_freeze(trace->class);
44c440bc 332 BT_LIB_LOGD("Freezing trace: %!+t", trace);
40f4ba76 333 ((struct bt_trace *) trace)->frozen = true;
5acf2ae6 334}
312c056a 335
44c440bc
PP
336BT_HIDDEN
337void bt_trace_add_stream(struct bt_trace *trace, struct bt_stream *stream)
338{
339 guint count = 0;
340
341 bt_object_set_parent(&stream->base, &trace->base);
342 g_ptr_array_add(trace->streams, stream);
cb6f1f7d 343 bt_trace_freeze(trace);
312c056a 344
44c440bc
PP
345 if (bt_g_hash_table_contains(trace->stream_classes_stream_count,
346 stream->class)) {
347 count = GPOINTER_TO_UINT(g_hash_table_lookup(
348 trace->stream_classes_stream_count, stream->class));
312c056a
PP
349 }
350
44c440bc
PP
351 g_hash_table_insert(trace->stream_classes_stream_count,
352 stream->class, GUINT_TO_POINTER(count + 1));
353}
354
355BT_HIDDEN
40f4ba76
PP
356uint64_t bt_trace_get_automatic_stream_id(const struct bt_trace *trace,
357 const struct bt_stream_class *stream_class)
44c440bc
PP
358{
359 gpointer orig_key;
360 gpointer value;
361 uint64_t id = 0;
362
363 BT_ASSERT(stream_class);
364 BT_ASSERT(trace);
365 if (g_hash_table_lookup_extended(trace->stream_classes_stream_count,
366 stream_class, &orig_key, &value)) {
367 id = (uint64_t) GPOINTER_TO_UINT(value);
368 }
369
370 return id;
312c056a 371}
862ca4ed
PP
372
373struct bt_trace_class *bt_trace_borrow_class(struct bt_trace *trace)
374{
375 BT_ASSERT_PRE_NON_NULL(trace, "Trace");
376 return trace->class;
377}
378
379const struct bt_trace_class *bt_trace_borrow_class_const(
380 const struct bt_trace *trace)
381{
382 return bt_trace_borrow_class((void *) trace);
383}
c5b9b441
PP
384
385void bt_trace_get_ref(const struct bt_trace *trace)
386{
387 bt_object_get_ref(trace);
388}
389
390void bt_trace_put_ref(const struct bt_trace *trace)
391{
392 bt_object_put_ref(trace);
393}
This page took 0.078133 seconds and 4 git commands to generate.