Fix: relayd: live: some listed sessions are not attacheable
[lttng-tools.git] / src / bin / lttng-relayd / live.c
index 6f50afc6cc6b1e2d2b48687cbf325521700b2392..8c4f501aa3446afd5b5cb5d7e72e42bf82dd2d11 100644 (file)
@@ -197,7 +197,7 @@ end:
  */
 static
 ssize_t send_viewer_streams(struct lttcomm_sock *sock,
-               struct relay_session *session, unsigned int ignore_sent_flag)
+               uint64_t session_id, unsigned int ignore_sent_flag)
 {
        ssize_t ret;
        struct lttng_viewer_stream send_stream;
@@ -218,7 +218,7 @@ ssize_t send_viewer_streams(struct lttcomm_sock *sock,
 
                pthread_mutex_lock(&vstream->stream->lock);
                /* Ignore if not the same session. */
-               if (vstream->stream->trace->session->id != session->id ||
+               if (vstream->stream->trace->session->id != session_id ||
                                (!ignore_sent_flag && vstream->sent_flag)) {
                        pthread_mutex_unlock(&vstream->stream->lock);
                        viewer_stream_put(vstream);
@@ -271,24 +271,25 @@ end_unlock:
  * viewer stream of the session, the number of unsent stream and the number of
  * stream created. Those counters can be NULL and thus will be ignored.
  *
+ * session must be locked to ensure that we see either none or all initial
+ * streams for a session, but no intermediate state..
+ *
  * Return 0 on success or else a negative value.
  */
-static
-int make_viewer_streams(struct relay_session *session,
-               enum lttng_viewer_seek seek_t, uint32_t *nb_total, uint32_t *nb_unsent,
-               uint32_t *nb_created, bool *closed)
+static int make_viewer_streams(struct relay_session *session,
+               struct lttng_trace_chunk *viewer_trace_chunk,
+               enum lttng_viewer_seek seek_t,
+               uint32_t *nb_total,
+               uint32_t *nb_unsent,
+               uint32_t *nb_created,
+               bool *closed)
 {
        int ret;
        struct lttng_ht_iter iter;
        struct ctf_trace *ctf_trace;
 
        assert(session);
-
-       /*
-        * Hold the session lock to ensure that we see either none or
-        * all initial streams for a session, but no intermediate state.
-        */
-       pthread_mutex_lock(&session->lock);
+       ASSERT_LOCKED(session->lock);
 
        if (session->connection_closed) {
                *closed = true;
@@ -323,7 +324,8 @@ int make_viewer_streams(struct relay_session *session,
                        }
                        vstream = viewer_stream_get_by_id(stream->stream_handle);
                        if (!vstream) {
-                               vstream = viewer_stream_create(stream, seek_t);
+                               vstream = viewer_stream_create(stream,
+                                               viewer_trace_chunk, seek_t);
                                if (!vstream) {
                                        ret = -1;
                                        ctf_trace_put(ctf_trace);
@@ -358,7 +360,7 @@ int make_viewer_streams(struct relay_session *session,
                                        }
                                } else {
                                        if (!stream->closed ||
-                                               !(((int64_t) (stream->prev_seq - stream->last_net_seq_num)) >= 0)) {
+                                               !(((int64_t) (stream->prev_data_seq - stream->last_net_seq_num)) >= 0)) {
 
                                                (*nb_total)++;
                                        }
@@ -376,7 +378,6 @@ int make_viewer_streams(struct relay_session *session,
 
 error_unlock:
        rcu_read_unlock();
-       pthread_mutex_unlock(&session->lock);
        return ret;
 }
 
@@ -543,11 +544,6 @@ restart:
                        revents = LTTNG_POLL_GETEV(&events, i);
                        pollfd = LTTNG_POLL_GETFD(&events, i);
 
-                       if (!revents) {
-                               /* No activity for this FD (poll implementation). */
-                               continue;
-                       }
-
                        /* Thread quit pipe has been closed. Killing thread. */
                        ret = check_thread_quit_pipe(pollfd, revents);
                        if (ret) {
@@ -835,6 +831,20 @@ int viewer_list_sessions(struct relay_connection *conn)
 
                health_code_update();
 
+               pthread_mutex_lock(&session->lock);
+               if (session->connection_closed) {
+                       /* Skip closed session */
+                       goto next_session;
+               }
+               if (!session->current_trace_chunk) {
+                       /*
+                        * Skip un-attachable session. It is either
+                        * being destroyed or has not had a trace
+                        * chunk created against it yet.
+                        */
+                       goto next_session;
+               }
+
                if (count >= buf_count) {
                        struct lttng_viewer_session *newbuf;
                        uint32_t new_buf_count = buf_count << 1;
@@ -843,7 +853,7 @@ int viewer_list_sessions(struct relay_connection *conn)
                                new_buf_count * sizeof(*send_session_buf));
                        if (!newbuf) {
                                ret = -1;
-                               break;
+                               goto break_loop;
                        }
                        send_session_buf = newbuf;
                        buf_count = new_buf_count;
@@ -853,12 +863,12 @@ int viewer_list_sessions(struct relay_connection *conn)
                                session->session_name,
                                sizeof(send_session->session_name))) {
                        ret = -1;
-                       break;
+                       goto break_loop;
                }
                if (lttng_strncpy(send_session->hostname, session->hostname,
                                sizeof(send_session->hostname))) {
                        ret = -1;
-                       break;
+                       goto break_loop;
                }
                send_session->id = htobe64(session->id);
                send_session->live_timer = htobe32(session->live_timer);
@@ -869,6 +879,12 @@ int viewer_list_sessions(struct relay_connection *conn)
                }
                send_session->streams = htobe32(session->stream_count);
                count++;
+       next_session:
+               pthread_mutex_unlock(&session->lock);
+               continue;
+       break_loop:
+               pthread_mutex_unlock(&session->lock);
+               break;
        }
        rcu_read_unlock();
        if (ret < 0) {
@@ -909,7 +925,7 @@ int viewer_get_new_streams(struct relay_connection *conn)
        uint32_t nb_created = 0, nb_unsent = 0, nb_streams = 0, nb_total = 0;
        struct lttng_viewer_new_streams_request request;
        struct lttng_viewer_new_streams_response response;
-       struct relay_session *session;
+       struct relay_session *session = NULL;
        uint64_t session_id;
        bool closed = false;
 
@@ -946,11 +962,24 @@ int viewer_get_new_streams(struct relay_connection *conn)
        send_streams = 1;
        response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
 
-       ret = make_viewer_streams(session, LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
+       pthread_mutex_lock(&session->lock);
+       if (!conn->viewer_session->current_trace_chunk &&
+                       session->current_trace_chunk) {
+               ret = viewer_session_set_trace_chunk(conn->viewer_session,
+                               session->current_trace_chunk);
+               if (ret) {
+                       goto error_unlock_session;
+               }
+       }
+       ret = make_viewer_streams(session,
+                       conn->viewer_session->current_trace_chunk,
+                       LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
                        &nb_created, &closed);
        if (ret < 0) {
-               goto end_put_session;
+               goto error_unlock_session;
        }
+       pthread_mutex_unlock(&session->lock);
+
        /* Only send back the newly created streams with the unsent ones. */
        nb_streams = nb_created + nb_unsent;
        response.streams_count = htobe32(nb_streams);
@@ -988,7 +1017,7 @@ send_reply:
         * streams that were not sent from that point will be sent to
         * the viewer.
         */
-       ret = send_viewer_streams(conn->sock, session, 0);
+       ret = send_viewer_streams(conn->sock, session_id, 0);
        if (ret < 0) {
                goto end_put_session;
        }
@@ -999,6 +1028,10 @@ end_put_session:
        }
 error:
        return ret;
+error_unlock_session:
+       pthread_mutex_unlock(&session->lock);
+       session_put(session);
+       return ret;
 }
 
 /*
@@ -1015,6 +1048,7 @@ int viewer_attach_session(struct relay_connection *conn)
        struct lttng_viewer_attach_session_response response;
        struct relay_session *session = NULL;
        bool closed = false;
+       uint64_t session_id;
 
        assert(conn);
 
@@ -1026,6 +1060,7 @@ int viewer_attach_session(struct relay_connection *conn)
                goto error;
        }
 
+       session_id = be64toh(request.session_id);
        health_code_update();
 
        memset(&response, 0, sizeof(response));
@@ -1036,16 +1071,15 @@ int viewer_attach_session(struct relay_connection *conn)
                goto send_reply;
        }
 
-       session = session_get_by_id(be64toh(request.session_id));
+       session = session_get_by_id(session_id);
        if (!session) {
-               DBG("Relay session %" PRIu64 " not found",
-                               (uint64_t) be64toh(request.session_id));
+               DBG("Relay session %" PRIu64 " not found", session_id);
                response.status = htobe32(LTTNG_VIEWER_ATTACH_UNK);
                goto send_reply;
        }
-       DBG("Attach session ID %" PRIu64 " received",
-               (uint64_t) be64toh(request.session_id));
+       DBG("Attach session ID %" PRIu64 " received", session_id);
 
+       pthread_mutex_lock(&session->lock);
        if (session->live_timer == 0) {
                DBG("Not live session");
                response.status = htobe32(LTTNG_VIEWER_ATTACH_NOT_LIVE);
@@ -1073,13 +1107,25 @@ int viewer_attach_session(struct relay_connection *conn)
                goto send_reply;
        }
 
-       ret = make_viewer_streams(session, seek_type, &nb_streams, NULL,
-                       NULL, &closed);
+       if (!conn->viewer_session->current_trace_chunk &&
+                       session->current_trace_chunk) {
+               ret = viewer_session_set_trace_chunk(conn->viewer_session,
+                               session->current_trace_chunk);
+               if (ret) {
+                       goto end_put_session;
+               }
+       }
+       ret = make_viewer_streams(session,
+                       conn->viewer_session->current_trace_chunk, seek_type,
+                       &nb_streams, NULL, NULL, &closed);
        if (ret < 0) {
                goto end_put_session;
        }
-       response.streams_count = htobe32(nb_streams);
+       pthread_mutex_unlock(&session->lock);
+       session_put(session);
+       session = NULL;
 
+       response.streams_count = htobe32(nb_streams);
        /*
         * If the session is closed when the viewer is attaching, it
         * means some of the streams may have been concurrently removed,
@@ -1089,7 +1135,7 @@ int viewer_attach_session(struct relay_connection *conn)
        if (closed) {
                send_streams = 0;
                response.streams_count = 0;
-               response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_HUP);
+               response.status = htobe32(LTTNG_VIEWER_ATTACH_UNK);
                goto send_reply;
        }
 
@@ -1111,13 +1157,14 @@ send_reply:
        }
 
        /* Send stream and ignore the sent flag. */
-       ret = send_viewer_streams(conn->sock, session, 1);
+       ret = send_viewer_streams(conn->sock, session_id, 1);
        if (ret < 0) {
                goto end_put_session;
        }
 
 end_put_session:
        if (session) {
+               pthread_mutex_unlock(&session->lock);
                session_put(session);
        }
 error:
@@ -1138,6 +1185,8 @@ static int try_open_index(struct relay_viewer_stream *vstream,
                struct relay_stream *rstream)
 {
        int ret = 0;
+       const uint32_t connection_major = rstream->trace->session->major;
+       const uint32_t connection_minor = rstream->trace->session->minor;
 
        if (vstream->index_file) {
                goto end;
@@ -1150,10 +1199,12 @@ static int try_open_index(struct relay_viewer_stream *vstream,
                ret = -ENOENT;
                goto end;
        }
-       vstream->index_file = lttng_index_file_open(vstream->path_name,
-                       vstream->channel_name,
-                       vstream->stream->tracefile_count,
-                       vstream->current_tracefile_id);
+       vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only(
+                       vstream->stream_file.trace_chunk, rstream->path_name,
+                       rstream->channel_name, rstream->tracefile_size,
+                       vstream->current_tracefile_id,
+                       lttng_to_index_major(connection_major, connection_minor),
+                       lttng_to_index_minor(connection_major, connection_minor));
        if (!vstream->index_file) {
                ret = -1;
        }
@@ -1361,31 +1412,30 @@ int viewer_get_next_index(struct relay_connection *conn)
         * overwrite caused by tracefile rotation (in association with
         * unlink performed before overwrite).
         */
-       if (!vstream->stream_fd) {
-               char fullpath[PATH_MAX];
-
-               if (vstream->stream->tracefile_count > 0) {
-                       ret = snprintf(fullpath, PATH_MAX, "%s/%s_%" PRIu64,
-                                       vstream->path_name,
-                                       vstream->channel_name,
-                                       vstream->current_tracefile_id);
-               } else {
-                       ret = snprintf(fullpath, PATH_MAX, "%s/%s",
-                                       vstream->path_name,
-                                       vstream->channel_name);
-               }
+       if (!vstream->stream_file.fd) {
+               int fd;
+               char file_path[LTTNG_PATH_MAX];
+               enum lttng_trace_chunk_status status;
+
+               ret = utils_stream_file_path(rstream->path_name,
+                               rstream->channel_name, rstream->tracefile_size,
+                               vstream->current_tracefile_id, NULL, file_path,
+                               sizeof(file_path));
                if (ret < 0) {
                        goto error_put;
                }
-               ret = open(fullpath, O_RDONLY);
-               if (ret < 0) {
-                       PERROR("Relay opening trace file");
+
+               status = lttng_trace_chunk_open_file(
+                               vstream->stream_file.trace_chunk,
+                               file_path, O_RDONLY, 0, &fd);
+               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+                       PERROR("Failed to open trace file for viewer stream");
                        goto error_put;
                }
-               vstream->stream_fd = stream_fd_create(ret);
-               if (!vstream->stream_fd) {
-                       if (close(ret)) {
-                               PERROR("close");
+               vstream->stream_file.fd = stream_fd_create(fd);
+               if (!vstream->stream_file.fd) {
+                       if (close(fd)) {
+                               PERROR("Failed to close viewer stream file");
                        }
                        goto error_put;
                }
@@ -1526,19 +1576,19 @@ int viewer_get_packet(struct relay_connection *conn)
        }
 
        pthread_mutex_lock(&vstream->stream->lock);
-       lseek_ret = lseek(vstream->stream_fd->fd, be64toh(get_packet_info.offset),
-                       SEEK_SET);
+       lseek_ret = lseek(vstream->stream_file.fd->fd,
+                       be64toh(get_packet_info.offset), SEEK_SET);
        if (lseek_ret < 0) {
-               PERROR("lseek fd %d to offset %" PRIu64, vstream->stream_fd->fd,
-                       (uint64_t) be64toh(get_packet_info.offset));
+               PERROR("lseek fd %d to offset %" PRIu64,
+                               vstream->stream_file.fd->fd,
+                               (uint64_t) be64toh(get_packet_info.offset));
                goto error;
        }
-       read_len = lttng_read(vstream->stream_fd->fd,
-                       reply + sizeof(reply_header),
-                       packet_data_len);
+       read_len = lttng_read(vstream->stream_file.fd->fd,
+                       reply + sizeof(reply_header), packet_data_len);
        if (read_len < packet_data_len) {
                PERROR("Relay reading trace file, fd: %d, offset: %" PRIu64,
-                               vstream->stream_fd->fd,
+                               vstream->stream_file.fd->fd,
                                (uint64_t) be64toh(get_packet_info.offset));
                goto error;
        }
@@ -1644,23 +1694,31 @@ int viewer_get_metadata(struct relay_connection *conn)
        }
 
        /* first time, we open the metadata file */
-       if (!vstream->stream_fd) {
-               char fullpath[PATH_MAX];
-
-               ret = snprintf(fullpath, PATH_MAX, "%s/%s", vstream->path_name,
-                               vstream->channel_name);
+       if (!vstream->stream_file.fd) {
+               int fd;
+               char file_path[LTTNG_PATH_MAX];
+               enum lttng_trace_chunk_status status;
+               struct relay_stream *rstream = vstream->stream;
+
+               ret = utils_stream_file_path(rstream->path_name,
+                               rstream->channel_name, rstream->tracefile_size,
+                               vstream->current_tracefile_id, NULL, file_path,
+                               sizeof(file_path));
                if (ret < 0) {
                        goto error;
                }
-               ret = open(fullpath, O_RDONLY);
-               if (ret < 0) {
-                       PERROR("Relay opening metadata file");
+
+               status = lttng_trace_chunk_open_file(
+                               vstream->stream_file.trace_chunk,
+                               file_path, O_RDONLY, 0, &fd);
+               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+                       PERROR("Failed to open metadata file for viewer stream");
                        goto error;
                }
-               vstream->stream_fd = stream_fd_create(ret);
-               if (!vstream->stream_fd) {
-                       if (close(ret)) {
-                               PERROR("close");
+               vstream->stream_file.fd = stream_fd_create(fd);
+               if (!vstream->stream_file.fd) {
+                       if (close(fd)) {
+                               PERROR("Failed to close viewer metadata file");
                        }
                        goto error;
                }
@@ -1673,7 +1731,7 @@ int viewer_get_metadata(struct relay_connection *conn)
                goto error;
        }
 
-       read_len = lttng_read(vstream->stream_fd->fd, data, len);
+       read_len = lttng_read(vstream->stream_file.fd->fd, data, len);
        if (read_len < len) {
                PERROR("Relay reading metadata file");
                goto error;
@@ -1995,11 +2053,6 @@ restart:
 
                        health_code_update();
 
-                       if (!revents) {
-                               /* No activity for this FD (poll implementation). */
-                               continue;
-                       }
-
                        /* Thread quit pipe has been closed. Killing thread. */
                        ret = check_thread_quit_pipe(pollfd, revents);
                        if (ret) {
@@ -2017,8 +2070,13 @@ restart:
                                        if (ret < 0) {
                                                goto error;
                                        }
-                                       lttng_poll_add(&events, conn->sock->fd,
+                                       ret = lttng_poll_add(&events,
+                                                       conn->sock->fd,
                                                        LPOLLIN | LPOLLRDHUP);
+                                       if (ret) {
+                                               ERR("Failed to add new live connection file descriptor to poll set");
+                                               goto error;
+                                       }
                                        connection_ht_add(viewer_connections_ht, conn);
                                        DBG("Connection socket %d added to poll", conn->sock->fd);
                                } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
This page took 0.033633 seconds and 4 git commands to generate.