From: Jérémie Galarneau Date: Wed, 18 Sep 2019 16:34:07 +0000 (-0400) Subject: Add a copy method to the trace chunk interface X-Git-Tag: v2.12.0-rc1~367 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=1a414e3a88844a96aa23842822150ac44c391ed2 Add a copy method to the trace chunk interface Trace chunks may now be copied. This will allow, in a follow-up fix, streams to use the trace chunk facilities without extending the life-time of an existing chunk. However, note that the copy of an "owner" chunk returns a "user" chunk. While this may be surprising at first, it makes no sense for two "owner" trace chunks to point to the same location. In such a case, it would be legal for both trace chunks to arbitrarily modify their underlying sub-folder hierarchies without coordinating among themselves. This would break the existing "move to completed" close command, for instance. Signed-off-by: Jérémie Galarneau --- diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c index fb4d16724..6770bd982 100644 --- a/src/common/trace-chunk.c +++ b/src/common/trace-chunk.c @@ -66,6 +66,7 @@ struct chunk_credentials { struct lttng_credentials user; }; +/* NOTE: Make sure to update lttng_trace_chunk_copy if you modify this. */ struct lttng_trace_chunk { pthread_mutex_t lock; struct urcu_ref ref; @@ -73,6 +74,8 @@ struct lttng_trace_chunk { /* * First-level directories created within the trace chunk. * Elements are of type 'char *'. + * + * Only used by _owner_ mode chunks. */ struct lttng_dynamic_pointer_array top_level_directories; /* Is contained within an lttng_trace_chunk_registry_element? */ @@ -302,6 +305,71 @@ error: return NULL; } +LTTNG_HIDDEN +struct lttng_trace_chunk *lttng_trace_chunk_copy( + struct lttng_trace_chunk *source_chunk) +{ + struct lttng_trace_chunk *new_chunk = lttng_trace_chunk_allocate(); + + if (!new_chunk) { + goto end; + } + + pthread_mutex_lock(&source_chunk->lock); + /* + * A new chunk is always a user; it shall create no new trace + * subdirectories. + */ + new_chunk->mode = (typeof(new_chunk->mode)) { + .is_set = true, + .value = TRACE_CHUNK_MODE_USER, + }; + /* + * top_level_directories is not copied as it is never used + * by _user_ mode chunks. + */ + /* The new chunk is not part of a registry (yet, at least). */ + new_chunk->in_registry_element = false; + new_chunk->name_overridden = source_chunk->name_overridden; + if (source_chunk->name) { + new_chunk->name = strdup(source_chunk->name); + if (!new_chunk->name) { + ERR("Failed to copy source trace chunk name in %s()", + __FUNCTION__); + goto error_unlock; + } + } + new_chunk->id = source_chunk->id; + new_chunk->timestamp_creation = source_chunk->timestamp_creation; + new_chunk->timestamp_close = source_chunk->timestamp_close; + new_chunk->credentials = source_chunk->credentials; + if (source_chunk->session_output_directory.is_set) { + if (lttng_directory_handle_copy( + &source_chunk->session_output_directory.value, + &new_chunk->session_output_directory.value)) { + goto error_unlock; + } else { + new_chunk->session_output_directory.is_set = true; + } + } + if (source_chunk->chunk_directory.is_set) { + if (lttng_directory_handle_copy( + &source_chunk->chunk_directory.value, + &new_chunk->chunk_directory.value)) { + goto error_unlock; + } else { + new_chunk->chunk_directory.is_set = true; + } + } + new_chunk->close_command = source_chunk->close_command; + pthread_mutex_unlock(&source_chunk->lock); +end: + return new_chunk; +error_unlock: + pthread_mutex_unlock(&source_chunk->lock); + return NULL; +} + LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_id( struct lttng_trace_chunk *chunk, uint64_t *id) diff --git a/src/common/trace-chunk.h b/src/common/trace-chunk.h index 8703d0044..41c50b637 100644 --- a/src/common/trace-chunk.h +++ b/src/common/trace-chunk.h @@ -83,6 +83,15 @@ struct lttng_trace_chunk *lttng_trace_chunk_create( uint64_t chunk_id, time_t chunk_creation_time); +/* + * Copy a trace chunk. The copy that is returned is always a _user_ + * mode chunk even if the source chunk was an _owner_ as there can never be + * two _owners_ of the same trace output. + */ +LTTNG_HIDDEN +struct lttng_trace_chunk *lttng_trace_chunk_copy( + struct lttng_trace_chunk *source_chunk); + LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_id( struct lttng_trace_chunk *chunk, uint64_t *id);