common: compile libcommon as C++
[lttng-tools.git] / src / common / trace-chunk.c
diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c
deleted file mode 100644 (file)
index d04d516..0000000
+++ /dev/null
@@ -1,2191 +0,0 @@
-/*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * SPDX-License-Identifier: LGPL-2.1-only
- *
- */
-
-#include <common/compat/directory-handle.h>
-#include <common/credentials.h>
-#include <common/defaults.h>
-#include <common/dynamic-array.h>
-#include <common/error.h>
-#include <common/fd-tracker/fd-tracker.h>
-#include <common/fd-tracker/utils.h>
-#include <common/fs-handle.h>
-#include <common/fs-handle-internal.h>
-#include <common/hashtable/hashtable.h>
-#include <common/hashtable/utils.h>
-#include <common/optional.h>
-#include <common/string-utils/format.h>
-#include <common/time.h>
-#include <common/trace-chunk-registry.h>
-#include <common/trace-chunk.h>
-#include <common/utils.h>
-#include <lttng/constant.h>
-
-#include <inttypes.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <urcu/rculfhash.h>
-#include <urcu/ref.h>
-
-/*
- * Two ISO 8601-compatible timestamps, separated by a hypen, followed an
- * index, i.e. <start-iso-8601>-<end-iso-8601>-<id-uint64_t>.
- */
-#define GENERATED_CHUNK_NAME_LEN (2 * sizeof("YYYYmmddTHHMMSS+HHMM") + MAX_INT_DEC_LEN(uint64_t))
-#define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
-
-enum trace_chunk_mode {
-       TRACE_CHUNK_MODE_USER,
-       TRACE_CHUNK_MODE_OWNER,
-};
-
-/*
- * Callback to invoke on release of a trace chunk. Note that there is no
- * need to 'lock' the trace chunk during the execution of these callbacks
- * since only one thread may access a chunk during its destruction (the last
- * to release its reference to the chunk).
- */
-typedef int (*chunk_command)(struct lttng_trace_chunk *trace_chunk);
-
-/* Move a completed trace chunk to the 'completed' trace archive folder. */
-static
-int lttng_trace_chunk_move_to_completed_post_release(struct lttng_trace_chunk *trace_chunk);
-/* Empty callback. */
-static
-int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk);
-/* Unlink old chunk files. */
-static
-int lttng_trace_chunk_delete_post_release(struct lttng_trace_chunk *trace_chunk);
-static
-enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
-               struct lttng_trace_chunk *chunk, const char *path);
-
-struct chunk_credentials {
-       bool use_current_user;
-       struct lttng_credentials user;
-};
-
-/*
- * NOTE: Make sure to update:
- * - lttng_trace_chunk_copy(),
- * - lttng_trace_chunk_registry_element_create_from_chunk()
- * if you modify this structure.
- */
-struct lttng_trace_chunk {
-       pthread_mutex_t lock;
-       struct urcu_ref ref;
-       LTTNG_OPTIONAL(enum trace_chunk_mode) mode;
-       /*
-        * 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;
-       /*
-        * 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;
-       char *name;
-       char *path;
-       /* An unset id means the chunk is anonymous. */
-       LTTNG_OPTIONAL(uint64_t) id;
-
-       /*
-        * The creation and close timestamps are NOT monotonic.
-        * They must not be used in context were monotonicity is required.
-        */
-       LTTNG_OPTIONAL(time_t) timestamp_creation;
-       LTTNG_OPTIONAL(time_t) timestamp_close;
-
-       LTTNG_OPTIONAL(struct chunk_credentials) credentials;
-       struct lttng_directory_handle *session_output_directory;
-       struct lttng_directory_handle *chunk_directory;
-       LTTNG_OPTIONAL(enum lttng_trace_chunk_command_type) close_command;
-       /*
-        * fd_tracker instance through which file descriptors should be
-        * created/closed.
-        *
-        * An fd_tracker always outlives any trace chunk; there is no
-        * need to perform any reference counting of that object.
-        */
-       struct fd_tracker *fd_tracker;
-};
-
-/* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
-struct lttng_trace_chunk_registry_element {
-       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;
-       /* call_rcu delayed reclaim. */
-       struct rcu_head rcu_node;
-};
-
-struct lttng_trace_chunk_registry {
-       struct cds_lfht *ht;
-};
-
-struct fs_handle_untracked {
-       struct fs_handle parent;
-       int fd;
-       struct {
-               struct lttng_directory_handle *directory_handle;
-               char *path;
-       } location;
-};
-
-static
-int fs_handle_untracked_get_fd(struct fs_handle *handle);
-static
-void fs_handle_untracked_put_fd(struct fs_handle *handle);
-static
-int fs_handle_untracked_unlink(struct fs_handle *handle);
-static
-int fs_handle_untracked_close(struct fs_handle *handle);
-
-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
-chunk_command close_command_post_release_funcs[] = {
-       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] =
-                       lttng_trace_chunk_move_to_completed_post_release,
-       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION] =
-                       lttng_trace_chunk_no_operation,
-       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE] =
-                       lttng_trace_chunk_delete_post_release,
-};
-
-static
-struct fs_handle *fs_handle_untracked_create(
-               struct lttng_directory_handle *directory_handle,
-               const char *path,
-               int fd)
-{
-       struct fs_handle_untracked *handle = NULL;
-       bool reference_acquired;
-       char *path_copy = strdup(path);
-
-       LTTNG_ASSERT(fd >= 0);
-       if (!path_copy) {
-               PERROR("Failed to copy file path while creating untracked filesystem handle");
-               goto end;
-       }
-
-       handle = zmalloc(sizeof(typeof(*handle)));
-       if (!handle) {
-               PERROR("Failed to allocate untracked filesystem handle");
-               goto end;
-       }
-
-       handle->parent = (typeof(handle->parent)) {
-               .get_fd = fs_handle_untracked_get_fd,
-               .put_fd = fs_handle_untracked_put_fd,
-               .unlink = fs_handle_untracked_unlink,
-               .close = fs_handle_untracked_close,
-       };
-
-       handle->fd = fd;
-       reference_acquired = lttng_directory_handle_get(directory_handle);
-       LTTNG_ASSERT(reference_acquired);
-       handle->location.directory_handle = directory_handle;
-       /* Ownership is transferred. */
-       handle->location.path = path_copy;
-       path_copy = NULL;
-end:
-       free(path_copy);
-       return handle ? &handle->parent : NULL;
-}
-
-static
-int fs_handle_untracked_get_fd(struct fs_handle *_handle)
-{
-       struct fs_handle_untracked *handle = container_of(
-                       _handle, struct fs_handle_untracked, parent);
-
-       return handle->fd;
-}
-
-static
-void fs_handle_untracked_put_fd(struct fs_handle *_handle)
-{
-       /* no-op. */
-}
-
-static
-int fs_handle_untracked_unlink(struct fs_handle *_handle)
-{
-       struct fs_handle_untracked *handle = container_of(
-                       _handle, struct fs_handle_untracked, parent);
-
-       return lttng_directory_handle_unlink_file(
-                       handle->location.directory_handle,
-                       handle->location.path);
-}
-
-static
-void fs_handle_untracked_destroy(struct fs_handle_untracked *handle)
-{
-       lttng_directory_handle_put(handle->location.directory_handle);
-       free(handle->location.path);
-       free(handle);
-}
-
-static
-int fs_handle_untracked_close(struct fs_handle *_handle)
-{
-       struct fs_handle_untracked *handle = container_of(
-                       _handle, struct fs_handle_untracked, parent);
-       int ret = close(handle->fd);
-
-       fs_handle_untracked_destroy(handle);
-       return ret;
-}
-
-static
-bool lttng_trace_chunk_registry_element_equals(
-               const struct lttng_trace_chunk_registry_element *a,
-               const struct lttng_trace_chunk_registry_element *b)
-{
-       if (a->session_id != b->session_id) {
-               goto not_equal;
-       }
-       if (a->chunk.id.is_set != b->chunk.id.is_set) {
-               goto not_equal;
-       }
-       if (a->chunk.id.is_set && a->chunk.id.value != b->chunk.id.value) {
-               goto not_equal;
-       }
-       return true;
-not_equal:
-       return false;
-}
-
-static
-int lttng_trace_chunk_registry_element_match(struct cds_lfht_node *node,
-               const void *key)
-{
-       const struct lttng_trace_chunk_registry_element *element_a, *element_b;
-
-       element_a = (const struct lttng_trace_chunk_registry_element *) key;
-       element_b = caa_container_of(node, typeof(*element_b),
-                       trace_chunk_registry_ht_node);
-       return lttng_trace_chunk_registry_element_equals(element_a, element_b);
-}
-
-static
-unsigned long lttng_trace_chunk_registry_element_hash(
-               const struct lttng_trace_chunk_registry_element *element)
-{
-       unsigned long hash = hash_key_u64(&element->session_id,
-                       lttng_ht_seed);
-
-       if (element->chunk.id.is_set) {
-               hash ^= hash_key_u64(&element->chunk.id.value, lttng_ht_seed);
-       }
-
-       return hash;
-}
-
-static
-char *generate_chunk_name(uint64_t chunk_id, time_t creation_timestamp,
-               const time_t *close_timestamp)
-{
-       int ret = 0;
-       char *new_name= NULL;
-       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,
-                       start_datetime, sizeof(start_datetime));
-       if (ret) {
-               ERR("Failed to format trace chunk start date time");
-               goto error;
-       }
-       if (close_timestamp) {
-               *end_datetime_suffix = '-';
-               ret = time_to_iso8601_str(
-                               *close_timestamp,
-                               end_datetime_suffix + 1,
-                               sizeof(end_datetime_suffix) - 1);
-               if (ret) {
-                       ERR("Failed to format trace chunk end date time");
-                       goto error;
-               }
-       }
-       new_name = zmalloc(GENERATED_CHUNK_NAME_LEN);
-       if (!new_name) {
-               ERR("Failed to allocate buffer for automatically-generated trace chunk name");
-               goto error;
-       }
-       ret = snprintf(new_name, GENERATED_CHUNK_NAME_LEN, "%s%s-%" PRIu64,
-                       start_datetime, end_datetime_suffix, chunk_id);
-       if (ret >= GENERATED_CHUNK_NAME_LEN || ret == -1) {
-               ERR("Failed to format trace chunk name");
-               goto error;
-       }
-
-       return new_name;
-error:
-       free(new_name);
-       return NULL;
-}
-
-static
-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
-void lttng_trace_chunk_fini(struct lttng_trace_chunk *chunk)
-{
-       if (chunk->session_output_directory) {
-               lttng_directory_handle_put(
-                               chunk->session_output_directory);
-               chunk->session_output_directory = NULL;
-       }
-       if (chunk->chunk_directory) {
-               lttng_directory_handle_put(chunk->chunk_directory);
-               chunk->chunk_directory = NULL;
-       }
-       free(chunk->name);
-       chunk->name = NULL;
-       free(chunk->path);
-       chunk->path = NULL;
-       lttng_dynamic_pointer_array_reset(&chunk->top_level_directories);
-       lttng_dynamic_pointer_array_reset(&chunk->files);
-       pthread_mutex_destroy(&chunk->lock);
-}
-
-static
-struct lttng_trace_chunk *lttng_trace_chunk_allocate(void)
-{
-       struct lttng_trace_chunk *chunk = NULL;
-
-       chunk = zmalloc(sizeof(*chunk));
-       if (!chunk) {
-               ERR("Failed to allocate trace chunk");
-               goto end;
-       }
-       lttng_trace_chunk_init(chunk);
-end:
-       return chunk;
-}
-
-struct lttng_trace_chunk *lttng_trace_chunk_create_anonymous(void)
-{
-       DBG("Creating anonymous trace chunk");
-       return lttng_trace_chunk_allocate();
-}
-
-struct lttng_trace_chunk *lttng_trace_chunk_create(
-               uint64_t chunk_id, time_t chunk_creation_time, const char *path)
-{
-       struct lttng_trace_chunk *chunk;
-       char chunk_creation_datetime_buf[16] = {};
-       const char *chunk_creation_datetime_str = "(formatting error)";
-       struct tm timeinfo_buf, *timeinfo;
-
-       timeinfo = localtime_r(&chunk_creation_time, &timeinfo_buf);
-       if (timeinfo) {
-               size_t strftime_ret;
-
-               /* Don't fail because of this; it is only used for logging. */
-               strftime_ret = strftime(chunk_creation_datetime_buf,
-                               sizeof(chunk_creation_datetime_buf),
-                               "%Y%m%d-%H%M%S", timeinfo);
-               if (strftime_ret) {
-                       chunk_creation_datetime_str =
-                                       chunk_creation_datetime_buf;
-               }
-       }
-
-       DBG("Creating trace chunk: chunk_id = %" PRIu64 ", creation time = %s",
-                       chunk_id, chunk_creation_datetime_str);
-       chunk = lttng_trace_chunk_allocate();
-       if (!chunk) {
-               goto end;
-       }
-
-       LTTNG_OPTIONAL_SET(&chunk->id, chunk_id);
-       LTTNG_OPTIONAL_SET(&chunk->timestamp_creation, chunk_creation_time);
-       if (chunk_id != 0) {
-               chunk->name = generate_chunk_name(chunk_id,
-                               chunk_creation_time, NULL);
-               if (!chunk->name) {
-                       ERR("Failed to allocate trace chunk name storage");
-                       goto error;
-               }
-       }
-       if (path) {
-               chunk->path = strdup(path);
-               if (!chunk->path) {
-                       goto error;
-               }
-       } else {
-               if (chunk->name) {
-                       chunk->path = strdup(chunk->name);
-                       if (!chunk->path) {
-                               goto error;
-                       }
-               }
-       }
-
-       DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
-end:
-       return chunk;
-error:
-       lttng_trace_chunk_put(chunk);
-       return NULL;
-}
-
-void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk,
-               struct fd_tracker *fd_tracker)
-{
-       LTTNG_ASSERT(!chunk->session_output_directory);
-       LTTNG_ASSERT(!chunk->chunk_directory);
-       LTTNG_ASSERT(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0);
-       chunk->fd_tracker = fd_tracker;
-}
-
-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;
-               }
-       }
-       if (source_chunk->path) {
-               new_chunk->path = strdup(source_chunk->path);
-               if (!new_chunk->path) {
-                       ERR("Failed to copy source trace chunk path in %s()",
-                                       __FUNCTION__);
-               }
-       }
-       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) {
-               const bool reference_acquired = lttng_directory_handle_get(
-                               source_chunk->session_output_directory);
-
-               LTTNG_ASSERT(reference_acquired);
-               new_chunk->session_output_directory =
-                               source_chunk->session_output_directory;
-       }
-       if (source_chunk->chunk_directory) {
-               const bool reference_acquired = lttng_directory_handle_get(
-                               source_chunk->chunk_directory);
-
-               LTTNG_ASSERT(reference_acquired);
-               new_chunk->chunk_directory = source_chunk->chunk_directory;
-       }
-       new_chunk->close_command = source_chunk->close_command;
-       new_chunk->fd_tracker = source_chunk->fd_tracker;
-       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;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_id(
-               struct lttng_trace_chunk *chunk, uint64_t *id)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->id.is_set) {
-               *id = chunk->id.value;
-       } else {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-       }
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp(
-               struct lttng_trace_chunk *chunk, time_t *creation_ts)
-
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->timestamp_creation.is_set) {
-               *creation_ts = chunk->timestamp_creation.value;
-       } else {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-       }
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp(
-               struct lttng_trace_chunk *chunk, time_t *close_ts)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->timestamp_close.is_set) {
-               *close_ts = chunk->timestamp_close.value;
-       } else {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-       }
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp(
-               struct lttng_trace_chunk *chunk, time_t close_ts)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->timestamp_creation.is_set) {
-               ERR("Failed to set trace chunk close timestamp: creation timestamp is unset");
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
-               goto end;
-       }
-
-       /*
-        * Note: we do not enforce that the closing timestamp be greater or
-        * equal to the begin timestamp. These timestamps are used for
-        * generating the chunk name and should only be used in context where
-        * the monotonicity of time is not important. The source of those
-        * timestamps is NOT monotonic and represent the system calendar time,
-        * also know as the wall time.
-        */
-       if (chunk->timestamp_creation.value > close_ts) {
-               WARN("Set trace chunk close timestamp: close timestamp is before creation timestamp, begin : %ld, close : %ld",
-                               chunk->timestamp_creation.value, close_ts);
-       }
-
-       LTTNG_OPTIONAL_SET(&chunk->timestamp_close, close_ts);
-       if (!chunk->name_overridden) {
-               free(chunk->name);
-               chunk->name = generate_chunk_name(LTTNG_OPTIONAL_GET(chunk->id),
-                               LTTNG_OPTIONAL_GET(chunk->timestamp_creation),
-                               &close_ts);
-               if (!chunk->name) {
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               }
-       }
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_name(
-               struct lttng_trace_chunk *chunk, const char **name,
-               bool *name_overridden)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (name_overridden) {
-               *name_overridden = chunk->name_overridden;
-       }
-       if (!chunk->name) {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-               goto end;
-       }
-       *name = chunk->name;
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-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)
-{
-       size_t len;
-
-       if (!name) {
-               return false;
-       }
-
-       len = lttng_strnlen(name, LTTNG_NAME_MAX);
-       if (len == 0 || len == LTTNG_NAME_MAX) {
-               return false;
-       }
-
-       if (strchr(name, '/') || strchr(name, '.')) {
-               return false;
-       }
-
-       return true;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_override_name(
-               struct lttng_trace_chunk *chunk, const char *name)
-
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       char *new_name, *new_path;
-
-       DBG("Override trace chunk name from %s to %s", chunk->name, name);
-       if (!is_valid_chunk_name(name)) {
-               ERR("Attempted to set an invalid name on a trace chunk: name = %s",
-                               name ? : "NULL");
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
-               goto end;
-       }
-
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->id.is_set) {
-               ERR("Attempted to set an override name on an anonymous trace chunk: name = %s",
-                               name);
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
-               goto end_unlock;
-       }
-
-       new_name = strdup(name);
-       if (!new_name) {
-               ERR("Failed to allocate new trace chunk name");
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end_unlock;
-       }
-       free(chunk->name);
-       chunk->name = new_name;
-
-       new_path = strdup(name);
-       if (!new_path) {
-               ERR("Failed to allocate new trace chunk path");
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end_unlock;
-       }
-       free(chunk->path);
-       chunk->path = new_path;
-
-       chunk->name_overridden = true;
-end_unlock:
-       pthread_mutex_unlock(&chunk->lock);
-end:
-       return status;
-}
-
-static
-enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
-               struct lttng_trace_chunk *chunk, const char *path)
-
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       struct lttng_directory_handle *rename_directory = NULL;
-       char *new_path, *old_path;
-       int ret;
-
-       if (chunk->name_overridden) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-
-       old_path = chunk->path;
-       DBG("lttng_trace_chunk_rename_path from %s to %s", old_path, path);
-
-       if ((!old_path && !path) ||
-                       (old_path && path && !strcmp(old_path, path)))  {
-               goto end;
-       }
-       /*
-        * Use chunk name as path if NULL path is specified.
-        */
-       if (!path) {
-               path = chunk->name;
-       }
-
-       /* Renaming from "" to "" is not accepted. */
-       if (path[0] == '\0' && old_path[0] == '\0') {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-
-       /*
-        * If a rename is performed on a chunk for which the chunk_directory
-        * is not set (yet), or the session_output_directory is not set
-        * (interacting with a relay daemon), there is no rename to perform.
-        */
-       if (!chunk->chunk_directory ||
-                       !chunk->session_output_directory) {
-               goto skip_move;
-       }
-
-       if (old_path && old_path[0] != '\0' && path[0] != '\0') {
-               /* Rename chunk directory. */
-               ret = lttng_directory_handle_rename_as_user(
-                       chunk->session_output_directory,
-                       old_path,
-                       chunk->session_output_directory,
-                       path,
-                       LTTNG_OPTIONAL_GET(chunk->credentials).use_current_user ?
-                               NULL :
-                               &chunk->credentials.value.user);
-               if (ret) {
-                       PERROR("Failed to move trace chunk directory \"%s\" to \"%s\"",
-                                       old_path, path);
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-               rename_directory = chunk->fd_tracker ?
-                               fd_tracker_create_directory_handle_from_handle(
-                                               chunk->fd_tracker,
-                                               chunk->session_output_directory,
-                                               path) :
-                               lttng_directory_handle_create_from_handle(
-                                               path,
-                                               chunk->session_output_directory);
-               if (!rename_directory) {
-                       ERR("Failed to get handle to trace chunk rename directory");
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-
-               /* Release old handle. */
-               lttng_directory_handle_put(chunk->chunk_directory);
-               /*
-                * Transfer new handle reference to chunk as the current chunk
-                * handle.
-                */
-               chunk->chunk_directory = rename_directory;
-               rename_directory = NULL;
-       } else if (old_path && old_path[0] == '\0') {
-               size_t i, count = lttng_dynamic_pointer_array_get_count(
-                               &chunk->top_level_directories);
-
-               ret = lttng_directory_handle_create_subdirectory_as_user(
-                               chunk->session_output_directory,
-                               path,
-                               DIR_CREATION_MODE,
-                               LTTNG_OPTIONAL_GET(chunk->credentials).use_current_user ?
-                                       NULL :
-                                       &chunk->credentials.value.user);
-               if (ret) {
-                       PERROR("Failed to create trace chunk rename directory \"%s\"",
-                                       path);
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-
-               rename_directory = lttng_directory_handle_create_from_handle(
-                               path, chunk->session_output_directory);
-               if (!rename_directory) {
-                       ERR("Failed to get handle to trace chunk rename directory");
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-
-               /* Move toplevel directories. */
-               for (i = 0; i < count; i++) {
-                       const char *top_level_name =
-                               lttng_dynamic_pointer_array_get_pointer(
-                                       &chunk->top_level_directories, i);
-
-                       ret = lttng_directory_handle_rename_as_user(
-                                       chunk->chunk_directory,
-                                       top_level_name,
-                                       rename_directory,
-                                       top_level_name,
-                                       LTTNG_OPTIONAL_GET(chunk->credentials).use_current_user ?
-                                               NULL :
-                                               &chunk->credentials.value.user);
-                       if (ret) {
-                               PERROR("Failed to move \"%s\" to trace chunk rename directory",
-                                               top_level_name);
-                               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                               goto end;
-                       }
-               }
-               /* Release old handle. */
-               lttng_directory_handle_put(chunk->chunk_directory);
-               /*
-                * Transfer new handle reference to chunk as the current chunk
-                * handle.
-                */
-               chunk->chunk_directory = rename_directory;
-               rename_directory = NULL;
-       } else if (old_path) {
-               size_t i, count = lttng_dynamic_pointer_array_get_count(
-                               &chunk->top_level_directories);
-               const bool reference_acquired = lttng_directory_handle_get(
-                               chunk->session_output_directory);
-
-               LTTNG_ASSERT(reference_acquired);
-               rename_directory = chunk->session_output_directory;
-
-               /* Move toplevel directories. */
-               for (i = 0; i < count; i++) {
-                       const char *top_level_name =
-                               lttng_dynamic_pointer_array_get_pointer(
-                                       &chunk->top_level_directories, i);
-
-                       ret = lttng_directory_handle_rename_as_user(
-                                       chunk->chunk_directory,
-                                       top_level_name,
-                                       rename_directory,
-                                       top_level_name,
-                                       LTTNG_OPTIONAL_GET(chunk->credentials).use_current_user ?
-                                               NULL :
-                                               &chunk->credentials.value.user);
-                       if (ret) {
-                               PERROR("Failed to move \"%s\" to trace chunk rename directory",
-                                               top_level_name);
-                               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                               goto end;
-                       }
-               }
-               /* Release old handle. */
-               lttng_directory_handle_put(chunk->chunk_directory);
-               /*
-                * Transfer new handle reference to chunk as the current chunk
-                * handle.
-                */
-               chunk->chunk_directory = rename_directory;
-               rename_directory = NULL;
-
-               /* Remove old directory. */
-               status = lttng_directory_handle_remove_subdirectory(
-                               chunk->session_output_directory,
-                               old_path);
-               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
-                       ERR("Error removing subdirectory '%s' file when deleting chunk",
-                               old_path);
-                       goto end;
-               }
-       } else {
-               /* Unexpected !old_path && !path. */
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
-               goto end;
-       }
-
-skip_move:
-       new_path = strdup(path);
-       if (!new_path) {
-               ERR("Failed to allocate new trace chunk path");
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       free(chunk->path);
-       chunk->path = new_path;
-end:
-       lttng_directory_handle_put(rename_directory);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_rename_path(
-               struct lttng_trace_chunk *chunk, const char *path)
-
-{
-       enum lttng_trace_chunk_status status;
-
-       pthread_mutex_lock(&chunk->lock);
-       status = lttng_trace_chunk_rename_path_no_lock(chunk, path);
-       pthread_mutex_unlock(&chunk->lock);
-
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_credentials *credentials)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->credentials.is_set) {
-               if (chunk->credentials.value.use_current_user) {
-                       LTTNG_OPTIONAL_SET(&credentials->uid, geteuid());
-                       LTTNG_OPTIONAL_SET(&credentials->gid, getegid());
-               } else {
-                       *credentials = chunk->credentials.value.user;
-               }
-       } else {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-       }
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials(
-               struct lttng_trace_chunk *chunk,
-               const struct lttng_credentials *user_credentials)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       const struct chunk_credentials credentials = {
-               .user = *user_credentials,
-               .use_current_user = false,
-       };
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->credentials.is_set) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       LTTNG_OPTIONAL_SET(&chunk->credentials, credentials);
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user(
-               struct lttng_trace_chunk *chunk)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       const struct chunk_credentials credentials = {
-               .use_current_user = true,
-       };
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->credentials.is_set) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       LTTNG_OPTIONAL_SET(&chunk->credentials, credentials);
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle *session_output_directory)
-{
-       int ret;
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       struct lttng_directory_handle *chunk_directory_handle = NULL;
-       bool reference_acquired;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->mode.is_set) {
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
-               goto end;
-       }
-       if (!chunk->credentials.is_set) {
-               /*
-                * Fatal error, credentials must be set before a
-                * directory is created.
-                */
-               ERR("Credentials of trace chunk are unset: refusing to set session output directory");
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (chunk->path && chunk->path[0] != '\0') {
-               ret = lttng_directory_handle_create_subdirectory_as_user(
-                               session_output_directory,
-                               chunk->path,
-                               DIR_CREATION_MODE,
-                               !chunk->credentials.value.use_current_user ?
-                                       &chunk->credentials.value.user : NULL);
-               if (ret) {
-                       PERROR("Failed to create chunk output directory \"%s\"",
-                               chunk->path);
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-               chunk_directory_handle =
-                               chunk->fd_tracker ?
-                                       fd_tracker_create_directory_handle_from_handle(
-                                                       chunk->fd_tracker,
-                                                       session_output_directory,
-                                                       chunk->path) :
-                                       lttng_directory_handle_create_from_handle(
-                                                       chunk->path,
-                                                       session_output_directory);
-               if (!chunk_directory_handle) {
-                       /* The function already logs on all error paths. */
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-       } else {
-               /*
-                * A nameless chunk does not need its own output directory.
-                * The session's output directory will be used.
-                */
-               reference_acquired = lttng_directory_handle_get(
-                               session_output_directory);
-
-               LTTNG_ASSERT(reference_acquired);
-               chunk_directory_handle = session_output_directory;
-       }
-       chunk->chunk_directory = chunk_directory_handle;
-       chunk_directory_handle = NULL;
-       reference_acquired = lttng_directory_handle_get(
-                       session_output_directory);
-       LTTNG_ASSERT(reference_acquired);
-       chunk->session_output_directory = session_output_directory;
-       LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_OWNER);
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle *chunk_directory)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       bool reference_acquired;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->mode.is_set) {
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
-               goto end;
-       }
-       if (!chunk->credentials.is_set) {
-               ERR("Credentials of trace chunk are unset: refusing to set chunk output directory");
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       reference_acquired = lttng_directory_handle_get(chunk_directory);
-       LTTNG_ASSERT(reference_acquired);
-       chunk->chunk_directory = chunk_directory;
-       LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_USER);
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status
-lttng_trace_chunk_get_session_output_directory_handle(
-               struct lttng_trace_chunk *chunk,
-               struct lttng_directory_handle **handle)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->session_output_directory) {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-               *handle = NULL;
-               goto end;
-       } else {
-               const bool reference_acquired = lttng_directory_handle_get(
-                               chunk->session_output_directory);
-
-               LTTNG_ASSERT(reference_acquired);
-               *handle = chunk->session_output_directory;
-       }
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle(
-               struct lttng_trace_chunk *chunk,
-               const struct lttng_directory_handle **handle)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->chunk_directory) {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-               goto end;
-       }
-
-       *handle = chunk->chunk_directory;
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-/* Add a top-level directory to the trace chunk if it was previously unknown. */
-static
-int add_top_level_directory_unique(struct lttng_trace_chunk *chunk,
-               const char *new_path)
-{
-       int ret = 0;
-       bool found = false;
-       size_t i, count = lttng_dynamic_pointer_array_get_count(
-                       &chunk->top_level_directories);
-       const char *new_path_separator_pos = strchr(new_path, '/');
-       const ptrdiff_t new_path_top_level_len = new_path_separator_pos ?
-                       new_path_separator_pos - new_path : strlen(new_path);
-
-       for (i = 0; i < count; i++) {
-               const char *path = lttng_dynamic_pointer_array_get_pointer(
-                               &chunk->top_level_directories, i);
-               const ptrdiff_t path_top_level_len = strlen(path);
-
-               if (path_top_level_len != new_path_top_level_len) {
-                       continue;
-               }
-               if (!strncmp(path, new_path, path_top_level_len)) {
-                       found = true;
-                       break;
-               }
-       }
-
-       if (!found) {
-               char *copy = lttng_strndup(new_path, new_path_top_level_len);
-
-               DBG("Adding new top-level directory \"%s\" to trace chunk \"%s\"",
-                               new_path, chunk->name ? : "(unnamed)");
-               if (!copy) {
-                       PERROR("Failed to copy path");
-                       ret = -1;
-                       goto end;
-               }
-               ret = lttng_dynamic_pointer_array_add_pointer(
-                               &chunk->top_level_directories, copy);
-               if (ret) {
-                       ERR("Allocation failure while adding top-level directory entry to a trace chunk");
-                       free(copy);
-                       goto end;
-               }
-       }
-end:
-       return ret;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_create_subdirectory(
-               struct lttng_trace_chunk *chunk,
-               const char *path)
-{
-       int ret;
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       DBG("Creating trace chunk subdirectory \"%s\"", path);
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->credentials.is_set) {
-               /*
-                * Fatal error, credentials must be set before a
-                * directory is created.
-                */
-               ERR("Credentials of trace chunk are unset: refusing to create subdirectory \"%s\"",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (!chunk->mode.is_set ||
-                       chunk->mode.value != TRACE_CHUNK_MODE_OWNER) {
-               ERR("Attempted to create trace chunk subdirectory \"%s\" through a non-owner chunk",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
-               goto end;
-       }
-       if (!chunk->chunk_directory) {
-               ERR("Attempted to create trace chunk subdirectory \"%s\" before setting the chunk output directory",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (*path == '/') {
-               ERR("Refusing to create absolute trace chunk directory \"%s\"",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
-               goto end;
-       }
-       ret = lttng_directory_handle_create_subdirectory_recursive_as_user(
-                       chunk->chunk_directory, path,
-                       DIR_CREATION_MODE,
-                       chunk->credentials.value.use_current_user ?
-                                       NULL : &chunk->credentials.value.user);
-       if (ret) {
-               PERROR("Failed to create trace chunk subdirectory \"%s\"",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       ret = add_top_level_directory_unique(chunk, path);
-       if (ret) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       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);
-       LTTNG_ASSERT(!ret);
-}
-
-static
-enum lttng_trace_chunk_status _lttng_trace_chunk_open_fs_handle_locked(
-               struct lttng_trace_chunk *chunk,
-               const char *file_path,
-               int flags,
-               mode_t mode,
-               struct fs_handle **out_handle,
-               bool expect_no_file)
-{
-       int ret;
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       DBG("Opening trace chunk file \"%s\"", file_path);
-       if (!chunk->credentials.is_set) {
-               /*
-                * Fatal error, credentials must be set before a
-                * file is created.
-                */
-               ERR("Credentials of trace chunk are unset: refusing to open file \"%s\"",
-                               file_path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (!chunk->chunk_directory) {
-               ERR("Attempted to open trace chunk file \"%s\" before setting the chunk output directory",
-                               file_path);
-               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;
-       }
-       if (chunk->fd_tracker) {
-               LTTNG_ASSERT(chunk->credentials.value.use_current_user);
-               *out_handle = fd_tracker_open_fs_handle(chunk->fd_tracker,
-                               chunk->chunk_directory, file_path, flags, &mode);
-               ret = *out_handle ? 0 : -1;
-       } else {
-               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) {
-                       *out_handle = fs_handle_untracked_create(
-                                       chunk->chunk_directory, file_path, ret);
-                       if (!*out_handle) {
-                               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                               goto end;
-                       }
-               }
-       }
-       if (ret < 0) {
-               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;
-               }
-               lttng_trace_chunk_remove_file(chunk, file_path);
-               goto end;
-       }
-end:
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_open_fs_handle(
-               struct lttng_trace_chunk *chunk,
-               const char *file_path,
-               int flags,
-               mode_t mode,
-               struct fs_handle **out_handle,
-               bool expect_no_file)
-{
-       enum lttng_trace_chunk_status status;
-
-       pthread_mutex_lock(&chunk->lock);
-       status = _lttng_trace_chunk_open_fs_handle_locked(chunk, file_path,
-                       flags, mode, out_handle, expect_no_file);
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-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,
-               bool expect_no_file)
-{
-       enum lttng_trace_chunk_status status;
-       struct fs_handle *fs_handle;
-
-       pthread_mutex_lock(&chunk->lock);
-       /*
-        * Using this method is never valid when an fd_tracker is being
-        * used since the resulting file descriptor would not be tracked.
-        */
-       LTTNG_ASSERT(!chunk->fd_tracker);
-       status = _lttng_trace_chunk_open_fs_handle_locked(chunk, file_path,
-                       flags, mode, &fs_handle, expect_no_file);
-       pthread_mutex_unlock(&chunk->lock);
-
-       if (status == LTTNG_TRACE_CHUNK_STATUS_OK) {
-               *out_fd = fs_handle_get_fd(fs_handle);
-               /*
-                * Does not close the fd; we just "unbox" it from the fs_handle.
-                */
-               fs_handle_untracked_destroy(container_of(
-                               fs_handle, struct fs_handle_untracked, parent));
-       }
-
-       return status;
-}
-
-int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
-               const char *file_path)
-{
-       int ret;
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       DBG("Unlinking trace chunk file \"%s\"", file_path);
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->credentials.is_set) {
-               /*
-                * Fatal error, credentials must be set before a
-                * file is unlinked.
-                */
-               ERR("Credentials of trace chunk are unset: refusing to unlink file \"%s\"",
-                               file_path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (!chunk->chunk_directory) {
-               ERR("Attempted to unlink trace chunk file \"%s\" before setting the chunk output directory",
-                               file_path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       ret = lttng_directory_handle_unlink_file_as_user(
-                       chunk->chunk_directory, file_path,
-                       chunk->credentials.value.use_current_user ?
-                                       NULL : &chunk->credentials.value.user);
-       if (ret < 0) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       lttng_trace_chunk_remove_file(chunk, file_path);
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-static
-int lttng_trace_chunk_remove_subdirectory_recursive(struct lttng_trace_chunk *chunk,
-               const char *path)
-{
-       int ret;
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       DBG("Recursively removing trace chunk directory \"%s\"", path);
-       pthread_mutex_lock(&chunk->lock);
-       if (!chunk->credentials.is_set) {
-               /*
-                * Fatal error, credentials must be set before a
-                * directory is removed.
-                */
-               ERR("Credentials of trace chunk are unset: refusing to recursively remove directory \"%s\"",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       if (!chunk->chunk_directory) {
-               ERR("Attempted to recursively remove trace chunk directory \"%s\" before setting the chunk output directory",
-                               path);
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-       ret = lttng_directory_handle_remove_subdirectory_recursive_as_user(
-                       chunk->chunk_directory, path,
-                       chunk->credentials.value.use_current_user ?
-                                       NULL : &chunk->credentials.value.user,
-                       LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
-       if (ret < 0) {
-               status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-               goto end;
-       }
-end:
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-static
-int lttng_trace_chunk_move_to_completed_post_release(
-               struct lttng_trace_chunk *trace_chunk)
-{
-       int ret = 0;
-       char *archived_chunk_name = NULL;
-       const uint64_t chunk_id = LTTNG_OPTIONAL_GET(trace_chunk->id);
-       const time_t creation_timestamp =
-                       LTTNG_OPTIONAL_GET(trace_chunk->timestamp_creation);
-       const time_t close_timestamp =
-                       LTTNG_OPTIONAL_GET(trace_chunk->timestamp_close);
-       struct lttng_directory_handle *archived_chunks_directory = NULL;
-       enum lttng_trace_chunk_status status;
-
-       if (!trace_chunk->mode.is_set ||
-                       trace_chunk->mode.value != TRACE_CHUNK_MODE_OWNER ||
-                       !trace_chunk->session_output_directory) {
-               /*
-                * This command doesn't need to run if the output is remote
-                * or if the trace chunk is not owned by this process.
-                */
-               goto end;
-       }
-
-       LTTNG_ASSERT(trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER);
-       LTTNG_ASSERT(!trace_chunk->name_overridden);
-       LTTNG_ASSERT(trace_chunk->path);
-
-       archived_chunk_name = generate_chunk_name(chunk_id, creation_timestamp,
-                       &close_timestamp);
-       if (!archived_chunk_name) {
-               ERR("Failed to generate archived trace chunk name while renaming trace chunk");
-               ret = -1;
-               goto end;
-       }
-
-       ret = lttng_directory_handle_create_subdirectory_as_user(
-                       trace_chunk->session_output_directory,
-                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
-                       DIR_CREATION_MODE,
-                       !trace_chunk->credentials.value.use_current_user ?
-                                       &trace_chunk->credentials.value.user :
-                                       NULL);
-       if (ret) {
-               PERROR("Failed to create \"" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY
-                               "\" directory for archived trace chunks");
-               goto end;
-       }
-
-       archived_chunks_directory = trace_chunk->fd_tracker ?
-                       fd_tracker_create_directory_handle_from_handle(
-                                       trace_chunk->fd_tracker,
-                                       trace_chunk->session_output_directory,
-                                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY) :
-                       lttng_directory_handle_create_from_handle(
-                                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
-                                       trace_chunk->session_output_directory);
-       if (!archived_chunks_directory) {
-               PERROR("Failed to get handle to archived trace chunks directory");
-               ret = -1;
-               goto end;
-       }
-
-       /*
-        * Make sure chunk is renamed to old directory if not already done by
-        * the creation of the next chunk. This happens if a rotation is
-        * performed while tracing is stopped.
-        */
-       if (!trace_chunk->path || strcmp(trace_chunk->path,
-                       DEFAULT_CHUNK_TMP_OLD_DIRECTORY)) {
-               status = lttng_trace_chunk_rename_path_no_lock(trace_chunk,
-                               DEFAULT_CHUNK_TMP_OLD_DIRECTORY);
-               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
-                       ERR("Failed to rename chunk to %s", DEFAULT_CHUNK_TMP_OLD_DIRECTORY);
-                       ret = -1;
-                       goto end;
-               }
-       }
-
-       ret = lttng_directory_handle_rename_as_user(
-                       trace_chunk->session_output_directory,
-                       trace_chunk->path,
-                       archived_chunks_directory,
-                       archived_chunk_name,
-                       LTTNG_OPTIONAL_GET(trace_chunk->credentials).use_current_user ?
-                               NULL :
-                               &trace_chunk->credentials.value.user);
-       if (ret) {
-               PERROR("Failed to rename folder \"%s\" to \"%s\"",
-                               trace_chunk->path,
-                               archived_chunk_name);
-       }
-
-end:
-       lttng_directory_handle_put(archived_chunks_directory);
-       free(archived_chunk_name);
-       return ret;
-}
-
-static
-int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk)
-{
-       return 0;
-}
-
-static
-int lttng_trace_chunk_delete_post_release_user(
-               struct lttng_trace_chunk *trace_chunk)
-{
-       int ret = 0;
-
-       DBG("Trace chunk \"delete\" close command post-release (User)");
-
-       /* Unlink all files. */
-       while (lttng_dynamic_pointer_array_get_count(&trace_chunk->files) != 0) {
-               enum lttng_trace_chunk_status status;
-               const char *path;
-
-               /* Remove first. */
-               path = lttng_dynamic_pointer_array_get_pointer(
-                               &trace_chunk->files, 0);
-               DBG("Unlink file: %s", path);
-               status = lttng_trace_chunk_unlink_file(trace_chunk, path);
-               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
-                       ERR("Error unlinking file '%s' when deleting chunk", path);
-                       ret = -1;
-                       goto end;
-               }
-       }
-end:
-       return ret;
-}
-
-static
-int lttng_trace_chunk_delete_post_release_owner(
-               struct lttng_trace_chunk *trace_chunk)
-{
-       enum lttng_trace_chunk_status status;
-       size_t i, count;
-       int ret = 0;
-
-       ret = lttng_trace_chunk_delete_post_release_user(trace_chunk);
-       if (ret) {
-               goto end;
-       }
-
-       DBG("Trace chunk \"delete\" close command post-release (Owner)");
-
-       LTTNG_ASSERT(trace_chunk->session_output_directory);
-       LTTNG_ASSERT(trace_chunk->chunk_directory);
-
-       /* Remove empty directories. */
-       count = lttng_dynamic_pointer_array_get_count(
-                       &trace_chunk->top_level_directories);
-
-       for (i = 0; i < count; i++) {
-               const char *top_level_name =
-                               lttng_dynamic_pointer_array_get_pointer(
-                                       &trace_chunk->top_level_directories, i);
-
-               status = lttng_trace_chunk_remove_subdirectory_recursive(trace_chunk, top_level_name);
-               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
-                       ERR("Error recursively removing subdirectory '%s' file when deleting chunk",
-                                       top_level_name);
-                       ret = -1;
-                       break;
-               }
-       }
-       if (!ret) {
-               lttng_directory_handle_put(trace_chunk->chunk_directory);
-               trace_chunk->chunk_directory = NULL;
-
-               if (trace_chunk->path && trace_chunk->path[0] != '\0') {
-                       status = lttng_directory_handle_remove_subdirectory(
-                                       trace_chunk->session_output_directory,
-                                       trace_chunk->path);
-                       if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
-                               ERR("Error removing subdirectory '%s' file when deleting chunk",
-                                       trace_chunk->path);
-                               ret = -1;
-                       }
-               }
-       }
-       free(trace_chunk->path);
-       trace_chunk->path = NULL;
-end:
-       return ret;
-}
-
-/*
- * For local files, session and consumer daemons all run the delete hook. The
- * consumer daemons have the list of files to unlink, and technically the
- * session daemon is the owner of the chunk. Unlink all files owned by each
- * consumer daemon.
- */
-static
-int lttng_trace_chunk_delete_post_release(
-               struct lttng_trace_chunk *trace_chunk)
-{
-       if (!trace_chunk->chunk_directory) {
-               return 0;
-       }
-
-       if (trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER) {
-               return lttng_trace_chunk_delete_post_release_owner(trace_chunk);
-       } else {
-               return lttng_trace_chunk_delete_post_release_user(trace_chunk);
-       }
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command(
-               struct lttng_trace_chunk *chunk,
-               enum lttng_trace_chunk_command_type *command_type)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->close_command.is_set) {
-               *command_type = chunk->close_command.value;
-               status = LTTNG_TRACE_CHUNK_STATUS_OK;
-       } else {
-               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
-       }
-       pthread_mutex_unlock(&chunk->lock);
-       return status;
-}
-
-enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
-               struct lttng_trace_chunk *chunk,
-               enum lttng_trace_chunk_command_type close_command)
-{
-       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
-
-       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;
-       }
-
-       pthread_mutex_lock(&chunk->lock);
-       if (chunk->close_command.is_set) {
-               DBG("Overriding trace chunk close command from \"%s\" to \"%s\"",
-                               close_command_names[chunk->close_command.value],
-                               close_command_names[close_command]);
-       } else {
-               DBG("Setting trace chunk close command to \"%s\"",
-                               close_command_names[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;
-}
-
-const char *lttng_trace_chunk_command_type_get_name(
-               enum lttng_trace_chunk_command_type command)
-{
-       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();
-       }
-}
-
-bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
-               const struct lttng_trace_chunk *chunk_b)
-{
-       bool equal = false;
-
-       if (chunk_a == chunk_b) {
-               equal = true;
-               goto end;
-       }
-
-       if (!!chunk_a ^ !!chunk_b) {
-               goto end;
-       }
-
-       if (chunk_a->id.is_set ^ chunk_a->id.is_set) {
-               /* One id is set and not the other, thus they are not equal. */
-               goto end;
-       }
-
-       if (!chunk_a->id.is_set) {
-               /* Both ids are unset. */
-               equal = true;
-       } else {
-               equal = chunk_a->id.value == chunk_b->id.value;
-       }
-
-end:
-       return equal;
-}
-
-bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk)
-{
-       return urcu_ref_get_unless_zero(&chunk->ref);
-}
-
-static
-void free_lttng_trace_chunk_registry_element(struct rcu_head *node)
-{
-       struct lttng_trace_chunk_registry_element *element =
-                       container_of(node, typeof(*element), rcu_node);
-
-       lttng_trace_chunk_fini(&element->chunk);
-       free(element);
-}
-
-static
-void lttng_trace_chunk_release(struct urcu_ref *ref)
-{
-       struct lttng_trace_chunk *chunk = container_of(ref, typeof(*chunk),
-                       ref);
-
-       if (chunk->close_command.is_set) {
-               if (close_command_post_release_funcs[
-                               chunk->close_command.value](chunk)) {
-                       ERR("Trace chunk post-release command %s has failed.",
-                                       close_command_names[chunk->close_command.value]);
-               }
-       }
-
-       if (chunk->in_registry_element) {
-               struct lttng_trace_chunk_registry_element *element;
-
-               element = container_of(chunk, typeof(*element), chunk);
-               if (element->registry) {
-                       rcu_read_lock();
-                       cds_lfht_del(element->registry->ht,
-                                       &element->trace_chunk_registry_ht_node);
-                       rcu_read_unlock();
-                       call_rcu(&element->rcu_node,
-                                       free_lttng_trace_chunk_registry_element);
-               } else {
-                       /* Never published, can be free'd immediately. */
-                       free_lttng_trace_chunk_registry_element(
-                                       &element->rcu_node);
-               }
-       } else {
-               /* Not RCU-protected, free immediately. */
-               lttng_trace_chunk_fini(chunk);
-               free(chunk);
-       }
-}
-
-void lttng_trace_chunk_put(struct lttng_trace_chunk *chunk)
-{
-       if (!chunk) {
-               return;
-       }
-       LTTNG_ASSERT(chunk->ref.refcount);
-       urcu_ref_put(&chunk->ref, lttng_trace_chunk_release);
-}
-
-struct lttng_trace_chunk_registry *lttng_trace_chunk_registry_create(void)
-{
-       struct lttng_trace_chunk_registry *registry;
-
-       registry = zmalloc(sizeof(*registry));
-       if (!registry) {
-               goto end;
-       }
-
-       registry->ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
-                       CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
-       if (!registry->ht) {
-               goto error;
-       }
-end:
-       return registry;
-error:
-       lttng_trace_chunk_registry_destroy(registry);
-       return NULL;
-}
-
-void lttng_trace_chunk_registry_destroy(
-               struct lttng_trace_chunk_registry *registry)
-{
-       if (!registry) {
-               return;
-       }
-       if (registry->ht) {
-               int ret = cds_lfht_destroy(registry->ht, NULL);
-               LTTNG_ASSERT(!ret);
-       }
-       free(registry);
-}
-
-static
-struct lttng_trace_chunk_registry_element *
-lttng_trace_chunk_registry_element_create_from_chunk(
-               struct lttng_trace_chunk *chunk, uint64_t session_id)
-{
-       struct lttng_trace_chunk_registry_element *element =
-                       zmalloc(sizeof(*element));
-
-       if (!element) {
-               goto end;
-       }
-       cds_lfht_node_init(&element->trace_chunk_registry_ht_node);
-       element->session_id = session_id;
-
-       element->chunk = *chunk;
-       lttng_trace_chunk_init(&element->chunk);
-       if (chunk->session_output_directory) {
-               /* Transferred ownership. */
-               element->chunk.session_output_directory =
-                               chunk->session_output_directory;
-               chunk->session_output_directory = NULL;
-       }
-       if (chunk->chunk_directory) {
-               /* Transferred ownership. */
-               element->chunk.chunk_directory = chunk->chunk_directory;
-               chunk->chunk_directory = NULL;
-       }
-       /*
-        * The original chunk becomes invalid; the name and path attributes are
-        * transferred to the new chunk instance.
-        */
-       chunk->name = NULL;
-       chunk->path = NULL;
-       element->chunk.fd_tracker = chunk->fd_tracker;
-       element->chunk.in_registry_element = true;
-end:
-       return element;
-}
-
-struct lttng_trace_chunk *
-lttng_trace_chunk_registry_publish_chunk(
-               struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, struct lttng_trace_chunk *chunk)
-{
-       struct lttng_trace_chunk_registry_element *element;
-       unsigned long element_hash;
-
-       pthread_mutex_lock(&chunk->lock);
-       element = lttng_trace_chunk_registry_element_create_from_chunk(chunk,
-                       session_id);
-       pthread_mutex_unlock(&chunk->lock);
-       if (!element) {
-               goto end;
-       }
-       /*
-        * chunk is now invalid, the only valid operation is a 'put' from the
-        * caller.
-        */
-       chunk = NULL;
-       element_hash = lttng_trace_chunk_registry_element_hash(element);
-
-       rcu_read_lock();
-       while (1) {
-               struct cds_lfht_node *published_node;
-               struct lttng_trace_chunk *published_chunk;
-               struct lttng_trace_chunk_registry_element *published_element;
-
-               published_node = cds_lfht_add_unique(registry->ht,
-                               element_hash,
-                               lttng_trace_chunk_registry_element_match,
-                               element,
-                               &element->trace_chunk_registry_ht_node);
-               if (published_node == &element->trace_chunk_registry_ht_node) {
-                       /* Successfully published the new element. */
-                       element->registry = registry;
-                       /* Acquire a reference for the caller. */
-                       if (lttng_trace_chunk_get(&element->chunk)) {
-                               break;
-                       } else {
-                               /*
-                                * Another thread concurrently unpublished the
-                                * trace chunk. This is currently unexpected.
-                                *
-                                * Re-attempt to publish.
-                                */
-                               ERR("Attempt to publish a trace chunk to the chunk registry raced with a trace chunk deletion");
-                               continue;
-                       }
-               }
-
-               /*
-                * An equivalent trace chunk was published before this trace
-                * chunk. Attempt to acquire a reference to the one that was
-                * already published and release the reference to the copy we
-                * created if successful.
-                */
-               published_element = container_of(published_node,
-                               typeof(*published_element),
-                               trace_chunk_registry_ht_node);
-               published_chunk = &published_element->chunk;
-               if (lttng_trace_chunk_get(published_chunk)) {
-                       lttng_trace_chunk_put(&element->chunk);
-                       element = published_element;
-                       break;
-               }
-               /*
-                * A reference to the previously published trace chunk could not
-                * be acquired. Hence, retry to publish our copy of the trace 
-                * chunk.
-                */
-       }
-       rcu_read_unlock();
-end:
-       return element ? &element->chunk : NULL;
-}
-
-/*
- * Note that the caller must be registered as an RCU thread.
- * However, it does not need to hold the RCU read lock. The RCU read lock is
- * acquired to perform the look-up in the registry's hash table and held until
- * after a reference to the "found" trace chunk is acquired.
- *
- * IOW, holding a reference guarantees the existence of the object for the
- * caller.
- */
-static
-struct lttng_trace_chunk *_lttng_trace_chunk_registry_find_chunk(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, uint64_t *chunk_id)
-{
-       const struct lttng_trace_chunk_registry_element target_element = {
-               .chunk.id.is_set = !!chunk_id,
-               .chunk.id.value = chunk_id ? *chunk_id : 0,
-               .session_id = session_id,
-       };
-       const unsigned long element_hash =
-                       lttng_trace_chunk_registry_element_hash(
-                               &target_element);
-       struct cds_lfht_node *published_node;
-       struct lttng_trace_chunk_registry_element *published_element;
-       struct lttng_trace_chunk *published_chunk = NULL;
-       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) {
-               goto end;
-       }
-
-       published_element = container_of(published_node,
-                       typeof(*published_element),
-                       trace_chunk_registry_ht_node);
-       if (lttng_trace_chunk_get(&published_element->chunk)) {
-               published_chunk = &published_element->chunk;
-       }
-end:
-       rcu_read_unlock();
-       return published_chunk;
-}
-
-struct lttng_trace_chunk *
-lttng_trace_chunk_registry_find_chunk(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id, uint64_t chunk_id)
-{
-       return _lttng_trace_chunk_registry_find_chunk(registry,
-                       session_id, &chunk_id);
-}
-
-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;
-}
-
-struct lttng_trace_chunk *
-lttng_trace_chunk_registry_find_anonymous_chunk(
-               const struct lttng_trace_chunk_registry *registry,
-               uint64_t session_id)
-{
-       return _lttng_trace_chunk_registry_find_chunk(registry,
-                       session_id, NULL);
-}
-
-unsigned int lttng_trace_chunk_registry_put_each_chunk(
-               const struct lttng_trace_chunk_registry *registry)
-{
-       struct cds_lfht_iter iter;
-       struct lttng_trace_chunk_registry_element *chunk_element;
-       unsigned int trace_chunks_left = 0;
-
-       DBG("Releasing trace chunk registry to all trace chunks");
-       rcu_read_lock();
-       cds_lfht_for_each_entry(registry->ht,
-                       &iter, chunk_element, trace_chunk_registry_ht_node) {
-               const char *chunk_id_str = "none";
-               char chunk_id_buf[MAX_INT_DEC_LEN(uint64_t)];
-
-               pthread_mutex_lock(&chunk_element->chunk.lock);
-               if (chunk_element->chunk.id.is_set) {
-                       int fmt_ret;
-
-                       fmt_ret = snprintf(chunk_id_buf, sizeof(chunk_id_buf),
-                                       "%" PRIu64,
-                                       chunk_element->chunk.id.value);
-                       if (fmt_ret < 0 || fmt_ret >= sizeof(chunk_id_buf)) {
-                               chunk_id_str = "formatting error";
-                       } else {
-                               chunk_id_str = chunk_id_buf;
-                       }
-               }
-
-               DBG("Releasing reference to trace chunk: session_id = %" PRIu64
-                               "chunk_id = %s, name = \"%s\", status = %s",
-                               chunk_element->session_id,
-                               chunk_id_str,
-                               chunk_element->chunk.name ? : "none",
-                               chunk_element->chunk.close_command.is_set ?
-                                               "open" : "closed");
-               pthread_mutex_unlock(&chunk_element->chunk.lock);
-               lttng_trace_chunk_put(&chunk_element->chunk);
-               trace_chunks_left++;
-       }
-       rcu_read_unlock();
-       DBG("Released reference to %u trace chunks in %s()", trace_chunks_left,
-                       __FUNCTION__);
-
-       return trace_chunks_left;
-}
This page took 0.044406 seconds and 4 git commands to generate.