Fix typo 'Attemp' -> 'Attempt'
[lttng-tools.git] / src / common / trace-chunk.c
index 9f0919a8896b7756121ffe18d6580e0550637f37..20dbd0a5ea933a853d328332d4c04def960fd917 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? */
@@ -91,8 +94,8 @@ struct lttng_trace_chunk {
 
 /* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
 struct lttng_trace_chunk_registry_element {
-       uint64_t session_id;
        struct lttng_trace_chunk chunk;
+       uint64_t session_id;
        /* Weak and only set when added. */
        struct lttng_trace_chunk_registry *registry;
        struct cds_lfht_node trace_chunk_registry_ht_node;
@@ -104,11 +107,13 @@ struct lttng_trace_chunk_registry {
        struct cds_lfht *ht;
 };
 
-const char *close_command_names[] = {
+static const
+char *close_command_names[] = {
        [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] =
                "move to completed chunk folder",
 };
 
+static const
 chunk_close_command close_command_funcs[] = {
        [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] =
                        lttng_trace_chunk_move_to_completed,
@@ -165,8 +170,9 @@ char *generate_chunk_name(uint64_t chunk_id, time_t creation_timestamp,
 {
        int ret = 0;
        char *new_name= NULL;
-       char start_datetime[sizeof("YYYYmmddTHHMMSS+HHMM")] = {};
-       char end_datetime_suffix[sizeof("-YYYYmmddTHHMMSS+HHMM")] = {};
+       char start_datetime[ISO8601_STR_LEN] = {};
+       /* Add 1 for a '-' prefix. */
+       char end_datetime_suffix[ISO8601_STR_LEN + 1] = {};
 
        ret = time_to_iso8601_str(
                        creation_timestamp,
@@ -180,7 +186,7 @@ char *generate_chunk_name(uint64_t chunk_id, time_t creation_timestamp,
                ret = time_to_iso8601_str(
                                *close_timestamp,
                                end_datetime_suffix + 1,
-                               sizeof(end_datetime_suffix));
+                               sizeof(end_datetime_suffix) - 1);
                if (ret) {
                        ERR("Failed to format trace chunk end date time");
                        goto error;
@@ -299,6 +305,72 @@ 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);
+       lttng_trace_chunk_put(new_chunk);
+       return NULL;
+}
+
 LTTNG_HIDDEN
 enum lttng_trace_chunk_status lttng_trace_chunk_get_id(
                struct lttng_trace_chunk *chunk, uint64_t *id)
@@ -903,6 +975,7 @@ void lttng_trace_chunk_move_to_completed(struct lttng_trace_chunk *trace_chunk)
                                creation_timestamp, NULL);
                if (!directory_to_rename) {
                        ERR("Failed to generate initial trace chunk name while renaming trace chunk");
+                       goto end;
                }
                free_directory_to_rename = true;
        }
@@ -988,7 +1061,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
        if (close_command < LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED ||
                        close_command >= LTTNG_TRACE_CHUNK_COMMAND_TYPE_MAX) {
                status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
-               goto end_unlock;
+               goto end;
        }
 
        pthread_mutex_lock(&chunk->lock);
@@ -1002,7 +1075,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
         }
        LTTNG_OPTIONAL_SET(&chunk->close_command, close_command);
        pthread_mutex_unlock(&chunk->lock);
-end_unlock:
+end:
        return status;
 }
 
@@ -1196,7 +1269,7 @@ lttng_trace_chunk_registry_publish_chunk(
                                 *
                                 * Re-attempt to publish.
                                 */
-                               ERR("Attemp to publish a trace chunk to the chunk registry raced with a trace chunk deletion");
+                               ERR("Attempt to publish a trace chunk to the chunk registry raced with a trace chunk deletion");
                                continue;
                        }
                }
@@ -1286,6 +1359,41 @@ lttng_trace_chunk_registry_find_chunk(
                        session_id, &chunk_id);
 }
 
+LTTNG_HIDDEN
+int lttng_trace_chunk_registry_chunk_exists(
+               const struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists)
+{
+       int ret = 0;
+       const struct lttng_trace_chunk_registry_element target_element = {
+               .chunk.id.is_set = true,
+               .chunk.id.value = chunk_id,
+               .session_id = session_id,
+       };
+       const unsigned long element_hash =
+                       lttng_trace_chunk_registry_element_hash(
+                               &target_element);
+       struct cds_lfht_node *published_node;
+       struct cds_lfht_iter iter;
+
+       rcu_read_lock();
+       cds_lfht_lookup(registry->ht,
+                       element_hash,
+                       lttng_trace_chunk_registry_element_match,
+                       &target_element,
+                       &iter);
+       published_node = cds_lfht_iter_get_node(&iter);
+       if (!published_node) {
+               *chunk_exists = false;
+               goto end;
+       }
+
+       *chunk_exists = !cds_lfht_is_node_deleted(published_node);
+end:
+       rcu_read_unlock();
+       return ret;
+}
+
 LTTNG_HIDDEN
 struct lttng_trace_chunk *
 lttng_trace_chunk_registry_find_anonymous_chunk(
This page took 0.026163 seconds and 4 git commands to generate.