Commit | Line | Data |
---|---|---|
91b73004 JD |
1 | /* |
2 | * copytrace.c | |
3 | * | |
4 | * Babeltrace library to create a copy of a CTF trace | |
5 | * | |
6 | * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com> | |
7 | * | |
8 | * Author: Julien Desfossez <jdesfossez@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-ir/event.h> | |
30 | #include <babeltrace/ctf-ir/packet.h> | |
31 | #include <babeltrace/ctf-ir/event-class.h> | |
32 | #include <babeltrace/ctf-ir/stream.h> | |
33 | #include <babeltrace/ctf-ir/stream-class.h> | |
34 | #include <babeltrace/ctf-ir/clock-class.h> | |
35 | #include <babeltrace/ctf-ir/fields.h> | |
36 | #include <babeltrace/ctf-writer/stream.h> | |
37 | #include <assert.h> | |
38 | ||
39 | #include "ctfcopytrace.h" | |
b2f1f465 | 40 | #include "clock-fields.h" |
91b73004 | 41 | |
9ac68eb1 | 42 | BT_HIDDEN |
91b73004 JD |
43 | struct bt_ctf_clock_class *ctf_copy_clock_class(FILE *err, |
44 | struct bt_ctf_clock_class *clock_class) | |
45 | { | |
46 | int64_t offset, offset_s; | |
47 | int int_ret; | |
48 | uint64_t u64_ret; | |
49 | const char *name, *description; | |
50 | struct bt_ctf_clock_class *writer_clock_class = NULL; | |
51 | ||
52 | assert(err && clock_class); | |
53 | ||
54 | name = bt_ctf_clock_class_get_name(clock_class); | |
55 | if (!name) { | |
56 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
57 | __LINE__); | |
58 | goto end; | |
59 | } | |
60 | ||
61 | writer_clock_class = bt_ctf_clock_class_create(name); | |
62 | if (!writer_clock_class) { | |
63 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
64 | __LINE__); | |
65 | goto end; | |
66 | } | |
67 | ||
68 | description = bt_ctf_clock_class_get_description(clock_class); | |
69 | if (!description) { | |
70 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
71 | __LINE__); | |
72 | goto end_destroy; | |
73 | } | |
74 | ||
75 | int_ret = bt_ctf_clock_class_set_description(writer_clock_class, | |
76 | description); | |
77 | if (int_ret != 0) { | |
78 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
79 | __LINE__); | |
80 | goto end_destroy; | |
81 | } | |
82 | ||
83 | u64_ret = bt_ctf_clock_class_get_frequency(clock_class); | |
84 | if (u64_ret == -1ULL) { | |
85 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
86 | __LINE__); | |
87 | goto end_destroy; | |
88 | } | |
89 | int_ret = bt_ctf_clock_class_set_frequency(writer_clock_class, u64_ret); | |
90 | if (int_ret != 0) { | |
91 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
92 | __LINE__); | |
93 | goto end_destroy; | |
94 | } | |
95 | ||
96 | u64_ret = bt_ctf_clock_class_get_precision(clock_class); | |
97 | if (u64_ret == -1ULL) { | |
98 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
99 | __LINE__); | |
100 | goto end_destroy; | |
101 | } | |
102 | int_ret = bt_ctf_clock_class_set_precision(writer_clock_class, | |
103 | u64_ret); | |
104 | if (int_ret != 0) { | |
105 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
106 | __LINE__); | |
107 | goto end_destroy; | |
108 | } | |
109 | ||
110 | int_ret = bt_ctf_clock_class_get_offset_s(clock_class, &offset_s); | |
111 | if (int_ret != 0) { | |
112 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
113 | __LINE__); | |
114 | goto end_destroy; | |
115 | } | |
116 | ||
117 | int_ret = bt_ctf_clock_class_set_offset_s(writer_clock_class, offset_s); | |
118 | if (int_ret != 0) { | |
119 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
120 | __LINE__); | |
121 | goto end_destroy; | |
122 | } | |
123 | ||
124 | int_ret = bt_ctf_clock_class_get_offset_cycles(clock_class, &offset); | |
125 | if (int_ret != 0) { | |
126 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
127 | __LINE__); | |
128 | goto end_destroy; | |
129 | } | |
130 | ||
131 | int_ret = bt_ctf_clock_class_set_offset_cycles(writer_clock_class, offset); | |
132 | if (int_ret != 0) { | |
133 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
134 | __LINE__); | |
135 | goto end_destroy; | |
136 | } | |
137 | ||
acd6aeb1 | 138 | int_ret = bt_ctf_clock_class_is_absolute(clock_class); |
91b73004 JD |
139 | if (int_ret == -1) { |
140 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
141 | __LINE__); | |
142 | goto end_destroy; | |
143 | } | |
144 | ||
145 | int_ret = bt_ctf_clock_class_set_is_absolute(writer_clock_class, int_ret); | |
146 | if (int_ret != 0) { | |
147 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
148 | __LINE__); | |
149 | goto end_destroy; | |
150 | } | |
151 | ||
152 | goto end; | |
153 | ||
154 | end_destroy: | |
155 | BT_PUT(writer_clock_class); | |
156 | end: | |
157 | return writer_clock_class; | |
158 | } | |
159 | ||
9ac68eb1 | 160 | BT_HIDDEN |
91b73004 JD |
161 | enum bt_component_status ctf_copy_clock_classes(FILE *err, |
162 | struct bt_ctf_trace *writer_trace, | |
163 | struct bt_ctf_stream_class *writer_stream_class, | |
164 | struct bt_ctf_trace *trace) | |
165 | { | |
166 | enum bt_component_status ret; | |
91b73004 JD |
167 | int int_ret, clock_class_count, i; |
168 | ||
169 | clock_class_count = bt_ctf_trace_get_clock_class_count(trace); | |
170 | ||
171 | for (i = 0; i < clock_class_count; i++) { | |
172 | struct bt_ctf_clock_class *writer_clock_class; | |
173 | struct bt_ctf_clock_class *clock_class = | |
9ac68eb1 | 174 | bt_ctf_trace_get_clock_class_by_index(trace, i); |
91b73004 JD |
175 | |
176 | if (!clock_class) { | |
177 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
178 | __LINE__); | |
179 | ret = BT_COMPONENT_STATUS_ERROR; | |
180 | goto end; | |
181 | } | |
182 | ||
183 | writer_clock_class = ctf_copy_clock_class(err, clock_class); | |
184 | bt_put(clock_class); | |
185 | if (!writer_clock_class) { | |
186 | fprintf(err, "Failed to copy clock class"); | |
187 | ret = BT_COMPONENT_STATUS_ERROR; | |
188 | goto end; | |
189 | } | |
190 | ||
191 | int_ret = bt_ctf_trace_add_clock_class(writer_trace, writer_clock_class); | |
192 | if (int_ret != 0) { | |
193 | BT_PUT(writer_clock_class); | |
194 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
195 | __LINE__); | |
196 | ret = BT_COMPONENT_STATUS_ERROR; | |
197 | goto end; | |
198 | } | |
199 | ||
200 | /* | |
b2f1f465 | 201 | * Ownership transferred to the trace. |
91b73004 JD |
202 | */ |
203 | bt_put(writer_clock_class); | |
204 | } | |
205 | ||
206 | ret = BT_COMPONENT_STATUS_OK; | |
207 | ||
208 | end: | |
209 | return ret; | |
210 | } | |
211 | ||
9ac68eb1 | 212 | BT_HIDDEN |
91b73004 JD |
213 | struct bt_ctf_event_class *ctf_copy_event_class(FILE *err, |
214 | struct bt_ctf_event_class *event_class) | |
215 | { | |
216 | struct bt_ctf_event_class *writer_event_class = NULL; | |
279c77d0 | 217 | struct bt_ctf_field_type *context; |
91b73004 | 218 | const char *name; |
279c77d0 | 219 | int count, i, ret; |
91b73004 JD |
220 | |
221 | name = bt_ctf_event_class_get_name(event_class); | |
222 | if (!name) { | |
223 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
224 | __FILE__, __LINE__); | |
225 | goto end; | |
226 | } | |
227 | ||
228 | writer_event_class = bt_ctf_event_class_create(name); | |
229 | if (!writer_event_class) { | |
230 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
231 | __FILE__, __LINE__); | |
232 | goto end; | |
233 | } | |
234 | ||
235 | count = bt_ctf_event_class_get_attribute_count(event_class); | |
236 | for (i = 0; i < count; i++) { | |
237 | const char *attr_name; | |
238 | struct bt_value *attr_value; | |
239 | int ret; | |
240 | ||
9ac68eb1 PP |
241 | attr_name = bt_ctf_event_class_get_attribute_name_by_index( |
242 | event_class, i); | |
91b73004 JD |
243 | if (!attr_name) { |
244 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
245 | __FILE__, __LINE__); | |
9ae49d3d | 246 | goto error; |
91b73004 | 247 | } |
9ac68eb1 PP |
248 | attr_value = bt_ctf_event_class_get_attribute_value_by_index( |
249 | event_class, i); | |
91b73004 JD |
250 | if (!attr_value) { |
251 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
252 | __FILE__, __LINE__); | |
9ae49d3d | 253 | goto error; |
91b73004 JD |
254 | } |
255 | ||
256 | ret = bt_ctf_event_class_set_attribute(writer_event_class, | |
257 | attr_name, attr_value); | |
9ae49d3d | 258 | BT_PUT(attr_value); |
91b73004 JD |
259 | if (ret < 0) { |
260 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
261 | __FILE__, __LINE__); | |
9ae49d3d | 262 | goto error; |
91b73004 JD |
263 | } |
264 | } | |
265 | ||
9ac68eb1 | 266 | count = bt_ctf_event_class_get_payload_type_field_count(event_class); |
91b73004 JD |
267 | for (i = 0; i < count; i++) { |
268 | const char *field_name; | |
269 | struct bt_ctf_field_type *field_type; | |
270 | int ret; | |
271 | ||
9ac68eb1 PP |
272 | ret = bt_ctf_event_class_get_payload_type_field_by_index( |
273 | event_class, &field_name, &field_type, i); | |
91b73004 JD |
274 | if (ret < 0) { |
275 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__); | |
9ae49d3d | 276 | goto error; |
91b73004 JD |
277 | } |
278 | ||
279 | ret = bt_ctf_event_class_add_field(writer_event_class, field_type, | |
280 | field_name); | |
9ae49d3d | 281 | BT_PUT(field_type); |
91b73004 JD |
282 | if (ret < 0) { |
283 | fprintf(err, "[error] Cannot add field %s\n", field_name); | |
284 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__); | |
9ae49d3d | 285 | goto error; |
91b73004 | 286 | } |
91b73004 JD |
287 | } |
288 | ||
279c77d0 JD |
289 | context = bt_ctf_event_class_get_context_type(event_class); |
290 | if (context) { | |
291 | ret = bt_ctf_event_class_set_context_type( | |
292 | writer_event_class, context); | |
293 | BT_PUT(context); | |
294 | if (ret < 0) { | |
295 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
296 | __LINE__); | |
297 | goto error; | |
298 | } | |
299 | } | |
300 | ||
9ae49d3d JD |
301 | goto end; |
302 | ||
303 | error: | |
304 | BT_PUT(writer_event_class); | |
91b73004 JD |
305 | end: |
306 | return writer_event_class; | |
307 | } | |
308 | ||
9ac68eb1 | 309 | BT_HIDDEN |
91b73004 JD |
310 | enum bt_component_status ctf_copy_event_classes(FILE *err, |
311 | struct bt_ctf_stream_class *stream_class, | |
312 | struct bt_ctf_stream_class *writer_stream_class) | |
313 | { | |
314 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
9ae49d3d | 315 | struct bt_ctf_event_class *event_class = NULL, *writer_event_class = NULL; |
91b73004 JD |
316 | int count, i; |
317 | ||
318 | count = bt_ctf_stream_class_get_event_class_count(stream_class); | |
319 | if (count < 0) { | |
320 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
321 | __FILE__, __LINE__); | |
322 | goto end; | |
323 | } | |
324 | ||
325 | for (i = 0; i < count; i++) { | |
91b73004 JD |
326 | int int_ret; |
327 | ||
9ac68eb1 | 328 | event_class = bt_ctf_stream_class_get_event_class_by_index( |
91b73004 JD |
329 | stream_class, i); |
330 | if (!event_class) { | |
331 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
332 | __FILE__, __LINE__); | |
333 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 334 | goto error; |
91b73004 JD |
335 | } |
336 | writer_event_class = ctf_copy_event_class(err, event_class); | |
337 | if (!writer_event_class) { | |
338 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
339 | __FILE__, __LINE__); | |
340 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 341 | goto error; |
91b73004 JD |
342 | } |
343 | ||
91b73004 JD |
344 | int_ret = bt_ctf_stream_class_add_event_class(writer_stream_class, |
345 | writer_event_class); | |
346 | if (int_ret < 0) { | |
347 | fprintf(err, "[error] Failed to add event class\n"); | |
348 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
349 | __FILE__, __LINE__); | |
350 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 351 | goto error; |
91b73004 | 352 | } |
9ae49d3d JD |
353 | BT_PUT(writer_event_class); |
354 | BT_PUT(event_class); | |
91b73004 JD |
355 | } |
356 | ||
9ae49d3d JD |
357 | goto end; |
358 | ||
359 | error: | |
360 | bt_put(event_class); | |
361 | bt_put(writer_event_class); | |
91b73004 JD |
362 | end: |
363 | return ret; | |
364 | } | |
365 | ||
9ac68eb1 | 366 | BT_HIDDEN |
91b73004 | 367 | struct bt_ctf_stream_class *ctf_copy_stream_class(FILE *err, |
b2f1f465 JD |
368 | struct bt_ctf_stream_class *stream_class, |
369 | struct bt_ctf_trace *writer_trace, | |
370 | bool override_ts64) | |
91b73004 | 371 | { |
9ae49d3d JD |
372 | struct bt_ctf_field_type *type = NULL; |
373 | struct bt_ctf_stream_class *writer_stream_class = NULL; | |
91b73004 JD |
374 | int ret_int; |
375 | const char *name = bt_ctf_stream_class_get_name(stream_class); | |
376 | ||
377 | if (strlen(name) == 0) { | |
378 | name = NULL; | |
379 | } | |
380 | ||
381 | writer_stream_class = bt_ctf_stream_class_create(name); | |
382 | if (!writer_stream_class) { | |
383 | fprintf(err, "[error] %s in %s:%d\n", | |
384 | __func__, __FILE__, __LINE__); | |
385 | goto end; | |
386 | } | |
387 | ||
388 | type = bt_ctf_stream_class_get_packet_context_type(stream_class); | |
389 | if (!type) { | |
390 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
391 | __LINE__); | |
392 | goto error; | |
393 | } | |
394 | ||
395 | ret_int = bt_ctf_stream_class_set_packet_context_type( | |
396 | writer_stream_class, type); | |
91b73004 JD |
397 | if (ret_int < 0) { |
398 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
399 | __LINE__); | |
400 | goto error; | |
401 | } | |
9ae49d3d | 402 | BT_PUT(type); |
91b73004 JD |
403 | |
404 | type = bt_ctf_stream_class_get_event_header_type(stream_class); | |
405 | if (!type) { | |
406 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
407 | __LINE__); | |
408 | goto error; | |
409 | } | |
410 | ||
b2f1f465 | 411 | if (override_ts64) { |
9ae49d3d JD |
412 | struct bt_ctf_field_type *new_event_header_type; |
413 | ||
b2f1f465 JD |
414 | new_event_header_type = override_header_type(err, type, |
415 | writer_trace); | |
b2f1f465 JD |
416 | if (!new_event_header_type) { |
417 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
418 | __LINE__); | |
419 | goto error; | |
420 | } | |
0f29db56 JD |
421 | ret_int = bt_ctf_stream_class_set_event_header_type( |
422 | writer_stream_class, new_event_header_type); | |
9ae49d3d | 423 | BT_PUT(new_event_header_type); |
0f29db56 JD |
424 | if (ret_int < 0) { |
425 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
426 | __LINE__); | |
427 | goto error; | |
428 | } | |
b2f1f465 | 429 | } else { |
0f29db56 JD |
430 | ret_int = bt_ctf_stream_class_set_event_header_type( |
431 | writer_stream_class, type); | |
0f29db56 JD |
432 | if (ret_int < 0) { |
433 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
434 | __LINE__); | |
435 | goto error; | |
436 | } | |
91b73004 | 437 | } |
9ae49d3d | 438 | BT_PUT(type); |
91b73004 JD |
439 | |
440 | type = bt_ctf_stream_class_get_event_context_type(stream_class); | |
441 | if (type) { | |
442 | ret_int = bt_ctf_stream_class_set_event_context_type( | |
443 | writer_stream_class, type); | |
91b73004 JD |
444 | if (ret_int < 0) { |
445 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
446 | __LINE__); | |
447 | goto error; | |
448 | } | |
449 | } | |
9ae49d3d | 450 | BT_PUT(type); |
91b73004 JD |
451 | |
452 | goto end; | |
453 | ||
454 | error: | |
455 | BT_PUT(writer_stream_class); | |
456 | end: | |
9ae49d3d | 457 | bt_put(type); |
91b73004 JD |
458 | return writer_stream_class; |
459 | } | |
460 | ||
9ac68eb1 | 461 | BT_HIDDEN |
91b73004 JD |
462 | enum bt_component_status ctf_copy_packet_context_field(FILE *err, |
463 | struct bt_ctf_field *field, const char *field_name, | |
464 | struct bt_ctf_field *writer_packet_context, | |
465 | struct bt_ctf_field_type *writer_packet_context_type) | |
466 | { | |
467 | enum bt_component_status ret; | |
9ae49d3d JD |
468 | struct bt_ctf_field *writer_field = NULL; |
469 | struct bt_ctf_field_type *field_type = NULL; | |
91b73004 JD |
470 | int int_ret; |
471 | uint64_t value; | |
472 | ||
473 | field_type = bt_ctf_field_get_type(field); | |
474 | if (!field_type) { | |
475 | ret = BT_COMPONENT_STATUS_ERROR; | |
476 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
477 | __LINE__); | |
478 | goto end; | |
479 | } | |
480 | /* | |
481 | * Only support for integers for now. | |
482 | */ | |
1487a16a | 483 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
91b73004 | 484 | fprintf(err, "[error] Unsupported packet context field type\n"); |
91b73004 | 485 | ret = BT_COMPONENT_STATUS_ERROR; |
9ae49d3d | 486 | goto error; |
91b73004 | 487 | } |
9ae49d3d | 488 | BT_PUT(field_type); |
91b73004 | 489 | |
9ac68eb1 PP |
490 | writer_field = bt_ctf_field_structure_get_field_by_name( |
491 | writer_packet_context, field_name); | |
91b73004 JD |
492 | if (!writer_field) { |
493 | ret = BT_COMPONENT_STATUS_ERROR; | |
494 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
495 | __LINE__); | |
496 | goto end; | |
497 | } | |
498 | ||
91b73004 JD |
499 | int_ret = bt_ctf_field_unsigned_integer_get_value(field, &value); |
500 | if (int_ret < 0) { | |
501 | fprintf(err, "[error] Wrong packet_context field type\n"); | |
502 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
503 | __LINE__); | |
504 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 505 | goto end; |
91b73004 JD |
506 | } |
507 | ||
508 | int_ret = bt_ctf_field_unsigned_integer_set_value(writer_field, value); | |
509 | if (int_ret < 0) { | |
510 | ret = BT_COMPONENT_STATUS_ERROR; | |
511 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
512 | __LINE__); | |
9ae49d3d | 513 | goto end; |
91b73004 JD |
514 | } |
515 | ||
516 | ret = BT_COMPONENT_STATUS_OK; | |
517 | ||
9ae49d3d JD |
518 | goto end; |
519 | ||
520 | error: | |
521 | bt_put(field_type); | |
91b73004 | 522 | end: |
9ae49d3d | 523 | bt_put(writer_field); |
91b73004 JD |
524 | return ret; |
525 | } | |
526 | ||
9ac68eb1 | 527 | BT_HIDDEN |
b2f1f465 | 528 | struct bt_ctf_field *ctf_copy_packet_context(FILE *err, |
91b73004 | 529 | struct bt_ctf_packet *packet, |
ab80adac JD |
530 | struct bt_ctf_stream *writer_stream, |
531 | int skip_content_size) | |
91b73004 JD |
532 | { |
533 | enum bt_component_status ret; | |
9ae49d3d JD |
534 | struct bt_ctf_field *packet_context = NULL, *writer_packet_context = NULL; |
535 | struct bt_ctf_field_type *struct_type = NULL, *writer_packet_context_type = NULL; | |
536 | struct bt_ctf_stream_class *writer_stream_class = NULL; | |
f6f999a3 | 537 | struct bt_ctf_field *field = NULL; |
9571c709 | 538 | struct bt_ctf_field_type *field_type = NULL; |
b2f1f465 | 539 | int nr_fields, i; |
91b73004 JD |
540 | |
541 | packet_context = bt_ctf_packet_get_context(packet); | |
542 | if (!packet_context) { | |
60ef553b | 543 | goto end; |
91b73004 JD |
544 | } |
545 | ||
546 | writer_stream_class = bt_ctf_stream_get_class(writer_stream); | |
547 | if (!writer_stream_class) { | |
91b73004 JD |
548 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, |
549 | __LINE__); | |
9ae49d3d | 550 | goto error; |
91b73004 JD |
551 | } |
552 | ||
553 | writer_packet_context_type = bt_ctf_stream_class_get_packet_context_type( | |
554 | writer_stream_class); | |
9ae49d3d | 555 | BT_PUT(writer_stream_class); |
91b73004 | 556 | if (!writer_packet_context_type) { |
91b73004 JD |
557 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, |
558 | __LINE__); | |
9ae49d3d | 559 | goto error; |
91b73004 JD |
560 | } |
561 | ||
562 | struct_type = bt_ctf_field_get_type(packet_context); | |
563 | if (!struct_type) { | |
91b73004 JD |
564 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, |
565 | __LINE__); | |
9ae49d3d | 566 | goto error; |
91b73004 JD |
567 | } |
568 | ||
569 | writer_packet_context = bt_ctf_field_create(writer_packet_context_type); | |
570 | if (!writer_packet_context) { | |
91b73004 JD |
571 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, |
572 | __LINE__); | |
9ae49d3d | 573 | goto error; |
91b73004 JD |
574 | } |
575 | ||
576 | nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type); | |
577 | for (i = 0; i < nr_fields; i++) { | |
91b73004 JD |
578 | const char *field_name; |
579 | ||
0f29db56 | 580 | field = bt_ctf_field_structure_get_field_by_index( |
91b73004 JD |
581 | packet_context, i); |
582 | if (!field) { | |
91b73004 JD |
583 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
584 | __FILE__, __LINE__); | |
9ae49d3d | 585 | goto error; |
91b73004 | 586 | } |
9ac68eb1 | 587 | if (bt_ctf_field_type_structure_get_field_by_index(struct_type, |
91b73004 | 588 | &field_name, &field_type, i) < 0) { |
91b73004 JD |
589 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
590 | __FILE__, __LINE__); | |
9ae49d3d | 591 | goto error; |
91b73004 | 592 | } |
ab80adac JD |
593 | if (skip_content_size && |
594 | (!strncmp(field_name, "content_size", strlen("content_size")) || | |
595 | !strncmp(field_name, "packet_size", strlen("packet_size")))) { | |
9ae49d3d JD |
596 | BT_PUT(field_type); |
597 | BT_PUT(field); | |
91b73004 JD |
598 | continue; |
599 | } | |
600 | ||
1487a16a | 601 | if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) { |
91b73004 | 602 | fprintf(err, "[error] Unexpected packet context field type\n"); |
9ae49d3d | 603 | goto error; |
91b73004 JD |
604 | } |
605 | ||
606 | ret = ctf_copy_packet_context_field(err, field, field_name, | |
607 | writer_packet_context, writer_packet_context_type); | |
9ae49d3d JD |
608 | BT_PUT(field_type); |
609 | BT_PUT(field); | |
91b73004 JD |
610 | if (ret != BT_COMPONENT_STATUS_OK) { |
611 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
612 | __FILE__, __LINE__); | |
9ae49d3d | 613 | goto error; |
91b73004 JD |
614 | } |
615 | } | |
616 | ||
9ae49d3d JD |
617 | goto end; |
618 | ||
619 | error: | |
620 | BT_PUT(writer_packet_context); | |
621 | end: | |
622 | bt_put(field); | |
623 | bt_put(field_type); | |
91b73004 | 624 | bt_put(struct_type); |
91b73004 | 625 | bt_put(writer_packet_context_type); |
91b73004 | 626 | bt_put(writer_stream_class); |
91b73004 | 627 | bt_put(packet_context); |
b2f1f465 JD |
628 | return writer_packet_context; |
629 | } | |
630 | ||
9ac68eb1 | 631 | BT_HIDDEN |
0f29db56 | 632 | int ctf_copy_event_header(FILE *err, struct bt_ctf_event *event, |
b2f1f465 JD |
633 | struct bt_ctf_event_class *writer_event_class, |
634 | struct bt_ctf_event *writer_event, | |
635 | struct bt_ctf_field *event_header) | |
636 | { | |
9ae49d3d JD |
637 | struct bt_ctf_clock_class *clock_class = NULL, *writer_clock_class = NULL; |
638 | struct bt_ctf_clock_value *clock_value = NULL, *writer_clock_value = NULL; | |
b2f1f465 JD |
639 | |
640 | int ret; | |
0f29db56 JD |
641 | struct bt_ctf_field *writer_event_header = NULL; |
642 | uint64_t value; | |
b2f1f465 | 643 | |
0f29db56 JD |
644 | clock_class = event_get_clock_class(err, event); |
645 | if (!clock_class) { | |
646 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
647 | __LINE__); | |
648 | goto error; | |
649 | } | |
650 | ||
651 | clock_value = bt_ctf_event_get_clock_value(event, clock_class); | |
9ae49d3d | 652 | BT_PUT(clock_class); |
0f29db56 JD |
653 | if (!clock_value) { |
654 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
655 | __LINE__); | |
656 | goto error; | |
657 | } | |
658 | ||
659 | ret = bt_ctf_clock_value_get_value(clock_value, &value); | |
9ae49d3d | 660 | BT_PUT(clock_value); |
0f29db56 JD |
661 | if (ret) { |
662 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
663 | __LINE__); | |
664 | goto error; | |
b2f1f465 JD |
665 | } |
666 | ||
667 | writer_clock_class = event_get_clock_class(err, writer_event); | |
668 | if (!writer_clock_class) { | |
669 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
670 | __LINE__); | |
671 | goto error; | |
672 | } | |
673 | ||
0f29db56 | 674 | writer_clock_value = bt_ctf_clock_value_create(writer_clock_class, value); |
9ae49d3d | 675 | BT_PUT(writer_clock_class); |
0f29db56 | 676 | if (!writer_clock_value) { |
b2f1f465 JD |
677 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, |
678 | __LINE__); | |
9ae49d3d | 679 | goto error; |
b2f1f465 JD |
680 | } |
681 | ||
0f29db56 | 682 | ret = bt_ctf_event_set_clock_value(writer_event, writer_clock_value); |
9ae49d3d | 683 | BT_PUT(writer_clock_value); |
b2f1f465 JD |
684 | if (ret) { |
685 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
686 | __LINE__); | |
687 | goto error; | |
688 | } | |
689 | ||
0f29db56 JD |
690 | writer_event_header = bt_ctf_field_copy(event_header); |
691 | if (!writer_event_header) { | |
692 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
693 | __FILE__, __LINE__); | |
0f29db56 JD |
694 | goto end; |
695 | } | |
696 | ||
b2f1f465 | 697 | ret = bt_ctf_event_set_header(writer_event, writer_event_header); |
9ae49d3d | 698 | BT_PUT(writer_event_header); |
b2f1f465 JD |
699 | if (ret < 0) { |
700 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
701 | __FILE__, __LINE__); | |
702 | goto error; | |
703 | } | |
b2f1f465 JD |
704 | |
705 | ret = 0; | |
706 | ||
707 | goto end; | |
708 | ||
709 | error: | |
b2f1f465 | 710 | ret = -1; |
91b73004 JD |
711 | end: |
712 | return ret; | |
713 | } | |
714 | ||
9ac68eb1 | 715 | BT_HIDDEN |
91b73004 | 716 | struct bt_ctf_event *ctf_copy_event(FILE *err, struct bt_ctf_event *event, |
b2f1f465 JD |
717 | struct bt_ctf_event_class *writer_event_class, |
718 | bool override_ts64) | |
91b73004 | 719 | { |
9ae49d3d JD |
720 | struct bt_ctf_event *writer_event = NULL; |
721 | struct bt_ctf_field *field = NULL, *copy_field = NULL; | |
91b73004 JD |
722 | int ret; |
723 | ||
724 | writer_event = bt_ctf_event_create(writer_event_class); | |
725 | if (!writer_event) { | |
726 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
727 | __LINE__); | |
728 | goto end; | |
729 | } | |
730 | ||
731 | field = bt_ctf_event_get_header(event); | |
732 | if (!field) { | |
91b73004 JD |
733 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
734 | __FILE__, __LINE__); | |
9ae49d3d | 735 | goto error; |
91b73004 JD |
736 | } |
737 | ||
b2f1f465 JD |
738 | /* |
739 | * If override_ts64, we override all integer fields mapped to a clock | |
740 | * to a uint64_t field type, otherwise, we just copy it as is. | |
741 | */ | |
742 | if (override_ts64) { | |
743 | copy_field = bt_ctf_event_get_header(writer_event); | |
744 | if (!copy_field) { | |
91b73004 JD |
745 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
746 | __FILE__, __LINE__); | |
9ae49d3d | 747 | goto error; |
b2f1f465 JD |
748 | } |
749 | ||
750 | ret = copy_override_field(err, event, writer_event, field, | |
751 | copy_field); | |
b2f1f465 | 752 | if (ret) { |
b2f1f465 JD |
753 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
754 | __FILE__, __LINE__); | |
9ae49d3d | 755 | goto error; |
b2f1f465 | 756 | } |
9ae49d3d | 757 | BT_PUT(copy_field); |
b2f1f465 | 758 | } else { |
0f29db56 | 759 | ret = ctf_copy_event_header(err, event, writer_event_class, |
b2f1f465 JD |
760 | writer_event, field); |
761 | if (ret) { | |
b2f1f465 JD |
762 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
763 | __FILE__, __LINE__); | |
9ae49d3d | 764 | goto error; |
91b73004 | 765 | } |
91b73004 | 766 | } |
9ae49d3d | 767 | BT_PUT(field); |
91b73004 JD |
768 | |
769 | /* Optional field, so it can fail silently. */ | |
770 | field = bt_ctf_event_get_stream_event_context(event); | |
771 | copy_field = bt_ctf_field_copy(field); | |
91b73004 JD |
772 | if (copy_field) { |
773 | ret = bt_ctf_event_set_stream_event_context(writer_event, | |
774 | copy_field); | |
91b73004 JD |
775 | if (ret < 0) { |
776 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
777 | __FILE__, __LINE__); | |
778 | goto error; | |
779 | } | |
780 | } | |
9ae49d3d JD |
781 | BT_PUT(field); |
782 | BT_PUT(copy_field); | |
91b73004 JD |
783 | |
784 | /* Optional field, so it can fail silently. */ | |
785 | field = bt_ctf_event_get_event_context(event); | |
786 | copy_field = bt_ctf_field_copy(field); | |
91b73004 JD |
787 | if (copy_field) { |
788 | ret = bt_ctf_event_set_event_context(writer_event, copy_field); | |
91b73004 JD |
789 | if (ret < 0) { |
790 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
791 | __FILE__, __LINE__); | |
792 | goto error; | |
793 | } | |
794 | } | |
9ae49d3d JD |
795 | BT_PUT(field); |
796 | BT_PUT(copy_field); | |
91b73004 | 797 | |
9ac68eb1 | 798 | field = bt_ctf_event_get_event_payload(event); |
91b73004 | 799 | if (!field) { |
91b73004 JD |
800 | fprintf(err, "[error] %s in %s:%d\n", __func__, |
801 | __FILE__, __LINE__); | |
9ae49d3d | 802 | goto error; |
91b73004 JD |
803 | } |
804 | copy_field = bt_ctf_field_copy(field); | |
91b73004 | 805 | if (copy_field) { |
9ac68eb1 | 806 | ret = bt_ctf_event_set_event_payload(writer_event, copy_field); |
91b73004 JD |
807 | if (ret < 0) { |
808 | fprintf(err, "[error] %s in %s:%d\n", __func__, | |
809 | __FILE__, __LINE__); | |
810 | goto error; | |
811 | } | |
812 | } | |
9ae49d3d JD |
813 | BT_PUT(field); |
814 | BT_PUT(copy_field); | |
815 | ||
91b73004 JD |
816 | goto end; |
817 | ||
818 | error: | |
819 | BT_PUT(writer_event); | |
820 | end: | |
9ae49d3d JD |
821 | bt_put(field); |
822 | bt_put(copy_field); | |
91b73004 JD |
823 | return writer_event; |
824 | } | |
825 | ||
9ac68eb1 | 826 | BT_HIDDEN |
91b73004 JD |
827 | enum bt_component_status ctf_copy_trace(FILE *err, struct bt_ctf_trace *trace, |
828 | struct bt_ctf_trace *writer_trace) | |
829 | { | |
830 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
831 | int field_count, i, int_ret; | |
9ae49d3d | 832 | struct bt_ctf_field_type *header_type = NULL; |
6468dbd6 | 833 | enum bt_ctf_byte_order order; |
91b73004 JD |
834 | |
835 | field_count = bt_ctf_trace_get_environment_field_count(trace); | |
836 | for (i = 0; i < field_count; i++) { | |
837 | int ret_int; | |
838 | const char *name; | |
9ae49d3d | 839 | struct bt_value *value = NULL; |
91b73004 | 840 | |
9ac68eb1 PP |
841 | name = bt_ctf_trace_get_environment_field_name_by_index( |
842 | trace, i); | |
91b73004 JD |
843 | if (!name) { |
844 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
845 | __LINE__); | |
846 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 847 | goto end; |
91b73004 | 848 | } |
9ac68eb1 PP |
849 | value = bt_ctf_trace_get_environment_field_value_by_index( |
850 | trace, i); | |
91b73004 JD |
851 | if (!value) { |
852 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
853 | __LINE__); | |
854 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 855 | goto end; |
91b73004 JD |
856 | } |
857 | ||
858 | ret_int = bt_ctf_trace_set_environment_field(writer_trace, | |
859 | name, value); | |
9ae49d3d | 860 | BT_PUT(value); |
91b73004 JD |
861 | if (ret_int < 0) { |
862 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, | |
863 | __LINE__); | |
864 | fprintf(err, "[error] Unable to set environment field %s\n", | |
865 | name); | |
866 | ret = BT_COMPONENT_STATUS_ERROR; | |
9ae49d3d | 867 | goto end; |
91b73004 JD |
868 | } |
869 | } | |
870 | ||
6468dbd6 JD |
871 | order = bt_ctf_trace_get_native_byte_order(trace); |
872 | if (order == BT_CTF_BYTE_ORDER_UNKNOWN) { | |
873 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__); | |
874 | ret = BT_COMPONENT_STATUS_ERROR; | |
875 | goto end; | |
876 | } | |
877 | ||
d41cff38 PP |
878 | /* |
879 | * Only explicitly set the writer trace's native byte order if | |
880 | * the original trace has a specific one. Otherwise leave what | |
881 | * the CTF writer object chooses, which is the machine's native | |
882 | * byte order. | |
883 | */ | |
884 | if (order != BT_CTF_BYTE_ORDER_NONE) { | |
885 | ret = bt_ctf_trace_set_native_byte_order(writer_trace, order); | |
886 | if (ret) { | |
887 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__); | |
888 | ret = BT_COMPONENT_STATUS_ERROR; | |
889 | goto end; | |
890 | } | |
6468dbd6 JD |
891 | } |
892 | ||
91b73004 | 893 | header_type = bt_ctf_trace_get_packet_header_type(writer_trace); |
944eed39 JD |
894 | if (header_type) { |
895 | int_ret = bt_ctf_trace_set_packet_header_type(writer_trace, header_type); | |
896 | BT_PUT(header_type); | |
897 | if (int_ret < 0) { | |
898 | fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__); | |
899 | ret = BT_COMPONENT_STATUS_ERROR; | |
900 | goto end; | |
901 | } | |
91b73004 JD |
902 | } |
903 | ||
9ae49d3d | 904 | end: |
91b73004 JD |
905 | return ret; |
906 | } |