lib: fully configure graph (add components, connect ports), then run
[babeltrace.git] / lib / graph / iterator.c
CommitLineData
47e5a032 1/*
e2f7325d 2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
47e5a032 3 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
47e5a032
JG
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
d6e69534 24#define BT_LOG_TAG "MSG-ITER"
5af447e5
PP
25#include <babeltrace/lib-logging-internal.h>
26
3d9990ac 27#include <babeltrace/compiler-internal.h>
c6bd8523 28#include <babeltrace/trace-ir/field.h>
40f4ba76 29#include <babeltrace/trace-ir/event-const.h>
56e18c4c 30#include <babeltrace/trace-ir/event-internal.h>
40f4ba76 31#include <babeltrace/trace-ir/packet-const.h>
56e18c4c
PP
32#include <babeltrace/trace-ir/packet-internal.h>
33#include <babeltrace/trace-ir/stream-internal.h>
0d72b8c3 34#include <babeltrace/graph/connection-const.h>
bd14d768 35#include <babeltrace/graph/connection-internal.h>
0d72b8c3 36#include <babeltrace/graph/component-const.h>
e5be10ef 37#include <babeltrace/graph/component-internal.h>
b2e0c907
PP
38#include <babeltrace/graph/component-source-internal.h>
39#include <babeltrace/graph/component-class-internal.h>
8ed535b5 40#include <babeltrace/graph/component-class-sink-colander-internal.h>
0d72b8c3 41#include <babeltrace/graph/component-sink-const.h>
d6e69534
PP
42#include <babeltrace/graph/message-const.h>
43#include <babeltrace/graph/message-iterator.h>
44#include <babeltrace/graph/message-iterator-internal.h>
45#include <babeltrace/graph/self-component-port-input-message-iterator.h>
46#include <babeltrace/graph/port-output-message-iterator.h>
47#include <babeltrace/graph/message-internal.h>
48#include <babeltrace/graph/message-event-const.h>
49#include <babeltrace/graph/message-event-internal.h>
50#include <babeltrace/graph/message-packet-const.h>
51#include <babeltrace/graph/message-packet-internal.h>
52#include <babeltrace/graph/message-stream-const.h>
53#include <babeltrace/graph/message-stream-internal.h>
0d72b8c3
PP
54#include <babeltrace/graph/port-const.h>
55#include <babeltrace/graph/graph.h>
56#include <babeltrace/graph/graph-const.h>
8ed535b5 57#include <babeltrace/graph/graph-internal.h>
c55a9f58 58#include <babeltrace/types.h>
f6ccaed9 59#include <babeltrace/assert-internal.h>
f42867e2 60#include <babeltrace/assert-pre-internal.h>
fa054faf 61#include <stdint.h>
2ec84d26 62#include <inttypes.h>
0fbb9a9f 63#include <stdlib.h>
3230ee6b 64
d4393e08
PP
65/*
66 * TODO: Use graph's state (number of active iterators, etc.) and
67 * possibly system specifications to make a better guess than this.
68 */
d6e69534 69#define MSG_BATCH_SIZE 15
d4393e08 70
3230ee6b 71struct stream_state {
40f4ba76
PP
72 const struct bt_stream *stream; /* owned by this */
73 const struct bt_packet *cur_packet; /* owned by this */
d6e69534 74 uint64_t expected_msg_seq_num;
c55a9f58 75 bt_bool is_ended;
3230ee6b
PP
76};
77
26e21a82 78BT_ASSERT_PRE_FUNC
3230ee6b
PP
79static
80void destroy_stream_state(struct stream_state *stream_state)
81{
82 if (!stream_state) {
83 return;
84 }
85
5af447e5
PP
86 BT_LOGV("Destroying stream state: stream-state-addr=%p", stream_state);
87 BT_LOGV_STR("Putting stream state's current packet.");
d94d92ac 88 BT_OBJECT_PUT_REF_AND_RESET(stream_state->cur_packet);
5af447e5 89 BT_LOGV_STR("Putting stream state's stream.");
d94d92ac 90 BT_OBJECT_PUT_REF_AND_RESET(stream_state->stream);
3230ee6b
PP
91 g_free(stream_state);
92}
93
26e21a82 94BT_ASSERT_PRE_FUNC
3230ee6b 95static
40f4ba76 96struct stream_state *create_stream_state(const struct bt_stream *stream)
3230ee6b
PP
97{
98 struct stream_state *stream_state = g_new0(struct stream_state, 1);
99
100 if (!stream_state) {
5af447e5 101 BT_LOGE_STR("Failed to allocate one stream state.");
3230ee6b
PP
102 goto end;
103 }
104
105 /*
f42867e2 106 * We keep a reference to the stream until we know it's ended.
3230ee6b 107 */
398454ed
PP
108 stream_state->stream = stream;
109 bt_object_get_no_null_check(stream_state->stream);
d94d92ac 110 BT_LIB_LOGV("Created stream state: %![stream-]+s, "
5af447e5 111 "stream-state-addr=%p",
d94d92ac 112 stream, stream_state);
3230ee6b
PP
113
114end:
115 return stream_state;
116}
47e5a032 117
d0fea130
PP
118static inline
119void _set_self_comp_port_input_msg_iterator_state(
120 struct bt_self_component_port_input_message_iterator *iterator,
121 enum bt_self_component_port_input_message_iterator_state state)
122{
123 BT_ASSERT(iterator);
124 BT_LIB_LOGD("Updating message iterator's state: "
125 "new-state=%s",
126 bt_self_component_port_input_message_iterator_state_string(state));
127 iterator->state = state;
128}
129
130#ifdef BT_DEV_MODE
131# define set_self_comp_port_input_msg_iterator_state _set_self_comp_port_input_msg_iterator_state
132#else
133# define set_self_comp_port_input_msg_iterator_state(_a, _b)
134#endif
135
8ed535b5 136static
d6e69534 137void destroy_base_message_iterator(struct bt_object *obj)
8ed535b5 138{
d6e69534 139 struct bt_message_iterator *iterator = (void *) obj;
d4393e08
PP
140
141 BT_ASSERT(iterator);
142
d6e69534
PP
143 if (iterator->msgs) {
144 g_ptr_array_free(iterator->msgs, TRUE);
145 iterator->msgs = NULL;
d4393e08
PP
146 }
147
148 g_free(iterator);
8ed535b5
PP
149}
150
47e5a032 151static
d6e69534 152void bt_self_component_port_input_message_iterator_destroy(struct bt_object *obj)
47e5a032 153{
d6e69534 154 struct bt_self_component_port_input_message_iterator *iterator;
8738a040 155
f6ccaed9 156 BT_ASSERT(obj);
d3eb6e8f 157
bd14d768 158 /*
d6e69534 159 * The message iterator's reference count is 0 if we're
bd14d768
PP
160 * here. Increment it to avoid a double-destroy (possibly
161 * infinitely recursive). This could happen for example if the
d6e69534 162 * message iterator's finalization function does
d94d92ac
PP
163 * bt_object_get_ref() (or anything that causes
164 * bt_object_get_ref() to be called) on itself (ref. count goes
165 * from 0 to 1), and then bt_object_put_ref(): the reference
166 * count would go from 1 to 0 again and this function would be
167 * called again.
bd14d768 168 */
3fea54f6 169 obj->ref_count++;
07245ac2 170 iterator = (void *) obj;
d6e69534 171 BT_LIB_LOGD("Destroying self component input port message iterator object: "
d94d92ac 172 "%!+i", iterator);
d0fea130 173 bt_self_component_port_input_message_iterator_try_finalize(iterator);
d3eb6e8f 174
3230ee6b
PP
175 if (iterator->stream_states) {
176 /*
177 * Remove our destroy listener from each stream which
178 * has a state in this iterator. Otherwise the destroy
179 * listener would be called with an invalid/other
d6e69534 180 * message iterator object.
3230ee6b 181 */
3230ee6b 182 g_hash_table_destroy(iterator->stream_states);
d94d92ac 183 iterator->stream_states = NULL;
3230ee6b
PP
184 }
185
bd14d768
PP
186 if (iterator->connection) {
187 /*
188 * Remove ourself from the originating connection so
189 * that it does not try to finalize a dangling pointer
190 * later.
191 */
192 bt_connection_remove_iterator(iterator->connection, iterator);
d94d92ac 193 iterator->connection = NULL;
bd14d768
PP
194 }
195
d6e69534 196 destroy_base_message_iterator(obj);
47e5a032
JG
197}
198
bd14d768 199BT_HIDDEN
d0fea130 200void bt_self_component_port_input_message_iterator_try_finalize(
d6e69534 201 struct bt_self_component_port_input_message_iterator *iterator)
bd14d768 202{
d94d92ac
PP
203 typedef void (*method_t)(void *);
204
bd14d768 205 struct bt_component_class *comp_class = NULL;
d94d92ac 206 method_t method = NULL;
bd14d768 207
f6ccaed9 208 BT_ASSERT(iterator);
bd14d768
PP
209
210 switch (iterator->state) {
d6e69534 211 case BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_NON_INITIALIZED:
088d4023 212 /* Skip user finalization if user initialization failed */
d6e69534 213 BT_LIB_LOGD("Not finalizing non-initialized message iterator: "
d94d92ac 214 "%!+i", iterator);
d0fea130 215 goto end;
d6e69534 216 case BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_FINALIZED:
bd14d768 217 /* Already finalized */
d6e69534 218 BT_LIB_LOGD("Not finalizing message iterator: already finalized: "
d94d92ac 219 "%!+i", iterator);
d0fea130
PP
220 goto end;
221 case BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_FINALIZING:
222 /* Already finalized */
223 BT_LIB_LOGF("Message iterator is already being finalized: "
224 "%!+i", iterator);
225 abort();
bd14d768
PP
226 default:
227 break;
228 }
229
d6e69534 230 BT_LIB_LOGD("Finalizing message iterator: %!+i", iterator);
d0fea130
PP
231 set_self_comp_port_input_msg_iterator_state(iterator,
232 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_FINALIZING);
f6ccaed9 233 BT_ASSERT(iterator->upstream_component);
bd14d768
PP
234 comp_class = iterator->upstream_component->class;
235
236 /* Call user-defined destroy method */
237 switch (comp_class->type) {
238 case BT_COMPONENT_CLASS_TYPE_SOURCE:
239 {
d94d92ac
PP
240 struct bt_component_class_source *src_comp_cls =
241 (void *) comp_class;
bd14d768 242
d6e69534 243 method = (method_t) src_comp_cls->methods.msg_iter_finalize;
bd14d768
PP
244 break;
245 }
246 case BT_COMPONENT_CLASS_TYPE_FILTER:
247 {
d94d92ac
PP
248 struct bt_component_class_filter *flt_comp_cls =
249 (void *) comp_class;
bd14d768 250
d6e69534 251 method = (method_t) flt_comp_cls->methods.msg_iter_finalize;
bd14d768
PP
252 break;
253 }
254 default:
255 /* Unreachable */
0fbb9a9f 256 abort();
bd14d768
PP
257 }
258
d94d92ac
PP
259 if (method) {
260 BT_LIB_LOGD("Calling user's finalization method: %!+i",
5af447e5 261 iterator);
d94d92ac 262 method(iterator);
bd14d768
PP
263 }
264
bd14d768
PP
265 iterator->upstream_component = NULL;
266 iterator->upstream_port = NULL;
d0fea130
PP
267 set_self_comp_port_input_msg_iterator_state(iterator,
268 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_FINALIZED);
d6e69534 269 BT_LIB_LOGD("Finalized message iterator: %!+i", iterator);
d0fea130
PP
270
271end:
272 return;
bd14d768
PP
273}
274
275BT_HIDDEN
d6e69534
PP
276void bt_self_component_port_input_message_iterator_set_connection(
277 struct bt_self_component_port_input_message_iterator *iterator,
bd14d768
PP
278 struct bt_connection *connection)
279{
f6ccaed9 280 BT_ASSERT(iterator);
bd14d768 281 iterator->connection = connection;
d6e69534 282 BT_LIB_LOGV("Set message iterator's connection: "
d94d92ac 283 "%![iter-]+i, %![conn-]+x", iterator, connection);
bd14d768
PP
284}
285
90157d89 286static
d6e69534
PP
287int init_message_iterator(struct bt_message_iterator *iterator,
288 enum bt_message_iterator_type type,
90157d89
PP
289 bt_object_release_func destroy)
290{
d4393e08
PP
291 int ret = 0;
292
3fea54f6 293 bt_object_init_shared(&iterator->base, destroy);
90157d89 294 iterator->type = type;
d6e69534
PP
295 iterator->msgs = g_ptr_array_new();
296 if (!iterator->msgs) {
d4393e08
PP
297 BT_LOGE_STR("Failed to allocate a GPtrArray.");
298 ret = -1;
299 goto end;
300 }
301
d6e69534 302 g_ptr_array_set_size(iterator->msgs, MSG_BATCH_SIZE);
d4393e08
PP
303
304end:
305 return ret;
90157d89
PP
306}
307
d94d92ac 308static
d6e69534
PP
309struct bt_self_component_port_input_message_iterator *
310bt_self_component_port_input_message_iterator_create_initial(
3230ee6b 311 struct bt_component *upstream_comp,
d94d92ac 312 struct bt_port *upstream_port)
47e5a032 313{
d4393e08 314 int ret;
d6e69534 315 struct bt_self_component_port_input_message_iterator *iterator = NULL;
47e5a032 316
f6ccaed9
PP
317 BT_ASSERT(upstream_comp);
318 BT_ASSERT(upstream_port);
f6ccaed9 319 BT_ASSERT(bt_port_is_connected(upstream_port));
d6e69534 320 BT_LIB_LOGD("Creating initial message iterator on self component input port: "
d94d92ac
PP
321 "%![up-comp-]+c, %![up-port-]+p", upstream_comp, upstream_port);
322 BT_ASSERT(bt_component_get_class_type(upstream_comp) ==
323 BT_COMPONENT_CLASS_TYPE_SOURCE ||
324 bt_component_get_class_type(upstream_comp) ==
325 BT_COMPONENT_CLASS_TYPE_FILTER);
326 iterator = g_new0(
d6e69534 327 struct bt_self_component_port_input_message_iterator, 1);
47e5a032 328 if (!iterator) {
d94d92ac 329 BT_LOGE_STR("Failed to allocate one self component input port "
d6e69534 330 "message iterator.");
73d5c1ad 331 goto end;
47e5a032
JG
332 }
333
d6e69534
PP
334 ret = init_message_iterator((void *) iterator,
335 BT_MESSAGE_ITERATOR_TYPE_SELF_COMPONENT_PORT_INPUT,
336 bt_self_component_port_input_message_iterator_destroy);
d4393e08 337 if (ret) {
d6e69534 338 /* init_message_iterator() logs errors */
d94d92ac 339 BT_OBJECT_PUT_REF_AND_RESET(iterator);
d4393e08
PP
340 goto end;
341 }
3230ee6b
PP
342
343 iterator->stream_states = g_hash_table_new_full(g_direct_hash,
344 g_direct_equal, NULL, (GDestroyNotify) destroy_stream_state);
345 if (!iterator->stream_states) {
5af447e5 346 BT_LOGE_STR("Failed to allocate a GHashTable.");
d94d92ac 347 BT_OBJECT_PUT_REF_AND_RESET(iterator);
73d5c1ad 348 goto end;
3230ee6b
PP
349 }
350
bd14d768
PP
351 iterator->upstream_component = upstream_comp;
352 iterator->upstream_port = upstream_port;
d94d92ac 353 iterator->connection = iterator->upstream_port->connection;
5c563278 354 iterator->graph = bt_component_borrow_graph(upstream_comp);
d0fea130
PP
355 set_self_comp_port_input_msg_iterator_state(iterator,
356 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_NON_INITIALIZED);
d6e69534 357 BT_LIB_LOGD("Created initial message iterator on self component input port: "
d94d92ac
PP
358 "%![up-port-]+p, %![up-comp-]+c, %![iter-]+i",
359 upstream_port, upstream_comp, iterator);
3230ee6b 360
47e5a032 361end:
d94d92ac 362 return iterator;
47e5a032
JG
363}
364
d6e69534
PP
365struct bt_self_component_port_input_message_iterator *
366bt_self_component_port_input_message_iterator_create(
d94d92ac 367 struct bt_self_component_port_input *self_port)
ea8d3e58 368{
d6e69534 369 typedef enum bt_self_message_iterator_status (*init_method_t)(
d94d92ac
PP
370 void *, void *, void *);
371
372 init_method_t init_method = NULL;
d6e69534 373 struct bt_self_component_port_input_message_iterator *iterator =
d94d92ac
PP
374 NULL;
375 struct bt_port *port = (void *) self_port;
376 struct bt_port *upstream_port;
377 struct bt_component *comp;
378 struct bt_component *upstream_comp;
379 struct bt_component_class *upstream_comp_cls;
380
381 BT_ASSERT_PRE_NON_NULL(port, "Port");
0d72b8c3 382 comp = bt_port_borrow_component_inline(port);
d94d92ac
PP
383 BT_ASSERT_PRE(bt_port_is_connected(port),
384 "Port is not connected: %![port-]+p", port);
385 BT_ASSERT_PRE(comp, "Port is not part of a component: %![port-]+p",
386 port);
387 BT_ASSERT_PRE(!bt_component_graph_is_canceled(comp),
388 "Port's component's graph is canceled: "
389 "%![port-]+p, %![comp-]+c", port, comp);
390 BT_ASSERT(port->connection);
391 upstream_port = port->connection->upstream_port;
392 BT_ASSERT(upstream_port);
0d72b8c3 393 upstream_comp = bt_port_borrow_component_inline(upstream_port);
d94d92ac
PP
394 BT_ASSERT(upstream_comp);
395 upstream_comp_cls = upstream_comp->class;
396 BT_ASSERT(upstream_comp->class->type ==
397 BT_COMPONENT_CLASS_TYPE_SOURCE ||
398 upstream_comp->class->type ==
399 BT_COMPONENT_CLASS_TYPE_FILTER);
d6e69534 400 iterator = bt_self_component_port_input_message_iterator_create_initial(
d94d92ac
PP
401 upstream_comp, upstream_port);
402 if (!iterator) {
403 BT_LOGW_STR("Cannot create self component input port "
d6e69534 404 "message iterator.");
d94d92ac
PP
405 goto end;
406 }
890882ef 407
d94d92ac
PP
408 switch (upstream_comp_cls->type) {
409 case BT_COMPONENT_CLASS_TYPE_SOURCE:
410 {
411 struct bt_component_class_source *src_comp_cls =
412 (void *) upstream_comp_cls;
413
414 init_method =
d6e69534 415 (init_method_t) src_comp_cls->methods.msg_iter_init;
d94d92ac
PP
416 break;
417 }
418 case BT_COMPONENT_CLASS_TYPE_FILTER:
419 {
420 struct bt_component_class_filter *flt_comp_cls =
421 (void *) upstream_comp_cls;
422
423 init_method =
d6e69534 424 (init_method_t) flt_comp_cls->methods.msg_iter_init;
d94d92ac
PP
425 break;
426 }
427 default:
428 /* Unreachable */
429 abort();
430 }
431
432 if (init_method) {
433 int iter_status;
434
435 BT_LIB_LOGD("Calling user's initialization method: %!+i", iterator);
436 iter_status = init_method(iterator, upstream_comp,
437 upstream_port);
438 BT_LOGD("User method returned: status=%s",
d6e69534
PP
439 bt_message_iterator_status_string(iter_status));
440 if (iter_status != BT_MESSAGE_ITERATOR_STATUS_OK) {
d94d92ac 441 BT_LOGW_STR("Initialization method failed.");
d0fea130 442 BT_OBJECT_PUT_REF_AND_RESET(iterator);
d94d92ac
PP
443 goto end;
444 }
445 }
446
d0fea130
PP
447 set_self_comp_port_input_msg_iterator_state(iterator,
448 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_ACTIVE);
d94d92ac 449 g_ptr_array_add(port->connection->iterators, iterator);
d6e69534 450 BT_LIB_LOGD("Created message iterator on self component input port: "
d94d92ac
PP
451 "%![up-port-]+p, %![up-comp-]+c, %![iter-]+i",
452 upstream_port, upstream_comp, iterator);
453
454end:
455 return iterator;
ea8d3e58
JG
456}
457
d6e69534
PP
458void *bt_self_message_iterator_get_data(
459 const struct bt_self_message_iterator *self_iterator)
ea8d3e58 460{
d6e69534 461 struct bt_self_component_port_input_message_iterator *iterator =
d94d92ac 462 (void *) self_iterator;
ea8d3e58 463
d6e69534 464 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
d94d92ac 465 return iterator->user_data;
8738a040 466}
413bc2c4 467
d6e69534
PP
468void bt_self_message_iterator_set_data(
469 struct bt_self_message_iterator *self_iterator, void *data)
5c563278 470{
d6e69534 471 struct bt_self_component_port_input_message_iterator *iterator =
d94d92ac 472 (void *) self_iterator;
5c563278 473
d6e69534 474 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
d94d92ac 475 iterator->user_data = data;
d6e69534 476 BT_LIB_LOGV("Set message iterator's user data: "
d94d92ac 477 "%!+i, user-data-addr=%p", iterator, data);
5c563278
PP
478}
479
f42867e2
PP
480BT_ASSERT_PRE_FUNC
481static inline
d6e69534 482void bt_message_borrow_packet_stream(const struct bt_message *msg,
40f4ba76
PP
483 const struct bt_stream **stream,
484 const struct bt_packet **packet)
fa054faf 485{
d6e69534 486 BT_ASSERT(msg);
fa054faf 487
d6e69534
PP
488 switch (msg->type) {
489 case BT_MESSAGE_TYPE_EVENT:
40f4ba76 490 *packet = bt_event_borrow_packet_const(
d6e69534 491 bt_message_event_borrow_event_const(msg));
40f4ba76 492 *stream = bt_packet_borrow_stream_const(*packet);
fa054faf 493 break;
d6e69534
PP
494 case BT_MESSAGE_TYPE_STREAM_BEGINNING:
495 *stream = bt_message_stream_beginning_borrow_stream_const(msg);
fa054faf 496 break;
d6e69534
PP
497 case BT_MESSAGE_TYPE_STREAM_END:
498 *stream = bt_message_stream_end_borrow_stream_const(msg);
fa054faf 499 break;
d6e69534
PP
500 case BT_MESSAGE_TYPE_PACKET_BEGINNING:
501 *packet = bt_message_packet_beginning_borrow_packet_const(msg);
40f4ba76 502 *stream = bt_packet_borrow_stream_const(*packet);
fa054faf 503 break;
d6e69534
PP
504 case BT_MESSAGE_TYPE_PACKET_END:
505 *packet = bt_message_packet_end_borrow_packet_const(msg);
40f4ba76 506 *stream = bt_packet_borrow_stream_const(*packet);
2ec84d26 507 break;
fa054faf 508 default:
f42867e2 509 break;
fa054faf 510 }
fa054faf
PP
511}
512
f42867e2
PP
513BT_ASSERT_PRE_FUNC
514static inline
d6e69534
PP
515bool validate_message(
516 struct bt_self_component_port_input_message_iterator *iterator,
517 const struct bt_message *c_msg)
3230ee6b 518{
f42867e2 519 bool is_valid = true;
3230ee6b 520 struct stream_state *stream_state;
40f4ba76
PP
521 const struct bt_stream *stream = NULL;
522 const struct bt_packet *packet = NULL;
d6e69534 523 struct bt_message *msg = (void *) c_msg;
f42867e2 524
d6e69534
PP
525 BT_ASSERT(msg);
526 bt_message_borrow_packet_stream(c_msg, &stream, &packet);
f42867e2
PP
527
528 if (!stream) {
d6e69534 529 /* we don't care about messages not attached to streams */
f42867e2
PP
530 goto end;
531 }
3230ee6b 532
f42867e2
PP
533 stream_state = g_hash_table_lookup(iterator->stream_states, stream);
534 if (!stream_state) {
3230ee6b 535 /*
d6e69534
PP
536 * No stream state for this stream: this message
537 * MUST be a BT_MESSAGE_TYPE_STREAM_BEGINNING message
f42867e2 538 * and its sequence number must be 0.
3230ee6b 539 */
d6e69534
PP
540 if (c_msg->type != BT_MESSAGE_TYPE_STREAM_BEGINNING) {
541 BT_ASSERT_PRE_MSG("Unexpected message: missing a "
542 "BT_MESSAGE_TYPE_STREAM_BEGINNING "
543 "message prior to this message: "
f42867e2
PP
544 "%![stream-]+s", stream);
545 is_valid = false;
3230ee6b
PP
546 goto end;
547 }
548
d6e69534
PP
549 if (c_msg->seq_num == -1ULL) {
550 msg->seq_num = 0;
3230ee6b
PP
551 }
552
d6e69534
PP
553 if (c_msg->seq_num != 0) {
554 BT_ASSERT_PRE_MSG("Unexpected message sequence "
555 "number for this message iterator: "
556 "this is the first message for this "
f42867e2
PP
557 "stream, expecting sequence number 0: "
558 "seq-num=%" PRIu64 ", %![stream-]+s",
d6e69534 559 c_msg->seq_num, stream);
f42867e2 560 is_valid = false;
3230ee6b 561 goto end;
3230ee6b 562 }
3230ee6b 563
f42867e2
PP
564 stream_state = create_stream_state(stream);
565 if (!stream_state) {
566 abort();
567 }
fa054faf 568
40f4ba76
PP
569 g_hash_table_insert(iterator->stream_states,
570 (void *) stream, stream_state);
d6e69534 571 stream_state->expected_msg_seq_num++;
f42867e2 572 goto end;
fa054faf
PP
573 }
574
f42867e2
PP
575 if (stream_state->is_ended) {
576 /*
d6e69534 577 * There's a new message which has a reference to a
f42867e2 578 * stream which, from this iterator's point of view, is
d6e69534 579 * ended ("end of stream" message was returned).
f42867e2
PP
580 * This is bad: the API guarantees that it can never
581 * happen.
582 */
583 BT_ASSERT_PRE_MSG("Stream is already ended: %![stream-]+s",
584 stream);
585 is_valid = false;
fa054faf
PP
586 goto end;
587 }
588
d6e69534
PP
589 if (c_msg->seq_num == -1ULL) {
590 msg->seq_num = stream_state->expected_msg_seq_num;
3230ee6b
PP
591 }
592
d6e69534
PP
593 if (c_msg->seq_num != -1ULL &&
594 c_msg->seq_num != stream_state->expected_msg_seq_num) {
595 BT_ASSERT_PRE_MSG("Unexpected message sequence number: "
f42867e2
PP
596 "seq-num=%" PRIu64 ", "
597 "expected-seq-num=%" PRIu64 ", %![stream-]+s",
d6e69534 598 c_msg->seq_num, stream_state->expected_msg_seq_num,
f42867e2
PP
599 stream);
600 is_valid = false;
fa054faf
PP
601 goto end;
602 }
603
d6e69534
PP
604 switch (c_msg->type) {
605 case BT_MESSAGE_TYPE_STREAM_BEGINNING:
606 BT_ASSERT_PRE_MSG("Unexpected BT_MESSAGE_TYPE_STREAM_BEGINNING "
607 "message at this point: msg-seq-num=%" PRIu64 ", "
608 "%![stream-]+s", c_msg->seq_num, stream);
f42867e2
PP
609 is_valid = false;
610 goto end;
d6e69534 611 case BT_MESSAGE_TYPE_STREAM_END:
f42867e2 612 if (stream_state->cur_packet) {
d6e69534
PP
613 BT_ASSERT_PRE_MSG("Unexpected BT_MESSAGE_TYPE_STREAM_END "
614 "message: missing a "
615 "BT_MESSAGE_TYPE_PACKET_END message "
616 "prior to this message: "
617 "msg-seq-num=%" PRIu64 ", "
618 "%![stream-]+s", c_msg->seq_num, stream);
f42867e2
PP
619 is_valid = false;
620 goto end;
621 }
d6e69534 622 stream_state->expected_msg_seq_num++;
f42867e2
PP
623 stream_state->is_ended = true;
624 goto end;
d6e69534 625 case BT_MESSAGE_TYPE_PACKET_BEGINNING:
f42867e2 626 if (stream_state->cur_packet) {
d6e69534
PP
627 BT_ASSERT_PRE_MSG("Unexpected BT_MESSAGE_TYPE_PACKET_BEGINNING "
628 "message at this point: missing a "
629 "BT_MESSAGE_TYPE_PACKET_END message "
630 "prior to this message: "
631 "msg-seq-num=%" PRIu64 ", %![stream-]+s, "
632 "%![packet-]+a", c_msg->seq_num, stream,
f42867e2
PP
633 packet);
634 is_valid = false;
635 goto end;
636 }
d6e69534 637 stream_state->expected_msg_seq_num++;
398454ed
PP
638 stream_state->cur_packet = packet;
639 bt_object_get_no_null_check(stream_state->cur_packet);
f42867e2 640 goto end;
d6e69534 641 case BT_MESSAGE_TYPE_PACKET_END:
f42867e2 642 if (!stream_state->cur_packet) {
d6e69534
PP
643 BT_ASSERT_PRE_MSG("Unexpected BT_MESSAGE_TYPE_PACKET_END "
644 "message at this point: missing a "
645 "BT_MESSAGE_TYPE_PACKET_BEGINNING message "
646 "prior to this message: "
647 "msg-seq-num=%" PRIu64 ", %![stream-]+s, "
648 "%![packet-]+a", c_msg->seq_num, stream,
f42867e2
PP
649 packet);
650 is_valid = false;
651 goto end;
652 }
d6e69534 653 stream_state->expected_msg_seq_num++;
65300d60 654 BT_OBJECT_PUT_REF_AND_RESET(stream_state->cur_packet);
f42867e2 655 goto end;
d6e69534 656 case BT_MESSAGE_TYPE_EVENT:
f42867e2
PP
657 if (packet != stream_state->cur_packet) {
658 BT_ASSERT_PRE_MSG("Unexpected packet for "
d6e69534
PP
659 "BT_MESSAGE_TYPE_EVENT message: "
660 "msg-seq-num=%" PRIu64 ", %![stream-]+s, "
661 "%![msg-packet-]+a, %![expected-packet-]+a",
662 c_msg->seq_num, stream,
f42867e2
PP
663 stream_state->cur_packet, packet);
664 is_valid = false;
665 goto end;
666 }
d6e69534 667 stream_state->expected_msg_seq_num++;
f42867e2
PP
668 goto end;
669 default:
670 break;
3230ee6b
PP
671 }
672
3230ee6b 673end:
f42867e2 674 return is_valid;
3230ee6b
PP
675}
676
d4393e08
PP
677BT_ASSERT_PRE_FUNC
678static inline
d6e69534
PP
679bool validate_messages(
680 struct bt_self_component_port_input_message_iterator *iterator,
d4393e08
PP
681 uint64_t count)
682{
683 bool ret = true;
d6e69534
PP
684 bt_message_array_const msgs =
685 (void *) iterator->base.msgs->pdata;
d4393e08
PP
686 uint64_t i;
687
688 for (i = 0; i < count; i++) {
d6e69534 689 ret = validate_message(iterator, msgs[i]);
d4393e08
PP
690 if (!ret) {
691 break;
692 }
693 }
694
695 return ret;
696}
697
f42867e2 698BT_ASSERT_PRE_FUNC
d6e69534
PP
699static inline bool self_comp_port_input_msg_iter_can_end(
700 struct bt_self_component_port_input_message_iterator *iterator)
3230ee6b 701{
f42867e2
PP
702 GHashTableIter iter;
703 gpointer stream_key, state_value;
704 bool ret = true;
3230ee6b 705
f42867e2
PP
706 /*
707 * Verify that this iterator received a
d6e69534 708 * BT_MESSAGE_TYPE_STREAM_END message for each stream
f42867e2
PP
709 * which has a state.
710 */
3230ee6b 711
f42867e2 712 g_hash_table_iter_init(&iter, iterator->stream_states);
3230ee6b 713
f42867e2
PP
714 while (g_hash_table_iter_next(&iter, &stream_key, &state_value)) {
715 struct stream_state *stream_state = (void *) state_value;
3230ee6b 716
f42867e2
PP
717 BT_ASSERT(stream_state);
718 BT_ASSERT(stream_key);
fa054faf 719
f42867e2 720 if (!stream_state->is_ended) {
d6e69534 721 BT_ASSERT_PRE_MSG("Ending message iterator, "
f42867e2
PP
722 "but stream is not ended: "
723 "%![stream-]s", stream_key);
724 ret = false;
725 goto end;
726 }
3230ee6b
PP
727 }
728
3230ee6b 729end:
3230ee6b
PP
730 return ret;
731}
732
d6e69534
PP
733enum bt_message_iterator_status
734bt_self_component_port_input_message_iterator_next(
735 struct bt_self_component_port_input_message_iterator *iterator,
736 bt_message_array_const *msgs, uint64_t *user_count)
3230ee6b 737{
d6e69534
PP
738 typedef enum bt_self_message_iterator_status (*method_t)(
739 void *, bt_message_array_const, uint64_t, uint64_t *);
d94d92ac
PP
740
741 method_t method = NULL;
742 struct bt_component_class *comp_cls;
d6e69534 743 int status = BT_MESSAGE_ITERATOR_STATUS_OK;
d94d92ac 744
d6e69534
PP
745 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
746 BT_ASSERT_PRE_NON_NULL(msgs, "Message array (output)");
747 BT_ASSERT_PRE_NON_NULL(user_count, "Message count (output)");
f42867e2 748 BT_ASSERT_PRE(iterator->state ==
d6e69534
PP
749 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_ACTIVE,
750 "Message iterator's \"next\" called, but "
f42867e2
PP
751 "iterator is in the wrong state: %!+i", iterator);
752 BT_ASSERT(iterator->upstream_component);
753 BT_ASSERT(iterator->upstream_component->class);
4725a201
PP
754 BT_ASSERT_PRE(bt_component_borrow_graph(iterator->upstream_component)->is_configured,
755 "Graph is not configured: %!+g",
756 bt_component_borrow_graph(iterator->upstream_component));
d94d92ac 757 BT_LIB_LOGD("Getting next self component input port "
d6e69534 758 "message iterator's messages: %!+i", iterator);
d94d92ac 759 comp_cls = iterator->upstream_component->class;
d3eb6e8f 760
3230ee6b 761 /* Pick the appropriate "next" method */
d94d92ac 762 switch (comp_cls->type) {
d3eb6e8f
PP
763 case BT_COMPONENT_CLASS_TYPE_SOURCE:
764 {
d94d92ac
PP
765 struct bt_component_class_source *src_comp_cls =
766 (void *) comp_cls;
d3eb6e8f 767
d6e69534 768 method = (method_t) src_comp_cls->methods.msg_iter_next;
d3eb6e8f
PP
769 break;
770 }
771 case BT_COMPONENT_CLASS_TYPE_FILTER:
772 {
d94d92ac
PP
773 struct bt_component_class_filter *flt_comp_cls =
774 (void *) comp_cls;
d3eb6e8f 775
d6e69534 776 method = (method_t) flt_comp_cls->methods.msg_iter_next;
d3eb6e8f
PP
777 break;
778 }
779 default:
0fbb9a9f 780 abort();
d3eb6e8f
PP
781 }
782
3230ee6b 783 /*
d6e69534 784 * Call the user's "next" method to get the next messages
fa054faf 785 * and status.
3230ee6b 786 */
d94d92ac 787 BT_ASSERT(method);
f42867e2 788 BT_LOGD_STR("Calling user's \"next\" method.");
d0fea130 789 status = method(iterator, (void *) iterator->base.msgs->pdata,
d6e69534 790 MSG_BATCH_SIZE, user_count);
f42867e2 791 BT_LOGD("User method returned: status=%s",
d6e69534 792 bt_message_iterator_status_string(status));
d4393e08 793 if (status < 0) {
f42867e2 794 BT_LOGW_STR("User method failed.");
f42867e2
PP
795 goto end;
796 }
3230ee6b 797
d0fea130
PP
798#ifdef BT_DEV_MODE
799 /*
800 * There is no way that this iterator could have been finalized
801 * during its "next" method, as the only way to do this is to
802 * put the last iterator's reference, and this can only be done
803 * by its downstream owner.
804 */
805 BT_ASSERT(iterator->state ==
806 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_ACTIVE);
807#endif
8cf27cc5 808
d4393e08 809 switch (status) {
d6e69534
PP
810 case BT_MESSAGE_ITERATOR_STATUS_OK:
811 BT_ASSERT_PRE(validate_messages(iterator, *user_count),
812 "Messages are invalid at this point: "
813 "%![msg-iter-]+i, count=%" PRIu64,
d4393e08 814 iterator, *user_count);
d6e69534 815 *msgs = (void *) iterator->base.msgs->pdata;
d4393e08 816 break;
d6e69534 817 case BT_MESSAGE_ITERATOR_STATUS_AGAIN:
d4393e08 818 goto end;
d6e69534
PP
819 case BT_MESSAGE_ITERATOR_STATUS_END:
820 BT_ASSERT_PRE(self_comp_port_input_msg_iter_can_end(iterator),
821 "Message iterator cannot end at this point: "
f42867e2 822 "%!+i", iterator);
d0fea130
PP
823 set_self_comp_port_input_msg_iterator_state(iterator,
824 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_ENDED);
f42867e2 825 goto end;
f42867e2
PP
826 default:
827 /* Unknown non-error status */
828 abort();
41a2b7ae
PP
829 }
830
831end:
3230ee6b
PP
832 return status;
833}
834
d0fea130 835enum bt_message_iterator_status bt_port_output_message_iterator_next(
d6e69534
PP
836 struct bt_port_output_message_iterator *iterator,
837 bt_message_array_const *msgs_to_user,
d4393e08 838 uint64_t *count_to_user)
3230ee6b 839{
d6e69534 840 enum bt_message_iterator_status status;
07245ac2 841 enum bt_graph_status graph_status;
3230ee6b 842
d6e69534
PP
843 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
844 BT_ASSERT_PRE_NON_NULL(msgs_to_user, "Message array (output)");
845 BT_ASSERT_PRE_NON_NULL(count_to_user, "Message count (output)");
846 BT_LIB_LOGD("Getting next output port message iterator's messages: "
07245ac2 847 "%!+i", iterator);
d4393e08 848
4725a201
PP
849 /*
850 * As soon as the user calls this function, we mark the graph as
851 * being definitely configured.
852 */
853 bt_graph_set_is_configured(iterator->graph, true);
854
d94d92ac
PP
855 graph_status = bt_graph_consume_sink_no_check(iterator->graph,
856 iterator->colander);
07245ac2
PP
857 switch (graph_status) {
858 case BT_GRAPH_STATUS_CANCELED:
07245ac2 859 case BT_GRAPH_STATUS_AGAIN:
07245ac2 860 case BT_GRAPH_STATUS_END:
07245ac2 861 case BT_GRAPH_STATUS_NOMEM:
d94d92ac 862 status = (int) graph_status;
07245ac2
PP
863 break;
864 case BT_GRAPH_STATUS_OK:
d6e69534 865 status = BT_MESSAGE_ITERATOR_STATUS_OK;
d4393e08
PP
866
867 /*
d6e69534 868 * On success, the colander sink moves the messages
d4393e08 869 * to this iterator's array and sets this iterator's
d6e69534 870 * message count: move them to the user.
d4393e08 871 */
d6e69534 872 *msgs_to_user = (void *) iterator->base.msgs->pdata;
d94d92ac 873 *count_to_user = iterator->count;
90157d89 874 break;
90157d89 875 default:
07245ac2 876 /* Other errors */
d6e69534 877 status = BT_MESSAGE_ITERATOR_STATUS_ERROR;
90157d89 878 }
3230ee6b 879
3230ee6b 880 return status;
53d45b87
JG
881}
882
d6e69534
PP
883struct bt_component *bt_self_component_port_input_message_iterator_borrow_component(
884 struct bt_self_component_port_input_message_iterator *iterator)
d94d92ac 885{
d6e69534 886 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
d94d92ac
PP
887 return iterator->upstream_component;
888}
889
d6e69534
PP
890struct bt_self_component *bt_self_message_iterator_borrow_component(
891 struct bt_self_message_iterator *self_iterator)
413bc2c4 892{
d6e69534 893 struct bt_self_component_port_input_message_iterator *iterator =
d94d92ac 894 (void *) self_iterator;
90157d89 895
d6e69534 896 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
d94d92ac 897 return (void *) iterator->upstream_component;
413bc2c4
JG
898}
899
d6e69534
PP
900struct bt_self_port_output *bt_self_message_iterator_borrow_port(
901 struct bt_self_message_iterator *self_iterator)
91457551 902{
d6e69534 903 struct bt_self_component_port_input_message_iterator *iterator =
d94d92ac
PP
904 (void *) self_iterator;
905
d6e69534 906 BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
d94d92ac 907 return (void *) iterator->upstream_port;
91457551 908}
8ed535b5
PP
909
910static
d6e69534 911void bt_port_output_message_iterator_destroy(struct bt_object *obj)
8ed535b5 912{
d6e69534 913 struct bt_port_output_message_iterator *iterator = (void *) obj;
8ed535b5 914
d6e69534 915 BT_LIB_LOGD("Destroying output port message iterator object: %!+i",
8ed535b5
PP
916 iterator);
917 BT_LOGD_STR("Putting graph.");
d94d92ac 918 BT_OBJECT_PUT_REF_AND_RESET(iterator->graph);
8ed535b5 919 BT_LOGD_STR("Putting colander sink component.");
d94d92ac 920 BT_OBJECT_PUT_REF_AND_RESET(iterator->colander);
d6e69534 921 destroy_base_message_iterator(obj);
8ed535b5
PP
922}
923
d6e69534
PP
924struct bt_port_output_message_iterator *
925bt_port_output_message_iterator_create(
0d72b8c3
PP
926 struct bt_graph *graph,
927 const struct bt_port_output *output_port)
8ed535b5 928{
d6e69534 929 struct bt_port_output_message_iterator *iterator = NULL;
d94d92ac 930 struct bt_component_class_sink *colander_comp_cls = NULL;
8ed535b5 931 struct bt_component *output_port_comp = NULL;
d94d92ac 932 struct bt_component_sink *colander_comp;
8ed535b5 933 enum bt_graph_status graph_status;
d94d92ac 934 struct bt_port_input *colander_in_port = NULL;
8ed535b5 935 struct bt_component_class_sink_colander_data colander_data;
d4393e08 936 int ret;
8ed535b5 937
d94d92ac 938 BT_ASSERT_PRE_NON_NULL(graph, "Graph");
f42867e2 939 BT_ASSERT_PRE_NON_NULL(output_port, "Output port");
0d72b8c3
PP
940 output_port_comp = bt_port_borrow_component_inline(
941 (const void *) output_port);
f42867e2
PP
942 BT_ASSERT_PRE(output_port_comp,
943 "Output port has no component: %!+p", output_port);
d94d92ac
PP
944 BT_ASSERT_PRE(bt_component_borrow_graph(output_port_comp) ==
945 (void *) graph,
946 "Output port is not part of graph: %![graph-]+g, %![port-]+p",
947 graph, output_port);
8ed535b5 948
d6e69534
PP
949 /* Create message iterator */
950 BT_LIB_LOGD("Creating message iterator on output port: "
d94d92ac 951 "%![port-]+p, %![comp-]+c", output_port, output_port_comp);
d6e69534 952 iterator = g_new0(struct bt_port_output_message_iterator, 1);
8ed535b5 953 if (!iterator) {
d6e69534 954 BT_LOGE_STR("Failed to allocate one output port message iterator.");
8ed535b5
PP
955 goto error;
956 }
957
d6e69534
PP
958 ret = init_message_iterator((void *) iterator,
959 BT_MESSAGE_ITERATOR_TYPE_PORT_OUTPUT,
960 bt_port_output_message_iterator_destroy);
d4393e08 961 if (ret) {
d6e69534 962 /* init_message_iterator() logs errors */
65300d60 963 BT_OBJECT_PUT_REF_AND_RESET(iterator);
d4393e08
PP
964 goto end;
965 }
8ed535b5
PP
966
967 /* Create colander component */
968 colander_comp_cls = bt_component_class_sink_colander_get();
969 if (!colander_comp_cls) {
970 BT_LOGW("Cannot get colander sink component class.");
971 goto error;
972 }
973
398454ed
PP
974 iterator->graph = graph;
975 bt_object_get_no_null_check(iterator->graph);
d6e69534 976 colander_data.msgs = (void *) iterator->base.msgs->pdata;
d4393e08 977 colander_data.count_addr = &iterator->count;
5fd91d88
PP
978
979 /* Hope that nobody uses this very unique name */
d94d92ac 980 graph_status =
0d72b8c3 981 bt_graph_add_sink_component_with_init_method_data(
5fd91d88
PP
982 (void *) graph, colander_comp_cls,
983 "colander-36ac3409-b1a8-4d60-ab1f-4fdf341a8fb1",
0d72b8c3 984 NULL, &colander_data, (void *) &iterator->colander);
8ed535b5 985 if (graph_status != BT_GRAPH_STATUS_OK) {
d94d92ac
PP
986 BT_LIB_LOGW("Cannot add colander sink component to graph: "
987 "%1[graph-]+g, status=%s", graph,
8ed535b5
PP
988 bt_graph_status_string(graph_status));
989 goto error;
990 }
991
992 /*
993 * Connect provided output port to the colander component's
994 * input port.
995 */
0d72b8c3
PP
996 colander_in_port =
997 (void *) bt_component_sink_borrow_input_port_by_index_const(
998 (void *) iterator->colander, 0);
f6ccaed9 999 BT_ASSERT(colander_in_port);
0d72b8c3 1000 graph_status = bt_graph_connect_ports(graph,
8ed535b5
PP
1001 output_port, colander_in_port, NULL);
1002 if (graph_status != BT_GRAPH_STATUS_OK) {
d94d92ac
PP
1003 BT_LIB_LOGW("Cannot add colander sink component to graph: "
1004 "%![graph-]+g, %![comp-]+c, status=%s", graph,
1005 iterator->colander,
8ed535b5
PP
1006 bt_graph_status_string(graph_status));
1007 goto error;
1008 }
1009
1010 /*
1011 * At this point everything went fine. Make the graph
d6e69534 1012 * nonconsumable forever so that only this message iterator
8ed535b5 1013 * can consume (thanks to bt_graph_consume_sink_no_check()).
d6e69534
PP
1014 * This avoids leaking the message created by the colander
1015 * sink and moved to the message iterator's message
07245ac2 1016 * member.
8ed535b5 1017 */
d94d92ac 1018 bt_graph_set_can_consume(iterator->graph, false);
8ed535b5
PP
1019 goto end;
1020
1021error:
1022 if (iterator && iterator->graph && iterator->colander) {
1023 int ret;
1024
1025 /* Remove created colander component from graph if any */
1026 colander_comp = iterator->colander;
65300d60 1027 BT_OBJECT_PUT_REF_AND_RESET(iterator->colander);
8ed535b5
PP
1028
1029 /*
1030 * At this point the colander component's reference
1031 * count is 0 because iterator->colander was the only
1032 * owner. We also know that it is not connected because
1033 * this is the last operation before this function
1034 * succeeds.
1035 *
1036 * Since we honor the preconditions here,
1037 * bt_graph_remove_unconnected_component() always
1038 * succeeds.
1039 */
1040 ret = bt_graph_remove_unconnected_component(iterator->graph,
d94d92ac 1041 (void *) colander_comp);
f6ccaed9 1042 BT_ASSERT(ret == 0);
8ed535b5
PP
1043 }
1044
65300d60 1045 BT_OBJECT_PUT_REF_AND_RESET(iterator);
8ed535b5
PP
1046
1047end:
65300d60 1048 bt_object_put_ref(colander_comp_cls);
8ed535b5
PP
1049 return (void *) iterator;
1050}
c5b9b441 1051
d6e69534
PP
1052void bt_port_output_message_iterator_get_ref(
1053 const struct bt_port_output_message_iterator *iterator)
c5b9b441
PP
1054{
1055 bt_object_get_ref(iterator);
1056}
1057
d6e69534
PP
1058void bt_port_output_message_iterator_put_ref(
1059 const struct bt_port_output_message_iterator *iterator)
c5b9b441
PP
1060{
1061 bt_object_put_ref(iterator);
1062}
1063
d6e69534
PP
1064void bt_self_component_port_input_message_iterator_get_ref(
1065 const struct bt_self_component_port_input_message_iterator *iterator)
c5b9b441
PP
1066{
1067 bt_object_get_ref(iterator);
1068}
1069
d6e69534
PP
1070void bt_self_component_port_input_message_iterator_put_ref(
1071 const struct bt_self_component_port_input_message_iterator *iterator)
c5b9b441
PP
1072{
1073 bt_object_put_ref(iterator);
1074}
This page took 0.099847 seconds and 4 git commands to generate.