From ad20f4747b375cf21623ece9f76c9a9b54c493bb Mon Sep 17 00:00:00 2001 From: David Goulet Date: Fri, 17 Aug 2012 12:47:16 -0400 Subject: [PATCH] Fix: lttng list command with network path With network consumer, the session path was simply NULL or set to the wrong local filesystem path when a consumer was set to use the network. This commit adds the support for network path description when a lttng list command is received. Signed-off-by: David Goulet --- src/bin/lttng-sessiond/consumer.c | 11 ++-- src/bin/lttng-sessiond/main.c | 92 +++++++++++++++++++++++++++++-- src/common/uri.c | 34 ++++++++++++ src/common/uri.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 2 +- 5 files changed, 131 insertions(+), 9 deletions(-) diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 9ff4eceb2..3503e0415 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -272,7 +272,8 @@ malloc_error: /* * Set network URI to the consumer output object. * - * Return 0 on success. Negative value on error. + * Return 0 on success. Return 1 if the URI were equal. Else, negative value on + * error. */ int consumer_set_network_uri(struct consumer_output *obj, struct lttng_uri *uri) @@ -294,6 +295,7 @@ int consumer_set_network_uri(struct consumer_output *obj, /* Assign default port. */ uri->port = DEFAULT_NETWORK_CONTROL_PORT; } + DBG3("Consumer control URI set with port %d", uri->port); break; case LTTNG_STREAM_DATA: dst_uri = &obj->dst.net.data; @@ -302,6 +304,7 @@ int consumer_set_network_uri(struct consumer_output *obj, /* Assign default port. */ uri->port = DEFAULT_NETWORK_DATA_PORT; } + DBG3("Consumer data URI set with port %d", uri->port); break; default: ERR("Set network uri type unknown %d", uri->stype); @@ -312,7 +315,7 @@ int consumer_set_network_uri(struct consumer_output *obj, if (!ret) { /* Same URI, don't touch it and return success. */ DBG3("URI network compare are the same"); - goto end; + goto equal; } /* URIs were not equal, replacing it. */ @@ -347,9 +350,9 @@ int consumer_set_network_uri(struct consumer_output *obj, DBG3("Consumer set network uri subdir path %s", tmp_path); } -end: return 0; - +equal: + return 1; error: return -1; } diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index d0b1e17e5..495465b6f 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2418,6 +2418,73 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid) return i; } +/* + * Create a session path used by list_lttng_sessions for the case that the + * session consumer is on the network. + */ +static int build_network_session_path(char *dst, size_t size, + struct ltt_session *session) +{ + int ret, kdata_port, udata_port; + struct lttng_uri *kuri = NULL, *uuri = NULL, *uri = NULL; + char tmp_uurl[PATH_MAX], tmp_urls[PATH_MAX]; + + assert(session); + assert(dst); + + memset(tmp_urls, 0, sizeof(tmp_urls)); + memset(tmp_uurl, 0, sizeof(tmp_uurl)); + + kdata_port = udata_port = DEFAULT_NETWORK_DATA_PORT; + + if (session->kernel_session && session->kernel_session->consumer) { + kuri = &session->kernel_session->consumer->dst.net.control; + kdata_port = session->kernel_session->consumer->dst.net.data.port; + } + + if (session->ust_session && session->ust_session->consumer) { + uuri = &session->ust_session->consumer->dst.net.control; + udata_port = session->ust_session->consumer->dst.net.data.port; + } + + if (uuri == NULL && kuri == NULL) { + uri = &session->consumer->dst.net.control; + kdata_port = session->consumer->dst.net.data.port; + } else if (kuri && uuri) { + ret = uri_compare(kuri, uuri); + if (ret) { + /* Not Equal */ + uri = kuri; + /* Build uuri URL string */ + ret = uri_to_str_url(uuri, tmp_uurl, sizeof(tmp_uurl)); + if (ret < 0) { + goto error; + } + } else { + uri = kuri; + } + } else if (kuri && uuri == NULL) { + uri = kuri; + } else if (uuri && kuri == NULL) { + uri = uuri; + } + + ret = uri_to_str_url(uri, tmp_urls, sizeof(tmp_urls)); + if (ret < 0) { + goto error; + } + + if (strlen(tmp_uurl) > 0) { + ret = snprintf(dst, size, "[K]: %s [data: %d] -- [U]: %s [data: %d]", + tmp_urls, kdata_port, tmp_uurl, udata_port); + } else { + ret = snprintf(dst, size, "%s [data: %d]", tmp_urls, kdata_port); + } + +error: + return ret; +} + /* * Using the session list, filled a lttng_session array to send back to the * client for session listing. @@ -2428,6 +2495,7 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid) static void list_lttng_sessions(struct lttng_session *sessions, uid_t uid, gid_t gid) { + int ret; unsigned int i = 0; struct ltt_session *session; @@ -2444,8 +2512,20 @@ static void list_lttng_sessions(struct lttng_session *sessions, uid_t uid, if (!session_access_ok(session, uid, gid)) { continue; } - strncpy(sessions[i].path, session->path, PATH_MAX); - sessions[i].path[PATH_MAX - 1] = '\0'; + + if (session->consumer->type == CONSUMER_DST_LOCAL && + (!session->kernel_session && !session->ust_session)) { + ret = snprintf(sessions[i].path, sizeof(session[i].path), "%s", + session->consumer->dst.trace_path); + } else { + ret = build_network_session_path(sessions[i].path, + sizeof(session[i].path), session); + } + if (ret < 0) { + PERROR("snprintf session path"); + continue; + } + strncpy(sessions[i].name, session->name, NAME_MAX); sessions[i].name[NAME_MAX - 1] = '\0'; sessions[i].enabled = session->enabled; @@ -2706,6 +2786,12 @@ static int add_uri_to_consumer(struct consumer_output *consumer, if (ret < 0) { ret = LTTCOMM_FATAL; goto error; + } else if (ret == 1) { + /* + * URI was the same in the consumer so we do not append the subdir + * again so to not duplicate output dir. + */ + goto error; } if (uri->stype == LTTNG_STREAM_CONTROL && strlen(uri->subdir) == 0) { @@ -3687,8 +3773,6 @@ static int cmd_create_session_uri(char *name, struct lttng_uri *uris, int ret; char *path = NULL; struct ltt_session *session; - //struct consumer_output *consumer = NULL; - //struct lttng_uri *ctrl_uri, *data_uri = NULL; assert(name); diff --git a/src/common/uri.c b/src/common/uri.c index e686f7c5d..ec5d42663 100644 --- a/src/common/uri.c +++ b/src/common/uri.c @@ -137,6 +137,40 @@ error: return -1; } +/* + * Build a string URL from a lttng_uri object. + */ +int uri_to_str_url(struct lttng_uri *uri, char *dst, size_t size) +{ + int ipver, ret; + const char *addr; + char proto[4], port[7]; + + assert(uri); + assert(dst); + + if (uri->dtype == LTTNG_DST_PATH) { + ipver = 0; + addr = uri->dst.path; + (void) snprintf(proto, sizeof(proto), "file"); + (void) snprintf(port, sizeof(port), "%s", ""); + } else { + ipver = (uri->dtype == LTTNG_DST_IPV4) ? 4 : 6; + addr = (ipver == 4) ? uri->dst.ipv4 : uri->dst.ipv6; + (void) snprintf(proto, sizeof(proto), "net%d", ipver); + (void) snprintf(port, sizeof(port), ":%d", uri->port); + } + + ret = snprintf(dst, size, "%s://%s%s%s%s/%s", proto, + (ipver == 6) ? "[" : "", addr, (ipver == 6) ? "]" : "", + port, uri->subdir); + if (ret < 0) { + PERROR("snprintf uri to url"); + } + + return ret; +} + /* * Compare two URIs. * diff --git a/src/common/uri.h b/src/common/uri.h index d768e8724..347b639b0 100644 --- a/src/common/uri.h +++ b/src/common/uri.h @@ -77,5 +77,6 @@ struct lttng_uri { int uri_compare(struct lttng_uri *uri1, struct lttng_uri *uri2); void uri_free(struct lttng_uri *uri); ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris); +int uri_to_str_url(struct lttng_uri *uri, char *dst, size_t size); #endif /* _LTT_URI_H */ diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index f18e8ca07..3bef3b6d7 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1549,7 +1549,7 @@ int _lttng_create_session_ext(const char *name, const char *url, 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, + ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s-%s", name, datetime); if (ret < 0) { PERROR("snprintf uri subdir"); -- 2.34.1