common trace-chunk: introduce lttng_trace_chunk_get_name_overridden
[lttng-tools.git] / src / common / trace-chunk.c
index 6181520fa7362b8b18732658fde146534a7dde01..c549f46b33c855334814355ef8a6e37f6cacadf2 100644 (file)
@@ -78,6 +78,11 @@ struct lttng_trace_chunk {
         * Only used by _owner_ mode chunks.
         */
        struct lttng_dynamic_pointer_array top_level_directories;
+       /*
+        * All files contained within the trace chunk.
+        * Array of paths (char *).
+        */
+       struct lttng_dynamic_pointer_array files;
        /* Is contained within an lttng_trace_chunk_registry_element? */
        bool in_registry_element;
        bool name_overridden;
@@ -111,6 +116,10 @@ static const
 char *close_command_names[] = {
        [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] =
                "move to completed chunk folder",
+       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION] =
+               "no operation",
+       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE] =
+               "delete",
 };
 
 static const
@@ -216,6 +225,7 @@ void lttng_trace_chunk_init(struct lttng_trace_chunk *chunk)
        urcu_ref_init(&chunk->ref);
        pthread_mutex_init(&chunk->lock, NULL);
        lttng_dynamic_pointer_array_init(&chunk->top_level_directories, free);
+       lttng_dynamic_pointer_array_init(&chunk->files, free);
 }
 
 static
@@ -233,6 +243,7 @@ void lttng_trace_chunk_fini(struct lttng_trace_chunk *chunk)
        free(chunk->name);
        chunk->name = NULL;
        lttng_dynamic_pointer_array_reset(&chunk->top_level_directories);
+       lttng_dynamic_pointer_array_reset(&chunk->files);
        pthread_mutex_destroy(&chunk->lock);
 }
 
@@ -472,6 +483,17 @@ end:
        return status;
 }
 
+LTTNG_HIDDEN
+bool lttng_trace_chunk_get_name_overridden(struct lttng_trace_chunk *chunk)
+{
+       bool name_overridden;
+
+       pthread_mutex_lock(&chunk->lock);
+       name_overridden = chunk->name_overridden;
+       pthread_mutex_unlock(&chunk->lock);
+       return name_overridden;
+}
+
 static
 bool is_valid_chunk_name(const char *name)
 {
@@ -813,10 +835,84 @@ end:
        return status;
 }
 
+/*
+ * TODO: Implement O(1) lookup.
+ */
+static
+bool lttng_trace_chunk_find_file(struct lttng_trace_chunk *chunk,
+               const char *path, size_t *index)
+{
+       size_t i, count;
+
+       count = lttng_dynamic_pointer_array_get_count(&chunk->files);
+       for (i = 0; i < count; i++) {
+               const char *iter_path =
+                               lttng_dynamic_pointer_array_get_pointer(
+                                       &chunk->files, i);
+               if (!strcmp(iter_path, path)) {
+                       if (index) {
+                               *index = i;
+                       }
+                       return true;
+               }
+       }
+       return false;
+}
+
+static
+enum lttng_trace_chunk_status lttng_trace_chunk_add_file(
+               struct lttng_trace_chunk *chunk,
+               const char *path)
+{
+       char *copy;
+       int ret;
+       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+
+       if (lttng_trace_chunk_find_file(chunk, path, NULL)) {
+               return LTTNG_TRACE_CHUNK_STATUS_OK;
+       }
+       DBG("Adding new file \"%s\" to trace chunk \"%s\"",
+                       path, chunk->name ? : "(unnamed)");
+       copy = strdup(path);
+       if (!copy) {
+               PERROR("Failed to copy path");
+               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+               goto end;
+       }
+       ret = lttng_dynamic_pointer_array_add_pointer(
+                       &chunk->files, copy);
+       if (ret) {
+               ERR("Allocation failure while adding file to a trace chunk");
+               free(copy);
+               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+               goto end;
+       }
+end:
+       return status;
+}
+
+static
+void lttng_trace_chunk_remove_file(
+               struct lttng_trace_chunk *chunk,
+               const char *path)
+{
+       size_t index;
+       bool found;
+       int ret;
+
+       found = lttng_trace_chunk_find_file(chunk, path, &index);
+       if (!found) {
+               return;
+       }
+       ret = lttng_dynamic_pointer_array_remove_pointer(
+                       &chunk->files, index);
+       assert(!ret);
+}
+
 LTTNG_HIDDEN
 enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
                struct lttng_trace_chunk *chunk, const char *file_path,
-               int flags, mode_t mode, int *out_fd)
+               int flags, mode_t mode, int *out_fd, bool expect_no_file)
 {
        int ret;
        enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
@@ -839,14 +935,23 @@ enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
                status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
                goto end;
        }
+       status = lttng_trace_chunk_add_file(chunk, file_path);
+       if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+               goto end;
+       }
        ret = lttng_directory_handle_open_file_as_user(
                        chunk->chunk_directory, file_path, flags, mode,
                        chunk->credentials.value.use_current_user ?
                                        NULL : &chunk->credentials.value.user);
        if (ret < 0) {
-               PERROR("Failed to open file relative to trace chunk file_path = \"%s\", flags = %d, mode = %d",
+               if (errno == ENOENT && expect_no_file) {
+                       status = LTTNG_TRACE_CHUNK_STATUS_NO_FILE;
+               } else {
+                       PERROR("Failed to open file relative to trace chunk file_path = \"%s\", flags = %d, mode = %d",
                                file_path, flags, (int) mode);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+               }
+               lttng_trace_chunk_remove_file(chunk, file_path);
                goto end;
        }
        *out_fd = ret;
@@ -888,6 +993,7 @@ int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
                status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
                goto end;
        }
+       lttng_trace_chunk_remove_file(chunk, file_path);
 end:
        pthread_mutex_unlock(&chunk->lock);
        return status;
@@ -1074,7 +1180,15 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
                DBG("Setting trace chunk close command to \"%s\"",
                                close_command_names[close_command]);
         }
-       LTTNG_OPTIONAL_SET(&chunk->close_command, close_command);
+       /*
+        * Unset close command for no-op for backward compatibility with relayd
+        * 2.11.
+        */
+       if (close_command != LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION) {
+               LTTNG_OPTIONAL_SET(&chunk->close_command, close_command);
+       } else {
+               LTTNG_OPTIONAL_UNSET(&chunk->close_command);
+       }
        pthread_mutex_unlock(&chunk->lock);
 end:
        return status;
@@ -1087,6 +1201,10 @@ const char *lttng_trace_chunk_command_type_get_name(
        switch (command) {
        case LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED:
                return "move to completed trace chunk folder";
+       case LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION:
+               return "no operation";
+       case LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE:
+               return "delete";
        default:
                abort();
        }
This page took 0.025898 seconds and 5 git commands to generate.