+ /* EOF across entire stream. */
+ index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
+ goto hup;
+ }
+ /*
+ * If we have been pushed due to overwrite, it
+ * necessarily means there is data that can be read in
+ * the stream. If we rotated because we reached the end
+ * of a tracefile, it means the following tracefile
+ * needs to contain at least one index, else we would
+ * have already returned LTTNG_VIEWER_INDEX_RETRY to the
+ * viewer. The updated index_sent_seqcount needs to
+ * point to a readable index entry now.
+ *
+ * In the case where we "rotate" on a single file, we
+ * can end up in a case where the requested index is
+ * still unavailable.
+ */
+ if (rstream->tracefile_count == 1 &&
+ !tracefile_array_seq_in_file(
+ rstream->tfa,
+ vstream->current_tracefile_id,
+ vstream->index_sent_seqcount)) {
+ index->status = htobe32(LTTNG_VIEWER_INDEX_RETRY);
+ goto index_ready;
+ }
+ assert(tracefile_array_seq_in_file(rstream->tfa,
+ vstream->current_tracefile_id,
+ vstream->index_sent_seqcount));
+ }
+ /* ret == 0 means successful so we continue. */
+ ret = 0;
+end:
+ return ret;
+
+hup:
+ viewer_stream_put(vstream);
+index_ready:
+ return 1;
+}
+
+/*
+ * Send the next index for a stream.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static
+int viewer_get_next_index(struct relay_connection *conn)
+{
+ int ret;
+ struct lttng_viewer_get_next_index request_index;
+ struct lttng_viewer_index viewer_index;
+ struct ctf_packet_index packet_index;
+ struct relay_viewer_stream *vstream = NULL;
+ struct relay_stream *rstream = NULL;
+ struct ctf_trace *ctf_trace = NULL;
+ struct relay_viewer_stream *metadata_viewer_stream = NULL;
+
+ assert(conn);
+
+ DBG("Viewer get next index");
+
+ memset(&viewer_index, 0, sizeof(viewer_index));
+ health_code_update();
+
+ ret = recv_request(conn->sock, &request_index, sizeof(request_index));
+ if (ret < 0) {
+ goto end;
+ }
+ health_code_update();
+
+ vstream = viewer_stream_get_by_id(be64toh(request_index.stream_id));
+ if (!vstream) {
+ DBG("Client requested index of unknown stream id %" PRIu64,
+ (uint64_t) be64toh(request_index.stream_id));
+ viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_ERR);
+ goto send_reply;
+ }
+
+ /* Use back. ref. Protected by refcounts. */
+ rstream = vstream->stream;
+ ctf_trace = rstream->trace;
+
+ /* metadata_viewer_stream may be NULL. */
+ metadata_viewer_stream =
+ ctf_trace_get_viewer_metadata_stream(ctf_trace);
+
+ pthread_mutex_lock(&rstream->lock);
+
+ /*
+ * The viewer should not ask for index on metadata stream.
+ */
+ if (rstream->is_metadata) {
+ viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_HUP);
+ goto send_reply;
+ }
+
+ /* Try to open an index if one is needed for that stream. */
+ ret = try_open_index(vstream, rstream);
+ if (ret < 0) {
+ if (ret == -ENOENT) {
+ /*
+ * The index is created only when the first data
+ * packet arrives, it might not be ready at the
+ * beginning of the session
+ */
+ viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_RETRY);
+ } else {
+ /* Unhandled error. */
+ viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_ERR);