lib: make the "port connected" method return a status
[babeltrace.git] / lib / ctf-ir / packet.c
CommitLineData
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
3dca2276 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>
312c056a 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>
f6ccaed9 43#include <babeltrace/assert-internal.h>
be514b0c 44#include <inttypes.h>
f79cf0f0 45
094ff7c0 46struct bt_stream *bt_packet_borrow_stream(struct bt_packet *packet)
f79cf0f0 47{
f6ccaed9 48 BT_ASSERT_PRE_NON_NULL(packet, "Packet");
094ff7c0 49 return packet->stream;
f79cf0f0
PP
50}
51
312c056a 52struct bt_field *bt_packet_borrow_header(struct bt_packet *packet)
f79cf0f0 53{
f6ccaed9 54 BT_ASSERT_PRE_NON_NULL(packet, "Packet");
312c056a 55 return packet->header ? (void *) packet->header->field : NULL;
f79cf0f0
PP
56}
57
312c056a 58struct bt_field *bt_packet_borrow_context(struct bt_packet *packet)
f79cf0f0 59{
312c056a
PP
60 BT_ASSERT_PRE_NON_NULL(packet, "Packet");
61 return packet->context ? (void *) packet->context->field : NULL;
62}
c5c82c6e 63
312c056a 64BT_HIDDEN
6c677fb5 65void _bt_packet_set_is_frozen(struct bt_packet *packet, bool is_frozen)
312c056a
PP
66{
67 if (!packet || packet->frozen) {
68 return;
c5c82c6e
PP
69 }
70
312c056a
PP
71 BT_LOGD("Freezing packet: addr=%p", packet);
72
73 if (packet->header) {
74 BT_LOGD_STR("Freezing packet's header field.");
6c677fb5
PP
75 bt_field_set_is_frozen_recursive((void *) packet->header->field,
76 is_frozen);
f79cf0f0
PP
77 }
78
312c056a
PP
79 if (packet->context) {
80 BT_LOGD_STR("Freezing packet's context field.");
6c677fb5
PP
81 bt_field_set_is_frozen_recursive((void *) packet->context->field,
82 is_frozen);
312c056a
PP
83 }
84
6c677fb5 85 packet->frozen = is_frozen;
f6ccaed9
PP
86}
87
312c056a
PP
88static inline
89void bt_packet_reset(struct bt_packet *packet)
f6ccaed9 90{
312c056a 91 BT_ASSERT(packet);
6c677fb5 92 bt_packet_set_is_frozen(packet, false);
312c056a
PP
93
94 if (packet->header) {
95 bt_field_set_is_frozen_recursive(
96 (void *) packet->header->field, false);
97 bt_field_reset_recursive((void *) packet->header->field);
98 }
99
100 if (packet->context) {
101 bt_field_set_is_frozen_recursive(
102 (void *) packet->context->field, false);
103 bt_field_reset_recursive((void *) packet->context->field);
104 }
f79cf0f0
PP
105}
106
312c056a
PP
107static
108void bt_packet_header_field_recycle(struct bt_field_wrapper *header_field,
109 struct bt_trace *trace)
f79cf0f0 110{
312c056a
PP
111 BT_ASSERT(header_field);
112 BT_LIB_LOGD("Recycling packet header field: "
113 "addr=%p, %![trace-]+t, %![field-]+f", header_field,
114 trace, header_field->field);
115 bt_object_pool_recycle_object(&trace->packet_header_field_pool,
116 header_field);
f79cf0f0
PP
117}
118
312c056a
PP
119static
120void bt_packet_context_field_recycle(struct bt_field_wrapper *context_field,
121 struct bt_stream_class *stream_class)
f79cf0f0 122{
312c056a
PP
123 BT_ASSERT(context_field);
124 BT_LIB_LOGD("Recycling packet context field: "
125 "addr=%p, %![sc-]+S, %![field-]+f", context_field,
126 stream_class, context_field->field);
127 bt_object_pool_recycle_object(&stream_class->packet_context_field_pool,
128 context_field);
f79cf0f0
PP
129}
130
131BT_HIDDEN
312c056a 132void bt_packet_recycle(struct bt_packet *packet)
f79cf0f0 133{
312c056a 134 struct bt_stream *stream;
f79cf0f0 135
312c056a
PP
136 BT_ASSERT(packet);
137 BT_LIB_LOGD("Recycling packet: %!+a", packet);
138
139 /*
140 * Those are the important ordered steps:
141 *
142 * 1. Reset the packet object (put any permanent reference it
143 * has, unfreeze it and its fields in developer mode, etc.),
144 * but do NOT put its stream's reference. This stream
145 * contains the pool to which we're about to recycle this
146 * packet object, so we must guarantee its existence thanks
147 * to this existing reference.
148 *
149 * 2. Move the stream reference to our `stream`
150 * variable so that we can set the packet's stream member
151 * to NULL before recycling it. We CANNOT do this after
152 * we put the stream reference because this bt_put()
153 * could destroy the stream, also destroying its
154 * packet pool, thus also destroying our packet object (this
155 * would result in an invalid write access).
156 *
157 * 3. Recycle the packet object.
158 *
159 * 4. Put our stream reference.
160 */
161 bt_packet_reset(packet);
162 stream = packet->stream;
163 BT_ASSERT(stream);
164 packet->stream = NULL;
165 bt_object_pool_recycle_object(&stream->packet_pool, packet);
6c677fb5 166 bt_object_put_no_null_check(&stream->common.base);
f79cf0f0
PP
167}
168
312c056a
PP
169BT_HIDDEN
170void bt_packet_destroy(struct bt_packet *packet)
f79cf0f0 171{
8ea705f0 172 BT_LOGD("Destroying packet: addr=%p", packet);
312c056a
PP
173 BT_LOGD_STR("Destroying packet's header field.");
174
175 if (packet->header) {
176 if (packet->stream) {
177 BT_LOGD_STR("Recycling packet's header field.");
178 bt_packet_header_field_recycle(packet->header,
179 bt_stream_class_borrow_trace(
180 bt_stream_borrow_class(packet->stream)));
181 } else {
182 bt_field_wrapper_destroy(packet->header);
183 }
184 }
185
186 if (packet->context) {
187 if (packet->stream) {
188 BT_LOGD_STR("Recycling packet's context field.");
189 bt_packet_context_field_recycle(packet->context,
190 bt_stream_borrow_class(packet->stream));
191 } else {
192 bt_field_wrapper_destroy(packet->context);
193 }
194 }
195
d409daba 196 BT_LOGD_STR("Putting packet's stream.");
f79cf0f0
PP
197 bt_put(packet->stream);
198 g_free(packet);
199}
200
312c056a
PP
201BT_HIDDEN
202struct bt_packet *bt_packet_new(struct bt_stream *stream)
f79cf0f0 203{
50842bdc
PP
204 struct bt_packet *packet = NULL;
205 struct bt_stream_class *stream_class = NULL;
206 struct bt_trace *trace = NULL;
f79cf0f0 207
312c056a 208 BT_ASSERT(stream);
be514b0c
PP
209 BT_LOGD("Creating packet object: stream-addr=%p, "
210 "stream-name=\"%s\", stream-class-addr=%p, "
211 "stream-class-name=\"%s\", stream-class-id=%" PRId64,
50842bdc 212 stream, bt_stream_get_name(stream),
3dca2276
PP
213 stream->common.stream_class,
214 bt_stream_class_common_get_name(stream->common.stream_class),
215 bt_stream_class_common_get_id(stream->common.stream_class));
094ff7c0 216 stream_class = bt_stream_borrow_class(stream);
f6ccaed9 217 BT_ASSERT(stream_class);
094ff7c0 218 trace = bt_stream_class_borrow_trace(stream_class);
f6ccaed9 219 BT_ASSERT(trace);
50842bdc 220 packet = g_new0(struct bt_packet, 1);
f79cf0f0 221 if (!packet) {
8ea705f0 222 BT_LOGE_STR("Failed to allocate one packet object.");
f79cf0f0
PP
223 goto end;
224 }
225
3fea54f6
PP
226 bt_object_init_shared(&packet->base,
227 (bt_object_release_func) bt_packet_recycle);
f79cf0f0 228 packet->stream = bt_get(stream);
be514b0c 229
3dca2276 230 if (trace->common.packet_header_field_type) {
be514b0c 231 BT_LOGD("Creating initial packet header field: ft-addr=%p",
3dca2276 232 trace->common.packet_header_field_type);
312c056a
PP
233 packet->header = bt_field_wrapper_create(
234 &trace->packet_header_field_pool,
235 (void *) trace->common.packet_header_field_type);
be514b0c 236 if (!packet->header) {
312c056a 237 BT_LOGE("Cannot create packet header field wrapper.");
be514b0c
PP
238 BT_PUT(packet);
239 goto end;
240 }
f79cf0f0
PP
241 }
242
3dca2276 243 if (stream->common.stream_class->packet_context_field_type) {
be514b0c 244 BT_LOGD("Creating initial packet context field: ft-addr=%p",
3dca2276 245 stream->common.stream_class->packet_context_field_type);
312c056a
PP
246 packet->context = bt_field_wrapper_create(
247 &stream_class->packet_context_field_pool,
248 (void *) stream->common.stream_class->packet_context_field_type);
be514b0c 249 if (!packet->context) {
312c056a 250 BT_LOGE("Cannot create packet context field wrapper.");
be514b0c
PP
251 BT_PUT(packet);
252 goto end;
253 }
f79cf0f0
PP
254 }
255
8ea705f0
PP
256 BT_LOGD("Created packet object: addr=%p", packet);
257
f79cf0f0 258end:
f79cf0f0
PP
259 return packet;
260}
312c056a
PP
261
262struct bt_packet *bt_packet_create(struct bt_stream *stream)
263{
264 struct bt_packet *packet = NULL;
265
266 BT_ASSERT_PRE_NON_NULL(stream, "Stream");
267 packet = bt_object_pool_create_object(&stream->packet_pool);
6c677fb5 268 if (unlikely(!packet)) {
312c056a
PP
269 BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: "
270 "%![stream-]+s", stream);
6c677fb5 271 goto end;
312c056a
PP
272 }
273
6c677fb5
PP
274 if (unlikely(!packet->stream)) {
275 packet->stream = stream;
276 bt_object_get_no_null_check_no_parent_check(
277 &packet->stream->common.base);
312c056a
PP
278 }
279
280 goto end;
281
312c056a
PP
282end:
283 return packet;
284}
285
286int bt_packet_move_header(struct bt_packet *packet,
287 struct bt_packet_header_field *header_field)
288{
289 struct bt_trace *trace;
290 struct bt_field_wrapper *field_wrapper = (void *) header_field;
291
292 BT_ASSERT_PRE_NON_NULL(packet, "Event");
293 BT_ASSERT_PRE_NON_NULL(field_wrapper, "Header field");
294 BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
295 trace = bt_stream_class_borrow_trace(
296 bt_stream_borrow_class(packet->stream));
297 BT_ASSERT_PRE(trace->common.packet_header_field_type,
298 "Trace has no packet header field type: %!+t",
299 trace);
300
301 /* TODO: compare field types (precondition) */
302
303 /* Recycle current header field: always exists */
304 BT_ASSERT(packet->header);
305 bt_packet_header_field_recycle(packet->header, trace);
306
307 /* Move new field */
308 packet->header = field_wrapper;
309 return 0;
310}
311
312int bt_packet_move_context(struct bt_packet *packet,
313 struct bt_packet_context_field *context_field)
314{
315 struct bt_stream_class *stream_class;
316 struct bt_field_wrapper *field_wrapper = (void *) context_field;
317
318 BT_ASSERT_PRE_NON_NULL(packet, "Event");
319 BT_ASSERT_PRE_NON_NULL(field_wrapper, "Context field");
320 BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
321 stream_class = bt_stream_borrow_class(packet->stream);
322 BT_ASSERT_PRE(stream_class->common.packet_context_field_type,
323 "Stream class has no packet context field type: %!+S",
324 stream_class);
325
326 /* TODO: compare field types (precondition) */
327
328 /* Recycle current context field: always exists */
329 BT_ASSERT(packet->context);
330 bt_packet_context_field_recycle(packet->context, stream_class);
331
332 /* Move new field */
333 packet->context = field_wrapper;
334 return 0;
335}
This page took 0.051574 seconds and 4 git commands to generate.