+/*
+ * When we have received all the streams and the metadata for a channel,
+ * we make them visible to the viewer threads.
+ */
+static
+void set_viewer_ready_flag(struct relay_command *cmd)
+{
+ struct relay_stream_recv_handle *node, *tmp_node;
+
+ cds_list_for_each_entry_safe(node, tmp_node, &cmd->recv_head, node) {
+ struct relay_stream *stream;
+
+ rcu_read_lock();
+ stream = relay_stream_find_by_id(node->id);
+ if (!stream) {
+ /*
+ * Stream is most probably being cleaned up by the data thread thus
+ * simply continue to the next one.
+ */
+ continue;
+ }
+
+ /*
+ * If any of the streams in the list doesn't have a ctf_trace assigned,
+ * it means that we never received the metadata stream, so we have to
+ * wait until it arrives to make the streams available to the viewer.
+ */
+ if (!stream->ctf_trace) {
+ goto end;
+ }
+
+ stream->viewer_ready = 1;
+ rcu_read_unlock();
+
+ /* Clean stream handle node. */
+ cds_list_del(&node->node);
+ free(node);
+ }
+
+end:
+ return;
+}
+
+/*
+ * Add a recv handle node to the connection recv list with the given stream
+ * handle. A new node is allocated thus must be freed when the node is deleted
+ * from the list.
+ */
+static void queue_stream_handle(uint64_t handle, struct relay_command *cmd)
+{
+ struct relay_stream_recv_handle *node;
+
+ assert(cmd);
+
+ node = zmalloc(sizeof(*node));
+ if (!node) {
+ PERROR("zmalloc queue stream handle");
+ return;
+ }
+
+ node->id = handle;
+ cds_list_add(&node->node, &cmd->recv_head);
+}
+