summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
1a414e3)
Live clients currently hold a reference to their relay_session's trace
chunk through the viewer streams. This causes the destruction of live
session to hang for as long as a client is consuming a session's
contents.
The reason for the hang itself is that the "quiet" rotation performed
as part of the session's destruction can never complete. Indeed, a
rotation completes when the last reference to the trace chunk being
archived is released. Since viewer streams hold references to this
trace chunk, they bound its lifetime to their own lifetime, resulting
in the destruction operation appearing to hang to users of
liblttng-ctl / the lttng client.
Since session rotations are not allowed for live sessions, it is safe
to presume that a session's output folder hierarchy will not change
over its lifetime with the exception of sub-folder additions, such as
in per-PID tracing mode where new traces may be added at any time
within the session's output directory.
The viewer session now copies its corresponding relay_session's trace
chunk to obtain a 'user' mode trace chunk. A user mode trace chunk
will prevent the viewer session from modifying the session output
hierarchy and prevent it from keeping the relay_session's trace chunk
"alive". The viewer stream simply use this trace chunk to perform
their filesystem operations, but they no longer extend the lifetime of
the relayd_session trace chunks.
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
*
* Return 0 on success or else a negative value.
*/
*
* 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;
{
int ret;
struct lttng_ht_iter iter;
}
vstream = viewer_stream_get_by_id(stream->stream_handle);
if (!vstream) {
}
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);
if (!vstream) {
ret = -1;
ctf_trace_put(ctf_trace);
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;
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;
uint64_t session_id;
bool closed = false;
response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
pthread_mutex_lock(&session->lock);
response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
pthread_mutex_lock(&session->lock);
- ret = make_viewer_streams(session, LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
+ 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,
- pthread_mutex_unlock(&session->lock);
+ 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);
/* Only send back the newly created streams with the unsent ones. */
nb_streams = nb_created + nb_unsent;
response.streams_count = htobe32(nb_streams);
+error_unlock_session:
+ pthread_mutex_unlock(&session->lock);
+ session_put(session);
+ return ret;
- 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;
}
if (ret < 0) {
goto end_put_session;
}
pthread_mutex_unlock(&session->lock);
session_put(session);
session = NULL;
pthread_mutex_unlock(&session->lock);
session_put(session);
session = NULL;
goto end;
}
vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only(
goto end;
}
vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only(
- rstream->trace_chunk, rstream->path_name,
+ 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),
rstream->channel_name, rstream->tracefile_size,
vstream->current_tracefile_id,
lttng_to_index_major(connection_major, connection_minor),
void viewer_session_destroy(struct relay_viewer_session *vsession)
{
void viewer_session_destroy(struct relay_viewer_session *vsession)
{
+ lttng_trace_chunk_put(vsession->current_trace_chunk);
pthread_mutex_unlock(&session->lock);
return found;
}
pthread_mutex_unlock(&session->lock);
return found;
}
+
+int viewer_session_set_trace_chunk(struct relay_viewer_session *vsession,
+ struct lttng_trace_chunk *relay_session_trace_chunk)
+{
+ int ret = 0;
+ struct lttng_trace_chunk *viewer_chunk;
+
+ assert(relay_session_trace_chunk);
+ assert(!vsession->current_trace_chunk);
+
+ DBG("Copying relay session's current trace chunk to the viewer session");
+ viewer_chunk = lttng_trace_chunk_copy(relay_session_trace_chunk);
+ if (!viewer_chunk) {
+ ERR("Failed to create a viewer trace chunk from the relay session's current chunk");
+ ret = -1;
+ goto end;
+ }
+
+ vsession->current_trace_chunk = viewer_chunk;
+end:
+ return ret;
+}
#include <urcu/ref.h>
#include <common/hashtable/hashtable.h>
#include <urcu/ref.h>
#include <common/hashtable/hashtable.h>
+#include <common/trace-chunk.h>
*/
struct cds_list_head session_list; /* RCU list. */
pthread_mutex_t session_list_lock; /* Protects list updates. */
*/
struct cds_list_head session_list; /* RCU list. */
pthread_mutex_t session_list_lock; /* Protects list updates. */
+ /* Once set, the current trace chunk of a viewer must not change. */
+ struct lttng_trace_chunk *current_trace_chunk;
};
struct relay_viewer_session *viewer_session_create(void);
};
struct relay_viewer_session *viewer_session_create(void);
struct relay_session *session);
void viewer_session_close_one_session(struct relay_viewer_session *vsession,
struct relay_session *session);
struct relay_session *session);
void viewer_session_close_one_session(struct relay_viewer_session *vsession,
struct relay_session *session);
+int viewer_session_set_trace_chunk(struct relay_viewer_session *vsession,
+ struct lttng_trace_chunk *relay_session_trace_chunk);
#endif /* _VIEWER_SESSION_H */
#endif /* _VIEWER_SESSION_H */
}
struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
}
struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
+ struct lttng_trace_chunk *viewer_trace_chunk,
enum lttng_viewer_seek seek_t)
{
struct relay_viewer_stream *vstream = NULL;
const bool acquired_reference = lttng_trace_chunk_get(
enum lttng_viewer_seek seek_t)
{
struct relay_viewer_stream *vstream = NULL;
const bool acquired_reference = lttng_trace_chunk_get(
if (!acquired_reference) {
goto error;
if (!acquired_reference) {
goto error;
- vstream->stream_file.trace_chunk = stream->trace_chunk;
+ vstream->stream_file.trace_chunk = viewer_trace_chunk;
+ viewer_trace_chunk = NULL;
vstream->path_name = lttng_strndup(stream->path_name, LTTNG_VIEWER_PATH_MAX);
if (vstream->path_name == NULL) {
PERROR("relay viewer path_name alloc");
vstream->path_name = lttng_strndup(stream->path_name, LTTNG_VIEWER_PATH_MAX);
if (vstream->path_name == NULL) {
PERROR("relay viewer path_name alloc");
const uint32_t connection_minor = stream->trace->session->minor;
vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only(
const uint32_t connection_minor = stream->trace->session->minor;
vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only(
- stream->trace_chunk, stream->path_name,
+ vstream->stream_file.trace_chunk,
+ stream->path_name,
stream->channel_name, stream->tracefile_size,
vstream->current_tracefile_id,
lttng_to_index_major(connection_major,
stream->channel_name, stream->tracefile_size,
vstream->current_tracefile_id,
lttng_to_index_major(connection_major,
if (vstream) {
viewer_stream_destroy(vstream);
}
if (vstream) {
viewer_stream_destroy(vstream);
}
+ if (viewer_trace_chunk) {
+ lttng_trace_chunk_put(viewer_trace_chunk);
+ }
}
vstream->index_file =
lttng_index_file_create_from_trace_chunk_read_only(
}
vstream->index_file =
lttng_index_file_create_from_trace_chunk_read_only(
- stream->trace_chunk, stream->path_name,
+ vstream->stream_file.trace_chunk,
+ stream->path_name,
stream->channel_name,
stream->tracefile_size,
vstream->current_tracefile_id,
stream->channel_name,
stream->tracefile_size,
vstream->current_tracefile_id,
};
struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
};
struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream,
+ struct lttng_trace_chunk *viewer_trace_chunk,
enum lttng_viewer_seek seek_t);
struct relay_viewer_stream *viewer_stream_get_by_id(uint64_t id);
enum lttng_viewer_seek seek_t);
struct relay_viewer_stream *viewer_stream_get_by_id(uint64_t id);