Add a copy method to the trace chunk interface
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 18 Sep 2019 16:34:07 +0000 (12:34 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 19 Sep 2019 18:33:21 +0000 (14:33 -0400)
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 <jeremie.galarneau@efficios.com>
src/common/trace-chunk.c
src/common/trace-chunk.h

index fb4d1672490d49b889e98646ecee7bc6bcea788a..6770bd982db393a45bdfda698614a1af2b4a6b54 100644 (file)
@@ -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)
index 8703d00444df7837069fdc54dc7fb68926456bf5..41c50b637661f5470a4866e317b2edb07ca072f4 100644 (file)
@@ -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);
This page took 0.028363 seconds and 4 git commands to generate.