relayd: create stream files relative to a session's trace chunk
[lttng-tools.git] / src / bin / lttng-sessiond / session.c
index abac2404f04bdda9b2c3a94ec8507c950f3a427a..20edd47e4c707a109b350795c0eb1d725406b7bf 100644 (file)
 #include "trace-ust.h"
 #include "timer.h"
 
+struct ltt_session_destroy_notifier_element {
+       ltt_session_destroy_notifier notifier;
+       void *user_data;
+};
+
 /*
  * NOTES:
  *
@@ -245,7 +250,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;
@@ -424,8 +429,6 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session,
        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 +468,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;
@@ -490,6 +499,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;
@@ -550,21 +565,11 @@ error:
 }
 
 static
-bool output_supports_trace_chunks(const struct ltt_session *session)
+bool output_supports_trace_chunks(const struct consumer_output *output)
 {
-       if (session->consumer->type == CONSUMER_DST_LOCAL) {
+       if (output->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 &&
@@ -576,7 +581,8 @@ bool output_supports_trace_chunks(const struct ltt_session *session)
 }
 
 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 +590,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);
+       bool is_local_trace;
+       const char *base_path;
        struct lttng_directory_handle session_output_directory;
        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,7 +619,7 @@ struct lttng_trace_chunk *session_create_new_trace_chunk(
                goto error;
        }
 
-       if (!output_supports_trace_chunks(session)) {
+       if (!output_supports_trace_chunks(output)) {
                goto end;
        }
        next_chunk_id = session->most_recent_chunk_id.is_set ?
@@ -662,7 +680,8 @@ error:
 }
 
 int session_close_trace_chunk(const struct ltt_session *session,
-               struct lttng_trace_chunk *trace_chunk)
+               struct lttng_trace_chunk *trace_chunk,
+               const enum lttng_trace_chunk_command_type *close_command)
 {
        int ret = 0;
        bool error_occurred = false;
@@ -671,6 +690,15 @@ 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);
 
+       if (close_command) {
+               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);
@@ -737,6 +765,22 @@ 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);
+       }
+}
+
 static
 void session_release(struct urcu_ref *ref)
 {
@@ -749,8 +793,11 @@ void session_release(struct urcu_ref *ref)
 
        usess = session->ust_session;
        ksess = session->kernel_session;
+
+       session_notify_destruction(session);
+       lttng_dynamic_array_reset(&session->destroy_notifiers);
        if (session->current_trace_chunk) {
-               ret = session_close_trace_chunk(session, session->current_trace_chunk);
+               ret = session_close_trace_chunk(session, session->current_trace_chunk, NULL);
                if (ret) {
                        ERR("Failed to close the current trace chunk of session \"%s\" during its release",
                                        session->name);
@@ -852,6 +899,18 @@ 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);
+}
+
 /*
  * 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 +999,9 @@ 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);
        urcu_ref_init(&new_session->ref);
        pthread_mutex_init(&new_session->lock, NULL);
 
This page took 0.026273 seconds and 4 git commands to generate.