X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ftrace-chunk.c;h=20dbd0a5ea933a853d328332d4c04def960fd917;hp=29977cabb1ae48e7ab015e717dc38173fcfd93d8;hb=87cee602585868bc895eec98a38c08964c08511d;hpb=6def6cd7c0d7fc16c679898ccf170d8a45d68ab4 diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c index 29977cabb..20dbd0a5e 100644 --- a/src/common/trace-chunk.c +++ b/src/common/trace-chunk.c @@ -66,6 +66,7 @@ struct chunk_credentials { struct lttng_credentials user; }; +/* NOTE: Make sure to update lttng_trace_chunk_copy if you modify this. */ struct lttng_trace_chunk { pthread_mutex_t lock; struct urcu_ref ref; @@ -73,6 +74,8 @@ struct lttng_trace_chunk { /* * First-level directories created within the trace chunk. * Elements are of type 'char *'. + * + * Only used by _owner_ mode chunks. */ struct lttng_dynamic_pointer_array top_level_directories; /* Is contained within an lttng_trace_chunk_registry_element? */ @@ -104,11 +107,13 @@ struct lttng_trace_chunk_registry { struct cds_lfht *ht; }; -const char *close_command_names[] = { +static const +char *close_command_names[] = { [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] = "move to completed chunk folder", }; +static const chunk_close_command close_command_funcs[] = { [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] = lttng_trace_chunk_move_to_completed, @@ -300,6 +305,72 @@ error: return NULL; } +LTTNG_HIDDEN +struct lttng_trace_chunk *lttng_trace_chunk_copy( + struct lttng_trace_chunk *source_chunk) +{ + struct lttng_trace_chunk *new_chunk = lttng_trace_chunk_allocate(); + + if (!new_chunk) { + goto end; + } + + pthread_mutex_lock(&source_chunk->lock); + /* + * A new chunk is always a user; it shall create no new trace + * subdirectories. + */ + new_chunk->mode = (typeof(new_chunk->mode)) { + .is_set = true, + .value = TRACE_CHUNK_MODE_USER, + }; + /* + * top_level_directories is not copied as it is never used + * by _user_ mode chunks. + */ + /* The new chunk is not part of a registry (yet, at least). */ + new_chunk->in_registry_element = false; + new_chunk->name_overridden = source_chunk->name_overridden; + if (source_chunk->name) { + new_chunk->name = strdup(source_chunk->name); + if (!new_chunk->name) { + ERR("Failed to copy source trace chunk name in %s()", + __FUNCTION__); + goto error_unlock; + } + } + new_chunk->id = source_chunk->id; + new_chunk->timestamp_creation = source_chunk->timestamp_creation; + new_chunk->timestamp_close = source_chunk->timestamp_close; + new_chunk->credentials = source_chunk->credentials; + if (source_chunk->session_output_directory.is_set) { + if (lttng_directory_handle_copy( + &source_chunk->session_output_directory.value, + &new_chunk->session_output_directory.value)) { + goto error_unlock; + } else { + new_chunk->session_output_directory.is_set = true; + } + } + if (source_chunk->chunk_directory.is_set) { + if (lttng_directory_handle_copy( + &source_chunk->chunk_directory.value, + &new_chunk->chunk_directory.value)) { + goto error_unlock; + } else { + new_chunk->chunk_directory.is_set = true; + } + } + new_chunk->close_command = source_chunk->close_command; + pthread_mutex_unlock(&source_chunk->lock); +end: + return new_chunk; +error_unlock: + pthread_mutex_unlock(&source_chunk->lock); + lttng_trace_chunk_put(new_chunk); + return NULL; +} + LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_id( struct lttng_trace_chunk *chunk, uint64_t *id) @@ -904,6 +975,7 @@ void lttng_trace_chunk_move_to_completed(struct lttng_trace_chunk *trace_chunk) creation_timestamp, NULL); if (!directory_to_rename) { ERR("Failed to generate initial trace chunk name while renaming trace chunk"); + goto end; } free_directory_to_rename = true; } @@ -1197,7 +1269,7 @@ lttng_trace_chunk_registry_publish_chunk( * * Re-attempt to publish. */ - ERR("Attemp to publish a trace chunk to the chunk registry raced with a trace chunk deletion"); + ERR("Attempt to publish a trace chunk to the chunk registry raced with a trace chunk deletion"); continue; } } @@ -1287,6 +1359,41 @@ lttng_trace_chunk_registry_find_chunk( session_id, &chunk_id); } +LTTNG_HIDDEN +int lttng_trace_chunk_registry_chunk_exists( + const struct lttng_trace_chunk_registry *registry, + uint64_t session_id, uint64_t chunk_id, bool *chunk_exists) +{ + int ret = 0; + const struct lttng_trace_chunk_registry_element target_element = { + .chunk.id.is_set = true, + .chunk.id.value = chunk_id, + .session_id = session_id, + }; + const unsigned long element_hash = + lttng_trace_chunk_registry_element_hash( + &target_element); + struct cds_lfht_node *published_node; + struct cds_lfht_iter iter; + + rcu_read_lock(); + cds_lfht_lookup(registry->ht, + element_hash, + lttng_trace_chunk_registry_element_match, + &target_element, + &iter); + published_node = cds_lfht_iter_get_node(&iter); + if (!published_node) { + *chunk_exists = false; + goto end; + } + + *chunk_exists = !cds_lfht_is_node_deleted(published_node); +end: + rcu_read_unlock(); + return ret; +} + LTTNG_HIDDEN struct lttng_trace_chunk * lttng_trace_chunk_registry_find_anonymous_chunk(