X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsession.c;h=0da2058fdf28dbbef05f0d2490cfbf49a089a294;hp=6c10aaeba9259286cdac4a43db72619d8a4e8f51;hb=ccbdaca404a66cf124ec7e4926b1507327f6d165;hpb=82b69413fa2d05d8643c4fb900b88f5d41206cfc diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index 6c10aaeba..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: @@ -67,13 +78,6 @@ static const char *forbidden_name_chars = "/"; /* Global hash table to keep the sessions, indexed by id. */ static struct lttng_ht *ltt_sessions_ht_by_id = NULL; -struct consumer_create_chunk_transaction { - struct consumer_socket *socket; - struct lttng_trace_chunk *new_chunk; - struct lttng_trace_chunk *previous_chunk; - bool new_chunk_created; -}; - /* * Validate the session name for forbidden characters. * @@ -252,18 +256,28 @@ 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; + char *chunk_path = NULL; - if (session->rotation_state != LTTNG_ROTATION_STATE_COMPLETED) { + if (session->rotation_state != LTTNG_ROTATION_STATE_COMPLETED || + !session->last_archived_chunk_name) { 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( - session->rotation_chunk.current_rotate_path); + chunk_path); break; case CONSUMER_DST_NET: { @@ -277,14 +291,14 @@ 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, - session->rotation_chunk.current_rotate_path); + control_port, data_port, session->last_chunk_path); break; } default: abort(); } end: + free(chunk_path); return location; } @@ -293,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; @@ -411,150 +425,140 @@ void session_unlock(struct ltt_session *session) static int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, - struct lttng_trace_chunk *new_trace_chunk) + 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; - unsigned int consumer_count = 0; - /* - * The maximum amount of consumers to reach is 3 - * (32/64 userspace + kernel). - */ - struct consumer_create_chunk_transaction transactions[3] = {}; struct cds_lfht_iter iter; struct consumer_socket *socket; - bool close_error_occured = false; - - if (new_trace_chunk) { - uint64_t chunk_id; - enum lttng_trace_chunk_status chunk_status = - lttng_trace_chunk_get_id(new_trace_chunk, - &chunk_id); - - assert(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); - LTTNG_OPTIONAL_SET(&session->last_trace_chunk_id, chunk_id) - } - - if (new_trace_chunk) { - refs_to_acquire = 1; - refs_to_acquire += !!session->ust_session; - refs_to_acquire += !!session->kernel_session; - } + struct lttng_trace_chunk *current_trace_chunk; + uint64_t chunk_id; + enum lttng_trace_chunk_status chunk_status; + rcu_read_lock(); /* - * Build a list of consumers to reach to announce the new trace chunk. - * - * Rolling back the annoucement in case of an error is important since - * not doing so would result in a leak; the chunk will not be - * "reclaimed" by the consumer(s) since they have no concept of the - * lifetime of a session. + * Ownership of current trace chunk is transferred to + * `current_trace_chunk`. */ + current_trace_chunk = session->current_trace_chunk; + session->current_trace_chunk = NULL; if (session->ust_session) { - cds_lfht_for_each_entry( - session->ust_session->consumer->socks->ht, - &iter, socket, node.node) { - transactions[consumer_count].socket = socket; - transactions[consumer_count].new_chunk = new_trace_chunk; - transactions[consumer_count].previous_chunk = - session->current_trace_chunk; - consumer_count++; - assert(consumer_count <= 3); - } + lttng_trace_chunk_put( + session->ust_session->current_trace_chunk); + session->ust_session->current_trace_chunk = NULL; } if (session->kernel_session) { - cds_lfht_for_each_entry( - session->kernel_session->consumer->socks->ht, - &iter, socket, node.node) { - transactions[consumer_count].socket = socket; - transactions[consumer_count].new_chunk = new_trace_chunk; - transactions[consumer_count].previous_chunk = - session->current_trace_chunk; - consumer_count++; - assert(consumer_count <= 3); - } + lttng_trace_chunk_put( + session->kernel_session->current_trace_chunk); + session->kernel_session->current_trace_chunk = NULL; } - for (refs_acquired = 0; refs_acquired < refs_to_acquire; refs_acquired++) { - if (new_trace_chunk && !lttng_trace_chunk_get(new_trace_chunk)) { - ERR("Failed to acquire reference to new current trace chunk of session \"%s\"", + if (!new_trace_chunk) { + ret = 0; + goto end; + } + chunk_status = lttng_trace_chunk_get_id(new_trace_chunk, &chunk_id); + assert(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); + + refs_to_acquire = 1; + refs_to_acquire += !!session->ust_session; + refs_to_acquire += !!session->kernel_session; + + for (refs_acquired = 0; refs_acquired < refs_to_acquire; + refs_acquired++) { + if (!lttng_trace_chunk_get(new_trace_chunk)) { + ERR("Failed to acquire reference to new trace chunk of session \"%s\"", session->name); goto error; } } - /* - * Close the previous chunk on remote peers (consumers and relayd). - */ - for (i = 0; i < consumer_count; i++) { - if (!transactions[i].previous_chunk) { - continue; - } - pthread_mutex_lock(transactions[i].socket->lock); - ret = consumer_close_trace_chunk(transactions[i].socket, - session->consumer->net_seq_index, - session->id, - transactions[i].previous_chunk); - pthread_mutex_unlock(transactions[i].socket->lock); - if (ret) { - ERR("Failed to close trace chunk on consumer"); - close_error_occured = true; - } - } + 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; - if (close_error_occured) { - /* - * Skip the creation of the new trace chunk and report the - * error. - */ - goto error; - } + session->ust_session->current_trace_chunk = new_trace_chunk; + if (is_local_trace) { + enum lttng_error_code ret_error_code; - /* Create the new chunk on remote peers (consumers and relayd) */ - if (new_trace_chunk) { - for (i = 0; i < consumer_count; i++) { - pthread_mutex_lock(transactions[i].socket->lock); - ret = consumer_create_trace_chunk(transactions[i].socket, - session->consumer->net_seq_index, - session->id, - transactions[i].new_chunk); - pthread_mutex_unlock(transactions[i].socket->lock); - if (ret) { - ERR("Failed to create trace chunk on consumer"); + ret_error_code = ust_app_create_channel_subdirectories( + session->ust_session); + if (ret_error_code != LTTNG_OK) { goto error; } - /* This will have to be rolled-back on error. */ - transactions[i].new_chunk_created = true; - } - } - - lttng_trace_chunk_put(session->current_trace_chunk); - session->current_trace_chunk = NULL; - if (session->ust_session) { - lttng_trace_chunk_put( - session->ust_session->current_trace_chunk); - session->ust_session->current_trace_chunk = NULL; - } + } + cds_lfht_for_each_entry( + session->ust_session->consumer->socks->ht, + &iter, socket, node.node) { + pthread_mutex_lock(socket->lock); + ret = consumer_create_trace_chunk(socket, + relayd_id, + session->id, new_trace_chunk, + DEFAULT_UST_TRACE_DIR); + pthread_mutex_unlock(socket->lock); + if (ret) { + goto error; + } + } + } if (session->kernel_session) { - lttng_trace_chunk_put( - session->kernel_session->current_trace_chunk); - session->kernel_session->current_trace_chunk = NULL; - } + 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; + + ret_error_code = kernel_create_channel_subdirectories( + session->kernel_session); + if (ret_error_code != LTTNG_OK) { + goto error; + } + } + cds_lfht_for_each_entry( + session->kernel_session->consumer->socks->ht, + &iter, socket, node.node) { + pthread_mutex_lock(socket->lock); + ret = consumer_create_trace_chunk(socket, + relayd_id, + session->id, new_trace_chunk, + DEFAULT_KERNEL_TRACE_DIR); + pthread_mutex_unlock(socket->lock); + if (ret) { + goto error; + } + } + } /* * Update local current trace chunk state last, only if all remote - * annoucements succeeded. + * creations succeeded. */ session->current_trace_chunk = new_trace_chunk; + LTTNG_OPTIONAL_SET(&session->most_recent_chunk_id, chunk_id); +end: + if (_current_trace_chunk) { + *_current_trace_chunk = current_trace_chunk; + current_trace_chunk = NULL; + } +end_no_move: + rcu_read_unlock(); + lttng_trace_chunk_put(current_trace_chunk); + return ret; +error: if (session->ust_session) { - session->ust_session->current_trace_chunk = new_trace_chunk; + session->ust_session->current_trace_chunk = NULL; } if (session->kernel_session) { - session->kernel_session->current_trace_chunk = - new_trace_chunk; + session->kernel_session->current_trace_chunk = NULL; } - - return 0; -error: - /* + /* * Release references taken in the case where all references could not * be acquired. */ @@ -562,109 +566,62 @@ error: for (i = 0; i < refs_to_release; i++) { lttng_trace_chunk_put(new_trace_chunk); } - - /* - * Close the newly-created chunk from remote peers (consumers and - * relayd). - */ - DBG("Rolling back the creation of the new trace chunk on consumers"); - for (i = 0; i < consumer_count; i++) { - if (!transactions[i].new_chunk_created) { - continue; - } - - pthread_mutex_lock(transactions[i].socket->lock); - ret = consumer_close_trace_chunk(transactions[i].socket, - session->consumer->net_seq_index, - session->id, - transactions[i].new_chunk); - pthread_mutex_unlock(transactions[i].socket->lock); - if (ret) { - ERR("Failed to close trace chunk on consumer"); - close_error_occured = true; - } - } - - return -1; -} - -static -bool output_supports_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; + ret = -1; + goto end_no_move; } -enum lttng_error_code session_switch_trace_chunk(struct ltt_session *session, +struct lttng_trace_chunk *session_create_new_trace_chunk( + const struct ltt_session *session, + const struct consumer_output *consumer_output_override, const char *session_base_path_override, const char *chunk_name_override) { int ret; - enum lttng_error_code ret_code = LTTNG_OK; struct lttng_trace_chunk *trace_chunk = NULL; enum lttng_trace_chunk_status chunk_status; - const time_t timestamp_begin = 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; + const time_t chunk_creation_ts = time(NULL); + 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 (timestamp_begin == (time_t) -1) { - PERROR("Failed to sample time while changing session \"%s\" trace chunk", + 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", session->name); - ret_code = LTTNG_ERR_FATAL; goto error; } - session->current_chunk_start_ts = timestamp_begin; - if (!output_supports_chunks(session)) { - goto end; - } - next_chunk_id = session->last_trace_chunk_id.is_set ? - session->last_trace_chunk_id.value + 1 : 0; + next_chunk_id = session->most_recent_chunk_id.is_set ? + session->most_recent_chunk_id.value + 1 : 0; - trace_chunk = lttng_trace_chunk_create(next_chunk_id, timestamp_begin); + trace_chunk = lttng_trace_chunk_create(next_chunk_id, + chunk_creation_ts); if (!trace_chunk) { - ret_code = LTTNG_ERR_FATAL; goto error; } if (chunk_name_override) { chunk_status = lttng_trace_chunk_override_name(trace_chunk, chunk_name_override); - switch (chunk_status) { - case LTTNG_TRACE_CHUNK_STATUS_OK: - break; - case LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT: - ret_code = LTTNG_ERR_INVALID; - goto error; - default: - ret_code = LTTNG_ERR_NOMEM; + if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { goto error; } } @@ -674,49 +631,117 @@ enum lttng_error_code session_switch_trace_chunk(struct ltt_session *session, * No need to set crendentials and output directory * for remote trace chunks. */ - goto publish; + goto end; } chunk_status = lttng_trace_chunk_set_credentials(trace_chunk, &session_credentials); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { - ret_code = LTTNG_ERR_FATAL; goto error; } - if (!session->current_trace_chunk) { - DBG("Creating base output directory of session \"%s\" at %s", - session->name, base_path); - } + DBG("Creating base output directory of session \"%s\" at %s", + session->name, base_path); ret = utils_mkdir_recursive(base_path, S_IRWXU | S_IRWXG, session->uid, session->gid); if (ret) { - ret = LTTNG_ERR_FATAL; goto error; } - ret = lttng_directory_handle_init(&session_output_directory, - base_path); - if (ret) { - ret = LTTNG_ERR_FATAL; + 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) { - ret = LTTNG_ERR_CREATE_DIR_FAIL; - goto error; - } -publish: - ret = session_set_trace_chunk(session, trace_chunk); - if (ret) { - ret_code = LTTNG_ERR_FATAL; 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(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; + struct cds_lfht_iter iter; + struct consumer_socket *socket; + 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); + ret = -1; + goto end; + } + chunk_status = lttng_trace_chunk_set_close_timestamp(trace_chunk, + chunk_close_timestamp); + if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { + ERR("Failed to set the close timestamp of the current trace chunk of session \"%s\"", + session->name); + ret = -1; + goto end; + } + + 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, + relayd_id, + session->id, + trace_chunk, closed_trace_chunk_path); + pthread_mutex_unlock(socket->lock); + if (ret) { + ERR("Failed to close trace chunk on user space consumer"); + error_occurred = true; + } + } + } + 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, + relayd_id, + session->id, + trace_chunk, closed_trace_chunk_path); + pthread_mutex_unlock(socket->lock); + if (ret) { + ERR("Failed to close trace chunk on kernel consumer"); + error_occurred = true; + } + } + } + ret = error_occurred ? -1 : 0; end: - return ret_code; + return ret; } /* @@ -725,10 +750,47 @@ end: * Must be called with the session lock held. */ int session_set_trace_chunk(struct ltt_session *session, - struct lttng_trace_chunk *new_trace_chunk) + struct lttng_trace_chunk *new_trace_chunk, + struct lttng_trace_chunk **current_trace_chunk) { ASSERT_LOCKED(session->lock); - return _session_set_trace_chunk_no_lock_check(session, new_trace_chunk); + return _session_set_trace_chunk_no_lock_check(session, new_trace_chunk, + 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 @@ -738,16 +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; - (void) _session_set_trace_chunk_no_lock_check(session, NULL); - /* 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); @@ -758,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; } /* @@ -774,18 +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); + } } /* @@ -832,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 @@ -920,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); @@ -976,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 @@ -1083,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. * @@ -1097,12 +1208,27 @@ int session_reset_rotation_state(struct ltt_session *session, ASSERT_LOCKED(ltt_session_list.lock); ASSERT_LOCKED(session->lock); - session->rotation_pending_local = false; - session->rotation_pending_relay = false; - session->rotated_after_last_stop = false; session->rotation_state = result; if (session->rotation_pending_check_timer_enabled) { ret = timer_session_rotation_pending_check_stop(session); } + if (session->chunk_being_archived) { + uint64_t chunk_id; + enum lttng_trace_chunk_status chunk_status; + + chunk_status = lttng_trace_chunk_get_id( + session->chunk_being_archived, + &chunk_id); + assert(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); + LTTNG_OPTIONAL_SET(&session->last_archived_chunk_id, + 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; }