lib: add internal object pool API and use it; adapt plugins/tests
[babeltrace.git] / lib / ctf-writer / event.c
1 /*
2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
4 *
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
24 #define BT_LOG_TAG "CTF-WRITER-EVENT"
25 #include <babeltrace/lib-logging-internal.h>
26
27 #include <babeltrace/ctf-ir/event-internal.h>
28 #include <babeltrace/ctf-writer/clock-internal.h>
29 #include <babeltrace/ctf-writer/event-internal.h>
30 #include <babeltrace/ctf-writer/event.h>
31 #include <babeltrace/ctf-writer/fields-internal.h>
32 #include <babeltrace/ctf-writer/field-types-internal.h>
33 #include <babeltrace/ctf-writer/field-types.h>
34 #include <babeltrace/ctf-writer/fields.h>
35 #include <babeltrace/ctf-writer/stream-class-internal.h>
36 #include <babeltrace/ctf-writer/stream-class.h>
37 #include <babeltrace/ctf-writer/trace-internal.h>
38 #include <babeltrace/ctf-writer/trace.h>
39 #include <babeltrace/ref.h>
40 #include <babeltrace/compiler-internal.h>
41 #include <babeltrace/assert-internal.h>
42 #include <babeltrace/assert-pre-internal.h>
43 #include <inttypes.h>
44
45 static
46 void bt_ctf_event_destroy(struct bt_object *obj);
47
48 static
49 int map_clock_classes_func(struct bt_stream_class_common *stream_class,
50 struct bt_field_type_common *packet_context_type,
51 struct bt_field_type_common *event_header_type)
52 {
53 int ret = bt_ctf_stream_class_map_clock_class(
54 BT_FROM_COMMON(stream_class),
55 BT_FROM_COMMON(packet_context_type),
56 BT_FROM_COMMON(event_header_type));
57
58 if (ret) {
59 BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
60 }
61
62 return ret;
63 }
64
65 static
66 void destroy_event_header_field(struct bt_field_wrapper *field_wrapper)
67 {
68 BT_ASSERT(field_wrapper);
69 bt_put(field_wrapper->field);
70 bt_field_wrapper_destroy(field_wrapper);
71 }
72
73 static
74 struct bt_field_wrapper *create_event_header_field(
75 struct bt_stream_class *stream_class,
76 struct bt_field_type_common *ft)
77 {
78 struct bt_field_wrapper *field_wrapper = NULL;
79 struct bt_ctf_field *field = bt_ctf_field_create((void *) ft);
80
81 if (!field) {
82 goto error;
83 }
84
85 field_wrapper = bt_field_wrapper_new(NULL);
86 if (!field_wrapper) {
87 goto error;
88 }
89
90 field_wrapper->field = (void *) field;
91 field = NULL;
92 goto end;
93
94 error:
95 bt_put(field);
96
97 if (field_wrapper) {
98 destroy_event_header_field(field_wrapper);
99 field_wrapper = NULL;
100 }
101
102 end:
103 return field_wrapper;
104 }
105
106 struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
107 {
108 int ret;
109 struct bt_ctf_event *event = NULL;
110 struct bt_clock_class *expected_clock_class = NULL;
111
112 event = g_new0(struct bt_ctf_event, 1);
113 if (!event) {
114 BT_LOGE_STR("Failed to allocate one CTF writer event.");
115 goto error;
116 }
117
118 if (event_class) {
119 struct bt_ctf_stream_class *stream_class =
120 BT_FROM_COMMON(bt_event_class_common_borrow_stream_class(
121 BT_TO_COMMON(event_class)));
122
123 if (stream_class && stream_class->clock) {
124 expected_clock_class = BT_TO_COMMON(
125 stream_class->clock->clock_class);
126 }
127 }
128
129 ret = bt_event_common_initialize(BT_TO_COMMON(event),
130 BT_TO_COMMON(event_class), expected_clock_class,
131 bt_ctf_event_destroy,
132 (bt_validation_flag_copy_field_type_func)
133 bt_ctf_field_type_copy,
134 false, map_clock_classes_func,
135 (void *) bt_ctf_field_create,
136 (void *) bt_put,
137 (void *) create_event_header_field,
138 (void *) destroy_event_header_field);
139 if (ret) {
140 /* bt_event_common_initialize() logs errors */
141 goto error;
142 }
143
144 goto end;
145
146 error:
147 BT_PUT(event);
148
149 end:
150 return event;
151 }
152
153 struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
154 {
155 BT_ASSERT_PRE_NON_NULL(event, "Event");
156 return bt_get(bt_event_common_borrow_class(BT_TO_COMMON(event)));
157 }
158
159 BT_HIDDEN
160 struct bt_ctf_stream *bt_ctf_event_borrow_stream(struct bt_ctf_event *event)
161 {
162 BT_ASSERT(event);
163 return (struct bt_ctf_stream *)
164 bt_object_borrow_parent(BT_TO_COMMON(event));
165 }
166
167 struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
168 {
169 BT_ASSERT_PRE_NON_NULL(event, "Event");
170 return bt_get(bt_ctf_event_borrow_stream(event));
171 }
172
173 int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name,
174 struct bt_ctf_field *field)
175 {
176 BT_ASSERT_PRE_NON_NULL(event, "Event");
177 BT_ASSERT_PRE_NON_NULL(field, "Payload field");
178 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
179 return bt_ctf_field_structure_set_field_by_name(
180 (void *) event->common.payload_field, name, field);
181 }
182
183 struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
184 const char *name)
185 {
186 struct bt_ctf_field *field = NULL;
187
188 BT_ASSERT_PRE_NON_NULL(event, "Event");
189
190 if (name) {
191 field = bt_ctf_field_structure_get_field_by_name(
192 BT_FROM_COMMON(event->common.payload_field), name);
193 } else {
194 field = BT_FROM_COMMON(event->common.payload_field);
195 bt_get(field);
196 }
197
198 return field;
199 }
200
201 struct bt_ctf_field *bt_ctf_event_get_payload_field(
202 struct bt_ctf_event *event)
203 {
204 return bt_get(bt_event_common_borrow_payload(BT_TO_COMMON(event)));
205 }
206
207 struct bt_ctf_field *bt_ctf_event_get_header(struct bt_ctf_event *event)
208 {
209 return bt_get(bt_event_common_borrow_header(BT_TO_COMMON(event)));
210 }
211
212 struct bt_ctf_field *bt_ctf_event_get_context(struct bt_ctf_event *event)
213 {
214 return bt_get(bt_event_common_borrow_context(BT_TO_COMMON(event)));
215 }
216
217 struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
218 struct bt_ctf_event *event)
219 {
220 return bt_get(bt_event_common_borrow_stream_event_context(
221 BT_TO_COMMON(event)));
222 }
223
224 static
225 void release_event_header_field(struct bt_field_wrapper *field_wrapper,
226 struct bt_event_common *event_common)
227 {
228 BT_ASSERT(field_wrapper);
229 BT_PUT(field_wrapper->field);
230 bt_field_wrapper_destroy(field_wrapper);
231 }
232
233 static
234 void bt_ctf_event_destroy(struct bt_object *obj)
235 {
236 bt_event_common_finalize(obj, (void *) bt_put,
237 (void *) release_event_header_field);
238 g_free(obj);
239 }
240
241 BT_HIDDEN
242 int bt_ctf_event_serialize(struct bt_ctf_event *event,
243 struct bt_ctf_stream_pos *pos,
244 enum bt_ctf_byte_order native_byte_order)
245 {
246 int ret = 0;
247
248 BT_ASSERT(event);
249 BT_ASSERT(pos);
250
251 BT_LOGV_STR("Serializing event's context field.");
252 if (event->common.context_field) {
253 ret = bt_ctf_field_serialize_recursive(
254 (void *) event->common.context_field, pos,
255 native_byte_order);
256 if (ret) {
257 BT_LOGW("Cannot serialize event's context field: "
258 "event-addr=%p, event-class-name=\"%s\", "
259 "event-class-id=%" PRId64,
260 event,
261 bt_event_class_common_get_name(event->common.class),
262 bt_event_class_common_get_id(event->common.class));
263 goto end;
264 }
265 }
266
267 BT_LOGV_STR("Serializing event's payload field.");
268 if (event->common.payload_field) {
269 ret = bt_ctf_field_serialize_recursive(
270 (void *) event->common.payload_field, pos,
271 native_byte_order);
272 if (ret) {
273 BT_LOGW("Cannot serialize event's payload field: "
274 "event-addr=%p, event-class-name=\"%s\", "
275 "event-class-id=%" PRId64,
276 event,
277 bt_event_class_common_get_name(event->common.class),
278 bt_event_class_common_get_id(event->common.class));
279 goto end;
280 }
281 }
282
283 end:
284 return ret;
285 }
286
287 BT_HIDDEN
288 void _bt_ctf_event_freeze(struct bt_ctf_event *event)
289 {
290 _bt_event_common_freeze(BT_TO_COMMON(event));
291 }
292
293 int bt_ctf_event_set_header(struct bt_ctf_event *event,
294 struct bt_ctf_field *header)
295 {
296 BT_ASSERT_PRE_NON_NULL(event, "Event");
297 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
298
299 /*
300 * Ensure the provided header's type matches the one registered to the
301 * stream class.
302 */
303 if (header) {
304 BT_ASSERT_PRE(bt_field_type_common_compare(
305 ((struct bt_field_common *) header)->type,
306 bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type) == 0,
307 "Header field's type is different from the "
308 "expected field type: %![event-]+we, %![ft-]+wF, "
309 "%![expected-ft-]+wF",
310 event, ((struct bt_field_common *) header)->type,
311 bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
312 } else {
313 BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type,
314 "Setting no event header field, "
315 "but event header field type is not NULL: ",
316 "%![event-]+we, %![header-ft-]+wF",
317 event,
318 bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
319 }
320
321 bt_put(event->common.header_field->field);
322 event->common.header_field->field = bt_get(header);
323 BT_LOGV("Set event's header field: event-addr=%p, "
324 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
325 "header-field-addr=%p",
326 event, bt_event_class_common_get_name(event->common.class),
327 bt_event_class_common_get_id(event->common.class), header);
328 return 0;
329 }
330
331 int bt_ctf_event_common_set_payload(struct bt_ctf_event *event,
332 struct bt_ctf_field *payload)
333 {
334 BT_ASSERT_PRE_NON_NULL(event, "Event");
335 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
336
337 if (payload) {
338 BT_ASSERT_PRE(bt_field_type_common_compare(
339 ((struct bt_field_common *) payload)->type,
340 event->common.class->payload_field_type) == 0,
341 "Payload field's type is different from the "
342 "expected field type: %![event-]+we, %![ft-]+wF, "
343 "%![expected-ft-]+wF",
344 event,
345 ((struct bt_field_common *) payload)->type,
346 event->common.class->payload_field_type);
347 } else {
348 BT_ASSERT_PRE(!event->common.class->payload_field_type,
349 "Setting no event payload field, "
350 "but event payload field type is not NULL: ",
351 "%![event-]+we, %![payload-ft-]+wF",
352 event, event->common.class->payload_field_type);
353 }
354
355 bt_put(event->common.payload_field);
356 event->common.payload_field = bt_get(payload);
357 BT_LOGV("Set event's payload field: event-addr=%p, "
358 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
359 "payload-field-addr=%p",
360 event, bt_event_class_common_get_name(event->common.class),
361 bt_event_class_common_get_id(event->common.class), payload);
362 return 0;
363 }
364
365 int bt_ctf_event_set_context(struct bt_ctf_event *event,
366 struct bt_ctf_field *context)
367 {
368 BT_ASSERT_PRE_NON_NULL(event, "Event");
369 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
370
371 if (context) {
372 BT_ASSERT_PRE(bt_field_type_common_compare(
373 ((struct bt_field_common *) context)->type,
374 event->common.class->context_field_type) == 0,
375 "Context field's type is different from the "
376 "expected field type: %![event-]+we, %![ft-]+wF, "
377 "%![expected-ft-]+wF",
378 event, ((struct bt_field_common *) context)->type,
379 event->common.class->context_field_type);
380 } else {
381 BT_ASSERT_PRE(!event->common.class->context_field_type,
382 "Setting no event context field, "
383 "but event context field type is not NULL: ",
384 "%![event-]+we, %![context-ft-]+wF",
385 event, event->common.class->context_field_type);
386 }
387
388 bt_put(event->common.context_field);
389 event->common.context_field = bt_get(context);
390 BT_LOGV("Set event's context field: event-addr=%p, "
391 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
392 "context-field-addr=%p",
393 event, bt_event_class_common_get_name(event->common.class),
394 bt_event_class_common_get_id(event->common.class), context);
395 return 0;
396 }
397
398 int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
399 struct bt_ctf_field *stream_event_context)
400 {
401 BT_ASSERT_PRE_NON_NULL(event, "Event");
402 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
403
404 if (stream_event_context) {
405 BT_ASSERT_PRE(bt_field_type_common_compare(
406 ((struct bt_field_common *) stream_event_context)->type,
407 bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type) == 0,
408 "Stream event context field's type is different from the "
409 "expected field type: %![event-]+we, %![ft-]+wF, "
410 "%![expected-ft-]+wF",
411 event,
412 ((struct bt_field_common *) stream_event_context)->type,
413 bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
414 } else {
415 BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type,
416 "Setting no stream event context field, "
417 "but stream event context field type is not NULL: ",
418 "%![event-]+we, %![context-ft-]+wF",
419 event,
420 bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
421 }
422
423 bt_put(event->common.stream_event_context_field);
424 event->common.stream_event_context_field = bt_get(stream_event_context);
425 BT_LOGV("Set event's stream event context field: event-addr=%p, "
426 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
427 "stream-event-context-field-addr=%p",
428 event, bt_event_class_common_get_name(event->common.class),
429 bt_event_class_common_get_id(event->common.class),
430 stream_event_context);
431 return 0;
432 }
This page took 0.037997 seconds and 4 git commands to generate.