X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsession.c;h=0da2058fdf28dbbef05f0d2490cfbf49a089a294;hp=abac2404f04bdda9b2c3a94ec8507c950f3a427a;hb=ccbdaca404a66cf124ec7e4926b1507327f6d165;hpb=d295668767ac8234e83984e1812d342d03293d88 diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index abac2404f..0da2058fd 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -39,6 +39,17 @@ #include "utils.h" #include "trace-ust.h" #include "timer.h" +#include "cmd.h" + +struct ltt_session_destroy_notifier_element { + ltt_session_destroy_notifier notifier; + void *user_data; +}; + +struct ltt_session_clear_notifier_element { + ltt_session_clear_notifier notifier; + void *user_data; +}; /* * NOTES: @@ -245,7 +256,7 @@ void session_get_net_consumer_ports(const struct ltt_session *session, * The caller must hold the session lock. */ struct lttng_trace_archive_location *session_get_trace_archive_location( - struct ltt_session *session) + const struct ltt_session *session) { int ret; struct lttng_trace_archive_location *location = NULL; @@ -256,15 +267,15 @@ struct lttng_trace_archive_location *session_get_trace_archive_location( goto end; } - ret = asprintf(&chunk_path, "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY "/%s", - session_get_base_path(session), - session->last_archived_chunk_name); - if (ret == -1) { - goto end; - } - switch (session_get_consumer_destination_type(session)) { case CONSUMER_DST_LOCAL: + ret = asprintf(&chunk_path, + "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY "/%s", + session_get_base_path(session), + session->last_archived_chunk_name); + if (ret == -1) { + goto end; + } location = lttng_trace_archive_location_local_create( chunk_path); break; @@ -280,7 +291,7 @@ struct lttng_trace_archive_location *session_get_trace_archive_location( location = lttng_trace_archive_location_relay_create( hostname, LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP, - control_port, data_port, chunk_path); + control_port, data_port, session->last_chunk_path); break; } default: @@ -296,7 +307,7 @@ end: * * The session list lock must be held. */ -int ltt_sessions_ht_alloc(void) +static int ltt_sessions_ht_alloc(void) { int ret = 0; @@ -417,15 +428,13 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, struct lttng_trace_chunk *new_trace_chunk, struct lttng_trace_chunk **_current_trace_chunk) { - int ret; + int ret = 0; unsigned int i, refs_to_acquire = 0, refs_acquired = 0, refs_to_release = 0; struct cds_lfht_iter iter; struct consumer_socket *socket; struct lttng_trace_chunk *current_trace_chunk; uint64_t chunk_id; enum lttng_trace_chunk_status chunk_status; - const uint64_t relayd_id = session->consumer->net_seq_index; - const bool is_local_trace = relayd_id == -1ULL; rcu_read_lock(); /* @@ -465,6 +474,12 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, } if (session->ust_session) { + const uint64_t relayd_id = + session->ust_session->consumer->net_seq_index; + const bool is_local_trace = + session->ust_session->consumer->type == + CONSUMER_DST_LOCAL; + session->ust_session->current_trace_chunk = new_trace_chunk; if (is_local_trace) { enum lttng_error_code ret_error_code; @@ -472,7 +487,6 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, ret_error_code = ust_app_create_channel_subdirectories( session->ust_session); if (ret_error_code != LTTNG_OK) { - ret = -ret_error_code; goto error; } } @@ -482,7 +496,8 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, pthread_mutex_lock(socket->lock); ret = consumer_create_trace_chunk(socket, relayd_id, - session->id, new_trace_chunk); + session->id, new_trace_chunk, + DEFAULT_UST_TRACE_DIR); pthread_mutex_unlock(socket->lock); if (ret) { goto error; @@ -490,6 +505,12 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, } } if (session->kernel_session) { + const uint64_t relayd_id = + session->kernel_session->consumer->net_seq_index; + const bool is_local_trace = + session->kernel_session->consumer->type == + CONSUMER_DST_LOCAL; + session->kernel_session->current_trace_chunk = new_trace_chunk; if (is_local_trace) { enum lttng_error_code ret_error_code; @@ -497,7 +518,6 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, ret_error_code = kernel_create_channel_subdirectories( session->kernel_session); if (ret_error_code != LTTNG_OK) { - ret = -ret_error_code; goto error; } } @@ -507,7 +527,8 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, pthread_mutex_lock(socket->lock); ret = consumer_create_trace_chunk(socket, relayd_id, - session->id, new_trace_chunk); + session->id, new_trace_chunk, + DEFAULT_KERNEL_TRACE_DIR); pthread_mutex_unlock(socket->lock); if (ret) { goto error; @@ -549,34 +570,9 @@ error: goto end_no_move; } -static -bool output_supports_trace_chunks(const struct ltt_session *session) -{ - if (session->consumer->type == CONSUMER_DST_LOCAL) { - return true; - } else { - struct consumer_output *output; - - if (session->ust_session) { - output = session->ust_session->consumer; - } else if (session->kernel_session) { - output = session->kernel_session->consumer; - } else { - abort(); - } - - if (output->relay_major_version > 2) { - return true; - } else if (output->relay_major_version == 2 && - output->relay_minor_version >= 11) { - return true; - } - } - return false; -} - struct lttng_trace_chunk *session_create_new_trace_chunk( - struct ltt_session *session, + const struct ltt_session *session, + const struct consumer_output *consumer_output_override, const char *session_base_path_override, const char *chunk_name_override) { @@ -584,16 +580,28 @@ struct lttng_trace_chunk *session_create_new_trace_chunk( struct lttng_trace_chunk *trace_chunk = NULL; enum lttng_trace_chunk_status chunk_status; const time_t chunk_creation_ts = time(NULL); - const bool is_local_trace = - session->consumer->type == CONSUMER_DST_LOCAL; - const char *base_path = session_base_path_override ? : - session_get_base_path(session); - struct lttng_directory_handle session_output_directory; + bool is_local_trace; + const char *base_path; + struct lttng_directory_handle *session_output_directory = NULL; const struct lttng_credentials session_credentials = { .uid = session->uid, .gid = session->gid, }; uint64_t next_chunk_id; + const struct consumer_output *output; + + if (consumer_output_override) { + output = consumer_output_override; + } else { + assert(session->ust_session || session->kernel_session); + output = session->ust_session ? + session->ust_session->consumer : + session->kernel_session->consumer; + } + + is_local_trace = output->type == CONSUMER_DST_LOCAL; + base_path = session_base_path_override ? : + consumer_output_get_base_path(output); if (chunk_creation_ts == (time_t) -1) { PERROR("Failed to sample time while creation session \"%s\" trace chunk", @@ -601,9 +609,6 @@ struct lttng_trace_chunk *session_create_new_trace_chunk( goto error; } - if (!output_supports_trace_chunks(session)) { - goto end; - } next_chunk_id = session->most_recent_chunk_id.is_set ? session->most_recent_chunk_id.value + 1 : 0; @@ -642,27 +647,30 @@ struct lttng_trace_chunk *session_create_new_trace_chunk( if (ret) { goto error; } - ret = lttng_directory_handle_init(&session_output_directory, - base_path); - if (ret) { + session_output_directory = lttng_directory_handle_create(base_path); + if (!session_output_directory) { goto error; } chunk_status = lttng_trace_chunk_set_as_owner(trace_chunk, - &session_output_directory); - lttng_directory_handle_fini(&session_output_directory); + session_output_directory); + lttng_directory_handle_put(session_output_directory); + session_output_directory = NULL; if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { goto error; } end: return trace_chunk; error: + lttng_directory_handle_put(session_output_directory); lttng_trace_chunk_put(trace_chunk); trace_chunk = NULL; goto end; } -int session_close_trace_chunk(const struct ltt_session *session, - struct lttng_trace_chunk *trace_chunk) +int session_close_trace_chunk(struct ltt_session *session, + struct lttng_trace_chunk *trace_chunk, + enum lttng_trace_chunk_command_type close_command, + char *closed_trace_chunk_path) { int ret = 0; bool error_occurred = false; @@ -671,6 +679,13 @@ int session_close_trace_chunk(const struct ltt_session *session, enum lttng_trace_chunk_status chunk_status; const time_t chunk_close_timestamp = time(NULL); + chunk_status = lttng_trace_chunk_set_close_command( + trace_chunk, close_command); + if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { + ret = -1; + goto end; + } + if (chunk_close_timestamp == (time_t) -1) { ERR("Failed to sample the close timestamp of the current trace chunk of session \"%s\"", session->name); @@ -687,14 +702,17 @@ int session_close_trace_chunk(const struct ltt_session *session, } if (session->ust_session) { + const uint64_t relayd_id = + session->ust_session->consumer->net_seq_index; + cds_lfht_for_each_entry( session->ust_session->consumer->socks->ht, &iter, socket, node.node) { pthread_mutex_lock(socket->lock); ret = consumer_close_trace_chunk(socket, - session->consumer->net_seq_index, + relayd_id, session->id, - trace_chunk); + trace_chunk, closed_trace_chunk_path); pthread_mutex_unlock(socket->lock); if (ret) { ERR("Failed to close trace chunk on user space consumer"); @@ -703,14 +721,17 @@ int session_close_trace_chunk(const struct ltt_session *session, } } if (session->kernel_session) { + const uint64_t relayd_id = + session->kernel_session->consumer->net_seq_index; + cds_lfht_for_each_entry( session->kernel_session->consumer->socks->ht, &iter, socket, node.node) { pthread_mutex_lock(socket->lock); ret = consumer_close_trace_chunk(socket, - session->consumer->net_seq_index, + relayd_id, session->id, - trace_chunk); + trace_chunk, closed_trace_chunk_path); pthread_mutex_unlock(socket->lock); if (ret) { ERR("Failed to close trace chunk on kernel consumer"); @@ -737,6 +758,41 @@ int session_set_trace_chunk(struct ltt_session *session, current_trace_chunk); } +static +void session_notify_destruction(const struct ltt_session *session) +{ + size_t i; + const size_t count = lttng_dynamic_array_get_count( + &session->destroy_notifiers); + + for (i = 0; i < count; i++) { + const struct ltt_session_destroy_notifier_element *element = + lttng_dynamic_array_get_element( + &session->destroy_notifiers, i); + + element->notifier(session, element->user_data); + } +} + +/* + * Fire each clear notifier once, and remove them from the array. + */ +void session_notify_clear(struct ltt_session *session) +{ + size_t i; + const size_t count = lttng_dynamic_array_get_count( + &session->clear_notifiers); + + for (i = 0; i < count; i++) { + const struct ltt_session_clear_notifier_element *element = + lttng_dynamic_array_get_element( + &session->clear_notifiers, i); + + element->notifier(session, element->user_data); + } + lttng_dynamic_array_clear(&session->clear_notifiers); +} + static void session_release(struct urcu_ref *ref) { @@ -744,29 +800,17 @@ void session_release(struct urcu_ref *ref) struct ltt_ust_session *usess; struct ltt_kernel_session *ksess; struct ltt_session *session = container_of(ref, typeof(*session), ref); + const bool session_published = session->published; assert(!session->chunk_being_archived); usess = session->ust_session; ksess = session->kernel_session; - if (session->current_trace_chunk) { - ret = session_close_trace_chunk(session, session->current_trace_chunk); - if (ret) { - ERR("Failed to close the current trace chunk of session \"%s\" during its release", - session->name); - } - ret = _session_set_trace_chunk_no_lock_check(session, NULL, NULL); - if (ret) { - ERR("Failed to release the current trace chunk of session \"%s\" during its release", - session->name); - } - } - /* Clean kernel session teardown */ + /* Clean kernel session teardown, keeping data for destroy notifier. */ kernel_destroy_session(ksess); - session->kernel_session = NULL; - /* UST session teardown */ + /* UST session teardown, keeping data for destroy notifier. */ if (usess) { /* Close any relayd session */ consumer_output_send_destroy_relayd(usess->consumer); @@ -777,9 +821,8 @@ void session_release(struct urcu_ref *ref) ERR("Error in ust_app_destroy_trace_all"); } - /* Clean up the rest. */ + /* Clean up the rest, keeping destroy notifier data. */ trace_ust_destroy_session(usess); - session->ust_session = NULL; } /* @@ -793,19 +836,36 @@ void session_release(struct urcu_ref *ref) DBG("Destroying session %s (id %" PRIu64 ")", session->name, session->id); - consumer_output_put(session->consumer); snapshot_destroy(&session->snapshot); pthread_mutex_destroy(&session->lock); - if (session->published) { + if (session_published) { ASSERT_LOCKED(ltt_session_list.lock); del_session_list(session); del_session_ht(session); - pthread_cond_broadcast(<t_session_list.removal_cond); } + session_notify_destruction(session); + + consumer_output_put(session->consumer); + kernel_free_session(ksess); + session->kernel_session = NULL; + if (usess) { + trace_ust_free_session(usess); + session->ust_session = NULL; + } + lttng_dynamic_array_reset(&session->destroy_notifiers); + lttng_dynamic_array_reset(&session->clear_notifiers); free(session->last_archived_chunk_name); + free(session->base_path); free(session); + if (session_published) { + /* + * Broadcast after free-ing to ensure the memory is + * reclaimed before the main thread exits. + */ + pthread_cond_broadcast(<t_session_list.removal_cond); + } } /* @@ -852,6 +912,30 @@ void session_destroy(struct ltt_session *session) session_put(session); } +int session_add_destroy_notifier(struct ltt_session *session, + ltt_session_destroy_notifier notifier, void *user_data) +{ + const struct ltt_session_destroy_notifier_element element = { + .notifier = notifier, + .user_data = user_data + }; + + return lttng_dynamic_array_add_element(&session->destroy_notifiers, + &element); +} + +int session_add_clear_notifier(struct ltt_session *session, + ltt_session_clear_notifier notifier, void *user_data) +{ + const struct ltt_session_clear_notifier_element element = { + .notifier = notifier, + .user_data = user_data + }; + + return lttng_dynamic_array_add_element(&session->clear_notifiers, + &element); +} + /* * Return a ltt_session structure ptr that matches name. If no session found, * NULL is returned. This must be called with the session list lock held using @@ -940,6 +1024,12 @@ enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid, goto error; } + lttng_dynamic_array_init(&new_session->destroy_notifiers, + sizeof(struct ltt_session_destroy_notifier_element), + NULL); + lttng_dynamic_array_init(&new_session->clear_notifiers, + sizeof(struct ltt_session_clear_notifier_element), + NULL); urcu_ref_init(&new_session->ref); pthread_mutex_init(&new_session->lock, NULL); @@ -996,6 +1086,7 @@ enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid, DEFAULT_SESSION_NAME, i, datetime); } + new_session->name_contains_creation_time = true; if (ret == -1 || ret >= sizeof(new_session->name)) { /* * Null-terminate in case the name is used @@ -1103,7 +1194,7 @@ int session_access_ok(struct ltt_session *session, uid_t uid, gid_t gid) * * Be careful of the result passed to this function. For instance, * on failure to launch a rotation, a client will expect the rotation - * state to be set to "NO_ROTATION". If an error occured while the + * state to be set to "NO_ROTATION". If an error occurred while the * rotation was "ONGOING", result should be set to "ERROR", which will * allow a client to report it. * @@ -1133,6 +1224,11 @@ int session_reset_rotation_state(struct ltt_session *session, chunk_id); lttng_trace_chunk_put(session->chunk_being_archived); session->chunk_being_archived = NULL; + /* + * Fire the clear reply notifiers if we are completing a clear + * rotation. + */ + session_notify_clear(session); } return ret; }