From 07424f161f4afbd07fd165e4ae492726e1de7769 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Thu, 16 Aug 2012 14:57:13 -0400 Subject: [PATCH] Fix: Subdirectory handling for lttng and sessiond The subdirectory creation was not right for a number of scenarios. With this commit, if the user defines a path (either local or remote), the session name will NOT be added to the path. To handle the timestamp creation of the directory, a hidden function was added to the lttng-ctl (meaning not visible through lttng.h) which takes the date and time as a string and append it to the URI subdirectory if none was provided for a network destination. This function is declared as extern in the lttng client so it could link to it through the liblttng-ctl (_lttng_create_session_ext). It allows the timestamp of a session to be created on the client side and keep the lttng_create_session() behavior intact meaning if a path is define by the user when using the API directly, the traces are written in that path without an extra session name directory. There is one case where the timestamp is generated on the daemon side. When creating a session with a local filesystem destination and then switching to a network consumer, at that time the timestamp is generated. The real problematic, and why this has been done this way, is because we can't transfer the timestamp between the client and the session daemon. The only possible way that could be achieve right now is by parsing the subdirectory of the URI containing the session name and timestamp appended. This could be error prone and bring false negative. CC: Julien Desfossez Signed-off-by: David Goulet --- src/bin/lttng-sessiond/Makefile.am | 2 +- src/bin/lttng-sessiond/main.c | 470 ++++++++++++++--------------- src/bin/lttng-sessiond/session.c | 4 + src/bin/lttng/commands/create.c | 42 ++- src/common/defaults.h | 2 +- src/lib/lttng-ctl/lttng-ctl.c | 65 ++++ tests/tools/Makefile.am | 7 +- 7 files changed, 334 insertions(+), 258 deletions(-) diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 9b6c4b057..de5a252ca 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -13,11 +13,11 @@ lttng_sessiond_SOURCES = utils.c utils.h \ channel.c channel.h \ event.c event.h \ shm.c shm.h \ + consumer.c consumer.h \ session.c session.h \ modprobe.c modprobe.h kern-modules.h \ lttng-ust-ctl.h lttng-ust-abi.h \ fd-limit.c fd-limit.h \ - consumer.c consumer.h \ kernel-consumer.c kernel-consumer.h \ consumer.h filter.c filter.h \ health.c health.h diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 2b40e7aec..f24b317d0 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2186,6 +2186,54 @@ error: return ret; } +/* + * Set consumer subdirectory using the session name and a generated datetime if + * needed. This is appended to the current subdirectory. + */ +static int set_consumer_subdir(struct consumer_output *consumer, + const char *session_name) +{ + int ret = 0; + unsigned int have_default_name = 0; + char datetime[16], tmp_path[PATH_MAX]; + time_t rawtime; + struct tm *timeinfo; + + assert(consumer); + assert(session_name); + + memset(tmp_path, 0, sizeof(tmp_path)); + + /* Flag if we have a default session. */ + if (strncmp(session_name, DEFAULT_SESSION_NAME "-", + strlen(DEFAULT_SESSION_NAME) + 1) == 0) { + have_default_name = 1; + } else { + /* Get date and time for session path */ + time(&rawtime); + timeinfo = localtime(&rawtime); + strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); + } + + if (have_default_name) { + ret = snprintf(tmp_path, sizeof(tmp_path), + "%s/%s", consumer->subdir, session_name); + } else { + ret = snprintf(tmp_path, sizeof(tmp_path), + "%s/%s-%s/", consumer->subdir, session_name, datetime); + } + if (ret < 0) { + PERROR("snprintf session name date"); + goto error; + } + + strncpy(consumer->subdir, tmp_path, sizeof(consumer->subdir)); + DBG2("Consumer subdir set to %s", consumer->subdir); + +error: + return ret; +} + /* * Copy consumer output from the tracing session to the domain session. The * function also applies the right modification on a per domain basis for the @@ -2222,6 +2270,12 @@ static int copy_session_consumer(int domain, struct ltt_session *session) goto error; } + ret = set_consumer_subdir(session->consumer, session->name); + if (ret < 0) { + ret = LTTCOMM_FATAL; + goto error; + } + /* Append correct directory to subdir */ strncat(consumer->subdir, dir_name, sizeof(consumer->subdir)); DBG3("Copy session consumer subdir %s", consumer->subdir); @@ -2614,9 +2668,9 @@ error: * domain adding the default trace directory. */ static int add_uri_to_consumer(struct consumer_output *consumer, - struct lttng_uri *uri, int domain) + struct lttng_uri *uri, int domain, const char *session_name) { - int ret; + int ret = LTTCOMM_OK; const char *default_trace_dir; assert(uri); @@ -2654,10 +2708,18 @@ static int add_uri_to_consumer(struct consumer_output *consumer, goto error; } - /* On a new subdir, reappend the default trace dir. */ - if (strlen(uri->subdir) != 0) { - strncat(consumer->subdir, default_trace_dir, - sizeof(consumer->subdir)); + if (uri->stype == LTTNG_STREAM_CONTROL && strlen(uri->subdir) == 0) { + ret = set_consumer_subdir(consumer, session_name); + if (ret < 0) { + ret = LTTCOMM_FATAL; + goto error; + } + } + + if (uri->stype == LTTNG_STREAM_CONTROL) { + /* On a new subdir, reappend the default trace dir. */ + strncat(consumer->subdir, default_trace_dir, sizeof(consumer->subdir)); + DBG3("Append domain trace name to subdir %s", consumer->subdir); } break; @@ -3496,135 +3558,158 @@ error: } /* - * Command LTTNG_CREATE_SESSION processed by the client thread. + * Command LTTNG_SET_CONSUMER_URI processed by the client thread. */ -static int cmd_create_session_uri(char *name, struct lttng_uri *uris, - size_t nb_uri, lttng_sock_cred *creds) +static int cmd_set_consumer_uri(int domain, struct ltt_session *session, + size_t nb_uri, struct lttng_uri *uris) { - int ret, have_default_name = 0; - char *path = NULL, datetime[16]; - struct ltt_session *session; + int ret, i; + struct ltt_kernel_session *ksess = session->kernel_session; + struct ltt_ust_session *usess = session->ust_session; struct consumer_output *consumer = NULL; - struct lttng_uri *ctrl_uri, *data_uri = NULL; - time_t rawtime; - struct tm *timeinfo; - - assert(name); - /* Flag if we have a default session. */ - if (strncmp(name, DEFAULT_SESSION_NAME, - strlen(DEFAULT_SESSION_NAME)) == 0) { - have_default_name = 1; - } else { - /* Get date and time for session path */ - time(&rawtime); - timeinfo = localtime(&rawtime); - strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); - } - - /* - * Verify if the session already exist - * - * XXX: There is no need for the session lock list here since the caller - * (process_client_msg) is holding it. We might want to change that so a - * single command does not lock the entire session list. - */ - session = session_find_by_name(name); - if (session != NULL) { - ret = LTTCOMM_EXIST_SESS; - goto consumer_error; - } + assert(session); + assert(uris); + assert(nb_uri > 0); - /* Create default consumer output for the session not yet created. */ - consumer = consumer_create_output(CONSUMER_DST_LOCAL); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto consumer_error; + /* Can't enable consumer after session started. */ + if (session->enabled) { + ret = LTTCOMM_TRACE_ALREADY_STARTED; + goto error; } - /* Add session name and data to the consumer subdir */ - if (have_default_name) { - ret = snprintf(consumer->subdir, sizeof(consumer->subdir), "/%s", - name); - } else { - ret = snprintf(consumer->subdir, sizeof(consumer->subdir), "/%s-%s", - name, datetime); - } - if (ret < 0) { - PERROR("snprintf consumer subdir"); + if (!session->start_consumer) { + ret = LTTCOMM_NO_CONSUMER; goto error; } - DBG2("Consumer subdir set to '%s'", consumer->subdir); /* - * This means that the lttng_create_session call was called with the _path_ - * argument set to NULL. + * This case switch makes sure the domain session has a temporary consumer + * so the URL can be set. */ - if (uris == NULL) { + switch (domain) { + case 0: + /* Code flow error. A session MUST always have a consumer object */ + assert(session->consumer); /* - * At this point, we'll skip the consumer URI setup and create a - * session with a NULL path which will flag the session to NOT spawn a - * consumer. + * The URL will be added to the tracing session consumer instead of a + * specific domain consumer. */ - DBG("Create session %s with NO uri, skipping consumer setup", name); - goto skip_consumer; - } + consumer = session->consumer; + break; + case LTTNG_DOMAIN_KERNEL: + /* Code flow error if we don't have a kernel session here. */ + assert(ksess); - /* TODO: validate URIs */ + /* Create consumer output if none exists */ + consumer = ksess->tmp_consumer; + if (consumer == NULL) { + consumer = consumer_copy_output(ksess->consumer); + if (consumer == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + /* Trash the consumer subdir, we are about to set a new one. */ + memset(consumer->subdir, 0, sizeof(consumer->subdir)); + ksess->tmp_consumer = consumer; + } - ctrl_uri = &uris[0]; - if (nb_uri > 1) { - data_uri = &uris[1]; - } + break; + case LTTNG_DOMAIN_UST: + /* Code flow error if we don't have a kernel session here. */ + assert(usess); - /* Set subdirectory from the ctrl_uri received. */ - if (strlen(ctrl_uri->subdir) > 0) { - strncpy(consumer->subdir, ctrl_uri->subdir, sizeof(consumer->subdir)); - DBG2("Consumer subdir copy from ctrl_uri '%s'", consumer->subdir); + /* Create consumer output if none exists */ + consumer = usess->tmp_consumer; + if (consumer == NULL) { + consumer = consumer_copy_output(usess->consumer); + if (consumer == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + /* Trash the consumer subdir, we are about to set a new one. */ + memset(consumer->subdir, 0, sizeof(consumer->subdir)); + usess->tmp_consumer = consumer; + } + + break; } - switch (ctrl_uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - /* - * We MUST have a data_uri set at this point or else there is a code - * flow error. The caller should check that. - */ - assert(data_uri); + for (i = 0; i < nb_uri; i++) { + struct consumer_socket *socket; + struct lttng_ht_iter iter; - /* Set control URI into consumer output object */ - ret = consumer_set_network_uri(consumer, ctrl_uri); + ret = add_uri_to_consumer(consumer, &uris[i], domain, session->name); if (ret < 0) { - ret = LTTCOMM_FATAL; goto error; } - /* Set data URI into consumer output object */ - ret = consumer_set_network_uri(consumer, data_uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; + /* + * Don't send relayd socket if URI is NOT remote or if the relayd + * sockets for the session are already sent. + */ + if (uris[i].dtype == LTTNG_DST_PATH || + consumer->dst.net.relayd_socks_sent) { + continue; } - /* Empty path since the session is network */ - path = ""; - break; - case LTTNG_DST_PATH: - /* Very volatile pointer. Only used for the create session. */ - path = ctrl_uri->dst.path; - strncpy(consumer->dst.trace_path, path, - sizeof(consumer->dst.trace_path)); - break; + /* Try to send relayd URI to the consumer if exist. */ + cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, + socket, node.node) { + + /* A socket in the HT should never have a negative fd */ + assert(socket->fd >= 0); + + pthread_mutex_lock(socket->lock); + ret = send_socket_relayd_consumer(domain, session, &uris[i], + consumer, socket->fd); + pthread_mutex_unlock(socket->lock); + if (ret != LTTCOMM_OK) { + goto error; + } + } } - consumer->enabled = 1; + /* All good! */ + ret = LTTCOMM_OK; + +error: + return ret; +} + + +/* + * Command LTTNG_CREATE_SESSION processed by the client thread. + */ +static int cmd_create_session_uri(char *name, struct lttng_uri *uris, + size_t nb_uri, lttng_sock_cred *creds) +{ + int ret; + char *path = NULL; + struct ltt_session *session; + //struct consumer_output *consumer = NULL; + //struct lttng_uri *ctrl_uri, *data_uri = NULL; + + assert(name); + + /* + * Verify if the session already exist + * + * XXX: There is no need for the session lock list here since the caller + * (process_client_msg) is holding it. We might want to change that so a + * single command does not lock the entire session list. + */ + session = session_find_by_name(name); + if (session != NULL) { + ret = LTTCOMM_EXIST_SESS; + goto find_error; + } -skip_consumer: /* Create tracing session in the registry */ ret = session_create(name, path, LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds)); if (ret != LTTCOMM_OK) { - goto error; + goto session_error; } /* @@ -3637,32 +3722,43 @@ skip_consumer: session = session_find_by_name(name); assert(session); - /* Assign consumer to session */ - session->consumer = consumer; + /* Create default consumer output for the session not yet created. */ + session->consumer = consumer_create_output(CONSUMER_DST_LOCAL); + if (session->consumer == NULL) { + ret = LTTCOMM_FATAL; + goto consumer_error; + } - /* Set correct path to session */ - if (have_default_name) { - /* We have the default session so the date-time is already appended */ - ret = snprintf(session->path, sizeof(session->path), "%s/%s", - path, name); - } else { - ret = snprintf(session->path, sizeof(session->path), "%s/%s-%s", - path, name, datetime); + /* + * This means that the lttng_create_session call was called with the _path_ + * argument set to NULL. + */ + if (uris == NULL) { + /* + * At this point, we'll skip the consumer URI setup and create a + * session with a NULL path which will flag the session to NOT spawn a + * consumer. + */ + DBG("Create session %s with NO uri, skipping consumer setup", name); + goto end; } - if (ret < 0) { - PERROR("snprintf session path"); - goto session_error; + + session->start_consumer = 1; + + ret = cmd_set_consumer_uri(0, session, nb_uri, uris); + if (ret != LTTCOMM_OK) { + goto consumer_error; } + session->consumer->enabled = 1; + +end: return LTTCOMM_OK; -session_error: - session_destroy(session); -error: - rcu_read_lock(); - consumer_destroy_output(consumer); - rcu_read_unlock(); consumer_error: + session_destroy(session); +session_error: +find_error: return ret; } @@ -3920,122 +4016,6 @@ error: return ret; } -/* - * Command LTTNG_SET_CONSUMER_URI processed by the client thread. - */ -static int cmd_set_consumer_uri(int domain, struct ltt_session *session, - size_t nb_uri, struct lttng_uri *uris) -{ - int ret, i; - struct ltt_kernel_session *ksess = session->kernel_session; - struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer = NULL; - - assert(session); - assert(uris); - assert(nb_uri > 0); - - /* Can't enable consumer after session started. */ - if (session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - if (!session->start_consumer) { - ret = LTTCOMM_NO_CONSUMER; - goto error; - } - - /* - * This case switch makes sure the domain session has a temporary consumer - * so the URL can be set. - */ - switch (domain) { - case 0: - /* Code flow error. A session MUST always have a consumer object */ - assert(session->consumer); - /* - * The URL will be added to the tracing session consumer instead of a - * specific domain consumer. - */ - consumer = session->consumer; - break; - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - /* Create consumer output if none exists */ - consumer = ksess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(ksess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - ksess->tmp_consumer = consumer; - } - - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a kernel session here. */ - assert(usess); - - /* Create consumer output if none exists */ - consumer = usess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(usess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - usess->tmp_consumer = consumer; - } - - break; - } - - for (i = 0; i < nb_uri; i++) { - struct consumer_socket *socket; - struct lttng_ht_iter iter; - - ret = add_uri_to_consumer(consumer, &uris[i], domain); - if (ret < 0) { - goto error; - } - - /* - * Don't send relayd socket if URI is NOT remote or if the relayd - * sockets for the session are already sent. - */ - if (uris[i].dtype == LTTNG_DST_PATH || - consumer->dst.net.relayd_socks_sent) { - continue; - } - - /* Try to send relayd URI to the consumer if exist. */ - cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, - socket, node.node) { - - /* A socket in the HT should never have a negative fd */ - assert(socket->fd >= 0); - - pthread_mutex_lock(socket->lock); - ret = send_socket_relayd_consumer(domain, session, &uris[i], - consumer, socket->fd); - pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { - goto error; - } - } - } - - /* All good! */ - ret = LTTCOMM_OK; - -error: - return ret; -} - /* * Command LTTNG_DISABLE_CONSUMER processed by the client thread. */ @@ -4183,13 +4163,13 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } - /* Append default kernel trace dir to subdir */ - strncat(ksess->consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, - sizeof(ksess->consumer->subdir)); - break; } + /* Append default kernel trace dir to subdir */ + strncat(ksess->consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, + sizeof(ksess->consumer->subdir)); + /* * @session-lock * This is race free for now since the session lock is acquired before @@ -4268,13 +4248,13 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } - /* Append default kernel trace dir to subdir */ - strncat(usess->consumer->subdir, DEFAULT_UST_TRACE_DIR, - sizeof(usess->consumer->subdir)); - break; } + /* Append default kernel trace dir to subdir */ + strncat(usess->consumer->subdir, DEFAULT_UST_TRACE_DIR, + sizeof(usess->consumer->subdir)); + /* * @session-lock * This is race free for now since the session lock is acquired before diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index e445363ea..75fcf4bfd 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -149,6 +149,10 @@ int session_destroy(struct ltt_session *session) DBG("Destroying session %s", session->name); del_session_list(session); pthread_mutex_destroy(&session->lock); + + rcu_read_lock(); + consumer_destroy_output(session->consumer); + rcu_read_unlock(); free(session); return LTTCOMM_OK; diff --git a/src/bin/lttng/commands/create.c b/src/bin/lttng/commands/create.c index 3e7074e02..dd10ab227 100644 --- a/src/bin/lttng/commands/create.c +++ b/src/bin/lttng/commands/create.c @@ -60,6 +60,10 @@ static struct poptOption long_options[] = { {0, 0, 0, 0, 0, 0, 0} }; +/* HACK */ +extern int _lttng_create_session_ext(const char *name, const char *url, + const char *datetime); + /* * usage */ @@ -245,8 +249,9 @@ error: static int create_session(void) { int ret; - char *session_name, *traces_path = NULL, *alloc_path = NULL; + char *session_name = NULL, *traces_path = NULL, *alloc_path = NULL; char *alloc_url = NULL, *url = NULL, datetime[16]; + char session_name_date[NAME_MAX]; time_t rawtime; struct tm *timeinfo; @@ -257,14 +262,26 @@ static int create_session(void) /* Auto session name creation */ if (opt_session_name == NULL) { - ret = asprintf(&session_name, DEFAULT_SESSION_NAME "%s", datetime); + ret = snprintf(session_name_date, sizeof(session_name_date), + DEFAULT_SESSION_NAME "-%s", datetime); if (ret < 0) { - PERROR("asprintf session name"); + PERROR("snprintf session name"); + goto error; + } + session_name = strdup(DEFAULT_SESSION_NAME); + if (session_name == NULL) { + PERROR("strdup session name"); goto error; } - DBG("Auto session name set to %s", session_name); + DBG("Auto session name set to %s", session_name_date); } else { session_name = opt_session_name; + ret = snprintf(session_name_date, sizeof(session_name_date), + "%s-%s", session_name, datetime); + if (ret < 0) { + PERROR("snprintf session name"); + goto error; + } } if (opt_no_consumer) { @@ -300,8 +317,9 @@ static int create_session(void) } alloc_path = strdup(alloc_path); - ret = asprintf(&alloc_url, "file://%s/" DEFAULT_TRACE_DIR_NAME, - alloc_path); + ret = asprintf(&alloc_url, + "file://%s/" DEFAULT_TRACE_DIR_NAME "/%s", + alloc_path, session_name_date); if (ret < 0) { PERROR("asprintf trace dir name"); ret = CMD_FATAL; @@ -312,7 +330,7 @@ static int create_session(void) MSG("Trace(s) output set to %s", alloc_url + strlen("file://")); } - ret = lttng_create_session(session_name, url); + ret = _lttng_create_session_ext(session_name, url, datetime); if (ret < 0) { /* Don't set ret so lttng can interpret the sessiond error. */ switch (-ret) { @@ -324,7 +342,7 @@ static int create_session(void) } if (opt_session_name == NULL) { - MSG("Session created with default name %s", session_name); + MSG("Session created with default name %s", session_name_date); } else { MSG("Session %s created.", session_name); } @@ -349,6 +367,11 @@ static int create_session(void) } } + if (opt_session_name == NULL) { + free(session_name); + session_name = session_name_date; + } + /* Init lttng session config */ ret = config_init(session_name); if (ret < 0) { @@ -356,10 +379,11 @@ static int create_session(void) goto error; } + ret = CMD_SUCCESS; error: - if (opt_session_name == NULL) { + if (opt_session_name == NULL && session_name != session_name_date) { free(session_name); } diff --git a/src/common/defaults.h b/src/common/defaults.h index 0303c02ae..ad1b708a3 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -48,7 +48,7 @@ * Default session name for the lttng command line. This default value will * get the date and time appended (%Y%m%d-%H%M%S) to it. */ -#define DEFAULT_SESSION_NAME "auto-" +#define DEFAULT_SESSION_NAME "auto" /* Default consumer paths */ #define DEFAULT_CONSUMERD_RUNDIR "%s" diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 064f739aa..f18e8ca07 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1496,6 +1496,71 @@ error: return ret; } +/* + * This is an extension of create session that is ONLY and SHOULD only be used + * by the lttng command line program. It exists to avoid using URI parsing in + * the lttng client. + * + * We need the date and time for the trace path subdirectory for the case where + * the user does NOT define one using either -o or -U. Using the normal + * lttng_create_session API call, we have no clue on the session daemon side if + * the URL was generated automatically by the client or define by the user. + * + * So this function "wrapper" is hidden from the public API, takes the datetime + * string and appends it if necessary to the URI subdirectory before sending it + * to the session daemon. + * + * With this extra function, the lttng_create_session call behavior is not + * changed and the timestamp is appended to the URI on the session daemon side + * if necessary. + */ +int _lttng_create_session_ext(const char *name, const char *url, + const char *datetime) +{ + int ret; + ssize_t size; + struct lttcomm_session_msg lsm; + struct lttng_uri *uris = NULL; + + if (name == NULL || datetime == NULL) { + return -1; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_CREATE_SESSION; + if (!strncmp(name, DEFAULT_SESSION_NAME, strlen(DEFAULT_SESSION_NAME))) { + ret = snprintf(lsm.session.name, sizeof(lsm.session.name), "%s-%s", + name, datetime); + if (ret < 0) { + PERROR("snprintf session name datetime"); + return -1; + } + } else { + copy_string(lsm.session.name, name, sizeof(lsm.session.name)); + } + + /* There should never be a data URL */ + size = parse_str_urls_to_uri(url, NULL, &uris); + if (size < 0) { + return LTTCOMM_INVALID; + } + + lsm.u.uri.size = size; + + if (uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) { + ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "/%s-%s", name, + datetime); + if (ret < 0) { + PERROR("snprintf uri subdir"); + return -1; + } + } + + return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + NULL); +} + /* * lib constructor */ diff --git a/tests/tools/Makefile.am b/tests/tools/Makefile.am index f4cfe57b9..074c8ec8f 100644 --- a/tests/tools/Makefile.am +++ b/tests/tools/Makefile.am @@ -8,7 +8,10 @@ EXTRA_DIST = runall.sh noinst_PROGRAMS = test_sessions test_kernel_data_trace UTILS=../utils.h -SESSIONS=$(top_srcdir)/src/bin/lttng-sessiond/session.c +SESSIONS=$(top_srcdir)/src/bin/lttng-sessiond/session.c \ + $(top_srcdir)/src/bin/lttng-sessiond/consumer.c \ + $(top_srcdir)/src/common/uri.c \ + $(top_srcdir)/src/common/utils.c KERN_DATA_TRACE=$(top_srcdir)/src/bin/lttng-sessiond/trace-kernel.c \ $(top_srcdir)/src/bin/lttng-sessiond/consumer.c \ $(top_srcdir)/src/common/uri.c \ @@ -19,7 +22,7 @@ SESSIOND_COMM=$(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la # Tracing sessions unit tests test_sessions_SOURCES = test_sessions.c $(UTILS) $(SESSIONS) -test_sessions_LDADD = $(COMMON) $(HASHTABLE) +test_sessions_LDADD = $(COMMON) $(HASHTABLE) $(SESSIOND_COMM) # Kernel trace data unit tests test_kernel_data_trace_SOURCES = test_kernel_data_trace.c $(UTILS) $(KERN_DATA_TRACE) -- 2.34.1