+ has_timestamp = true;
+ }
+
+ if (has_timestamp) {
+ /* Set new start for the message portion of the line */
+ *new_start = strchr(line, ']');
+ BT_ASSERT(*new_start);
+ (*new_start)++;
+
+ if ((*new_start)[0] == ' ') {
+ (*new_start)++;
+ }
+ }
+
+skip_ts:
+ /*
+ * At this point, we know if the stream class's event header
+ * field class should have a timestamp or not, so we can lazily
+ * create the metadata, stream, and packet objects.
+ */
+ ret = try_create_meta_stream_packet(dmesg_comp, has_timestamp);
+ if (ret) {
+ /* try_create_meta_stream_packet() logs errors */
+ goto error;
+ }
+
+ if (dmesg_comp->clock_class) {
+ msg = bt_message_event_create_with_default_clock_snapshot(
+ msg_iter->pc_msg_iter,
+ dmesg_comp->event_class, dmesg_comp->packet, ts);
+ msg_iter->last_clock_value = ts;
+ } else {
+ msg = bt_message_event_create(msg_iter->pc_msg_iter,
+ dmesg_comp->event_class, dmesg_comp->packet);
+ }
+
+ if (!msg) {
+ BT_LOGE_STR("Cannot create event message.");
+ goto error;
+ }
+
+ event = bt_message_event_borrow_event(msg);
+ BT_ASSERT(event);
+ goto end;
+
+error:
+ BT_MESSAGE_PUT_REF_AND_RESET(msg);
+
+end:
+ return msg;
+}
+
+static
+int fill_event_payload_from_line(const char *line,
+ bt_event *event)
+{
+ bt_field *ep_field = NULL;
+ bt_field *str_field = NULL;
+ size_t len;
+ int ret;
+
+ ep_field = bt_event_borrow_payload_field(event);
+ BT_ASSERT(ep_field);
+ str_field = bt_field_structure_borrow_member_field_by_index(
+ ep_field, 0);
+ if (!str_field) {
+ BT_LOGE_STR("Cannot borrow `timestamp` field from event payload structure field.");
+ goto error;
+ }
+
+ len = strlen(line);
+ if (line[len - 1] == '\n') {
+ /* Do not include the newline character in the payload */
+ len--;
+ }
+
+ ret = bt_field_string_clear(str_field);
+ if (ret) {
+ BT_LOGE_STR("Cannot clear string field object.");
+ goto error;
+ }
+
+ ret = bt_field_string_append_with_length(str_field, line, len);
+ if (ret) {
+ BT_LOGE("Cannot append value to string field object: "
+ "len=%zu", len);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ return ret;
+}
+
+static
+bt_message *create_msg_from_line(
+ struct dmesg_msg_iter *dmesg_msg_iter, const char *line)
+{
+ bt_event *event = NULL;
+ bt_message *msg = NULL;
+ const char *new_start;
+ int ret;
+
+ msg = create_init_event_msg_from_line(dmesg_msg_iter,
+ line, &new_start);
+ if (!msg) {
+ BT_LOGE_STR("Cannot create and initialize event message from line.");
+ goto error;
+ }
+
+ event = bt_message_event_borrow_event(msg);
+ BT_ASSERT(event);
+ ret = fill_event_payload_from_line(new_start, event);
+ if (ret) {
+ BT_LOGE("Cannot fill event payload field from line: "
+ "ret=%d", ret);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_MESSAGE_PUT_REF_AND_RESET(msg);
+
+end:
+ return msg;
+}
+
+static
+void destroy_dmesg_msg_iter(struct dmesg_msg_iter *dmesg_msg_iter)
+{
+ if (!dmesg_msg_iter) {
+ return;
+ }
+
+ if (dmesg_msg_iter->fp && dmesg_msg_iter->fp != stdin) {
+ if (fclose(dmesg_msg_iter->fp)) {
+ BT_LOGE_ERRNO("Cannot close input file", ".");
+ }
+ }
+
+ bt_message_put_ref(dmesg_msg_iter->tmp_event_msg);
+ free(dmesg_msg_iter->linebuf);
+ g_free(dmesg_msg_iter);
+}
+
+
+
+BT_HIDDEN
+bt_self_message_iterator_status dmesg_msg_iter_init(
+ bt_self_message_iterator *self_msg_iter,
+ bt_self_component_source *self_comp,
+ bt_self_component_port_output *self_port)
+{
+ struct dmesg_component *dmesg_comp;
+ struct dmesg_msg_iter *dmesg_msg_iter =
+ g_new0(struct dmesg_msg_iter, 1);
+ bt_self_message_iterator_status status =
+ BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
+
+ if (!dmesg_msg_iter) {
+ BT_LOGE_STR("Failed to allocate on dmesg message iterator structure.");
+ goto error;
+ }
+
+ dmesg_comp = bt_self_component_get_data(
+ bt_self_component_source_as_self_component(self_comp));
+ BT_ASSERT(dmesg_comp);
+ dmesg_msg_iter->dmesg_comp = dmesg_comp;
+ dmesg_msg_iter->pc_msg_iter = self_msg_iter;
+
+ if (dmesg_comp->params.read_from_stdin) {
+ dmesg_msg_iter->fp = stdin;
+ } else {
+ dmesg_msg_iter->fp = fopen(dmesg_comp->params.path->str, "r");
+ if (!dmesg_msg_iter->fp) {
+ BT_LOGE_ERRNO("Cannot open input file in read mode", ": path=\"%s\"",
+ dmesg_comp->params.path->str);
+ goto error;
+ }
+ }
+
+ bt_self_message_iterator_set_data(self_msg_iter,
+ dmesg_msg_iter);
+ goto end;
+
+error:
+ destroy_dmesg_msg_iter(dmesg_msg_iter);
+ bt_self_message_iterator_set_data(self_msg_iter, NULL);
+ if (status >= 0) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
+ }
+
+end:
+ return status;
+}
+
+BT_HIDDEN
+void dmesg_msg_iter_finalize(
+ bt_self_message_iterator *priv_msg_iter)
+{
+ destroy_dmesg_msg_iter(bt_self_message_iterator_get_data(
+ priv_msg_iter));
+}
+
+static
+bt_self_message_iterator_status dmesg_msg_iter_next_one(
+ struct dmesg_msg_iter *dmesg_msg_iter,
+ bt_message **msg)
+{
+ ssize_t len;
+ struct dmesg_component *dmesg_comp;
+ bt_self_message_iterator_status status =
+ BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
+
+ BT_ASSERT(dmesg_msg_iter);
+ dmesg_comp = dmesg_msg_iter->dmesg_comp;
+ BT_ASSERT(dmesg_comp);
+
+ if (dmesg_msg_iter->state == STATE_DONE) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_END;
+ goto end;
+ }
+
+ if (dmesg_msg_iter->tmp_event_msg ||
+ dmesg_msg_iter->state == STATE_EMIT_PACKET_END ||
+ dmesg_msg_iter->state == STATE_EMIT_STREAM_ACTIVITY_END ||
+ dmesg_msg_iter->state == STATE_EMIT_STREAM_END) {
+ goto handle_state;
+ }
+
+ while (true) {
+ const char *ch;
+ bool only_spaces = true;
+
+ len = bt_getline(&dmesg_msg_iter->linebuf,
+ &dmesg_msg_iter->linebuf_len, dmesg_msg_iter->fp);
+ if (len < 0) {
+ if (errno == EINVAL) {
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
+ } else if (errno == ENOMEM) {
+ status =
+ BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
+ } else {
+ if (dmesg_msg_iter->state == STATE_EMIT_STREAM_BEGINNING) {
+ /* Stream did not even begin */
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_END;
+ goto end;
+ } else {
+ /* End current packet now */
+ dmesg_msg_iter->state =
+ STATE_EMIT_PACKET_END;
+ goto handle_state;
+ }
+ }
+
+ goto end;
+ }
+
+ BT_ASSERT(dmesg_msg_iter->linebuf);
+
+ /* Ignore empty lines, once trimmed */
+ for (ch = dmesg_msg_iter->linebuf; *ch != '\0'; ch++) {
+ if (!isspace(*ch)) {
+ only_spaces = false;
+ break;
+ }
+ }
+
+ if (!only_spaces) {
+ break;
+ }
+ }
+
+ dmesg_msg_iter->tmp_event_msg = create_msg_from_line(
+ dmesg_msg_iter, dmesg_msg_iter->linebuf);
+ if (!dmesg_msg_iter->tmp_event_msg) {
+ BT_LOGE("Cannot create event message from line: "
+ "dmesg-comp-addr=%p, line=\"%s\"", dmesg_comp,
+ dmesg_msg_iter->linebuf);
+ goto end;
+ }
+
+handle_state:
+ BT_ASSERT(dmesg_comp->trace);
+
+ switch (dmesg_msg_iter->state) {
+ case STATE_EMIT_STREAM_BEGINNING:
+ BT_ASSERT(dmesg_msg_iter->tmp_event_msg);
+ *msg = bt_message_stream_beginning_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->stream);
+ dmesg_msg_iter->state = STATE_EMIT_STREAM_ACTIVITY_BEGINNING;
+ break;
+ case STATE_EMIT_STREAM_ACTIVITY_BEGINNING:
+ BT_ASSERT(dmesg_msg_iter->tmp_event_msg);
+ *msg = bt_message_stream_activity_beginning_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->stream);
+ dmesg_msg_iter->state = STATE_EMIT_PACKET_BEGINNING;
+ break;
+ case STATE_EMIT_PACKET_BEGINNING:
+ BT_ASSERT(dmesg_msg_iter->tmp_event_msg);
+
+ if (dmesg_comp->clock_class) {
+ *msg = bt_message_packet_beginning_create_with_default_clock_snapshot(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->packet,
+ dmesg_msg_iter->last_clock_value);
+ } else {
+ *msg = bt_message_packet_beginning_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->packet);
+ }
+
+ dmesg_msg_iter->state = STATE_EMIT_EVENT;
+ break;
+ case STATE_EMIT_EVENT:
+ BT_ASSERT(dmesg_msg_iter->tmp_event_msg);
+ *msg = dmesg_msg_iter->tmp_event_msg;
+ dmesg_msg_iter->tmp_event_msg = NULL;
+ break;
+ case STATE_EMIT_PACKET_END:
+ if (dmesg_comp->clock_class) {
+ *msg = bt_message_packet_end_create_with_default_clock_snapshot(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->packet,
+ dmesg_msg_iter->last_clock_value);
+ } else {
+ *msg = bt_message_packet_end_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->packet);
+ }
+
+ dmesg_msg_iter->state = STATE_EMIT_STREAM_ACTIVITY_END;
+ break;
+ case STATE_EMIT_STREAM_ACTIVITY_END:
+ *msg = bt_message_stream_activity_end_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->stream);
+ dmesg_msg_iter->state = STATE_EMIT_STREAM_END;
+ break;
+ case STATE_EMIT_STREAM_END:
+ *msg = bt_message_stream_end_create(
+ dmesg_msg_iter->pc_msg_iter, dmesg_comp->stream);
+ dmesg_msg_iter->state = STATE_DONE;
+ break;
+ default:
+ break;
+ }
+
+ if (!*msg) {
+ BT_LOGE("Cannot create message: dmesg-comp-addr=%p",
+ dmesg_comp);
+ status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
+ }
+
+end:
+ return status;