X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=850bac508fb4972793c5991050d5c39f56a3f9fd;hb=b872baea3c26766331255b40ca7f9a9ad31e4ea6;hp=ed4d6c86f1a0b569892b0144c6f055a73983fbb1;hpb=5eecee74ccdce343ccf1504174eef7c03d859fb0;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index ed4d6c86f..850bac508 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "channel.h" #include "consumer.h" @@ -1742,6 +1743,72 @@ find_error: return ret; } +/* + * Command LTTNG_CREATE_SESSION_SNAPSHOT processed by the client thread. + */ +int cmd_create_session_snapshot(char *name, struct lttng_uri *uris, + size_t nb_uri, lttng_sock_cred *creds) +{ + int ret; + struct ltt_session *session; + struct snapshot_output *new_output = NULL; + + assert(name); + assert(creds); + + /* + * Create session in no output mode with URIs set to NULL. The uris we've + * received are for a default snapshot output if one. + */ + ret = cmd_create_session_uri(name, NULL, 0, creds); + if (ret != LTTNG_OK) { + goto error; + } + + /* Get the newly created session pointer back. This should NEVER fail. */ + session = session_find_by_name(name); + assert(session); + + /* Flag session for snapshot mode. */ + session->snapshot_mode = 1; + + /* Skip snapshot output creation if no URI is given. */ + if (nb_uri == 0) { + goto end; + } + + new_output = snapshot_output_alloc(); + if (!new_output) { + ret = LTTNG_ERR_NOMEM; + goto error_snapshot_alloc; + } + + ret = snapshot_output_init_with_uri(DEFAULT_SNAPSHOT_MAX_SIZE, NULL, + uris, nb_uri, session->consumer, new_output, &session->snapshot); + if (ret < 0) { + if (ret == -ENOMEM) { + ret = LTTNG_ERR_NOMEM; + } else { + ret = LTTNG_ERR_INVALID; + } + goto error_snapshot; + } + + rcu_read_lock(); + snapshot_add_output(&session->snapshot, new_output); + rcu_read_unlock(); + +end: + return LTTNG_OK; + +error_snapshot: + snapshot_output_destroy(new_output); +error_snapshot_alloc: + session_destroy(session); +error: + return ret; +} + /* * Command LTTNG_DESTROY_SESSION processed by the client thread. */ @@ -2093,6 +2160,7 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid, strncpy(sessions[i].name, session->name, NAME_MAX); sessions[i].name[NAME_MAX - 1] = '\0'; sessions[i].enabled = session->enabled; + sessions[i].snapshot_mode = session->snapshot_mode; i++; } } @@ -2187,27 +2255,6 @@ int cmd_snapshot_add_output(struct ltt_session *session, goto free_error; } - /* - * Copy sockets so the snapshot output can use them on destroy. - */ - - if (session->ust_session) { - ret = consumer_copy_sockets(new_output->consumer, - session->ust_session->consumer); - if (ret < 0) { - goto free_error; - } - new_output->ust_sockets_copied = 1; - } - if (session->kernel_session) { - ret = consumer_copy_sockets(new_output->consumer, - session->kernel_session->consumer); - if (ret < 0) { - goto free_error; - } - new_output->kernel_sockets_copied = 1; - } - rcu_read_lock(); snapshot_add_output(&session->snapshot, new_output); if (id) { @@ -2395,7 +2442,8 @@ error: * Return 0 on success or else a negative value. */ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, - struct snapshot_output *output, struct ltt_session *session, int wait) + struct snapshot_output *output, struct ltt_session *session, + int wait, int nb_streams) { int ret; @@ -2403,24 +2451,40 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, assert(output); assert(session); - if (!output->kernel_sockets_copied) { - ret = consumer_copy_sockets(output->consumer, ksess->consumer); - if (ret < 0) { - goto error; - } - output->kernel_sockets_copied = 1; + /* Get the datetime for the snapshot output directory. */ + ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, + sizeof(output->datetime)); + if (!ret) { + ret = -EINVAL; + goto error; } - ret = set_relayd_for_snapshot(ksess->consumer, output, session); + /* + * Copy kernel session sockets so we can communicate with the right + * consumer for the snapshot record command. + */ + ret = consumer_copy_sockets(output->consumer, ksess->consumer); if (ret < 0) { goto error; } - ret = kernel_snapshot_record(ksess, output, wait); + ret = set_relayd_for_snapshot(ksess->consumer, output, session); if (ret < 0) { - goto error; + goto error_snapshot; } + ret = kernel_snapshot_record(ksess, output, wait, nb_streams); + if (ret < 0) { + ret = -LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = -LTTNG_ERR_INVALID; + } + goto error_snapshot; + } + +error_snapshot: + /* Clean up copied sockets so this output can use some other later on. */ + consumer_destroy_output_sockets(output->consumer); error: return ret; } @@ -2431,7 +2495,8 @@ error: * Return 0 on success or else a negative value. */ static int record_ust_snapshot(struct ltt_ust_session *usess, - struct snapshot_output *output, struct ltt_session *session, int wait) + struct snapshot_output *output, struct ltt_session *session, + int wait, int nb_streams) { int ret; @@ -2439,28 +2504,67 @@ static int record_ust_snapshot(struct ltt_ust_session *usess, assert(output); assert(session); - if (!output->ust_sockets_copied) { - ret = consumer_copy_sockets(output->consumer, usess->consumer); - if (ret < 0) { - goto error; - } - output->ust_sockets_copied = 1; + /* Get the datetime for the snapshot output directory. */ + ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, + sizeof(output->datetime)); + if (!ret) { + ret = -EINVAL; + goto error; } - ret = set_relayd_for_snapshot(usess->consumer, output, session); + /* + * Copy kernel session sockets so we can communicate with the right + * consumer for the snapshot record command. + */ + ret = consumer_copy_sockets(output->consumer, usess->consumer); if (ret < 0) { goto error; } - ret = ust_app_snapshot_record(usess, output, wait); + ret = set_relayd_for_snapshot(usess->consumer, output, session); if (ret < 0) { - goto error; + goto error_snapshot; } + ret = ust_app_snapshot_record(usess, output, wait, nb_streams); + if (ret < 0) { + ret = -LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = -LTTNG_ERR_INVALID; + } + goto error_snapshot; + } + +error_snapshot: + /* Clean up copied sockets so this output can use some other later on. */ + consumer_destroy_output_sockets(output->consumer); error: return ret; } +/* + * Returns the total number of streams for a session or a negative value + * on error. + */ +static unsigned int get_total_nb_stream(struct ltt_session *session) +{ + unsigned int total_streams = 0; + + if (session->kernel_session) { + struct ltt_kernel_session *ksess = session->kernel_session; + + total_streams += ksess->stream_count_global; + } + + if (session->ust_session) { + struct ltt_ust_session *usess = session->ust_session; + + total_streams += ust_app_get_nb_stream(usess); + } + + return total_streams; +} + /* * Command LTTNG_SNAPSHOT_RECORD from lib lttng ctl. * @@ -2473,7 +2577,9 @@ int cmd_snapshot_record(struct ltt_session *session, struct lttng_snapshot_output *output, int wait) { int ret = LTTNG_OK; - struct snapshot_output *tmp_sout = NULL; + unsigned int use_tmp_output = 0; + struct snapshot_output tmp_output; + unsigned int nb_streams; assert(session); @@ -2496,15 +2602,9 @@ int cmd_snapshot_record(struct ltt_session *session, /* Use temporary output for the session. */ if (output && *output->ctrl_url != '\0') { - tmp_sout = snapshot_output_alloc(); - if (!tmp_sout) { - ret = LTTNG_ERR_NOMEM; - goto error; - } - ret = snapshot_output_init(output->max_size, output->name, output->ctrl_url, output->data_url, session->consumer, - tmp_sout, NULL); + &tmp_output, NULL); if (ret < 0) { if (ret == -ENOMEM) { ret = LTTNG_ERR_NOMEM; @@ -2513,13 +2613,21 @@ int cmd_snapshot_record(struct ltt_session *session, } goto error; } + use_tmp_output = 1; } + /* + * Get the total number of stream of that session which is used by the + * maximum size of the snapshot feature. + */ + nb_streams = get_total_nb_stream(session); + if (session->kernel_session) { struct ltt_kernel_session *ksess = session->kernel_session; - if (tmp_sout) { - ret = record_kernel_snapshot(ksess, tmp_sout, session, wait); + if (use_tmp_output) { + ret = record_kernel_snapshot(ksess, &tmp_output, session, + wait, nb_streams); if (ret < 0) { goto error; } @@ -2530,7 +2638,26 @@ int cmd_snapshot_record(struct ltt_session *session, rcu_read_lock(); cds_lfht_for_each_entry(session->snapshot.output_ht->ht, &iter.iter, sout, node.node) { - ret = record_kernel_snapshot(ksess, sout, session, wait); + /* + * Make a local copy of the output and assign the possible + * temporary value given by the caller. + */ + memset(&tmp_output, 0, sizeof(tmp_output)); + memcpy(&tmp_output, sout, sizeof(tmp_output)); + + /* Use temporary max size. */ + if (output->max_size != (uint64_t) -1ULL) { + tmp_output.max_size = output->max_size; + } + + /* Use temporary name. */ + if (*output->name != '\0') { + strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name)); + } + + ret = record_kernel_snapshot(ksess, &tmp_output, + session, wait, nb_streams); if (ret < 0) { rcu_read_unlock(); goto error; @@ -2543,8 +2670,9 @@ int cmd_snapshot_record(struct ltt_session *session, if (session->ust_session) { struct ltt_ust_session *usess = session->ust_session; - if (tmp_sout) { - ret = record_ust_snapshot(usess, tmp_sout, session, wait); + if (use_tmp_output) { + ret = record_ust_snapshot(usess, &tmp_output, session, + wait, nb_streams); if (ret < 0) { goto error; } @@ -2555,7 +2683,28 @@ int cmd_snapshot_record(struct ltt_session *session, rcu_read_lock(); cds_lfht_for_each_entry(session->snapshot.output_ht->ht, &iter.iter, sout, node.node) { - ret = record_ust_snapshot(usess, tmp_sout, session, wait); + /* + * Make a local copy of the output and assign the possible + * temporary value given by the caller. + */ + memset(&tmp_output, 0, sizeof(tmp_output)); + memcpy(&tmp_output, sout, sizeof(tmp_output)); + + fprintf(stderr, "Name: %s\n", output->name); + + /* Use temporary max size. */ + if (output->max_size != (uint64_t) -1ULL) { + tmp_output.max_size = output->max_size; + } + + /* Use temporary name. */ + if (*output->name != '\0') { + strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name)); + } + + ret = record_ust_snapshot(usess, &tmp_output, session, + wait, nb_streams); if (ret < 0) { rcu_read_unlock(); goto error; @@ -2566,9 +2715,6 @@ int cmd_snapshot_record(struct ltt_session *session, } error: - if (tmp_sout) { - snapshot_output_destroy(tmp_sout); - } return ret; }