X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fviewer-stream.c;h=67c452eec7d4264139f1134b1fcdd4bc2aa2d49c;hp=21294d1f32dfc700c33c1075b1343e36b84c2833;hb=80516611b6f19201b1e173fb448935aca7a9e668;hpb=ebb29c10d382c55529138ae70eb5a05bf3ccb9a6 diff --git a/src/bin/lttng-relayd/viewer-stream.c b/src/bin/lttng-relayd/viewer-stream.c index 21294d1f3..67c452eec 100644 --- a/src/bin/lttng-relayd/viewer-stream.c +++ b/src/bin/lttng-relayd/viewer-stream.c @@ -1,32 +1,27 @@ /* - * Copyright (C) 2013 - Julien Desfossez - * David Goulet - * 2015 - Mathieu Desnoyers + * Copyright (C) 2013 Julien Desfossez + * Copyright (C) 2013 David Goulet + * Copyright (C) 2015 Mathieu Desnoyers * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _LGPL_SOURCE #include #include #include +#include +#include +#include +#include #include "lttng-relayd.h" #include "viewer-stream.h" static void viewer_stream_destroy(struct relay_viewer_stream *vstream) { + lttng_trace_chunk_put(vstream->stream_file.trace_chunk); free(vstream->path_name); free(vstream->channel_name); free(vstream); @@ -40,16 +35,14 @@ static void viewer_stream_destroy_rcu(struct rcu_head *head) viewer_stream_destroy(vstream); } +/* Relay stream's lock must be held by the caller. */ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, + struct lttng_trace_chunk *trace_chunk, enum lttng_viewer_seek seek_t) { struct relay_viewer_stream *vstream = NULL; - const bool acquired_reference = lttng_trace_chunk_get( - stream->trace_chunk); - if (!acquired_reference) { - goto error; - } + ASSERT_LOCKED(stream->lock); vstream = zmalloc(sizeof(*vstream)); if (!vstream) { @@ -57,7 +50,14 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, goto error; } - vstream->stream_file.trace_chunk = stream->trace_chunk; + if (trace_chunk) { + const bool acquired_reference = lttng_trace_chunk_get( + trace_chunk); + + assert(acquired_reference); + } + + vstream->stream_file.trace_chunk = trace_chunk; vstream->path_name = lttng_strndup(stream->path_name, LTTNG_VIEWER_PATH_MAX); if (vstream->path_name == NULL) { PERROR("relay viewer path_name alloc"); @@ -76,11 +76,9 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, } vstream->stream = stream; - pthread_mutex_lock(&stream->lock); - if (stream->is_metadata && stream->trace->viewer_metadata_stream) { ERR("Cannot attach viewer metadata stream to trace (busy)."); - goto error_unlock; + goto error; } switch (seek_t) { @@ -103,7 +101,7 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, } case LTTNG_VIEWER_SEEK_LAST: vstream->current_tracefile_id = - tracefile_array_get_file_index_head(stream->tfa); + tracefile_array_get_read_file_index_head(stream->tfa); /* * We seek at the very end of each stream, awaiting for * a future packet to eventually come in. @@ -115,56 +113,88 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, tracefile_array_get_seq_head(stream->tfa) + 1; break; default: - goto error_unlock; + goto error; } /* * If we never received an index for the current stream, delay * the opening of the index, otherwise open it right now. */ - if (stream->index_received_seqcount == 0) { + if (stream->index_file == NULL) { vstream->index_file = NULL; } else { const uint32_t connection_major = stream->trace->session->major; const uint32_t connection_minor = stream->trace->session->minor; + enum lttng_trace_chunk_status chunk_status; - vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only( - stream->trace_chunk, stream->path_name, + chunk_status = lttng_index_file_create_from_trace_chunk_read_only( + vstream->stream_file.trace_chunk, + stream->path_name, stream->channel_name, stream->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) { - goto error_unlock; + connection_minor), + true, &vstream->index_file); + if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { + if (chunk_status == LTTNG_TRACE_CHUNK_STATUS_NO_FILE) { + vstream->index_file = NULL; + } else { + goto error; + } + } + } + + /* + * If we never received a data file for the current stream, delay the + * opening, otherwise open it right now. + */ + if (stream->file) { + int ret; + char file_path[LTTNG_PATH_MAX]; + enum lttng_trace_chunk_status status; + + ret = utils_stream_file_path(stream->path_name, + stream->channel_name, stream->tracefile_size, + vstream->current_tracefile_id, NULL, file_path, + sizeof(file_path)); + if (ret < 0) { + goto error; + } + + status = lttng_trace_chunk_open_fs_handle( + vstream->stream_file.trace_chunk, file_path, + O_RDONLY, 0, &vstream->stream_file.handle, + true); + if (status != LTTNG_TRACE_CHUNK_STATUS_OK) { + goto error; } } if (seek_t == LTTNG_VIEWER_SEEK_LAST && vstream->index_file) { off_t lseek_ret; - lseek_ret = lseek(vstream->index_file->fd, 0, SEEK_END); + lseek_ret = fs_handle_seek( + vstream->index_file->file, 0, SEEK_END); if (lseek_ret < 0) { - goto error_unlock; + goto error; } } if (stream->is_metadata) { rcu_assign_pointer(stream->trace->viewer_metadata_stream, vstream); } - pthread_mutex_unlock(&stream->lock); + + vstream->last_seen_rotation_count = stream->completed_rotation_count; /* Globally visible after the add unique. */ lttng_ht_node_init_u64(&vstream->stream_n, stream->stream_handle); - lttng_ht_add_unique_u64(viewer_streams_ht, &vstream->stream_n); - urcu_ref_init(&vstream->ref); + lttng_ht_add_unique_u64(viewer_streams_ht, &vstream->stream_n); return vstream; -error_unlock: - pthread_mutex_unlock(&stream->lock); error: if (vstream) { viewer_stream_destroy(vstream); @@ -193,9 +223,9 @@ static void viewer_stream_release(struct urcu_ref *ref) viewer_stream_unpublish(vstream); - if (vstream->stream_file.fd) { - stream_fd_put(vstream->stream_file.fd); - vstream->stream_file.fd = NULL; + if (vstream->stream_file.handle) { + fs_handle_close(vstream->stream_file.handle); + vstream->stream_file.handle = NULL; } if (vstream->index_file) { lttng_index_file_put(vstream->index_file); @@ -206,6 +236,7 @@ static void viewer_stream_release(struct urcu_ref *ref) vstream->stream = NULL; } lttng_trace_chunk_put(vstream->stream_file.trace_chunk); + vstream->stream_file.trace_chunk = NULL; call_rcu(&vstream->rcu_node, viewer_stream_destroy_rcu); } @@ -249,19 +280,42 @@ void viewer_stream_put(struct relay_viewer_stream *vstream) rcu_read_unlock(); } +void viewer_stream_close_files(struct relay_viewer_stream *vstream) +{ + if (vstream->index_file) { + lttng_index_file_put(vstream->index_file); + vstream->index_file = NULL; + } + if (vstream->stream_file.handle) { + fs_handle_close(vstream->stream_file.handle); + vstream->stream_file.handle = NULL; + } +} + +void viewer_stream_sync_tracefile_array_tail(struct relay_viewer_stream *vstream) +{ + const struct relay_stream *stream = vstream->stream; + uint64_t seq_tail; + + vstream->current_tracefile_id = tracefile_array_get_file_index_tail(stream->tfa); + seq_tail = tracefile_array_get_seq_tail(stream->tfa); + if (seq_tail == -1ULL) { + seq_tail = 0; + } + vstream->index_sent_seqcount = seq_tail; +} + /* * Rotate a stream to the next tracefile. * * Must be called with the rstream lock held. - * Returns 0 on success, 1 on EOF, a negative value on error. + * Returns 0 on success, 1 on EOF. */ int viewer_stream_rotate(struct relay_viewer_stream *vstream) { int ret; uint64_t new_id; const struct relay_stream *stream = vstream->stream; - const uint32_t connection_major = stream->trace->session->major; - const uint32_t connection_minor = stream->trace->session->minor; /* Detect the last tracefile to open. */ if (stream->index_received_seqcount @@ -301,31 +355,8 @@ int viewer_stream_rotate(struct relay_viewer_stream *vstream) tracefile_array_get_file_index_tail(stream->tfa); vstream->index_sent_seqcount = seq_tail; } - - if (vstream->index_file) { - lttng_index_file_put(vstream->index_file); - vstream->index_file = NULL; - } - if (vstream->stream_file.fd) { - stream_fd_put(vstream->stream_file.fd); - vstream->stream_file.fd = NULL; - } - vstream->index_file = - lttng_index_file_create_from_trace_chunk_read_only( - stream->trace_chunk, stream->path_name, - stream->channel_name, - stream->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; - goto end; - } else { - ret = 0; - } + viewer_stream_close_files(vstream); + ret = 0; end: return ret; }