SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / src / common / trace-chunk.c
index f045b50a950988acac7c6a4f025e4fccb13f6d70..242d0f71ed8e698ccae7a78a86f118346de93f02 100644 (file)
@@ -1,18 +1,8 @@
 /*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <common/compat/directory-handle.h>
@@ -21,6 +11,7 @@
 #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-internal.h>
 #include <common/hashtable/hashtable.h>
 #include <common/hashtable/utils.h>
@@ -106,8 +97,14 @@ struct lttng_trace_chunk {
        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;
@@ -371,7 +368,7 @@ void lttng_trace_chunk_fini(struct lttng_trace_chunk *chunk)
        }
        if (chunk->chunk_directory) {
                lttng_directory_handle_put(chunk->chunk_directory);
-               chunk->chunk_directory = NULL;
+               chunk->chunk_directory = NULL;
        }
        free(chunk->name);
        chunk->name = NULL;
@@ -409,9 +406,9 @@ 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] = {};
+       char chunk_creation_datetime_buf[16] = {};
        const char *chunk_creation_datetime_str = "(formatting error)";
-        struct tm timeinfo_buf, *timeinfo;
+       struct tm timeinfo_buf, *timeinfo;
 
        timeinfo = localtime_r(&chunk_creation_time, &timeinfo_buf);
        if (timeinfo) {
@@ -443,7 +440,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_create(
                        ERR("Failed to allocate trace chunk name storage");
                        goto error;
                }
-        }
+       }
        if (path) {
                chunk->path = strdup(path);
                if (!chunk->path) {
@@ -458,7 +455,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_create(
                }
        }
 
-        DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
+       DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
 end:
        return chunk;
 error:
@@ -608,11 +605,20 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp(
                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) {
-               ERR("Failed to set trace chunk close timestamp: close timestamp is before creation timestamp");
-               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
-               goto end;
+               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);
@@ -636,10 +642,10 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_name(
        enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
 
        pthread_mutex_lock(&chunk->lock);
-        if (name_overridden) {
+       if (name_overridden) {
                *name_overridden = chunk->name_overridden;
-        }
-        if (!chunk->name) {
+       }
+       if (!chunk->name) {
                status = LTTNG_TRACE_CHUNK_STATUS_NONE;
                goto end;
        }
@@ -775,7 +781,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                goto skip_move;
        }
 
-       if (old_path[0] != '\0' && path[0] != '\0') {
+       if (old_path && old_path[0] != '\0' && path[0] != '\0') {
                /* Rename chunk directory. */
                ret = lttng_directory_handle_rename_as_user(
                        chunk->session_output_directory,
@@ -791,9 +797,14 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                        status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
                        goto end;
                }
-               rename_directory = lttng_directory_handle_create_from_handle(
-                               path,
-                               chunk->session_output_directory);
+               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;
@@ -808,7 +819,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                 */
                chunk->chunk_directory = rename_directory;
                rename_directory = NULL;
-       } else if (old_path[0] == '\0') {
+       } else if (old_path && old_path[0] == '\0') {
                size_t i, count = lttng_dynamic_pointer_array_get_count(
                                &chunk->top_level_directories);
 
@@ -863,7 +874,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                 */
                chunk->chunk_directory = rename_directory;
                rename_directory = NULL;
-       } else {
+       } 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(
@@ -909,21 +920,20 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                        ERR("Error removing subdirectory '%s' file when deleting chunk",
                                old_path);
-                       ret = -1;
                        goto end;
                }
+       } else {
+               /* Unexpected !old_path && !path. */
+               status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT;
+               goto end;
        }
 
 skip_move:
-       if (path) {
-               new_path = strdup(path);
-               if (!new_path) {
-                       ERR("Failed to allocate new trace chunk path");
-                       status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
-                       goto end;
-               }
-       } else {
-               new_path = NULL;
+       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;
@@ -956,8 +966,8 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
        pthread_mutex_lock(&chunk->lock);
        if (chunk->credentials.is_set) {
                if (chunk->credentials.value.use_current_user) {
-                       credentials->uid = geteuid();
-                       credentials->gid = getegid();
+                       LTTNG_OPTIONAL_SET(&credentials->uid, geteuid());
+                       LTTNG_OPTIONAL_SET(&credentials->gid, getegid());
                } else {
                        *credentials = chunk->credentials.value.user;
                }
@@ -1035,7 +1045,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
                status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
                goto end;
        }
-       if (chunk->path[0] != '\0') {
+       if (chunk->path && chunk->path[0] != '\0') {
                ret = lttng_directory_handle_create_subdirectory_as_user(
                                session_output_directory,
                                chunk->path,
@@ -1049,9 +1059,14 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
                        goto end;
                }
                chunk_directory_handle =
-                               lttng_directory_handle_create_from_handle(
-                                       chunk->path,
-                                       session_output_directory);
+                               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;
@@ -1494,7 +1509,7 @@ end:
        return status;
 }
 
-LTTNG_HIDDEN
+static
 int lttng_trace_chunk_remove_subdirectory_recursive(struct lttng_trace_chunk *chunk,
                const char *path)
 {
@@ -1571,7 +1586,7 @@ int lttng_trace_chunk_move_to_completed_post_release(
 
        ret = lttng_directory_handle_create_subdirectory_as_user(
                        trace_chunk->session_output_directory,
-                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
+                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
                        DIR_CREATION_MODE,
                        !trace_chunk->credentials.value.use_current_user ?
                                        &trace_chunk->credentials.value.user :
@@ -1582,9 +1597,14 @@ int lttng_trace_chunk_move_to_completed_post_release(
                goto end;
        }
 
-       archived_chunks_directory = lttng_directory_handle_create_from_handle(
-                       DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
-                       trace_chunk->session_output_directory);
+       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;
@@ -1774,10 +1794,10 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command(
                DBG("Overriding trace chunk close command from \"%s\" to \"%s\"",
                                close_command_names[chunk->close_command.value],
                                close_command_names[close_command]);
-        } else {
+       } 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.
@@ -1808,6 +1828,32 @@ const char *lttng_trace_chunk_command_type_get_name(
        }
 }
 
+LTTNG_HIDDEN
+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) {
+               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;
+}
+
 LTTNG_HIDDEN
 bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk)
 {
@@ -1976,13 +2022,13 @@ lttng_trace_chunk_registry_publish_chunk(
                struct lttng_trace_chunk_registry_element *published_element;
 
                published_node = cds_lfht_add_unique(registry->ht,
-                               element_hash,
+                               element_hash,
                                lttng_trace_chunk_registry_element_match,
-                               element,
+                               element,
                                &element->trace_chunk_registry_ht_node);
                if (published_node == &element->trace_chunk_registry_ht_node) {
                        /* Successfully published the new element. */
-                       element->registry = registry;
+                       element->registry = registry;
                        /* Acquire a reference for the caller. */
                        if (lttng_trace_chunk_get(&element->chunk)) {
                                break;
@@ -2079,7 +2125,7 @@ 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,
+       return _lttng_trace_chunk_registry_find_chunk(registry,
                        session_id, &chunk_id);
 }
 
@@ -2124,7 +2170,7 @@ 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,
+       return _lttng_trace_chunk_registry_find_chunk(registry,
                        session_id, NULL);
 }
 
This page took 0.029336 seconds and 5 git commands to generate.