X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Ftrace-chunk.c;h=326d42ce2c6656c02f5d00cbba6359915536e5ab;hb=0e98551307eb5a7a59cc74982b386dc95f4c4f89;hp=266a02ee68e3933ea2533c70572c714098c4df45;hpb=a7ceb342d473cc37e00d74c45b04b5378965e055;p=lttng-tools.git diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c index 266a02ee6..326d42ce2 100644 --- a/src/common/trace-chunk.c +++ b/src/common/trace-chunk.c @@ -15,27 +15,28 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include -#include -#include #include #include #include +#include +#include +#include /* * Two ISO 8601-compatible timestamps, separated by a hypen, followed an @@ -60,6 +61,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); @@ -104,6 +111,14 @@ struct lttng_trace_chunk { 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. */ @@ -135,6 +150,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 @@ -342,6 +361,16 @@ error: return NULL; } +LTTNG_HIDDEN +void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk, + struct fd_tracker *fd_tracker) +{ + assert(!chunk->session_output_directory); + assert(!chunk->chunk_directory); + assert(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0); + chunk->fd_tracker = fd_tracker; +} + LTTNG_HIDDEN struct lttng_trace_chunk *lttng_trace_chunk_copy( struct lttng_trace_chunk *source_chunk) @@ -403,6 +432,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_copy( 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; @@ -973,6 +1003,31 @@ end: return status; } +LTTNG_HIDDEN +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); + + assert(reference_acquired); + *handle = chunk->session_output_directory; + } +end: + pthread_mutex_unlock(&chunk->lock); + return status; +} + LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle( struct lttng_trace_chunk *chunk, @@ -1398,6 +1453,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, @@ -1600,6 +1766,7 @@ lttng_trace_chunk_registry_element_create_from_chunk( */ chunk->name = NULL; chunk->path = NULL; + element->chunk.fd_tracker = chunk->fd_tracker; element->chunk.in_registry_element = true; end: return element; @@ -1787,8 +1954,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;