Commit | Line | Data |
---|---|---|
f79cf0f0 PP |
1 | /* |
2 | * packet.c | |
3 | * | |
4 | * Babeltrace CTF IR - Stream packet | |
5 | * | |
6 | * Copyright 2016 Philippe Proulx <pproulx@efficios.com> | |
7 | * | |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
9 | * of this software and associated documentation files (the "Software"), to deal | |
10 | * in the Software without restriction, including without limitation the rights | |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | * copies of the Software, and to permit persons to whom the Software is | |
13 | * furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be included in | |
16 | * all copies or substantial portions of the Software. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
24 | * SOFTWARE. | |
25 | */ | |
26 | ||
8ea705f0 | 27 | #define BT_LOG_TAG "PACKET" |
be514b0c | 28 | #include <babeltrace/lib-logging-internal.h> |
8ea705f0 | 29 | |
8deee039 | 30 | #include <babeltrace/assert-pre-internal.h> |
f79cf0f0 PP |
31 | #include <babeltrace/ctf-ir/fields-internal.h> |
32 | #include <babeltrace/ctf-ir/packet.h> | |
33 | #include <babeltrace/ctf-ir/packet-internal.h> | |
a6918753 | 34 | #include <babeltrace/ctf-ir/field-wrapper-internal.h> |
f79cf0f0 PP |
35 | #include <babeltrace/ctf-ir/trace.h> |
36 | #include <babeltrace/ctf-ir/stream-class-internal.h> | |
37 | #include <babeltrace/ctf-ir/stream-class.h> | |
38 | #include <babeltrace/ctf-ir/stream.h> | |
39 | #include <babeltrace/ctf-ir/stream-internal.h> | |
40 | #include <babeltrace/ctf-ir/trace-internal.h> | |
41 | #include <babeltrace/object-internal.h> | |
42 | #include <babeltrace/ref.h> | |
8b45963b | 43 | #include <babeltrace/assert-internal.h> |
be514b0c | 44 | #include <inttypes.h> |
f79cf0f0 | 45 | |
5fe68922 | 46 | struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet) |
f79cf0f0 | 47 | { |
8b45963b | 48 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
5fe68922 | 49 | return packet->stream; |
f79cf0f0 PP |
50 | } |
51 | ||
a6918753 | 52 | struct bt_field *bt_packet_borrow_header(struct bt_packet *packet) |
f79cf0f0 | 53 | { |
8b45963b | 54 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
a6918753 | 55 | return packet->header ? (void *) packet->header->field : NULL; |
f79cf0f0 PP |
56 | } |
57 | ||
a6918753 | 58 | struct bt_field *bt_packet_borrow_context(struct bt_packet *packet) |
f79cf0f0 | 59 | { |
a6918753 PP |
60 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
61 | return packet->context ? (void *) packet->context->field : NULL; | |
62 | } | |
c5c82c6e | 63 | |
a6918753 | 64 | BT_HIDDEN |
c5a24b0a | 65 | void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen) |
a6918753 | 66 | { |
435ec8af | 67 | if (!packet) { |
a6918753 | 68 | return; |
c5c82c6e PP |
69 | } |
70 | ||
4b7ed714 PP |
71 | BT_LOGD("Setting packet's frozen state: addr=%p, frozen=%d", |
72 | packet, is_frozen); | |
a6918753 PP |
73 | |
74 | if (packet->header) { | |
4b7ed714 PP |
75 | BT_LOGD("Setting packet's header field's frozen state: " |
76 | "frozen=%d", is_frozen); | |
c5a24b0a PP |
77 | bt_field_set_is_frozen_recursive((void *) packet->header->field, |
78 | is_frozen); | |
f79cf0f0 PP |
79 | } |
80 | ||
a6918753 | 81 | if (packet->context) { |
4b7ed714 PP |
82 | BT_LOGD("Setting packet's context field's frozen state: " |
83 | "frozen=%d", is_frozen); | |
c5a24b0a PP |
84 | bt_field_set_is_frozen_recursive((void *) packet->context->field, |
85 | is_frozen); | |
a6918753 PP |
86 | } |
87 | ||
c5a24b0a | 88 | packet->frozen = is_frozen; |
8b45963b PP |
89 | } |
90 | ||
e5815ba2 PP |
91 | static inline |
92 | void bt_packet_reset_avail(struct bt_packet *packet) | |
93 | { | |
94 | /* Previous packet */ | |
95 | packet->prev_packet_info.avail = | |
96 | BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE; | |
97 | packet->prev_packet_info.discarded_event_counter.avail = | |
98 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
99 | packet->prev_packet_info.seq_num.avail = | |
100 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
101 | packet->prev_packet_info.default_end_cv.avail = | |
102 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
103 | ||
104 | /* Current packet */ | |
105 | packet->discarded_event_counter.avail = | |
106 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
107 | packet->seq_num.avail = | |
108 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
109 | ||
110 | /* Computed */ | |
111 | packet->discarded_event_count.avail = | |
112 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
113 | packet->discarded_packet_count.avail = | |
114 | BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
115 | } | |
116 | ||
a6918753 PP |
117 | static inline |
118 | void bt_packet_reset(struct bt_packet *packet) | |
8b45963b | 119 | { |
a6918753 | 120 | BT_ASSERT(packet); |
c5a24b0a | 121 | bt_packet_set_is_frozen(packet, false); |
a6918753 PP |
122 | |
123 | if (packet->header) { | |
124 | bt_field_set_is_frozen_recursive( | |
125 | (void *) packet->header->field, false); | |
126 | bt_field_reset_recursive((void *) packet->header->field); | |
127 | } | |
128 | ||
129 | if (packet->context) { | |
130 | bt_field_set_is_frozen_recursive( | |
131 | (void *) packet->context->field, false); | |
132 | bt_field_reset_recursive((void *) packet->context->field); | |
133 | } | |
8fc063a2 PP |
134 | |
135 | bt_clock_value_set_reset(&packet->begin_cv_set); | |
136 | bt_clock_value_set_reset(&packet->end_cv_set); | |
e5815ba2 PP |
137 | bt_packet_reset_avail(packet); |
138 | bt_packet_invalidate_properties(packet); | |
139 | ||
140 | if (packet->prev_packet_info.default_end_cv.cv) { | |
141 | bt_clock_value_recycle(packet->prev_packet_info.default_end_cv.cv); | |
142 | packet->prev_packet_info.default_end_cv.cv = NULL; | |
143 | } | |
f79cf0f0 PP |
144 | } |
145 | ||
a6918753 PP |
146 | static |
147 | void bt_packet_header_field_recycle(struct bt_field_wrapper *header_field, | |
148 | struct bt_trace *trace) | |
f79cf0f0 | 149 | { |
a6918753 PP |
150 | BT_ASSERT(header_field); |
151 | BT_LIB_LOGD("Recycling packet header field: " | |
152 | "addr=%p, %![trace-]+t, %![field-]+f", header_field, | |
153 | trace, header_field->field); | |
154 | bt_object_pool_recycle_object(&trace->packet_header_field_pool, | |
155 | header_field); | |
f79cf0f0 PP |
156 | } |
157 | ||
a6918753 PP |
158 | static |
159 | void bt_packet_context_field_recycle(struct bt_field_wrapper *context_field, | |
160 | struct bt_stream_class *stream_class) | |
f79cf0f0 | 161 | { |
a6918753 PP |
162 | BT_ASSERT(context_field); |
163 | BT_LIB_LOGD("Recycling packet context field: " | |
164 | "addr=%p, %![sc-]+S, %![field-]+f", context_field, | |
165 | stream_class, context_field->field); | |
166 | bt_object_pool_recycle_object(&stream_class->packet_context_field_pool, | |
167 | context_field); | |
f79cf0f0 PP |
168 | } |
169 | ||
170 | BT_HIDDEN | |
a6918753 | 171 | void bt_packet_recycle(struct bt_packet *packet) |
f79cf0f0 | 172 | { |
a6918753 | 173 | struct bt_stream *stream; |
f79cf0f0 | 174 | |
a6918753 PP |
175 | BT_ASSERT(packet); |
176 | BT_LIB_LOGD("Recycling packet: %!+a", packet); | |
177 | ||
178 | /* | |
179 | * Those are the important ordered steps: | |
180 | * | |
181 | * 1. Reset the packet object (put any permanent reference it | |
182 | * has, unfreeze it and its fields in developer mode, etc.), | |
183 | * but do NOT put its stream's reference. This stream | |
184 | * contains the pool to which we're about to recycle this | |
185 | * packet object, so we must guarantee its existence thanks | |
186 | * to this existing reference. | |
187 | * | |
188 | * 2. Move the stream reference to our `stream` | |
189 | * variable so that we can set the packet's stream member | |
190 | * to NULL before recycling it. We CANNOT do this after | |
191 | * we put the stream reference because this bt_put() | |
192 | * could destroy the stream, also destroying its | |
193 | * packet pool, thus also destroying our packet object (this | |
194 | * would result in an invalid write access). | |
195 | * | |
196 | * 3. Recycle the packet object. | |
197 | * | |
198 | * 4. Put our stream reference. | |
199 | */ | |
200 | bt_packet_reset(packet); | |
201 | stream = packet->stream; | |
202 | BT_ASSERT(stream); | |
203 | packet->stream = NULL; | |
204 | bt_object_pool_recycle_object(&stream->packet_pool, packet); | |
18acc6f8 | 205 | bt_object_put_no_null_check(&stream->base); |
f79cf0f0 PP |
206 | } |
207 | ||
a6918753 PP |
208 | BT_HIDDEN |
209 | void bt_packet_destroy(struct bt_packet *packet) | |
f79cf0f0 | 210 | { |
8ea705f0 | 211 | BT_LOGD("Destroying packet: addr=%p", packet); |
a6918753 PP |
212 | BT_LOGD_STR("Destroying packet's header field."); |
213 | ||
214 | if (packet->header) { | |
215 | if (packet->stream) { | |
216 | BT_LOGD_STR("Recycling packet's header field."); | |
217 | bt_packet_header_field_recycle(packet->header, | |
218 | bt_stream_class_borrow_trace( | |
219 | bt_stream_borrow_class(packet->stream))); | |
220 | } else { | |
221 | bt_field_wrapper_destroy(packet->header); | |
222 | } | |
223 | } | |
224 | ||
225 | if (packet->context) { | |
226 | if (packet->stream) { | |
227 | BT_LOGD_STR("Recycling packet's context field."); | |
228 | bt_packet_context_field_recycle(packet->context, | |
229 | bt_stream_borrow_class(packet->stream)); | |
230 | } else { | |
231 | bt_field_wrapper_destroy(packet->context); | |
232 | } | |
233 | } | |
234 | ||
8fc063a2 PP |
235 | bt_clock_value_set_finalize(&packet->begin_cv_set); |
236 | bt_clock_value_set_finalize(&packet->end_cv_set); | |
d409daba | 237 | BT_LOGD_STR("Putting packet's stream."); |
f79cf0f0 PP |
238 | bt_put(packet->stream); |
239 | g_free(packet); | |
240 | } | |
241 | ||
a6918753 PP |
242 | BT_HIDDEN |
243 | struct bt_packet *bt_packet_new(struct bt_stream *stream) | |
f79cf0f0 | 244 | { |
839d52a5 PP |
245 | struct bt_packet *packet = NULL; |
246 | struct bt_stream_class *stream_class = NULL; | |
247 | struct bt_trace *trace = NULL; | |
f79cf0f0 | 248 | |
a6918753 | 249 | BT_ASSERT(stream); |
be514b0c PP |
250 | BT_LOGD("Creating packet object: stream-addr=%p, " |
251 | "stream-name=\"%s\", stream-class-addr=%p, " | |
252 | "stream-class-name=\"%s\", stream-class-id=%" PRId64, | |
839d52a5 | 253 | stream, bt_stream_get_name(stream), |
18acc6f8 PP |
254 | stream->stream_class, |
255 | bt_stream_class_get_name(stream->stream_class), | |
256 | bt_stream_class_get_id(stream->stream_class)); | |
5fe68922 | 257 | stream_class = bt_stream_borrow_class(stream); |
8b45963b | 258 | BT_ASSERT(stream_class); |
5fe68922 | 259 | trace = bt_stream_class_borrow_trace(stream_class); |
8b45963b | 260 | BT_ASSERT(trace); |
839d52a5 | 261 | packet = g_new0(struct bt_packet, 1); |
f79cf0f0 | 262 | if (!packet) { |
8ea705f0 | 263 | BT_LOGE_STR("Failed to allocate one packet object."); |
f79cf0f0 PP |
264 | goto end; |
265 | } | |
266 | ||
1d7bf349 PP |
267 | bt_object_init_shared(&packet->base, |
268 | (bt_object_release_func) bt_packet_recycle); | |
f79cf0f0 | 269 | packet->stream = bt_get(stream); |
be514b0c | 270 | |
18acc6f8 | 271 | if (trace->packet_header_field_type) { |
be514b0c | 272 | BT_LOGD("Creating initial packet header field: ft-addr=%p", |
18acc6f8 | 273 | trace->packet_header_field_type); |
a6918753 PP |
274 | packet->header = bt_field_wrapper_create( |
275 | &trace->packet_header_field_pool, | |
18acc6f8 | 276 | (void *) trace->packet_header_field_type); |
be514b0c | 277 | if (!packet->header) { |
a6918753 | 278 | BT_LOGE("Cannot create packet header field wrapper."); |
be514b0c PP |
279 | BT_PUT(packet); |
280 | goto end; | |
281 | } | |
f79cf0f0 PP |
282 | } |
283 | ||
18acc6f8 | 284 | if (stream->stream_class->packet_context_field_type) { |
be514b0c | 285 | BT_LOGD("Creating initial packet context field: ft-addr=%p", |
18acc6f8 | 286 | stream->stream_class->packet_context_field_type); |
a6918753 PP |
287 | packet->context = bt_field_wrapper_create( |
288 | &stream_class->packet_context_field_pool, | |
18acc6f8 | 289 | (void *) stream->stream_class->packet_context_field_type); |
be514b0c | 290 | if (!packet->context) { |
a6918753 | 291 | BT_LOGE("Cannot create packet context field wrapper."); |
be514b0c PP |
292 | BT_PUT(packet); |
293 | goto end; | |
294 | } | |
f79cf0f0 PP |
295 | } |
296 | ||
8fc063a2 PP |
297 | if (bt_clock_value_set_initialize(&packet->begin_cv_set)) { |
298 | BT_PUT(packet); | |
299 | goto end; | |
300 | } | |
301 | ||
302 | if (bt_clock_value_set_initialize(&packet->end_cv_set)) { | |
303 | BT_PUT(packet); | |
304 | goto end; | |
305 | } | |
306 | ||
e5815ba2 | 307 | bt_packet_reset_avail(packet); |
8ea705f0 PP |
308 | BT_LOGD("Created packet object: addr=%p", packet); |
309 | ||
f79cf0f0 | 310 | end: |
f79cf0f0 PP |
311 | return packet; |
312 | } | |
a6918753 | 313 | |
e5815ba2 PP |
314 | static inline |
315 | uint64_t get_uint_field_value(struct bt_field *parent_field, const char *name) | |
316 | { | |
317 | uint64_t val = UINT64_C(-1); | |
318 | struct bt_field *field = bt_field_structure_borrow_field_by_name( | |
319 | parent_field, name); | |
320 | int ret; | |
321 | ||
322 | if (!field) { | |
323 | goto end; | |
324 | } | |
325 | ||
326 | BT_ASSERT(bt_field_is_integer(field)); | |
327 | BT_ASSERT(!bt_field_type_integer_is_signed( | |
328 | bt_field_borrow_type(field))); | |
329 | ret = bt_field_integer_unsigned_get_value(field, &val); | |
330 | BT_ASSERT(ret == 0); | |
331 | ||
332 | end: | |
333 | return val; | |
334 | } | |
335 | ||
336 | static inline | |
337 | void set_packet_prop_uint64(struct bt_packet_prop_uint64 *prop, uint64_t val) | |
338 | { | |
339 | BT_ASSERT(prop); | |
340 | prop->value = val; | |
341 | prop->avail = BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE; | |
342 | } | |
343 | ||
344 | static inline | |
345 | int set_packet_default_clock_value(struct bt_field *pkt_ctx_field, | |
346 | const char *field_name, struct bt_clock_value_set *cv_set) | |
347 | { | |
348 | int ret = 0; | |
349 | uint64_t val = UINT64_C(-1); | |
350 | struct bt_field *field = bt_field_structure_borrow_field_by_name( | |
351 | pkt_ctx_field, field_name); | |
352 | struct bt_clock_class *clock_class; | |
353 | ||
354 | if (!field) { | |
355 | goto end; | |
356 | } | |
357 | ||
358 | BT_ASSERT(bt_field_is_integer(field)); | |
359 | BT_ASSERT(!bt_field_type_integer_is_signed( | |
360 | bt_field_borrow_type(field))); | |
361 | clock_class = bt_field_type_integer_borrow_mapped_clock_class( | |
362 | bt_field_borrow_type(field)); | |
363 | if (!clock_class) { | |
364 | goto end; | |
365 | } | |
366 | ||
367 | ret = bt_field_integer_unsigned_get_value(field, &val); | |
368 | BT_ASSERT(ret == 0); | |
369 | ret = bt_clock_value_set_set_clock_value(cv_set, clock_class, | |
370 | val, true); | |
371 | ||
372 | end: | |
373 | return ret; | |
374 | } | |
375 | ||
376 | BT_HIDDEN | |
377 | int bt_packet_set_properties(struct bt_packet *packet) | |
378 | { | |
379 | struct bt_field *pkt_context_field; | |
380 | uint64_t val; | |
381 | int ret = 0; | |
382 | ||
383 | BT_ASSERT(!packet->props_are_set); | |
384 | ||
385 | pkt_context_field = bt_packet_borrow_context(packet); | |
386 | if (!pkt_context_field) { | |
387 | goto end; | |
388 | } | |
389 | ||
390 | /* Discarded event counter */ | |
391 | val = get_uint_field_value(pkt_context_field, "events_discarded"); | |
392 | if (val != UINT64_C(-1)) { | |
393 | set_packet_prop_uint64(&packet->discarded_event_counter, val); | |
394 | } | |
395 | ||
396 | /* Sequence number */ | |
397 | val = get_uint_field_value(pkt_context_field, "packet_seq_num"); | |
398 | if (val != UINT64_C(-1)) { | |
399 | set_packet_prop_uint64(&packet->seq_num, val); | |
400 | } | |
401 | ||
402 | /* Beginning and end times */ | |
403 | ret = set_packet_default_clock_value(pkt_context_field, | |
404 | "timestamp_begin", &packet->begin_cv_set); | |
405 | if (ret) { | |
406 | goto end; | |
407 | } | |
408 | ||
409 | ret = set_packet_default_clock_value(pkt_context_field, | |
410 | "timestamp_end", &packet->end_cv_set); | |
411 | if (ret) { | |
412 | goto end; | |
413 | } | |
414 | ||
415 | /* Information from previous packet */ | |
416 | if (packet->prev_packet_info.avail == | |
417 | BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE) { | |
418 | /* Discarded event count */ | |
419 | if (packet->prev_packet_info.discarded_event_counter.avail == | |
420 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE) { | |
421 | BT_ASSERT(packet->discarded_event_counter.avail == | |
422 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE); | |
423 | set_packet_prop_uint64(&packet->discarded_event_count, | |
424 | packet->discarded_event_counter.value - | |
425 | packet->prev_packet_info.discarded_event_counter.value); | |
426 | } | |
427 | ||
428 | /* Discarded packet count */ | |
429 | if (packet->prev_packet_info.seq_num.avail == | |
430 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE) { | |
431 | BT_ASSERT(packet->seq_num.avail == | |
432 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE); | |
433 | set_packet_prop_uint64(&packet->discarded_packet_count, | |
434 | packet->seq_num.value - | |
435 | packet->prev_packet_info.seq_num.value - 1); | |
436 | } | |
437 | } | |
438 | ||
439 | end: | |
440 | return ret; | |
441 | } | |
442 | ||
443 | static | |
444 | int snapshot_prev_packet_properties(struct bt_packet *packet, | |
445 | enum bt_packet_previous_packet_availability prev_packet_avail, | |
446 | struct bt_packet *prev_packet) | |
447 | { | |
448 | int ret = 0; | |
449 | struct bt_clock_value *prev_packet_default_end_cv; | |
450 | ||
451 | if (!prev_packet) { | |
452 | goto end; | |
453 | } | |
454 | ||
455 | if (!prev_packet->props_are_set) { | |
456 | ret = bt_packet_set_properties(prev_packet); | |
457 | if (ret) { | |
458 | BT_LIB_LOGE("Cannot update previous packet's properties: " | |
459 | "%![prev-packet-]+a", prev_packet); | |
460 | goto end; | |
461 | } | |
462 | } | |
463 | ||
464 | packet->prev_packet_info.avail = prev_packet_avail; | |
465 | prev_packet_default_end_cv = prev_packet->end_cv_set.default_cv; | |
466 | ||
467 | /* End time */ | |
468 | if (prev_packet_default_end_cv) { | |
469 | /* Copy clock value */ | |
470 | packet->prev_packet_info.default_end_cv.cv = | |
471 | bt_clock_value_create( | |
472 | prev_packet_default_end_cv->clock_class); | |
473 | if (!packet->prev_packet_info.default_end_cv.cv) { | |
474 | BT_LIB_LOGE("Cannot create a clock value from a clock class: " | |
475 | "%![cc-]+K", | |
476 | prev_packet_default_end_cv->clock_class); | |
477 | ret = -1; | |
478 | goto end; | |
479 | } | |
480 | ||
481 | bt_clock_value_set_raw_value( | |
482 | packet->prev_packet_info.default_end_cv.cv, | |
483 | prev_packet_default_end_cv->value); | |
484 | packet->prev_packet_info.default_end_cv.avail = | |
485 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE; | |
486 | } | |
487 | ||
488 | /* Discarded event counter */ | |
489 | packet->prev_packet_info.discarded_event_counter = | |
490 | prev_packet->discarded_event_counter; | |
491 | ||
492 | /* Sequence number */ | |
493 | packet->prev_packet_info.seq_num = prev_packet->seq_num; | |
494 | ||
495 | end: | |
496 | return ret; | |
497 | } | |
498 | ||
499 | struct bt_packet *bt_packet_create(struct bt_stream *stream, | |
500 | enum bt_packet_previous_packet_availability prev_packet_avail, | |
501 | struct bt_packet *prev_packet) | |
a6918753 PP |
502 | { |
503 | struct bt_packet *packet = NULL; | |
e5815ba2 | 504 | int ret; |
a6918753 PP |
505 | |
506 | BT_ASSERT_PRE_NON_NULL(stream, "Stream"); | |
e5815ba2 PP |
507 | BT_ASSERT_PRE(!prev_packet || prev_packet->stream == stream, |
508 | "New packet's and previous packet's stream are not the same: " | |
509 | "%![new-packet-stream-]+s, %![prev-packet]+a, " | |
510 | "%![prev-packet-stream]+s", stream, prev_packet, | |
511 | prev_packet->stream); | |
512 | BT_ASSERT_PRE( | |
513 | prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE || | |
514 | prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE || | |
515 | prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE, | |
516 | "Invalid previous packet availability value: val=%d", | |
517 | prev_packet_avail); | |
518 | BT_ASSERT_PRE(!prev_packet || | |
519 | prev_packet_avail == BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE, | |
520 | "Previous packet is available, but previous packet is NULL."); | |
a6918753 | 521 | packet = bt_object_pool_create_object(&stream->packet_pool); |
c5a24b0a | 522 | if (unlikely(!packet)) { |
a6918753 PP |
523 | BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: " |
524 | "%![stream-]+s", stream); | |
c5a24b0a | 525 | goto end; |
a6918753 PP |
526 | } |
527 | ||
c5a24b0a PP |
528 | if (unlikely(!packet->stream)) { |
529 | packet->stream = stream; | |
530 | bt_object_get_no_null_check_no_parent_check( | |
18acc6f8 | 531 | &packet->stream->base); |
a6918753 PP |
532 | } |
533 | ||
e5815ba2 PP |
534 | ret = snapshot_prev_packet_properties(packet, prev_packet_avail, |
535 | prev_packet); | |
536 | if (ret) { | |
537 | /* Recycle */ | |
538 | BT_PUT(packet); | |
539 | goto end; | |
540 | } | |
541 | ||
542 | if (prev_packet) { | |
543 | bt_packet_validate_properties(prev_packet); | |
544 | bt_packet_set_is_frozen(prev_packet, true); | |
545 | } | |
546 | ||
a6918753 PP |
547 | goto end; |
548 | ||
a6918753 PP |
549 | end: |
550 | return packet; | |
551 | } | |
552 | ||
553 | int bt_packet_move_header(struct bt_packet *packet, | |
554 | struct bt_packet_header_field *header_field) | |
555 | { | |
556 | struct bt_trace *trace; | |
557 | struct bt_field_wrapper *field_wrapper = (void *) header_field; | |
558 | ||
559 | BT_ASSERT_PRE_NON_NULL(packet, "Event"); | |
560 | BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field"); | |
8fc063a2 | 561 | BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet); |
a6918753 PP |
562 | trace = bt_stream_class_borrow_trace( |
563 | bt_stream_borrow_class(packet->stream)); | |
18acc6f8 | 564 | BT_ASSERT_PRE(trace->packet_header_field_type, |
a6918753 PP |
565 | "Trace has no packet header field type: %!+t", |
566 | trace); | |
567 | ||
568 | /* TODO: compare field types (precondition) */ | |
569 | ||
570 | /* Recycle current header field: always exists */ | |
571 | BT_ASSERT(packet->header); | |
572 | bt_packet_header_field_recycle(packet->header, trace); | |
573 | ||
574 | /* Move new field */ | |
575 | packet->header = field_wrapper; | |
576 | return 0; | |
577 | } | |
578 | ||
579 | int bt_packet_move_context(struct bt_packet *packet, | |
580 | struct bt_packet_context_field *context_field) | |
581 | { | |
582 | struct bt_stream_class *stream_class; | |
583 | struct bt_field_wrapper *field_wrapper = (void *) context_field; | |
584 | ||
585 | BT_ASSERT_PRE_NON_NULL(packet, "Event"); | |
586 | BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field"); | |
8fc063a2 | 587 | BT_ASSERT_PRE_HOT(packet, "Packet", ": %!+a", packet); |
a6918753 | 588 | stream_class = bt_stream_borrow_class(packet->stream); |
18acc6f8 | 589 | BT_ASSERT_PRE(stream_class->packet_context_field_type, |
a6918753 PP |
590 | "Stream class has no packet context field type: %!+S", |
591 | stream_class); | |
592 | ||
593 | /* TODO: compare field types (precondition) */ | |
594 | ||
595 | /* Recycle current context field: always exists */ | |
596 | BT_ASSERT(packet->context); | |
597 | bt_packet_context_field_recycle(packet->context, stream_class); | |
598 | ||
599 | /* Move new field */ | |
600 | packet->context = field_wrapper; | |
601 | return 0; | |
602 | } | |
8fc063a2 | 603 | |
e5815ba2 PP |
604 | enum bt_packet_property_availability |
605 | bt_packet_borrow_default_beginning_clock_value(struct bt_packet *packet, | |
606 | struct bt_clock_value **clock_value) | |
8fc063a2 | 607 | { |
e5815ba2 PP |
608 | enum bt_packet_property_availability avail = |
609 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE; | |
610 | ||
8fc063a2 | 611 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
e5815ba2 PP |
612 | BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); |
613 | *clock_value = packet->begin_cv_set.default_cv; | |
614 | if (!*clock_value) { | |
615 | avail = BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
616 | } | |
617 | ||
618 | return avail; | |
8fc063a2 PP |
619 | } |
620 | ||
e5815ba2 PP |
621 | enum bt_packet_property_availability |
622 | bt_packet_borrow_default_end_clock_value(struct bt_packet *packet, | |
623 | struct bt_clock_value **clock_value) | |
8fc063a2 | 624 | { |
e5815ba2 PP |
625 | enum bt_packet_property_availability avail = |
626 | BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE; | |
8fc063a2 PP |
627 | |
628 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); | |
e5815ba2 PP |
629 | BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); |
630 | *clock_value = packet->end_cv_set.default_cv; | |
631 | if (!*clock_value) { | |
632 | avail = BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE; | |
8fc063a2 PP |
633 | } |
634 | ||
e5815ba2 | 635 | return avail; |
8fc063a2 PP |
636 | } |
637 | ||
e5815ba2 PP |
638 | enum bt_packet_previous_packet_availability |
639 | bt_packet_get_previous_packet_availability(struct bt_packet *packet) | |
8fc063a2 PP |
640 | { |
641 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); | |
e5815ba2 PP |
642 | return packet->prev_packet_info.avail; |
643 | } | |
644 | ||
645 | enum bt_packet_property_availability | |
646 | bt_packet_borrow_previous_packet_default_end_clock_value( | |
647 | struct bt_packet *packet, struct bt_clock_value **clock_value) | |
648 | { | |
649 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); | |
650 | BT_ASSERT_PRE_NON_NULL(clock_value, "Clock value"); | |
651 | *clock_value = packet->prev_packet_info.default_end_cv.cv; | |
652 | return packet->prev_packet_info.default_end_cv.avail; | |
8fc063a2 PP |
653 | } |
654 | ||
e5815ba2 PP |
655 | enum bt_packet_property_availability bt_packet_get_discarded_event_counter( |
656 | struct bt_packet *packet, uint64_t *counter) | |
8fc063a2 | 657 | { |
e5815ba2 PP |
658 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
659 | BT_ASSERT_PRE_NON_NULL(counter, "Counter"); | |
660 | *counter = packet->discarded_event_counter.value; | |
661 | return packet->discarded_event_counter.avail; | |
662 | } | |
8fc063a2 | 663 | |
e5815ba2 PP |
664 | enum bt_packet_property_availability bt_packet_get_sequence_number( |
665 | struct bt_packet *packet, uint64_t *sequence_number) | |
666 | { | |
8fc063a2 | 667 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); |
e5815ba2 PP |
668 | BT_ASSERT_PRE_NON_NULL(sequence_number, "Sequence number"); |
669 | *sequence_number = packet->seq_num.value; | |
670 | return packet->seq_num.avail; | |
671 | } | |
8fc063a2 | 672 | |
e5815ba2 PP |
673 | enum bt_packet_property_availability bt_packet_get_discarded_event_count( |
674 | struct bt_packet *packet, uint64_t *count) | |
675 | { | |
676 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); | |
677 | BT_ASSERT_PRE_NON_NULL(count, "Count"); | |
678 | *count = packet->discarded_event_count.value; | |
679 | return packet->discarded_event_count.avail; | |
680 | } | |
681 | ||
682 | enum bt_packet_property_availability bt_packet_get_discarded_packet_count( | |
683 | struct bt_packet *packet, uint64_t *count) | |
684 | { | |
685 | BT_ASSERT_PRE_NON_NULL(packet, "Packet"); | |
686 | BT_ASSERT_PRE_NON_NULL(count, "Count"); | |
687 | *count = packet->discarded_packet_count.value; | |
688 | return packet->discarded_packet_count.avail; | |
8fc063a2 | 689 | } |
e5815ba2 | 690 |