Fix: common: abort on rotation after time manipulation
[lttng-tools.git] / src / common / trace-chunk.c
index 601d402e0843639ac9457269b4916d2ace8dce29..bed6b73afb5d7cd79b3fab13552cb5d75a7df808 100644 (file)
@@ -84,8 +84,14 @@ struct lttng_trace_chunk {
        char *name;
        /* 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;
        LTTNG_OPTIONAL(struct lttng_directory_handle) session_output_directory;
        LTTNG_OPTIONAL(struct lttng_directory_handle) chunk_directory;
@@ -432,11 +438,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);
@@ -840,7 +855,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_open_file(
                        chunk->credentials.value.use_current_user ?
                                        NULL : &chunk->credentials.value.user);
        if (ret < 0) {
-               ERR("Failed to open file relative to trace chunk file_path = \"%s\", flags = %d, mode = %d",
+               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;
                goto end;
@@ -975,6 +990,7 @@ void lttng_trace_chunk_move_to_completed(struct lttng_trace_chunk *trace_chunk)
                                creation_timestamp, NULL);
                if (!directory_to_rename) {
                        ERR("Failed to generate initial trace chunk name while renaming trace chunk");
+                       goto end;
                }
                free_directory_to_rename = true;
        }
@@ -1268,7 +1284,7 @@ lttng_trace_chunk_registry_publish_chunk(
                                 *
                                 * Re-attempt to publish.
                                 */
-                               ERR("Attemp to publish a trace chunk to the chunk registry raced with a trace chunk deletion");
+                               ERR("Attempt to publish a trace chunk to the chunk registry raced with a trace chunk deletion");
                                continue;
                        }
                }
@@ -1358,6 +1374,41 @@ lttng_trace_chunk_registry_find_chunk(
                        session_id, &chunk_id);
 }
 
+LTTNG_HIDDEN
+int lttng_trace_chunk_registry_chunk_exists(
+               const struct lttng_trace_chunk_registry *registry,
+               uint64_t session_id, uint64_t chunk_id, bool *chunk_exists)
+{
+       int ret = 0;
+       const struct lttng_trace_chunk_registry_element target_element = {
+               .chunk.id.is_set = true,
+               .chunk.id.value = chunk_id,
+               .session_id = session_id,
+       };
+       const unsigned long element_hash =
+                       lttng_trace_chunk_registry_element_hash(
+                               &target_element);
+       struct cds_lfht_node *published_node;
+       struct cds_lfht_iter iter;
+
+       rcu_read_lock();
+       cds_lfht_lookup(registry->ht,
+                       element_hash,
+                       lttng_trace_chunk_registry_element_match,
+                       &target_element,
+                       &iter);
+       published_node = cds_lfht_iter_get_node(&iter);
+       if (!published_node) {
+               *chunk_exists = false;
+               goto end;
+       }
+
+       *chunk_exists = !cds_lfht_is_node_deleted(published_node);
+end:
+       rcu_read_unlock();
+       return ret;
+}
+
 LTTNG_HIDDEN
 struct lttng_trace_chunk *
 lttng_trace_chunk_registry_find_anonymous_chunk(
This page took 0.025149 seconds and 4 git commands to generate.