Implement CTF-IR event getters
[babeltrace.git] / formats / ctf / ir / stream-class.c
CommitLineData
11b0cdc8
JG
1/*
2 * stream.c
3 *
4 * Babeltrace CTF Writer
5 *
de9dd397 6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
11b0cdc8
JG
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#include <babeltrace/ctf-writer/clock.h>
30#include <babeltrace/ctf-ir/clock-internal.h>
31#include <babeltrace/ctf-writer/event.h>
32#include <babeltrace/ctf-ir/event-internal.h>
33#include <babeltrace/ctf-ir/event-types-internal.h>
34#include <babeltrace/ctf-ir/event-fields-internal.h>
35#include <babeltrace/ctf-writer/stream.h>
36#include <babeltrace/ctf-ir/stream-class-internal.h>
37#include <babeltrace/ctf-writer/functor-internal.h>
38#include <babeltrace/compiler.h>
39#include <babeltrace/align.h>
40
41static
42void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref);
43static
44int init_event_header(struct bt_ctf_stream_class *stream_class,
45 enum bt_ctf_byte_order byte_order);
46static
47int init_packet_context(struct bt_ctf_stream_class *stream_class,
48 enum bt_ctf_byte_order byte_order);
49
50struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
51{
52 struct bt_ctf_stream_class *stream_class = NULL;
53
54 if (!name || !strlen(name)) {
55 goto error;
56 }
57
58 stream_class = g_new0(struct bt_ctf_stream_class, 1);
59 if (!stream_class) {
60 goto error;
61 }
62
63 stream_class->name = g_string_new(name);
64 stream_class->event_classes = g_ptr_array_new_with_free_func(
65 (GDestroyNotify)bt_ctf_event_class_put);
66 if (!stream_class->event_classes) {
67 goto error_destroy;
68 }
69
70 bt_ctf_ref_init(&stream_class->ref_count);
71 return stream_class;
72
73error_destroy:
74 bt_ctf_stream_class_destroy(&stream_class->ref_count);
75 stream_class = NULL;
76error:
77 return stream_class;
78}
79
2f100782
JG
80struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
81 struct bt_ctf_stream_class *stream_class)
82{
83 struct bt_ctf_clock *clock = NULL;
84
85 if (!stream_class || !stream_class->clock) {
86 goto end;
87 }
88
89 clock = stream_class->clock;
90 bt_ctf_clock_get(clock);
91end:
92 return clock;
93}
94
11b0cdc8
JG
95int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
96 struct bt_ctf_clock *clock)
97{
98 int ret = 0;
99
100 if (!stream_class || !clock || stream_class->frozen) {
101 ret = -1;
102 goto end;
103 }
104
105 if (stream_class->clock) {
106 bt_ctf_clock_put(stream_class->clock);
107 }
108
109 stream_class->clock = clock;
110 bt_ctf_clock_get(clock);
111end:
112 return ret;
113}
114
2f100782
JG
115int64_t bt_ctf_stream_class_get_id(struct bt_ctf_stream_class *stream_class)
116{
117 int64_t ret;
118
119 if (!stream_class || !stream_class->id_set) {
120 ret = -1;
121 goto end;
122 }
123
124 ret = (int64_t) stream_class->id;
125end:
126 return ret;
127}
128
129int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
130 uint32_t id)
131{
132 int ret = 0;
133
134 if (!stream_class) {
135 ret = -1;
136 goto end;
137 }
138
139 stream_class->id = id;
140 stream_class->id_set = 1;
141end:
142 return ret;
143}
144
11b0cdc8
JG
145int bt_ctf_stream_class_add_event_class(
146 struct bt_ctf_stream_class *stream_class,
147 struct bt_ctf_event_class *event_class)
148{
149 int ret = 0;
2f100782 150 int64_t event_id;
11b0cdc8
JG
151
152 if (!stream_class || !event_class) {
153 ret = -1;
154 goto end;
155 }
156
157 /* Check for duplicate event classes */
158 struct search_query query = { .value = event_class, .found = 0 };
159 g_ptr_array_foreach(stream_class->event_classes, value_exists, &query);
160 if (query.found) {
161 ret = -1;
162 goto end;
163 }
164
2f100782
JG
165 /* Only set an event id if none was explicitly set before */
166 event_id = bt_ctf_event_class_get_id(event_class);
167 if (event_id < 0) {
168 if (bt_ctf_event_class_set_id(event_class,
169 stream_class->next_event_id++)) {
170 ret = -1;
171 goto end;
172 }
173 }
174
175 ret = bt_ctf_event_class_set_stream_class(event_class, stream_class);
176 if (ret) {
11b0cdc8
JG
177 goto end;
178 }
179
180 bt_ctf_event_class_get(event_class);
181 g_ptr_array_add(stream_class->event_classes, event_class);
182end:
183 return ret;
184}
185
186void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
187{
188 if (!stream_class) {
189 return;
190 }
191
192 bt_ctf_ref_get(&stream_class->ref_count);
193}
194
195void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
196{
197 if (!stream_class) {
198 return;
199 }
200
201 bt_ctf_ref_put(&stream_class->ref_count, bt_ctf_stream_class_destroy);
202}
203
204BT_HIDDEN
205void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
206{
207 if (!stream_class) {
208 return;
209 }
210
211 stream_class->frozen = 1;
212 bt_ctf_clock_freeze(stream_class->clock);
213 g_ptr_array_foreach(stream_class->event_classes,
214 (GFunc)bt_ctf_event_class_freeze, NULL);
215}
216
11b0cdc8
JG
217BT_HIDDEN
218int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
219 enum bt_ctf_byte_order byte_order)
220{
221 int ret = 0;
222
223 ret = init_packet_context(stream_class, byte_order);
224 if (ret) {
225 goto end;
226 }
227
228 ret = init_event_header(stream_class, byte_order);
229 if (ret) {
230 goto end;
231 }
232end:
233 return ret;
234}
235
236BT_HIDDEN
237int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
238 struct metadata_context *context)
239{
2f100782 240 int64_t ret = 0;
11b0cdc8
JG
241 size_t i;
242
243 g_string_assign(context->field_name, "");
244 context->current_indentation_level = 1;
245 if (!stream_class->id_set) {
246 ret = -1;
247 goto end;
248 }
249
250 g_string_append_printf(context->string,
251 "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
252 stream_class->id);
253 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
254 context);
255 if (ret) {
256 goto end;
257 }
258
259 g_string_append(context->string, ";\n\n\tpacket.context := ");
260 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
261 context);
262 if (ret) {
263 goto end;
264 }
265
266 if (stream_class->event_context_type) {
267 g_string_append(context->string, ";\n\n\tevent.context := ");
268 ret = bt_ctf_field_type_serialize(
269 stream_class->event_context_type, context);
270 if (ret) {
271 goto end;
272 }
273 }
274
275 g_string_append(context->string, ";\n};\n\n");
11b0cdc8
JG
276 for (i = 0; i < stream_class->event_classes->len; i++) {
277 struct bt_ctf_event_class *event_class =
278 stream_class->event_classes->pdata[i];
279
11b0cdc8
JG
280 if (ret) {
281 goto end;
282 }
283
284 ret = bt_ctf_event_class_serialize(event_class, context);
285 if (ret) {
286 goto end;
287 }
288 }
289end:
290 context->current_indentation_level = 0;
291 return ret;
292}
293
294static
295void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
296{
297 struct bt_ctf_stream_class *stream_class;
298
299 if (!ref) {
300 return;
301 }
302
303 stream_class = container_of(ref, struct bt_ctf_stream_class, ref_count);
304 bt_ctf_clock_put(stream_class->clock);
305
306 if (stream_class->event_classes) {
2f100782
JG
307 size_t i;
308
309 /* Unregister this stream class from the event classes */
310 for (i = 0; i < stream_class->event_classes->len; i++) {
311 struct bt_ctf_event_class *event_class =
312 g_ptr_array_index(stream_class->event_classes,
313 i);
314
315 bt_ctf_event_class_set_stream_class(event_class, NULL);
316 }
317
11b0cdc8
JG
318 g_ptr_array_free(stream_class->event_classes, TRUE);
319 }
320
321 if (stream_class->name) {
322 g_string_free(stream_class->name, TRUE);
323 }
324
325 bt_ctf_field_type_put(stream_class->event_header_type);
326 bt_ctf_field_put(stream_class->event_header);
327 bt_ctf_field_type_put(stream_class->packet_context_type);
328 bt_ctf_field_put(stream_class->packet_context);
329 bt_ctf_field_type_put(stream_class->event_context_type);
330 bt_ctf_field_put(stream_class->event_context);
331 g_free(stream_class);
332}
333
334static
335int init_event_header(struct bt_ctf_stream_class *stream_class,
336 enum bt_ctf_byte_order byte_order)
337{
338 int ret = 0;
339 struct bt_ctf_field_type *event_header_type =
340 bt_ctf_field_type_structure_create();
341 struct bt_ctf_field_type *_uint32_t =
342 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
343 struct bt_ctf_field_type *_uint64_t =
344 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
345
346 if (!event_header_type) {
347 ret = -1;
348 goto end;
349 }
350
351 ret = bt_ctf_field_type_set_byte_order(_uint32_t, byte_order);
352 if (ret) {
353 goto end;
354 }
355
356 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
357 if (ret) {
358 goto end;
359 }
360
361 ret = bt_ctf_field_type_structure_add_field(event_header_type,
362 _uint32_t, "id");
363 if (ret) {
364 goto end;
365 }
366
367 ret = bt_ctf_field_type_structure_add_field(event_header_type,
368 _uint64_t, "timestamp");
369 if (ret) {
370 goto end;
371 }
372
373 stream_class->event_header_type = event_header_type;
374 stream_class->event_header = bt_ctf_field_create(
375 stream_class->event_header_type);
376 if (!stream_class->event_header) {
377 ret = -1;
378 }
379end:
380 if (ret) {
381 bt_ctf_field_type_put(event_header_type);
382 }
383
384 bt_ctf_field_type_put(_uint32_t);
385 bt_ctf_field_type_put(_uint64_t);
386 return ret;
387}
388
389static
390int init_packet_context(struct bt_ctf_stream_class *stream_class,
391 enum bt_ctf_byte_order byte_order)
392{
393 int ret = 0;
394 struct bt_ctf_field_type *packet_context_type =
395 bt_ctf_field_type_structure_create();
396 struct bt_ctf_field_type *_uint64_t =
397 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
398
399 if (!packet_context_type) {
400 ret = -1;
401 goto end;
402 }
403
404 /*
405 * We create a stream packet context as proposed in the CTF
406 * specification.
407 */
408 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
409 if (ret) {
410 goto end;
411 }
412
413 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
414 _uint64_t, "timestamp_begin");
415 if (ret) {
416 goto end;
417 }
418
419 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
420 _uint64_t, "timestamp_end");
421 if (ret) {
422 goto end;
423 }
424
425 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
426 _uint64_t, "content_size");
427 if (ret) {
428 goto end;
429 }
430
431 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
432 _uint64_t, "packet_size");
433 if (ret) {
434 goto end;
435 }
436
437 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
438 _uint64_t, "events_discarded");
439 if (ret) {
440 goto end;
441 }
442
443 stream_class->packet_context_type = packet_context_type;
444 stream_class->packet_context = bt_ctf_field_create(packet_context_type);
445 if (!stream_class->packet_context) {
446 ret = -1;
447 }
448end:
449 if (ret) {
450 bt_ctf_field_type_put(packet_context_type);
451 goto end;
452 }
453
454 bt_ctf_field_type_put(_uint64_t);
455 return ret;
456}
This page took 0.040736 seconds and 4 git commands to generate.