+/*
+ * Open the index file if needed for the given vstream.
+ *
+ * If an index file is successfully opened, the index_read_fd of the stream is
+ * set with it.
+ *
+ * Return 0 on success, a negative value on error (-ENOENT if not ready yet).
+ */
+static int try_open_index(struct relay_viewer_stream *vstream,
+ struct relay_stream *rstream)
+{
+ int ret = 0;
+
+ assert(vstream);
+ assert(rstream);
+
+ if (vstream->index_read_fd >= 0) {
+ goto end;
+ }
+
+ /*
+ * First time, we open the index file and at least one index is ready. The
+ * race between the read and write of the total_index_received is
+ * acceptable here since the client will be notified to simply come back
+ * and get the next index.
+ */
+ if (rstream->total_index_received <= 0) {
+ ret = -ENOENT;
+ goto end;
+ }
+ ret = index_open(vstream->path_name, vstream->channel_name,
+ vstream->tracefile_count, vstream->tracefile_count_current);
+ if (ret >= 0) {
+ vstream->index_read_fd = ret;
+ ret = 0;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Check the status of the index for the given stream. This function updates
+ * the index structure if needed and can destroy the vstream also for the HUP
+ * situation.
+ *
+ * Return 0 means that we can proceed with the index. A value of 1 means that
+ * the index has been updated and is ready to be send to the client. A negative
+ * value indicates an error that can't be handled.
+ */
+static int check_index_status(struct relay_viewer_stream *vstream,
+ struct relay_stream *rstream, struct ctf_trace *trace,
+ struct lttng_viewer_index *index)
+{
+ int ret;
+
+ assert(vstream);
+ assert(rstream);
+ assert(index);
+ assert(trace);
+
+ if (!rstream->close_flag) {
+ /* Rotate on abort (overwrite). */
+ if (vstream->abort_flag) {
+ DBG("Viewer stream %" PRIu64 " rotate because of overwrite",
+ vstream->stream_handle);
+ ret = viewer_stream_rotate(vstream, rstream);
+ if (ret < 0) {
+ goto error;
+ } else if (ret == 1) {
+ /* EOF */
+ index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
+ goto hup;
+ }
+ /* ret == 0 means successful so we continue. */
+ }
+
+ /* Check if we are in the same trace file at this point. */
+ if (rstream->tracefile_count_current == vstream->tracefile_count_current) {
+ if (rstream->beacon_ts_end != -1ULL &&
+ vstream->last_sent_index == rstream->total_index_received) {
+ /*
+ * We've received a synchronization beacon and the last index
+ * available has been sent, the index for now is inactive.
+ */
+ index->status = htobe32(LTTNG_VIEWER_INDEX_INACTIVE);
+ index->timestamp_end = htobe64(rstream->beacon_ts_end);
+ goto index_ready;
+ } else if (rstream->total_index_received <= vstream->last_sent_index
+ && !vstream->close_write_flag) {
+ /*
+ * Reader and writer are working in the same tracefile, so we care
+ * about the number of index received and sent. Otherwise, we read
+ * up to EOF.
+ */
+ index->status = htobe32(LTTNG_VIEWER_INDEX_RETRY);
+ goto index_ready;
+ }
+ }
+ /* Nothing to do with the index, continue with it. */
+ ret = 0;
+ } else if (rstream->close_flag && vstream->close_write_flag &&
+ vstream->total_index_received == vstream->last_sent_index) {
+ /* Last index sent and current tracefile closed in write */
+ index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
+ goto hup;
+ } else {
+ vstream->close_write_flag = 1;
+ ret = 0;
+ }
+
+error:
+ return ret;
+
+hup:
+ viewer_stream_delete(vstream);
+ viewer_stream_destroy(trace, vstream);
+index_ready:
+ return 1;
+}
+