+ int status;
+
+ BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
+ BT_ASSERT_PRE_ITER_HAS_STATE_TO_SEEK(iterator);
+ BT_ASSERT_PRE(
+ bt_component_borrow_graph(iterator->upstream_component)->config_state !=
+ BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
+ "Graph is not configured: %!+g",
+ bt_component_borrow_graph(iterator->upstream_component));
+ BT_ASSERT_PRE(
+ bt_self_component_port_input_message_iterator_can_seek_ns_from_origin(
+ iterator, ns_from_origin),
+ "Message iterator cannot seek nanoseconds from origin: %!+i, "
+ "ns-from-origin=%" PRId64, iterator, ns_from_origin);
+ set_self_comp_port_input_msg_iterator_state(iterator,
+ BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_STATE_SEEKING);
+
+ if (iterator->methods.seek_ns_from_origin) {
+ BT_LIB_LOGD("Calling user's \"seek nanoseconds from origin\" method: "
+ "%![iter-]+i, ns=%" PRId64, iterator, ns_from_origin);
+ status = iterator->methods.seek_ns_from_origin(iterator,
+ ns_from_origin);
+ BT_LOGD("User method returned: status=%s",
+ bt_message_iterator_status_string(status));
+ BT_ASSERT_PRE(status == BT_MESSAGE_ITERATOR_STATUS_OK ||
+ status == BT_MESSAGE_ITERATOR_STATUS_ERROR ||
+ status == BT_MESSAGE_ITERATOR_STATUS_NOMEM ||
+ status == BT_MESSAGE_ITERATOR_STATUS_AGAIN,
+ "Unexpected status: %![iter-]+i, status=%s",
+ iterator,
+ bt_self_message_iterator_status_string(status));
+ } else {
+ /* Start automatic seeking: seek beginning first */
+ BT_ASSERT(iterator->methods.can_seek_beginning(iterator));
+ BT_ASSERT(iterator->methods.seek_beginning);
+ BT_LIB_LOGD("Calling user's \"seek beginning\" method: %!+i",
+ iterator);
+ status = iterator->methods.seek_beginning(iterator);
+ BT_LOGD("User method returned: status=%s",
+ bt_message_iterator_status_string(status));
+ BT_ASSERT_PRE(status == BT_MESSAGE_ITERATOR_STATUS_OK ||
+ status == BT_MESSAGE_ITERATOR_STATUS_ERROR ||
+ status == BT_MESSAGE_ITERATOR_STATUS_NOMEM ||
+ status == BT_MESSAGE_ITERATOR_STATUS_AGAIN,
+ "Unexpected status: %![iter-]+i, status=%s",
+ iterator,
+ bt_self_message_iterator_status_string(status));
+ switch (status) {
+ case BT_MESSAGE_ITERATOR_STATUS_OK:
+ break;
+ case BT_MESSAGE_ITERATOR_STATUS_ERROR:
+ case BT_MESSAGE_ITERATOR_STATUS_NOMEM:
+ case BT_MESSAGE_ITERATOR_STATUS_AGAIN:
+ goto end;
+ default:
+ abort();
+ }
+
+ /*
+ * Find the first message which has a default clock
+ * snapshot greater than or equal to the requested
+ * seeking time, and move the received messages from
+ * this point in the batch to this iterator's auto-seek
+ * message queue.
+ */
+ while (!g_queue_is_empty(iterator->auto_seek_msgs)) {
+ bt_object_put_no_null_check(
+ g_queue_pop_tail(iterator->auto_seek_msgs));
+ }
+
+ status = find_message_ge_ns_from_origin(iterator,
+ ns_from_origin);
+ switch (status) {
+ case BT_MESSAGE_ITERATOR_STATUS_OK:
+ case BT_MESSAGE_ITERATOR_STATUS_END:
+ /*
+ * If there are messages in the auto-seek
+ * message queue, replace the user's "next"
+ * method with a custom, temporary "next" method
+ * which returns them.
+ */
+ if (!g_queue_is_empty(iterator->auto_seek_msgs)) {
+ iterator->methods.next =
+ (bt_self_component_port_input_message_iterator_next_method)
+ post_auto_seek_next;
+ }
+
+ /*
+ * `BT_MESSAGE_ITERATOR_STATUS_END` becomes
+ * `BT_MESSAGE_ITERATOR_STATUS_OK`: the next
+ * time this iterator's "next" method is called,
+ * it will return
+ * `BT_MESSAGE_ITERATOR_STATUS_END`.
+ */
+ status = BT_MESSAGE_ITERATOR_STATUS_OK;
+ break;
+ case BT_MESSAGE_ITERATOR_STATUS_ERROR:
+ case BT_MESSAGE_ITERATOR_STATUS_NOMEM:
+ case BT_MESSAGE_ITERATOR_STATUS_AGAIN:
+ goto end;
+ default:
+ abort();
+ }
+ }
+
+end:
+ set_iterator_state_after_seeking(iterator, status);
+ return status;