From: Mathieu Desnoyers Date: Thu, 12 Dec 2019 18:05:15 +0000 (-0500) Subject: trace-chunk: implement no-op and delete release commands X-Git-Tag: v2.12.0-rc1~122 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=8ced4811fde7e82f71e55a9bdd21cd7ea96019e6 trace-chunk: implement no-op and delete release commands The delete release command is used by clear. The no-op command is used for implicit session rotations launched by the destroy command. Signed-off-by: Mathieu Desnoyers Change-Id: I49ea666ff77d3e5f6ac4b25977313ea18e10be62 Signed-off-by: Jérémie Galarneau --- diff --git a/src/common/trace-chunk-registry.h b/src/common/trace-chunk-registry.h index afe942ba9..b04609c32 100644 --- a/src/common/trace-chunk-registry.h +++ b/src/common/trace-chunk-registry.h @@ -107,6 +107,6 @@ lttng_trace_chunk_registry_find_anonymous_chunk( LTTNG_HIDDEN unsigned int lttng_trace_chunk_registry_put_each_chunk( - struct lttng_trace_chunk_registry *registry); + const struct lttng_trace_chunk_registry *registry); #endif /* LTTNG_TRACE_CHUNK_REGISTRY_H */ diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c index 266a02ee6..cd81909ff 100644 --- a/src/common/trace-chunk.c +++ b/src/common/trace-chunk.c @@ -60,6 +60,12 @@ 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); @@ -135,6 +141,10 @@ 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 @@ -1398,6 +1408,117 @@ end: 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)"); + + assert(trace_chunk->session_output_directory); + 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); + } +} + LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command( struct lttng_trace_chunk *chunk, @@ -1787,8 +1908,9 @@ lttng_trace_chunk_registry_find_anonymous_chunk( session_id, NULL); } +LTTNG_HIDDEN unsigned int lttng_trace_chunk_registry_put_each_chunk( - struct lttng_trace_chunk_registry *registry) + const struct lttng_trace_chunk_registry *registry) { struct cds_lfht_iter iter; struct lttng_trace_chunk_registry_element *chunk_element;