Split the CTF-Writer implementation in IR and Writer parts
[babeltrace.git] / formats / ctf / ir / stream-class.c
1 /*
2 * stream.c
3 *
4 * Babeltrace CTF Writer
5 *
6 * Copyright 2013 EfficiOS Inc.
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
41 static
42 void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref);
43 static
44 int init_event_header(struct bt_ctf_stream_class *stream_class,
45 enum bt_ctf_byte_order byte_order);
46 static
47 int init_packet_context(struct bt_ctf_stream_class *stream_class,
48 enum bt_ctf_byte_order byte_order);
49
50 struct 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
73 error_destroy:
74 bt_ctf_stream_class_destroy(&stream_class->ref_count);
75 stream_class = NULL;
76 error:
77 return stream_class;
78 }
79
80 int bt_ctf_stream_class_set_clock(struct bt_ctf_stream_class *stream_class,
81 struct bt_ctf_clock *clock)
82 {
83 int ret = 0;
84
85 if (!stream_class || !clock || stream_class->frozen) {
86 ret = -1;
87 goto end;
88 }
89
90 if (stream_class->clock) {
91 bt_ctf_clock_put(stream_class->clock);
92 }
93
94 stream_class->clock = clock;
95 bt_ctf_clock_get(clock);
96 end:
97 return ret;
98 }
99
100 int bt_ctf_stream_class_add_event_class(
101 struct bt_ctf_stream_class *stream_class,
102 struct bt_ctf_event_class *event_class)
103 {
104 int ret = 0;
105
106 if (!stream_class || !event_class) {
107 ret = -1;
108 goto end;
109 }
110
111 /* Check for duplicate event classes */
112 struct search_query query = { .value = event_class, .found = 0 };
113 g_ptr_array_foreach(stream_class->event_classes, value_exists, &query);
114 if (query.found) {
115 ret = -1;
116 goto end;
117 }
118
119 if (bt_ctf_event_class_set_id(event_class,
120 stream_class->next_event_id++)) {
121 /* The event is already associated to a stream class */
122 ret = -1;
123 goto end;
124 }
125
126 bt_ctf_event_class_get(event_class);
127 g_ptr_array_add(stream_class->event_classes, event_class);
128 end:
129 return ret;
130 }
131
132 void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
133 {
134 if (!stream_class) {
135 return;
136 }
137
138 bt_ctf_ref_get(&stream_class->ref_count);
139 }
140
141 void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
142 {
143 if (!stream_class) {
144 return;
145 }
146
147 bt_ctf_ref_put(&stream_class->ref_count, bt_ctf_stream_class_destroy);
148 }
149
150 BT_HIDDEN
151 void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class)
152 {
153 if (!stream_class) {
154 return;
155 }
156
157 stream_class->frozen = 1;
158 bt_ctf_clock_freeze(stream_class->clock);
159 g_ptr_array_foreach(stream_class->event_classes,
160 (GFunc)bt_ctf_event_class_freeze, NULL);
161 }
162
163 BT_HIDDEN
164 int bt_ctf_stream_class_set_id(struct bt_ctf_stream_class *stream_class,
165 uint32_t id)
166 {
167 int ret = 0;
168
169 if (!stream_class ||
170 (stream_class->id_set && (id != stream_class->id))) {
171 ret = -1;
172 goto end;
173 }
174
175 stream_class->id = id;
176 stream_class->id_set = 1;
177 end:
178 return ret;
179 }
180
181 BT_HIDDEN
182 int bt_ctf_stream_class_set_byte_order(struct bt_ctf_stream_class *stream_class,
183 enum bt_ctf_byte_order byte_order)
184 {
185 int ret = 0;
186
187 ret = init_packet_context(stream_class, byte_order);
188 if (ret) {
189 goto end;
190 }
191
192 ret = init_event_header(stream_class, byte_order);
193 if (ret) {
194 goto end;
195 }
196 end:
197 return ret;
198 }
199
200 BT_HIDDEN
201 int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
202 struct metadata_context *context)
203 {
204 int ret = 0;
205 size_t i;
206
207 g_string_assign(context->field_name, "");
208 context->current_indentation_level = 1;
209 if (!stream_class->id_set) {
210 ret = -1;
211 goto end;
212 }
213
214 g_string_append_printf(context->string,
215 "stream {\n\tid = %" PRIu32 ";\n\tevent.header := ",
216 stream_class->id);
217 ret = bt_ctf_field_type_serialize(stream_class->event_header_type,
218 context);
219 if (ret) {
220 goto end;
221 }
222
223 g_string_append(context->string, ";\n\n\tpacket.context := ");
224 ret = bt_ctf_field_type_serialize(stream_class->packet_context_type,
225 context);
226 if (ret) {
227 goto end;
228 }
229
230 if (stream_class->event_context_type) {
231 g_string_append(context->string, ";\n\n\tevent.context := ");
232 ret = bt_ctf_field_type_serialize(
233 stream_class->event_context_type, context);
234 if (ret) {
235 goto end;
236 }
237 }
238
239 g_string_append(context->string, ";\n};\n\n");
240
241 /* Assign this stream's ID to every event and serialize them */
242 g_ptr_array_foreach(stream_class->event_classes,
243 (GFunc) bt_ctf_event_class_set_stream_id,
244 GUINT_TO_POINTER(stream_class->id));
245 for (i = 0; i < stream_class->event_classes->len; i++) {
246 struct bt_ctf_event_class *event_class =
247 stream_class->event_classes->pdata[i];
248
249 ret = bt_ctf_event_class_set_stream_id(event_class,
250 stream_class->id);
251 if (ret) {
252 goto end;
253 }
254
255 ret = bt_ctf_event_class_serialize(event_class, context);
256 if (ret) {
257 goto end;
258 }
259 }
260 end:
261 context->current_indentation_level = 0;
262 return ret;
263 }
264
265 static
266 void bt_ctf_stream_class_destroy(struct bt_ctf_ref *ref)
267 {
268 struct bt_ctf_stream_class *stream_class;
269
270 if (!ref) {
271 return;
272 }
273
274 stream_class = container_of(ref, struct bt_ctf_stream_class, ref_count);
275 bt_ctf_clock_put(stream_class->clock);
276
277 if (stream_class->event_classes) {
278 g_ptr_array_free(stream_class->event_classes, TRUE);
279 }
280
281 if (stream_class->name) {
282 g_string_free(stream_class->name, TRUE);
283 }
284
285 bt_ctf_field_type_put(stream_class->event_header_type);
286 bt_ctf_field_put(stream_class->event_header);
287 bt_ctf_field_type_put(stream_class->packet_context_type);
288 bt_ctf_field_put(stream_class->packet_context);
289 bt_ctf_field_type_put(stream_class->event_context_type);
290 bt_ctf_field_put(stream_class->event_context);
291 g_free(stream_class);
292 }
293
294 static
295 int init_event_header(struct bt_ctf_stream_class *stream_class,
296 enum bt_ctf_byte_order byte_order)
297 {
298 int ret = 0;
299 struct bt_ctf_field_type *event_header_type =
300 bt_ctf_field_type_structure_create();
301 struct bt_ctf_field_type *_uint32_t =
302 get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
303 struct bt_ctf_field_type *_uint64_t =
304 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
305
306 if (!event_header_type) {
307 ret = -1;
308 goto end;
309 }
310
311 ret = bt_ctf_field_type_set_byte_order(_uint32_t, byte_order);
312 if (ret) {
313 goto end;
314 }
315
316 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
317 if (ret) {
318 goto end;
319 }
320
321 ret = bt_ctf_field_type_structure_add_field(event_header_type,
322 _uint32_t, "id");
323 if (ret) {
324 goto end;
325 }
326
327 ret = bt_ctf_field_type_structure_add_field(event_header_type,
328 _uint64_t, "timestamp");
329 if (ret) {
330 goto end;
331 }
332
333 stream_class->event_header_type = event_header_type;
334 stream_class->event_header = bt_ctf_field_create(
335 stream_class->event_header_type);
336 if (!stream_class->event_header) {
337 ret = -1;
338 }
339 end:
340 if (ret) {
341 bt_ctf_field_type_put(event_header_type);
342 }
343
344 bt_ctf_field_type_put(_uint32_t);
345 bt_ctf_field_type_put(_uint64_t);
346 return ret;
347 }
348
349 static
350 int init_packet_context(struct bt_ctf_stream_class *stream_class,
351 enum bt_ctf_byte_order byte_order)
352 {
353 int ret = 0;
354 struct bt_ctf_field_type *packet_context_type =
355 bt_ctf_field_type_structure_create();
356 struct bt_ctf_field_type *_uint64_t =
357 get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
358
359 if (!packet_context_type) {
360 ret = -1;
361 goto end;
362 }
363
364 /*
365 * We create a stream packet context as proposed in the CTF
366 * specification.
367 */
368 ret = bt_ctf_field_type_set_byte_order(_uint64_t, byte_order);
369 if (ret) {
370 goto end;
371 }
372
373 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
374 _uint64_t, "timestamp_begin");
375 if (ret) {
376 goto end;
377 }
378
379 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
380 _uint64_t, "timestamp_end");
381 if (ret) {
382 goto end;
383 }
384
385 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
386 _uint64_t, "content_size");
387 if (ret) {
388 goto end;
389 }
390
391 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
392 _uint64_t, "packet_size");
393 if (ret) {
394 goto end;
395 }
396
397 ret = bt_ctf_field_type_structure_add_field(packet_context_type,
398 _uint64_t, "events_discarded");
399 if (ret) {
400 goto end;
401 }
402
403 stream_class->packet_context_type = packet_context_type;
404 stream_class->packet_context = bt_ctf_field_create(packet_context_type);
405 if (!stream_class->packet_context) {
406 ret = -1;
407 }
408 end:
409 if (ret) {
410 bt_ctf_field_type_put(packet_context_type);
411 goto end;
412 }
413
414 bt_ctf_field_type_put(_uint64_t);
415 return ret;
416 }
This page took 0.037382 seconds and 4 git commands to generate.