From: David Goulet Date: Tue, 7 Aug 2012 19:47:19 +0000 (-0400) Subject: Extend API and remove lttng_uri from lttng.h X-Git-Tag: v2.1.0-rc1~25 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=a4b92340642035d1eafeb1eead0ad01f64d2007d;p=lttng-tools.git Extend API and remove lttng_uri from lttng.h This is a big commit but actually not adding much. First, struct lttng_uri is removed from lttng.h and replaced by calls using string URL. The lttng_set_consumer_url is changed to "_url" taking an handle, a control and a data string URL. You can find the definition in proposal doc/proposals/0004-lttng-address-api.txt. The lttng_create_session_uri is removed and the path from the original lttng_create_session is now used to either pass a local filesystem full path or a string URL. Multiple fixes in uri_parse() also especially for IPv6 where address MUST be enclosed in brackets [] in the string representation. The help of lttng create and enable-consumer is updated and improved. Also, the enable-consumer command can now be used without a domain switch (-u/-k) so the destination URL is set to the global tracing session and on both UST and kernel session if there is an existing consumer. Signed-off-by: David Goulet --- diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 7754bcdbc..d421ca518 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -23,7 +23,6 @@ #define _LTTNG_H #include -#include #include #include @@ -141,63 +140,6 @@ enum lttng_health_component { LTTNG_HEALTH_ALL, }; -/* Destination type of lttng URI */ -enum lttng_dst_type { - LTTNG_DST_IPV4 = 1, - LTTNG_DST_IPV6 = 2, - LTTNG_DST_PATH = 3, -}; - -/* Type of lttng URI where it is a final destination or a hop */ -enum lttng_uri_type { - LTTNG_URI_DST, /* The URI is a final destination */ - /* - * Hop are not supported yet but planned for a future release. - * - LTTNG_URI_HOP, - */ -}; - -/* Communication stream type of a lttng URI */ -enum lttng_stream_type { - LTTNG_STREAM_CONTROL, - LTTNG_STREAM_DATA, -}; - -/* - * Protocol type of a lttng URI. The value 0 indicate that the proto_type field - * should be ignored. - */ -enum lttng_proto_type { - LTTNG_TCP = 1, - /* - * UDP protocol is not supported for now. - * - LTTNG_UDP = 2, - */ -}; - -/* - * Structure representing an URI supported by lttng. - */ -#define LTTNG_URI_PADDING1_LEN 16 -#define LTTNG_URI_PADDING2_LEN LTTNG_SYMBOL_NAME_LEN + 32 -struct lttng_uri { - enum lttng_dst_type dtype; - enum lttng_uri_type utype; - enum lttng_stream_type stype; - enum lttng_proto_type proto; - in_port_t port; - char padding[LTTNG_URI_PADDING1_LEN]; - char subdir[PATH_MAX]; - union { - char ipv4[INET_ADDRSTRLEN]; - char ipv6[INET6_ADDRSTRLEN]; - char path[PATH_MAX]; - char padding[LTTNG_URI_PADDING2_LEN]; - } dst; -}; - /* * The structures should be initialized to zero before use. */ @@ -421,18 +363,11 @@ extern struct lttng_handle *lttng_create_handle(const char *session_name, extern void lttng_destroy_handle(struct lttng_handle *handle); /* - * Create a tracing session using a name and a path where the trace will be - * written. - */ -extern int lttng_create_session(const char *name, const char *path); - -/* - * Create a tracing sessioin using a name, URIs and a consumer enable flag. - * The control URI is mandatory for consumer local or network. + * Create a tracing session using a name and an optional URL. + * + * If _url_ is NULL, no consumer is created for the session. */ -extern int lttng_create_session_uri(const char *name, - struct lttng_uri *ctrl_uri, struct lttng_uri *data_uri, - unsigned int enable_consumer); +extern int lttng_create_session(const char *name, const char *url); /* * Destroy a tracing session. @@ -610,14 +545,16 @@ extern void lttng_channel_set_default_attr(struct lttng_domain *domain, struct lttng_channel_attr *attr); /* - * Set URI for a consumer for a session and domain. + * Set URL for a consumer for a session and domain. + * + * Both data and control URL must be defined. If both URLs are the same, only + * the control URL is used even for network streaming. * - * For network streaming, both data and control stream type MUST be defined - * with a specific URIs. Default port are 5342 and 5343 respectively for - * control and data which uses the TCP protocol. + * Default port are 5342 and 5343 respectively for control and data which uses + * the TCP protocol. */ -extern int lttng_set_consumer_uri(struct lttng_handle *handle, - struct lttng_uri *uri); +extern int lttng_set_consumer_url(struct lttng_handle *handle, + const char *control_url, const char *data_url); /* * Enable the consumer for a session and domain. diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 7071974a1..9ff4eceb2 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -30,6 +30,51 @@ #include "consumer.h" +/* + * From a consumer_data structure, allocate and add a consumer socket to the + * consumer output. + * + * Return 0 on success, else negative value on error + */ +int consumer_create_socket(struct consumer_data *data, + struct consumer_output *output) +{ + int ret = 0; + struct consumer_socket *socket; + + assert(data); + + if (output == NULL || data->cmd_sock < 0) { + /* + * Not an error. Possible there is simply not spawned consumer or it's + * disabled for the tracing session asking the socket. + */ + goto error; + } + + rcu_read_lock(); + socket = consumer_find_socket(data->cmd_sock, output); + rcu_read_unlock(); + if (socket == NULL) { + socket = consumer_allocate_socket(data->cmd_sock); + if (socket == NULL) { + ret = -1; + goto error; + } + + socket->lock = &data->lock; + rcu_read_lock(); + consumer_add_socket(socket, output); + rcu_read_unlock(); + } + + DBG3("Consumer socket created (fd: %d) and added to output", + data->cmd_sock); + +error: + return ret; +} + /* * Find a consumer_socket in a consumer_output hashtable. Read side lock must * be acquired before calling this function and across use of the @@ -43,7 +88,7 @@ struct consumer_socket *consumer_find_socket(int key, struct consumer_socket *socket = NULL; /* Negative keys are lookup failures */ - if (key < 0) { + if (key < 0 || consumer == NULL) { return NULL; } diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index ab1765c48..68a51bb6c 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -144,6 +144,8 @@ int consumer_send_relayd_socket(int consumer_sock, enum lttng_stream_type type); int consumer_send_destroy_relayd(struct consumer_socket *sock, struct consumer_output *consumer); +int consumer_create_socket(struct consumer_data *data, + struct consumer_output *output); void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg, enum lttng_consumer_command cmd, diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 9049022f4..6fce7d84f 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -356,13 +356,13 @@ error: * Create kernel metadata, open from the kernel tracer and add it to the * kernel session. */ -int kernel_open_metadata(struct ltt_kernel_session *session, char *path) +int kernel_open_metadata(struct ltt_kernel_session *session) { int ret; struct ltt_kernel_metadata *lkm; /* Allocate kernel metadata */ - lkm = trace_kernel_create_metadata(path); + lkm = trace_kernel_create_metadata(); if (lkm == NULL) { goto error; } diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 0ef083073..4591e48f3 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -42,7 +42,7 @@ int kernel_disable_channel(struct ltt_kernel_channel *chan); int kernel_disable_event(struct ltt_kernel_event *event); int kernel_enable_event(struct ltt_kernel_event *event); int kernel_enable_channel(struct ltt_kernel_channel *chan); -int kernel_open_metadata(struct ltt_kernel_session *session, char *path); +int kernel_open_metadata(struct ltt_kernel_session *session); int kernel_open_metadata_stream(struct ltt_kernel_session *session); int kernel_open_channel_stream(struct ltt_kernel_channel *channel); int kernel_flush_buffer(struct ltt_kernel_channel *channel); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 6955c80b0..1e9c0be94 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2135,8 +2135,8 @@ static int setup_relayd(struct ltt_session *session) DBG2("Setting relayd for session %s", session->name); - if (usess && usess->consumer->type == CONSUMER_DST_NET && - usess->consumer->enabled) { + if (usess && usess->consumer && usess->consumer->type == CONSUMER_DST_NET + && usess->consumer->enabled) { /* For each consumer socket, send relayd sockets */ cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter, socket, node.node) { @@ -2151,8 +2151,10 @@ static int setup_relayd(struct ltt_session *session) goto error; } } - } else if (ksess && ksess->consumer->type == CONSUMER_DST_NET && - ksess->consumer->enabled) { + } + + if (ksess && ksess->consumer && ksess->consumer->type == CONSUMER_DST_NET + && ksess->consumer->enabled) { cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, socket, node.node) { /* Code flow error */ @@ -2183,6 +2185,9 @@ static int copy_session_consumer(int domain, struct ltt_session *session) const char *dir_name; struct consumer_output *consumer; + assert(session); + assert(session->consumer); + switch (domain) { case LTTNG_DOMAIN_KERNEL: DBG3("Copying tracing session consumer output in kernel session"); @@ -2209,12 +2214,6 @@ static int copy_session_consumer(int domain, struct ltt_session *session) strncat(consumer->subdir, dir_name, sizeof(consumer->subdir)); DBG3("Copy session consumer subdir %s", consumer->subdir); - /* Add default trace directory name */ - if (consumer->type == CONSUMER_DST_LOCAL) { - strncat(consumer->dst.trace_path, dir_name, - sizeof(consumer->dst.trace_path)); - } - ret = LTTCOMM_OK; error: @@ -2231,6 +2230,7 @@ static int create_ust_session(struct ltt_session *session, struct ltt_ust_session *lus = NULL; assert(session); + assert(domain); assert(session->consumer); switch (domain->type) { @@ -2250,18 +2250,6 @@ static int create_ust_session(struct ltt_session *session, goto error; } - if (session->consumer->type == CONSUMER_DST_LOCAL) { - ret = run_as_mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG, - session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_UST_SESS_FAIL; - goto error; - } - } - } - lus->uid = session->uid; lus->gid = session->gid; session->ust_session = lus; @@ -2295,6 +2283,9 @@ static int create_kernel_session(struct ltt_session *session) goto error; } + /* Code flow safety */ + assert(session->kernel_session); + /* Copy session output to the newly created Kernel session */ ret = copy_session_consumer(LTTNG_DOMAIN_KERNEL, session); if (ret != LTTCOMM_OK) { @@ -2302,7 +2293,8 @@ static int create_kernel_session(struct ltt_session *session) } /* Create directory(ies) on local filesystem. */ - if (session->consumer->type == CONSUMER_DST_LOCAL) { + if (session->kernel_session->consumer->type == CONSUMER_DST_LOCAL && + strlen(session->kernel_session->consumer->dst.trace_path) > 0) { ret = run_as_mkdir_recursive( session->kernel_session->consumer->dst.trace_path, S_IRWXU | S_IRWXG, session->uid, session->gid); @@ -2604,6 +2596,77 @@ error: return ret; } + +/* + * Add URI so the consumer output object. Set the correct path depending on the + * domain adding the default trace directory. + */ +static int add_uri_to_consumer(struct consumer_output *consumer, + struct lttng_uri *uri, int domain) +{ + int ret; + const char *default_trace_dir; + + assert(uri); + + if (consumer == NULL) { + DBG("No consumer detected. Don't add URI. Stopping."); + ret = LTTCOMM_NO_CONSUMER; + goto error; + } + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + default_trace_dir = DEFAULT_KERNEL_TRACE_DIR; + break; + case LTTNG_DOMAIN_UST: + default_trace_dir = DEFAULT_UST_TRACE_DIR; + break; + default: + /* + * This case is possible is we try to add the URI to the global tracing + * session consumer object which in this case there is no subdir. + */ + default_trace_dir = ""; + } + + switch (uri->dtype) { + case LTTNG_DST_IPV4: + case LTTNG_DST_IPV6: + DBG2("Setting network URI to consumer"); + + /* Set URI into consumer output object */ + ret = consumer_set_network_uri(consumer, uri); + if (ret < 0) { + ret = LTTCOMM_FATAL; + 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)); + } + + break; + case LTTNG_DST_PATH: + DBG2("Setting trace directory path from URI to %s", uri->dst.path); + memset(consumer->dst.trace_path, 0, + sizeof(consumer->dst.trace_path)); + strncpy(consumer->dst.trace_path, uri->dst.path, + sizeof(consumer->dst.trace_path)); + /* Append default trace dir */ + strncat(consumer->dst.trace_path, default_trace_dir, + sizeof(consumer->dst.trace_path)); + /* Flag consumer as local. */ + consumer->type = CONSUMER_DST_LOCAL; + break; + } + +error: + return ret; +} + /* * Command LTTNG_DISABLE_CHANNEL processed by the client thread. */ @@ -3289,8 +3352,7 @@ static int cmd_start_trace(struct ltt_session *session) if (ksession != NULL) { /* Open kernel metadata */ if (ksession->metadata == NULL) { - ret = kernel_open_metadata(ksession, - ksession->consumer->dst.trace_path); + ret = kernel_open_metadata(ksession); if (ret < 0) { ret = LTTCOMM_KERN_META_FAIL; goto error; @@ -3422,38 +3484,102 @@ error: } /* - * Command LTTNG_CREATE_SESSION_URI processed by the client thread. + * Command LTTNG_CREATE_SESSION processed by the client thread. */ -static int cmd_create_session_uri(char *name, struct lttng_uri *ctrl_uri, - struct lttng_uri *data_uri, unsigned int enable_consumer, - lttng_sock_cred *creds) +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; + int ret, have_default_name = 0; + char *path = NULL, datetime[16]; struct ltt_session *session; - struct consumer_output *consumer; + 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 */ + /* + * 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 error; + goto consumer_error; } - /* TODO: validate URIs */ - - /* Create default consumer output */ + /* 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; + } + + /* 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"); goto error; } - strncpy(consumer->subdir, ctrl_uri->subdir, sizeof(consumer->subdir)); - DBG2("Consumer subdir set to %s", consumer->subdir); + 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. + */ + 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 skip_consumer; + } + + /* TODO: validate URIs */ + + ctrl_uri = &uris[0]; + if (nb_uri > 1) { + data_uri = &uris[1]; + } + + /* 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); + } 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); + /* Set control URI into consumer output object */ ret = consumer_set_network_uri(consumer, ctrl_uri); if (ret < 0) { @@ -3479,53 +3605,50 @@ static int cmd_create_session_uri(char *name, struct lttng_uri *ctrl_uri, break; } - /* Set if the consumer is enabled or not */ - consumer->enabled = enable_consumer; + consumer->enabled = 1; +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 consumer_error; + goto error; } - /* Get the newly created session pointer back */ + /* + * Get the newly created session pointer back + * + * 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); assert(session); /* Assign consumer to session */ session->consumer = consumer; - return LTTCOMM_OK; - -consumer_error: - consumer_destroy_output(consumer); -error: - return ret; -} - -/* - * Command LTTNG_CREATE_SESSION processed by the client thread. - */ -static int cmd_create_session(char *name, char *path, lttng_sock_cred *creds) -{ - int ret; - struct lttng_uri uri; - - /* Zeroed temporary URI */ - memset(&uri, 0, sizeof(uri)); - - uri.dtype = LTTNG_DST_PATH; - uri.utype = LTTNG_URI_DST; - strncpy(uri.dst.path, path, sizeof(uri.dst.path)); - - /* TODO: Strip date-time from path and put it in uri's subdir */ - - ret = cmd_create_session_uri(name, &uri, NULL, 1, creds); - if (ret != LTTCOMM_OK) { - goto 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); + } + if (ret < 0) { + PERROR("snprintf session path"); + goto session_error; } + return LTTCOMM_OK; + +session_error: + session_destroy(session); error: + consumer_destroy_output(consumer); +consumer_error: return ret; } @@ -3787,12 +3910,16 @@ error: * Command LTTNG_SET_CONSUMER_URI processed by the client thread. */ static int cmd_set_consumer_uri(int domain, struct ltt_session *session, - struct lttng_uri *uri) + size_t nb_uri, struct lttng_uri *uris) { - int ret; + int ret, i; struct ltt_kernel_session *ksess = session->kernel_session; struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer; + struct consumer_output *consumer = NULL; + + assert(session); + assert(uris); + assert(nb_uri > 0); /* Can't enable consumer after session started. */ if (session->enabled) { @@ -3800,14 +3927,29 @@ static int cmd_set_consumer_uri(int domain, struct ltt_session *session, 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: - { - struct lttng_ht_iter iter; - struct consumer_socket *socket; - /* Code flow error if we don't have a kernel session here. */ assert(ksess); + assert(ksess->consumer); /* Create consumer output if none exists */ consumer = ksess->tmp_consumer; @@ -3817,58 +3959,10 @@ static int cmd_set_consumer_uri(int domain, struct ltt_session *session, ret = LTTCOMM_FATAL; goto error; } - /* Reassign new pointer */ ksess->tmp_consumer = consumer; } - switch (uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - DBG2("Setting network URI for kernel session %s", session->name); - - /* Set URI into consumer output object */ - ret = consumer_set_network_uri(consumer, uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* On a new subdir, reappend the default trace dir. */ - if (strlen(uri->subdir) != 0) { - strncat(consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, - sizeof(consumer->subdir)); - } - - cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, - socket, node.node) { - /* Code flow error */ - assert(socket->fd >= 0); - - pthread_mutex_lock(socket->lock); - ret = send_socket_relayd_consumer(domain, session, uri, consumer, - socket->fd); - pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { - goto error; - } - } - - break; - case LTTNG_DST_PATH: - DBG2("Setting trace directory path from URI to %s", uri->dst.path); - memset(consumer->dst.trace_path, 0, - sizeof(consumer->dst.trace_path)); - strncpy(consumer->dst.trace_path, uri->dst.path, - sizeof(consumer->dst.trace_path)); - /* Append default kernel trace dir */ - strncat(consumer->dst.trace_path, DEFAULT_KERNEL_TRACE_DIR, - sizeof(consumer->dst.trace_path)); - break; - } - - /* All good! */ break; - } case LTTNG_DOMAIN_UST: /* Code flow error if we don't have a kernel session here. */ assert(usess); @@ -3881,70 +3975,41 @@ static int cmd_set_consumer_uri(int domain, struct ltt_session *session, ret = LTTCOMM_FATAL; goto error; } - /* Reassign new pointer */ usess->tmp_consumer = consumer; } - switch (uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - { - struct consumer_socket *socket; + break; + } - DBG2("Setting network URI for UST session %s", session->name); + for (i = 0; i < nb_uri; i++) { + struct consumer_socket *socket; + struct lttng_ht_iter iter; - /* Set URI into consumer object */ - ret = consumer_set_network_uri(consumer, uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } + ret = add_uri_to_consumer(consumer, &uris[i], domain); + if (ret < 0) { + goto error; + } - /* On a new subdir, reappend the default trace dir. */ - if (strlen(uri->subdir) != 0) { - strncat(consumer->subdir, DEFAULT_UST_TRACE_DIR, - sizeof(consumer->subdir)); - } + /* Don't send relayd socket if URI is NOT remote */ + if (uris[i].dtype == LTTNG_DST_PATH) { + continue; + } - rcu_read_lock(); - socket = consumer_find_socket(uatomic_read(&ust_consumerd64_fd), - consumer); - if (socket != NULL) { - pthread_mutex_lock(socket->lock); - ret = send_socket_relayd_consumer(domain, session, uri, - consumer, socket->fd); - pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { - goto error; - } - } + /* Try to send relayd URI to the consumer if exist. */ + cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, + socket, node.node) { - socket = consumer_find_socket(uatomic_read(&ust_consumerd32_fd), - consumer); - if (socket != NULL) { - pthread_mutex_lock(socket->lock); - ret = send_socket_relayd_consumer(domain, session, uri, - consumer, socket->fd); - pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { - goto error; - } + /* 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; } - rcu_read_unlock(); - break; } - case LTTNG_DST_PATH: - DBG2("Setting trace directory path from URI to %s", uri->dst.path); - memset(consumer->dst.trace_path, 0, - sizeof(consumer->dst.trace_path)); - strncpy(consumer->dst.trace_path, uri->dst.path, - sizeof(consumer->dst.trace_path)); - /* Append default UST trace dir */ - strncat(consumer->dst.trace_path, DEFAULT_UST_TRACE_DIR, - sizeof(consumer->dst.trace_path)); - break; - } - break; } /* All good! */ @@ -3964,13 +4029,24 @@ static int cmd_disable_consumer(int domain, struct ltt_session *session) struct ltt_ust_session *usess = session->ust_session; struct consumer_output *consumer; + assert(session); + if (session->enabled) { /* Can't disable consumer on an already started session */ ret = LTTCOMM_TRACE_ALREADY_STARTED; goto error; } + if (!session->start_consumer) { + ret = LTTCOMM_NO_CONSUMER; + goto error; + } + switch (domain) { + case 0: + DBG("Disable tracing session %s consumer", session->name); + consumer = session->consumer; + break; case LTTNG_DOMAIN_KERNEL: /* Code flow error if we don't have a kernel session here. */ assert(ksess); @@ -3992,11 +4068,13 @@ static int cmd_disable_consumer(int domain, struct ltt_session *session) goto error; } - assert(consumer); - consumer->enabled = 0; - - /* Success at this point */ - ret = LTTCOMM_OK; + if (consumer) { + consumer->enabled = 0; + /* Success at this point */ + ret = LTTCOMM_OK; + } else { + ret = LTTCOMM_NO_CONSUMER; + } error: return ret; @@ -4010,7 +4088,9 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) int ret; struct ltt_kernel_session *ksess = session->kernel_session; struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *tmp_out; + struct consumer_output *consumer = NULL; + + assert(session); /* Can't enable consumer after session started. */ if (session->enabled) { @@ -4018,7 +4098,16 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } + if (!session->start_consumer) { + ret = LTTCOMM_NO_CONSUMER; + goto error; + } + switch (domain) { + case 0: + assert(session->consumer); + consumer = session->consumer; + break; case LTTNG_DOMAIN_KERNEL: /* Code flow error if we don't have a kernel session here. */ assert(ksess); @@ -4033,20 +4122,21 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } - tmp_out = ksess->tmp_consumer; - if (tmp_out == NULL) { + consumer = ksess->tmp_consumer; + if (consumer == NULL) { + ret = LTTCOMM_OK; /* No temp. consumer output exists. Using the current one. */ DBG3("No temporary consumer. Using default"); - ret = LTTCOMM_OK; + consumer = ksess->consumer; goto error; } - switch (tmp_out->type) { + switch (consumer->type) { case CONSUMER_DST_LOCAL: DBG2("Consumer output is local. Creating directory(ies)"); /* Create directory(ies) */ - ret = run_as_mkdir_recursive(tmp_out->dst.trace_path, + ret = run_as_mkdir_recursive(consumer->dst.trace_path, S_IRWXU | S_IRWXG, session->uid, session->gid); if (ret < 0) { if (ret != -EEXIST) { @@ -4059,13 +4149,13 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) case CONSUMER_DST_NET: DBG2("Consumer output is network. Validating URIs"); /* Validate if we have both control and data path set. */ - if (!tmp_out->dst.net.control_isset) { - ret = LTTCOMM_URI_CTRL_MISS; + if (!consumer->dst.net.control_isset) { + ret = LTTCOMM_URL_CTRL_MISS; goto error; } - if (!tmp_out->dst.net.data_isset) { - ret = LTTCOMM_URI_DATA_MISS; + if (!consumer->dst.net.data_isset) { + ret = LTTCOMM_URL_DATA_MISS; goto error; } @@ -4091,7 +4181,7 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) * is valid. */ consumer_destroy_output(ksess->consumer); - ksess->consumer = tmp_out; + ksess->consumer = consumer; ksess->tmp_consumer = NULL; break; @@ -4109,20 +4199,21 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } - tmp_out = usess->tmp_consumer; - if (tmp_out == NULL) { + consumer = usess->tmp_consumer; + if (consumer == NULL) { + ret = LTTCOMM_OK; /* No temp. consumer output exists. Using the current one. */ DBG3("No temporary consumer. Using default"); - ret = LTTCOMM_OK; + consumer = usess->consumer; goto error; } - switch (tmp_out->type) { + switch (consumer->type) { case CONSUMER_DST_LOCAL: DBG2("Consumer output is local. Creating directory(ies)"); /* Create directory(ies) */ - ret = run_as_mkdir_recursive(tmp_out->dst.trace_path, + ret = run_as_mkdir_recursive(consumer->dst.trace_path, S_IRWXU | S_IRWXG, session->uid, session->gid); if (ret < 0) { if (ret != -EEXIST) { @@ -4135,13 +4226,13 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) case CONSUMER_DST_NET: DBG2("Consumer output is network. Validating URIs"); /* Validate if we have both control and data path set. */ - if (!tmp_out->dst.net.control_isset) { - ret = LTTCOMM_URI_CTRL_MISS; + if (!consumer->dst.net.control_isset) { + ret = LTTCOMM_URL_CTRL_MISS; goto error; } - if (!tmp_out->dst.net.data_isset) { - ret = LTTCOMM_URI_DATA_MISS; + if (!consumer->dst.net.data_isset) { + ret = LTTCOMM_URL_DATA_MISS; goto error; } @@ -4152,7 +4243,7 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) goto error; } - if (tmp_out->net_seq_index == -1) { + if (consumer->net_seq_index == -1) { ret = LTTCOMM_ENABLE_CONSUMER_FAIL; DBG2("Network index is not set on the consumer"); goto error; @@ -4173,14 +4264,21 @@ static int cmd_enable_consumer(int domain, struct ltt_session *session) * is valid. */ consumer_destroy_output(usess->consumer); - usess->consumer = tmp_out; + usess->consumer = consumer; usess->tmp_consumer = NULL; break; } - /* Success at this point */ - ret = LTTCOMM_OK; + /* Enable it */ + if (consumer) { + consumer->enabled = 1; + /* Success at this point */ + ret = LTTCOMM_OK; + } else { + /* Should not really happend... */ + ret = LTTCOMM_NO_CONSUMER; + } error: return ret; @@ -4208,7 +4306,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: - case LTTNG_CREATE_SESSION_URI: case LTTNG_DESTROY_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_DOMAINS: @@ -4255,7 +4352,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Commands that DO NOT need a session. */ switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: - case LTTNG_CREATE_SESSION_URI: case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: @@ -4289,6 +4385,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, if (!need_domain) { goto skip_domain; } + /* * Check domain type for specific "pre-action". */ @@ -4316,8 +4413,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Need a session for kernel command */ if (need_tracing_session) { - struct consumer_socket *socket; - if (cmd_ctx->session->kernel_session == NULL) { ret = create_kernel_session(cmd_ctx->session); if (ret < 0) { @@ -4329,7 +4424,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Start the kernel consumer daemon */ pthread_mutex_lock(&kconsumer_data.pid_mutex); if (kconsumer_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&kconsumer_data.pid_mutex); ret = start_consumerd(&kconsumer_data); if (ret < 0) { @@ -4341,24 +4437,14 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, pthread_mutex_unlock(&kconsumer_data.pid_mutex); } - /* Set kernel consumer socket fd */ - if (kconsumer_data.cmd_sock >= 0) { - rcu_read_lock(); - socket = consumer_find_socket(kconsumer_data.cmd_sock, - cmd_ctx->session->kernel_session->consumer); - rcu_read_unlock(); - if (socket == NULL) { - socket = consumer_allocate_socket(kconsumer_data.cmd_sock); - if (socket == NULL) { - goto error; - } - - socket->lock = &kconsumer_data.lock; - rcu_read_lock(); - consumer_add_socket(socket, - cmd_ctx->session->kernel_session->consumer); - rcu_read_unlock(); - } + /* + * The consumer was just spawned so we need to add the socket to + * the consumer output of the session if exist. + */ + ret = consumer_create_socket(&kconsumer_data, + cmd_ctx->session->kernel_session->consumer); + if (ret < 0) { + goto error; } } @@ -4372,8 +4458,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, } if (need_tracing_session) { - struct consumer_socket *socket; - + /* Create UST session if none exist. */ if (cmd_ctx->session->ust_session == NULL) { ret = create_ust_session(cmd_ctx->session, &cmd_ctx->lsm->domain); @@ -4387,7 +4472,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, pthread_mutex_lock(&ustconsumer64_data.pid_mutex); if (consumerd64_bin[0] != '\0' && ustconsumer64_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&ustconsumer64_data.pid_mutex); ret = start_consumerd(&ustconsumer64_data); if (ret < 0) { @@ -4406,30 +4492,17 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, * Setup socket for consumer 64 bit. No need for atomic access * since it was set above and can ONLY be set in this thread. */ - if (ust_consumerd64_fd >= 0) { - rcu_read_lock(); - socket = consumer_find_socket(uatomic_read(&ust_consumerd64_fd), - cmd_ctx->session->ust_session->consumer); - rcu_read_unlock(); - if (socket == NULL) { - socket = consumer_allocate_socket(ust_consumerd64_fd); - if (socket == NULL) { - goto error; - } - socket->lock = &ustconsumer32_data.lock; - - rcu_read_lock(); - consumer_add_socket(socket, - cmd_ctx->session->ust_session->consumer); - rcu_read_unlock(); - } - DBG3("UST consumer 64 bit socket set to %d", socket->fd); + ret = consumer_create_socket(&ustconsumer64_data, + cmd_ctx->session->ust_session->consumer); + if (ret < 0) { + goto error; } /* 32-bit */ if (consumerd32_bin[0] != '\0' && ustconsumer32_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&ustconsumer32_data.pid_mutex); ret = start_consumerd(&ustconsumer32_data); if (ret < 0) { @@ -4448,24 +4521,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, * Setup socket for consumer 64 bit. No need for atomic access * since it was set above and can ONLY be set in this thread. */ - if (ust_consumerd32_fd >= 0) { - rcu_read_lock(); - socket = consumer_find_socket(uatomic_read(&ust_consumerd64_fd), - cmd_ctx->session->ust_session->consumer); - rcu_read_unlock(); - if (socket == NULL) { - socket = consumer_allocate_socket(ust_consumerd32_fd); - if (socket == NULL) { - goto error; - } - socket->lock = &ustconsumer32_data.lock; - - rcu_read_lock(); - consumer_add_socket(socket, - cmd_ctx->session->ust_session->consumer); - rcu_read_unlock(); - } - DBG3("UST consumer 32 bit socket set to %d", socket->fd); + ret = consumer_create_socket(&ustconsumer32_data, + cmd_ctx->session->ust_session->consumer); + if (ret < 0) { + goto error; } } break; @@ -4551,7 +4610,26 @@ skip_domain: } case LTTNG_ENABLE_CONSUMER: { + /* + * XXX: 0 means that this URI should be applied on the session. Should + * be a DOMAIN enuam. + */ ret = cmd_enable_consumer(cmd_ctx->lsm->domain.type, cmd_ctx->session); + if (ret != LTTCOMM_OK) { + goto error; + } + + if (cmd_ctx->lsm->domain.type == 0) { + /* Add the URI for the UST session if a consumer is present. */ + if (cmd_ctx->session->ust_session && + cmd_ctx->session->ust_session->consumer) { + ret = cmd_enable_consumer(LTTNG_DOMAIN_UST, cmd_ctx->session); + } else if (cmd_ctx->session->kernel_session && + cmd_ctx->session->kernel_session->consumer) { + ret = cmd_enable_consumer(LTTNG_DOMAIN_KERNEL, + cmd_ctx->session); + } + } break; } case LTTNG_ENABLE_EVENT: @@ -4605,7 +4683,8 @@ skip_domain: struct lttng_event_field *fields; ssize_t nb_fields; - nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type, &fields); + nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type, + &fields); if (nb_fields < 0) { ret = -nb_fields; goto error; @@ -4615,7 +4694,8 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event_field) * nb_fields); + ret = setup_lttng_msg(cmd_ctx, + sizeof(struct lttng_event_field) * nb_fields); if (ret < 0) { free(fields); goto setup_error; @@ -4632,8 +4712,56 @@ skip_domain: } case LTTNG_SET_CONSUMER_URI: { + size_t nb_uri, len; + struct lttng_uri *uris; + + nb_uri = cmd_ctx->lsm->u.uri.size; + len = nb_uri * sizeof(struct lttng_uri); + + if (nb_uri == 0) { + ret = LTTCOMM_INVALID; + goto error; + } + + uris = zmalloc(len); + if (uris == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + + /* Receive variable len data */ + DBG("Receiving %lu URI(s) from client ...", nb_uri); + ret = lttcomm_recv_unix_sock(sock, uris, len); + if (ret <= 0) { + DBG("No URIs received from client... continuing"); + *sock_error = 1; + ret = LTTCOMM_SESSION_FAIL; + goto error; + } + ret = cmd_set_consumer_uri(cmd_ctx->lsm->domain.type, cmd_ctx->session, - &cmd_ctx->lsm->u.uri); + nb_uri, uris); + if (ret != LTTCOMM_OK) { + goto error; + } + + /* + * XXX: 0 means that this URI should be applied on the session. Should + * be a DOMAIN enuam. + */ + if (cmd_ctx->lsm->domain.type == 0) { + /* Add the URI for the UST session if a consumer is present. */ + if (cmd_ctx->session->ust_session && + cmd_ctx->session->ust_session->consumer) { + ret = cmd_set_consumer_uri(LTTNG_DOMAIN_UST, cmd_ctx->session, + nb_uri, uris); + } else if (cmd_ctx->session->kernel_session && + cmd_ctx->session->kernel_session->consumer) { + ret = cmd_set_consumer_uri(LTTNG_DOMAIN_KERNEL, + cmd_ctx->session, nb_uri, uris); + } + } + break; } case LTTNG_START_TRACE: @@ -4648,26 +4776,47 @@ skip_domain: } case LTTNG_CREATE_SESSION: { - ret = cmd_create_session(cmd_ctx->lsm->session.name, - cmd_ctx->lsm->session.path, &cmd_ctx->creds); - break; - } - case LTTNG_CREATE_SESSION_URI: - { - ret = cmd_create_session_uri(cmd_ctx->lsm->session.name, - &cmd_ctx->lsm->u.create_uri.ctrl_uri, - &cmd_ctx->lsm->u.create_uri.data_uri, - cmd_ctx->lsm->u.create_uri.enable_consumer, &cmd_ctx->creds); + size_t nb_uri, len; + struct lttng_uri *uris = NULL; + + nb_uri = cmd_ctx->lsm->u.uri.size; + len = nb_uri * sizeof(struct lttng_uri); + + if (nb_uri > 0) { + uris = zmalloc(len); + if (uris == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + + /* Receive variable len data */ + DBG("Waiting for %lu URIs from client ...", nb_uri); + ret = lttcomm_recv_unix_sock(sock, uris, len); + if (ret <= 0) { + DBG("No URIs received from client... continuing"); + *sock_error = 1; + ret = LTTCOMM_SESSION_FAIL; + goto error; + } + + if (nb_uri == 1 && uris[0].dtype != LTTNG_DST_PATH) { + DBG("Creating session with ONE network URI is a bad call"); + ret = LTTCOMM_SESSION_FAIL; + goto error; + } + } + + ret = cmd_create_session_uri(cmd_ctx->lsm->session.name, uris, nb_uri, + &cmd_ctx->creds); + break; } case LTTNG_DESTROY_SESSION: { ret = cmd_destroy_session(cmd_ctx->session, cmd_ctx->lsm->session.name); - /* - * Set session to NULL so we do not unlock it after - * free. - */ + + /* Set session to NULL so we do not unlock it after free. */ cmd_ctx->session = NULL; break; } diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index 2181c0dd5..e445363ea 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -188,10 +188,11 @@ int session_create(char *name, char *path, uid_t uid, gid_t gid) ret = LTTCOMM_FATAL; goto error_asprintf; } + new_session->start_consumer = 1; } else { - ERR("No session path given"); - ret = LTTCOMM_FATAL; - goto error; + /* No path indicates that there is no use for a consumer. */ + new_session->start_consumer = 0; + new_session->path[0] = '\0'; } /* Init kernel session */ @@ -204,7 +205,7 @@ int session_create(char *name, char *path, uid_t uid, gid_t gid) new_session->uid = uid; new_session->gid = gid; - /* Mkdir if we have a valid path length */ + /* Mkdir if we have a valid path and length */ if (strlen(new_session->path) > 0) { ret = run_as_mkdir_recursive(new_session->path, S_IRWXU | S_IRWXG, new_session->uid, new_session->gid); @@ -222,9 +223,13 @@ int session_create(char *name, char *path, uid_t uid, gid_t gid) new_session->id = add_session_list(new_session); session_unlock_list(); - DBG("Tracing session %s created in %s with ID %u by UID %d GID %d", - name, path, new_session->id, - new_session->uid, new_session->gid); + /* + * Consumer is let to NULL since the create_session_uri command will set it + * up and, if valid, assign it to the session. + */ + + DBG("Tracing session %s created in %s with ID %u by UID %d GID %d", name, + path, new_session->id, new_session->uid, new_session->gid); return LTTCOMM_OK; diff --git a/src/bin/lttng-sessiond/session.h b/src/bin/lttng-sessiond/session.h index 167ea9c05..b90e8f467 100644 --- a/src/bin/lttng-sessiond/session.h +++ b/src/bin/lttng-sessiond/session.h @@ -82,6 +82,9 @@ struct ltt_session { * copied into those sessions. */ struct consumer_output *consumer; + + /* Indicates whether or not we have to spawn consumer(s) */ + unsigned int start_consumer; }; /* Prototypes */ diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index c0239d4bb..7748b891f 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -86,13 +86,13 @@ error: struct ltt_kernel_session *trace_kernel_create_session(char *path) { int ret; - struct ltt_kernel_session *lks; + struct ltt_kernel_session *lks = NULL; /* Allocate a new ltt kernel session */ lks = zmalloc(sizeof(struct ltt_kernel_session)); if (lks == NULL) { PERROR("create kernel session zmalloc"); - goto error; + goto alloc_error; } /* Init data structure */ @@ -103,7 +103,6 @@ struct ltt_kernel_session *trace_kernel_create_session(char *path) lks->metadata = NULL; CDS_INIT_LIST_HEAD(&lks->channel_list.head); - /* Create default consumer output object */ lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); if (lks->consumer == NULL) { goto error; @@ -117,23 +116,29 @@ struct ltt_kernel_session *trace_kernel_create_session(char *path) */ lks->tmp_consumer = NULL; - /* Use the default consumer output which is the tracing session path. */ - ret = snprintf(lks->consumer->dst.trace_path, PATH_MAX, "%s/kernel", path); - if (ret < 0) { - PERROR("snprintf consumer trace path"); - goto error; - } + if (path && strlen(path) > 0) { + /* Use the default consumer output which is the tracing session path. */ + ret = snprintf(lks->consumer->dst.trace_path, PATH_MAX, + "%s" DEFAULT_KERNEL_TRACE_DIR, path); + if (ret < 0) { + PERROR("snprintf consumer trace path"); + goto error; + } - /* Set session path */ - ret = asprintf(&lks->trace_path, "%s/kernel", path); - if (ret < 0) { - PERROR("asprintf kernel traces path"); - goto error; + /* Set session path */ + ret = asprintf(&lks->trace_path, "%s" DEFAULT_KERNEL_TRACE_DIR, path); + if (ret < 0) { + PERROR("asprintf kernel traces path"); + goto error; + } } return lks; error: + free(lks); + +alloc_error: return NULL; } @@ -253,7 +258,7 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_kernel_metadata *trace_kernel_create_metadata(char *path) +struct ltt_kernel_metadata *trace_kernel_create_metadata(void) { struct ltt_kernel_metadata *lkm; struct lttng_channel *chan; diff --git a/src/bin/lttng-sessiond/trace-kernel.h b/src/bin/lttng-sessiond/trace-kernel.h index d34b83c8c..f04d9e7b5 100644 --- a/src/bin/lttng-sessiond/trace-kernel.h +++ b/src/bin/lttng-sessiond/trace-kernel.h @@ -122,7 +122,7 @@ struct ltt_kernel_channel *trace_kernel_get_channel_by_name( struct ltt_kernel_session *trace_kernel_create_session(char *path); struct ltt_kernel_channel *trace_kernel_create_channel(struct lttng_channel *chan, char *path); struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev); -struct ltt_kernel_metadata *trace_kernel_create_metadata(char *path); +struct ltt_kernel_metadata *trace_kernel_create_metadata(void); struct ltt_kernel_stream *trace_kernel_create_stream(const char *name, unsigned int count); diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 4001ec87b..d1e8b8dae 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -111,7 +111,7 @@ struct ltt_ust_session *trace_ust_create_session(char *path, lus->consumer = consumer_create_output(CONSUMER_DST_LOCAL); if (lus->consumer == NULL) { - goto error; + goto error_free_session; } /* @@ -123,17 +123,21 @@ struct ltt_ust_session *trace_ust_create_session(char *path, lus->tmp_consumer = NULL; /* Use the default consumer output which is the tracing session path. */ - ret = snprintf(lus->consumer->dst.trace_path, PATH_MAX, "%s/ust", path); - if (ret < 0) { - PERROR("snprintf UST consumer trace path"); - goto error; - } + if (path && strlen(path) > 0) { + ret = snprintf(lus->consumer->dst.trace_path, PATH_MAX, + "%s" DEFAULT_UST_TRACE_DIR, path); + if (ret < 0) { + PERROR("snprintf UST consumer trace path"); + goto error; + } - /* Set session path */ - ret = snprintf(lus->pathname, PATH_MAX, "%s/ust", path); - if (ret < 0) { - PERROR("snprintf kernel traces path"); - goto error_free_session; + /* Set session path */ + ret = snprintf(lus->pathname, PATH_MAX, "%s" DEFAULT_UST_TRACE_DIR, + path); + if (ret < 0) { + PERROR("snprintf kernel traces path"); + goto error_free_session; + } } DBG2("UST trace session create successful"); diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 087846df1..e5d8b5707 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -2177,6 +2177,20 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) goto skip_setup; } + /* Create directories if consumer is LOCAL and has a path defined. */ + if (usess->consumer->type == CONSUMER_DST_LOCAL && + strlen(usess->consumer->dst.trace_path) > 0) { + ret = run_as_mkdir_recursive(usess->consumer->dst.trace_path, + S_IRWXU | S_IRWXG, usess->uid, usess->gid); + if (ret < 0) { + if (ret != -EEXIST) { + ERR("Trace directory creation error"); + ret = -1; + goto error_rcu_unlock; + } + } + } + /* Indicate that the session has been started once */ ua_sess->started = 1; diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c index b7e0d3592..aabe49403 100644 --- a/src/bin/lttng-sessiond/ust-consumer.c +++ b/src/bin/lttng-sessiond/ust-consumer.c @@ -136,8 +136,8 @@ static int send_channel_streams(int sock, /* Get the right path name destination */ if (consumer->type == CONSUMER_DST_LOCAL) { /* Set application path to the destination path */ - ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s", - consumer->dst.trace_path, usess->path); + ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s/%s", + consumer->dst.trace_path, consumer->subdir, usess->path); if (ret < 0) { PERROR("snprintf stream path"); goto error; @@ -225,8 +225,8 @@ static int send_metadata(int sock, struct ust_app_session *usess, /* Get correct path name destination */ if (consumer->type == CONSUMER_DST_LOCAL) { /* Set application path to the destination path */ - ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s", - consumer->dst.trace_path, usess->path); + ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s/%s", + consumer->dst.trace_path, consumer->subdir, usess->path); if (ret < 0) { PERROR("snprintf stream path"); goto error; @@ -289,8 +289,12 @@ int ust_consumer_send_session(struct ust_app_session *usess, struct ust_app_channel *ua_chan; assert(usess); - assert(consumer); - assert(sock); + + if (consumer == NULL || sock == NULL) { + /* There is no consumer so just ignoring the command. */ + DBG("UST consumer does not exist. Not sending streams"); + return 0; + } DBG("Sending metadata stream fd to consumer on %d", sock->fd); diff --git a/src/bin/lttng/commands/create.c b/src/bin/lttng/commands/create.c index 354a68dcf..3e7074e02 100644 --- a/src/bin/lttng/commands/create.c +++ b/src/bin/lttng/commands/create.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -35,10 +36,11 @@ static char *opt_output_path; static char *opt_session_name; -static char *opt_uris; -static char *opt_ctrl_uris; -static char *opt_data_uris; -static int opt_no_consumer = 1; +static char *opt_url; +static char *opt_ctrl_url; +static char *opt_data_url; +static int opt_no_consumer; +static int opt_disable_consumer; enum { OPT_HELP = 1, @@ -50,10 +52,11 @@ static struct poptOption long_options[] = { {"help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL}, {"output", 'o', POPT_ARG_STRING, &opt_output_path, 0, NULL, NULL}, {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, - {"set-uri", 'U', POPT_ARG_STRING, &opt_uris, 0, 0, 0}, - {"ctrl-uri", 'C', POPT_ARG_STRING, &opt_ctrl_uris, 0, 0, 0}, - {"data-uri", 'D', POPT_ARG_STRING, &opt_data_uris, 0, 0, 0}, - {"no-consumer", 0, POPT_ARG_NONE, &opt_no_consumer, 0, 0, 0}, + {"set-uri", 'U', POPT_ARG_STRING, &opt_url, 0, 0, 0}, + {"ctrl-uri", 'C', POPT_ARG_STRING, &opt_ctrl_url, 0, 0, 0}, + {"data-uri", 'D', POPT_ARG_STRING, &opt_data_url, 0, 0, 0}, + {"no-consumer", 0, POPT_ARG_VAL, &opt_no_consumer, 1, 0, 0}, + {"disable-consumer", 0, POPT_ARG_VAL, &opt_disable_consumer, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0} }; @@ -62,85 +65,175 @@ static struct poptOption long_options[] = { */ static void usage(FILE *ofp) { - fprintf(ofp, "usage: lttng create [options] [NAME]\n"); + fprintf(ofp, "usage: lttng create [NAME] [OPTIONS] \n"); fprintf(ofp, "\n"); - fprintf(ofp, " The default NAME is 'auto-yyyymmdd-hhmmss'\n"); + fprintf(ofp, "Without a given NAME, the default is 'auto--'\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Options:\n"); fprintf(ofp, " -h, --help Show this help\n"); fprintf(ofp, " --list-options Simple listing of options\n"); fprintf(ofp, " -o, --output PATH Specify output path for traces\n"); - fprintf(ofp, " -U, --set-uri=URI Set URI for the enable-consumer destination.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Extended Options:\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Using these options, each API call can be controlled individually.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " -U, --set-url=URL Set URL destination of the trace data.\n"); fprintf(ofp, " It is persistent for the session lifetime.\n"); - fprintf(ofp, " Redo the command to change it.\n"); - fprintf(ofp, " This will set both data and control URI for network.\n"); - fprintf(ofp, " -C, --ctrl-uri=URI Set control path URI.\n"); - fprintf(ofp, " -D, --data-uri=URI Set data path URI.\n"); - fprintf(ofp, " --no-consumer Disable consumer for entire tracing session.\n"); + fprintf(ofp, " This will set both data and control URL.\n"); + fprintf(ofp, " You can change it with the enable-consumer cmd\n"); + fprintf(ofp, " -C, --ctrl-url=URL Set control path URL. (Must use -D also)\n"); + fprintf(ofp, " -D, --data-url=URL Set data path URL. (Must use -C also)\n"); + fprintf(ofp, " --no-consumer Don't activate a consumer for this session.\n"); + fprintf(ofp, " --disable-consumer\n"); + fprintf(ofp, " Disable consumer for this session.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Please refer to the man page (lttng(1)) for more information on network\n"); + fprintf(ofp, "streaming mechanisms and explanation of the control and data port\n"); + fprintf(ofp, "You must have a running remote lttng-relayd for network streaming\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "URL format is has followed:\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " proto://[HOST|IP][:PORT1[:PORT2]][/TRACE_PATH]\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " Supported protocols are (proto):\n"); + fprintf(ofp, " > file://...\n"); + fprintf(ofp, " Local filesystem full path.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " > net[4|6]://...\n"); + fprintf(ofp, " This will use the default network transport layer which is\n"); + fprintf(ofp, " TCP for both control (PORT1) and data port (PORT2).\n"); + fprintf(ofp, " The default ports are respectively 5342 and 5343.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " > tcp[4|6]://...\n"); + fprintf(ofp, " Can only be used with -C and -D together\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "NOTE: IPv6 address MUST be enclosed in brackets '[]' (rfc2732)\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Examples:\n"); + fprintf(ofp, " # lttng create -U net://192.168.1.42\n"); + fprintf(ofp, " Uses TCP and default ports for the given destination.\n"); + fprintf(ofp, " # lttng create -U net6://[fe80::f66d:4ff:fe53:d220]\n"); + fprintf(ofp, " Uses TCP, default ports and IPv6.\n"); + fprintf(ofp, " # lttng create s1 -U net://myhost.com:3229\n"); + fprintf(ofp, " Set the consumer to the remote HOST on port 3229 for control.\n"); fprintf(ofp, "\n"); } /* - * Parse URI from string to lttng_uri object array. + * For a session name, set the consumer URLs. */ -static ssize_t parse_uri_from_str(const char *str_uri, struct lttng_uri **uris) +static int set_consumer_url(const char *session_name, const char *ctrl_url, + const char *data_url) { - int i; - ssize_t size; - struct lttng_uri *uri; + int ret; + struct lttng_handle *handle; + struct lttng_domain dom; + + assert(session_name); + + /* + * Set handle with the session name and the domain set to 0. This means to + * the session daemon that the next action applies on the tracing session + * rather then the domain specific session. + */ + memset(&dom, 0, sizeof(dom)); + + handle = lttng_create_handle(session_name, &dom); + if (handle == NULL) { + ret = CMD_FATAL; + goto error; + } - if (*uris != NULL) { - free(*uris); + ret = lttng_set_consumer_url(handle, ctrl_url, data_url); + if (ret < 0) { + goto error; } - size = uri_parse(str_uri, uris); - if (size < 1) { - ERR("Bad URI %s. Either the hostname or IP is invalid", str_uri); - size = -1; + if (ctrl_url) { + MSG("Control URL %s set for session %s", ctrl_url, session_name); } - for (i = 0; i < size; i++) { - uri = (struct lttng_uri *) &uris[i]; - /* Set default port if none was given */ - if (uri->port == 0) { - if (uri->stype == LTTNG_STREAM_CONTROL) { - uri->port = DEFAULT_NETWORK_CONTROL_PORT; - } else if (uri->stype == LTTNG_STREAM_DATA) { - uri->port = DEFAULT_NETWORK_DATA_PORT; - } - } + if (data_url) { + MSG("Data URL %s set for session %s", data_url, session_name); + } + +error: + lttng_destroy_handle(handle); + return ret; +} + +/* + * For a session name, enable the consumer. + */ +static int enable_consumer(const char *session_name) +{ + int ret; + struct lttng_handle *handle; + struct lttng_domain dom; + + assert(session_name); + + /* + * Set handle with the session name and the domain set to 0. This means to + * the session daemon that the next action applies on the tracing session + * rather then the domain specific session. + * + * XXX: This '0' value should be a domain enum value. + */ + memset(&dom, 0, sizeof(dom)); + + handle = lttng_create_handle(session_name, 0); + if (handle == NULL) { + ret = CMD_FATAL; + goto error; } - return size; + ret = lttng_enable_consumer(handle); + if (ret < 0) { + goto error; + } + + MSG("Consumer enabled for session %s", session_name); + +error: + lttng_destroy_handle(handle); + return ret; } /* - * Print URI message. + * For a session name, disable the consumer. */ -static void print_uri_msg(struct lttng_uri *uri) +static int disable_consumer(const char *session_name) { - char *dst; - - switch (uri->dtype) { - case LTTNG_DST_IPV4: - dst = uri->dst.ipv4; - break; - case LTTNG_DST_IPV6: - dst = uri->dst.ipv6; - break; - case LTTNG_DST_PATH: - dst = uri->dst.path; - MSG("Consumer destination set to %s", dst); - goto end; - default: - DBG("Unknown URI destination"); - goto end; + int ret; + struct lttng_handle *handle; + + assert(session_name); + + /* + * Set handle with the session name and the domain set to 0. This means to + * the session daemon that the next action applies on the tracing session + * rather then the domain specific session. + * + * XXX: This '0' value should be a domain enum value. + */ + handle = lttng_create_handle(session_name, 0); + if (handle == NULL) { + ret = CMD_FATAL; + goto error; } - MSG("Consumer %s stream set to %s with the %s protocol on port %d", - uri->stype == LTTNG_STREAM_CONTROL ? "control" : "data", - dst, uri->proto == LTTNG_TCP ? "TCP" : "UNK", uri->port); + ret = lttng_disable_consumer(handle); + if (ret < 0) { + goto error; + } + free(handle); -end: - return; + MSG("Consumer disabled for session %s", session_name); + +error: + return ret; } /* @@ -149,15 +242,13 @@ end: * * Returns one of the CMD_* result constants. */ -static int create_session() +static int create_session(void) { - int ret, have_name = 0, i; - char datetime[16]; + int ret; char *session_name, *traces_path = NULL, *alloc_path = NULL; + char *alloc_url = NULL, *url = NULL, datetime[16]; time_t rawtime; - ssize_t size; struct tm *timeinfo; - struct lttng_uri *uris = NULL, *ctrl_uri = NULL, *data_uri = NULL; /* Get date and time for automatic session name/path */ time(&rawtime); @@ -166,102 +257,39 @@ static int create_session() /* Auto session name creation */ if (opt_session_name == NULL) { - ret = asprintf(&session_name, "auto-%s", datetime); + ret = asprintf(&session_name, DEFAULT_SESSION_NAME "%s", datetime); if (ret < 0) { - perror("asprintf session name"); + PERROR("asprintf session name"); goto error; } DBG("Auto session name set to %s", session_name); } else { session_name = opt_session_name; - have_name = 1; } - if (opt_output_path != NULL) { + if (opt_no_consumer) { + url = NULL; + } else if (opt_output_path != NULL) { traces_path = utils_expand_path(opt_output_path); if (traces_path == NULL) { ret = CMD_ERROR; goto error; } - ret = asprintf(&alloc_path, "file://%s", traces_path); + /* Create URL string from the local filesytem path */ + ret = asprintf(&alloc_url, "file://%s", traces_path); if (ret < 0) { - PERROR("asprintf expand path"); - ret = CMD_FATAL; - goto error; - } - - ret = uri_parse(alloc_path, &ctrl_uri); - if (ret < 1) { + PERROR("asprintf url path"); ret = CMD_FATAL; goto error; } - } else if (opt_uris) { /* Handling URIs (-U opt) */ - size = parse_uri_from_str(opt_uris, &uris); - if (size < 1) { - ret = CMD_ERROR; - goto error; - } else if (size == 1 && uris[0].dtype != LTTNG_DST_PATH) { - ERR("Only net:// and file:// are supported. " - "Use -C and -D for more fine grained control"); - ret = CMD_ERROR; - goto error; - } else if (size == 2) { - uris[0].stype = LTTNG_STREAM_CONTROL; - uris[1].stype = LTTNG_STREAM_DATA; - - for (i = 0; i < size; i++) { - /* Set default port if none was given */ - if (uris[i].port == 0) { - if (uris[i].stype == LTTNG_STREAM_CONTROL) { - uris[i].port = DEFAULT_NETWORK_CONTROL_PORT; - } else { - uris[i].port = DEFAULT_NETWORK_DATA_PORT; - } - } - } - - ctrl_uri = &uris[0]; - print_uri_msg(ctrl_uri); - data_uri = &uris[1]; - print_uri_msg(data_uri); - } else { - ctrl_uri = &uris[0]; - print_uri_msg(ctrl_uri); - } - } else if (opt_ctrl_uris || opt_data_uris) { - /* Setting up control URI (-C opt) */ - if (opt_ctrl_uris) { - size = parse_uri_from_str(opt_ctrl_uris, &uris); - if (size < 1) { - ret = CMD_ERROR; - goto error; - } - ctrl_uri = &uris[0]; - ctrl_uri->stype = LTTNG_STREAM_CONTROL; - /* Set default port if none specified */ - if (ctrl_uri->port == 0) { - ctrl_uri->port = DEFAULT_NETWORK_CONTROL_PORT; - } - print_uri_msg(ctrl_uri); - } - - /* Setting up data URI (-D opt) */ - if (opt_data_uris) { - size = parse_uri_from_str(opt_data_uris, &uris); - if (size < 1) { - ret = CMD_ERROR; - goto error; - } - data_uri = &uris[0]; - data_uri->stype = LTTNG_STREAM_DATA; - /* Set default port if none specified */ - if (data_uri->port == 0) { - data_uri->port = DEFAULT_NETWORK_DATA_PORT; - } - print_uri_msg(data_uri); - } - } else { + /* URL to use in the lttng_create_session() call */ + url = alloc_url; + MSG("Trace(s) output set to %s", traces_path); + } else if (opt_url) { /* Handling URL (-U opt) */ + url = opt_url; + MSG("Trace(s) output set to %s", url); + } else if (opt_ctrl_url == NULL && opt_data_url == NULL) { /* Auto output path */ alloc_path = config_get_default_path(); if (alloc_path == NULL) { @@ -272,44 +300,19 @@ static int create_session() } alloc_path = strdup(alloc_path); - if (have_name) { - ret = asprintf(&traces_path, "file://%s/" DEFAULT_TRACE_DIR_NAME - "/%s-%s", alloc_path, session_name, datetime); - } else { - ret = asprintf(&traces_path, "file://%s/" DEFAULT_TRACE_DIR_NAME - "/%s", alloc_path, session_name); - } + ret = asprintf(&alloc_url, "file://%s/" DEFAULT_TRACE_DIR_NAME, + alloc_path); if (ret < 0) { PERROR("asprintf trace dir name"); ret = CMD_FATAL; goto error; } - ret = uri_parse(traces_path, &ctrl_uri); - if (ret < 1) { - ret = CMD_FATAL; - goto error; - } + url = alloc_url; + MSG("Trace(s) output set to %s", alloc_url + strlen("file://")); } - /* If there is no subdir specified and the URI are network */ - if (strlen(ctrl_uri->subdir) == 0) { - if (have_name) { - ret = snprintf(ctrl_uri->subdir, sizeof(ctrl_uri->subdir), "%s-%s", - session_name, datetime); - } else { - ret = snprintf(ctrl_uri->subdir, sizeof(ctrl_uri->subdir), "%s", - session_name); - } - if (ret < 0) { - PERROR("snprintf subdir"); - goto error; - } - DBG("Subdir update to %s", ctrl_uri->subdir); - } - - ret = lttng_create_session_uri(session_name, ctrl_uri, data_uri, - opt_no_consumer); + ret = lttng_create_session(session_name, url); if (ret < 0) { /* Don't set ret so lttng can interpret the sessiond error. */ switch (-ret) { @@ -320,6 +323,32 @@ static int create_session() goto error; } + if (opt_session_name == NULL) { + MSG("Session created with default name %s", session_name); + } else { + MSG("Session %s created.", session_name); + } + + if (opt_ctrl_url || opt_data_url) { + /* Setting up control URI (-C or/and -D opt) */ + ret = set_consumer_url(session_name, opt_ctrl_url, opt_data_url); + if (ret < 0) { + goto error; + } + + ret = enable_consumer(session_name); + if (ret < 0) { + goto error; + } + } + + if (opt_disable_consumer && !opt_no_consumer) { + ret = disable_consumer(session_name); + if (ret < 0) { + goto error; + } + } + /* Init lttng session config */ ret = config_init(session_name); if (ret < 0) { @@ -327,11 +356,6 @@ static int create_session() goto error; } - MSG("Session %s created.", session_name); - if (ctrl_uri->dtype == LTTNG_DST_PATH) { - MSG("Traces will be written in %s" , ctrl_uri->dst.path); - } - ret = CMD_SUCCESS; error: @@ -339,13 +363,17 @@ error: free(session_name); } - if (alloc_path) { - free(alloc_path); + if (alloc_url) { + free(alloc_url); } if (traces_path) { free(traces_path); } + + if (ret < 0) { + ERR("%s", lttng_strerror(ret)); + } return ret; } diff --git a/src/bin/lttng/commands/enable_consumer.c b/src/bin/lttng/commands/enable_consumer.c index 67594529f..0a6136222 100644 --- a/src/bin/lttng/commands/enable_consumer.c +++ b/src/bin/lttng/commands/enable_consumer.c @@ -36,10 +36,10 @@ static int opt_kernel; static int opt_userspace; static int opt_enable; static char *opt_session_name; -static char *opt_uris; -static char *opt_ctrl_uris; -static char *opt_data_uris; -static char *opt_uris_arg; +static char *opt_url; +static char *opt_ctrl_url; +static char *opt_data_url; +static char *opt_url_arg; static struct lttng_handle *handle; @@ -55,9 +55,9 @@ static struct poptOption long_options[] = { {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0}, {"userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0}, - {"set-uri", 'U', POPT_ARG_STRING, &opt_uris, 0, 0, 0}, - {"ctrl-uri", 'C', POPT_ARG_STRING, &opt_ctrl_uris, 0, 0, 0}, - {"data-uri", 'D', POPT_ARG_STRING, &opt_data_uris, 0, 0, 0}, + {"set-uri", 'U', POPT_ARG_STRING, &opt_url, 0, 0, 0}, + {"ctrl-uri", 'C', POPT_ARG_STRING, &opt_ctrl_url, 0, 0, 0}, + {"data-uri", 'D', POPT_ARG_STRING, &opt_data_url, 0, 0, 0}, {"enable", 'e', POPT_ARG_VAL, &opt_enable, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0} }; @@ -67,154 +67,60 @@ static struct poptOption long_options[] = { */ static void usage(FILE *ofp) { - fprintf(ofp, "usage: lttng enable-consumer [-u|-k] [URI] [OPTIONS]\n"); + fprintf(ofp, "usage: lttng enable-consumer [-u|-k] [URL] [OPTIONS]\n"); fprintf(ofp, "\n"); - fprintf(ofp, "The default behavior is to enable a consumer to the current URI.\n"); - fprintf(ofp, "The default URI is the local filesystem at the path of the session.\n"); + fprintf(ofp, "The default behavior is to enable a consumer to the current URL.\n"); + fprintf(ofp, "The default URL is the local filesystem at the path of the session.\n"); fprintf(ofp, "\n"); fprintf(ofp, "The enable-consumer feature supports both local and network transport.\n"); fprintf(ofp, "You must have a running lttng-relayd for network transmission.\n"); fprintf(ofp, "\n"); - fprintf(ofp, "You can optionally specify two URIs for respectively the\n"); - fprintf(ofp, "control and data channel. URI supported:\n"); - fprintf(ofp, " > file://PATH\n"); - fprintf(ofp, " Local file full system path.\n"); - fprintf(ofp, "\n"); - fprintf(ofp, " > net://DST[:CTRL_PORT[:DATA_PORT]] and net6://...\n"); - fprintf(ofp, " This will use the default network transport layer which is\n"); - fprintf(ofp, " TCP for both control and data port. The default ports are\n"); - fprintf(ofp, " respectively 5342 and 5343.\n"); - fprintf(ofp, " Example:\n"); - fprintf(ofp, " # lttng enable-consumer net://192.168.1.42 -k\n"); - fprintf(ofp, " Uses TCP and default ports for the given destination.\n"); - fprintf(ofp, "\n"); - fprintf(ofp, " > tcp://DST:PORT and tcp6://DST:PORT\n"); - fprintf(ofp, "\n"); fprintf(ofp, "Options:\n"); fprintf(ofp, " -h, --help Show this help\n"); fprintf(ofp, " --list-options Simple listing of options\n"); fprintf(ofp, " -s, --session=NAME Apply to session name\n"); fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n"); fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n"); - //fprintf(ofp, " -U, --set-uri=URI1[,URI2,...]\n"); fprintf(ofp, "\n"); fprintf(ofp, "Extended Options:\n"); fprintf(ofp, "\n"); - fprintf(ofp, "Using these options, each API call is controlled individually.\n"); + fprintf(ofp, "Using these options, each API call can be controlled individually.\n"); fprintf(ofp, "For instance, -C does not enable the consumer automatically.\n"); fprintf(ofp, "\n"); - fprintf(ofp, " -U, --set-uri=URI Set URI for the enable-consumer destination.\n"); + fprintf(ofp, " -U, --set-uri=URL Set URL for the enable-consumer destination.\n"); fprintf(ofp, " It is persistent for the session lifetime.\n"); fprintf(ofp, " Redo the command to change it.\n"); - fprintf(ofp, " This will set both data and control URI for network.\n"); - //fprintf(ofp, " -C, --ctrl-uri=URI1[,URI2,...]\n"); - fprintf(ofp, " -C, --ctrl-uri=URI Set control path URI.\n"); - //fprintf(ofp, " -D, --data-uri=URI1[,URI2,...]\n"); - fprintf(ofp, " -D, --data-uri=URI Set data path URI.\n"); + fprintf(ofp, " This will set both data and control URL for network.\n"); + fprintf(ofp, " -C, --ctrl-url=URL Set control path URL. (Must use -D also)\n"); + fprintf(ofp, " -D, --data-url=URL Set data path URL. (Must use -C also)\n"); fprintf(ofp, " -e, --enable Enable consumer\n"); fprintf(ofp, "\n"); -} - -/* - * Print URI message. - */ -static void print_uri_msg(struct lttng_uri *uri) -{ - char *dst; - - switch (uri->dtype) { - case LTTNG_DST_IPV4: - dst = uri->dst.ipv4; - break; - case LTTNG_DST_IPV6: - dst = uri->dst.ipv6; - break; - case LTTNG_DST_PATH: - dst = uri->dst.path; - MSG("Consumer destination set to %s", dst); - goto end; - default: - DBG("Unknown URI destination"); - goto end; - } - - MSG("Consumer %s stream set to %s with the %s protocol on port %d", - uri->stype == LTTNG_STREAM_CONTROL ? "control" : "data", - dst, uri->proto == LTTNG_TCP ? "TCP" : "UNK", uri->port); - -end: - return; -} - -/* - * Setting URIs taking from the command line arguments. There is some - * manipulations and special cases using the default args. - */ -static int set_consumer_arg_uris(struct lttng_uri *uri, size_t size) -{ - int ret, i; - - if (size == 2) { - /* URIs are the control and data stream respectively for net:// */ - uri[0].stype = LTTNG_STREAM_CONTROL; - uri[1].stype = LTTNG_STREAM_DATA; - - for (i = 0; i < size; i++) { - ret = lttng_set_consumer_uri(handle, &uri[i]); - if (ret < 0) { - ERR("Setting %s stream URI: %s", - uri[i].stype == LTTNG_STREAM_DATA ? "data" : "control", - lttng_strerror(ret)); - goto error; - } - /* Set default port if none was given */ - if (uri[i].port == 0) { - if (uri[i].stype == LTTNG_STREAM_CONTROL) { - uri[i].port = DEFAULT_NETWORK_CONTROL_PORT; - } else { - uri[i].port = DEFAULT_NETWORK_DATA_PORT; - } - } - print_uri_msg(&uri[i]); - } - } else if (size == 1 && uri[0].dtype == LTTNG_DST_PATH) { - /* Set URI if it's file:// */ - ret = lttng_set_consumer_uri(handle, &uri[0]); - if (ret < 0) { - ERR("Failed to set URI %s: %s", opt_uris_arg, - lttng_strerror(ret)); - goto error; - } - print_uri_msg(&uri[0]); - } else { - ERR("Only net:// and file:// are supported. " - "Use -D or -U for more fine grained control"); - ret = CMD_ERROR; - goto error; - } - -error: - return ret; -} - -/* - * Parse URI from string to lttng_uri object array. - */ -static ssize_t parse_uri_from_str(const char *str_uri, struct lttng_uri **uris) -{ - ssize_t size; - - if (*uris != NULL) { - free(*uris); - } - - size = uri_parse(str_uri, uris); - if (size < 1) { - ERR("Bad URI %s. Either the hostname or IP is invalid", str_uri); - size = -1; - } - - return size; + fprintf(ofp, "\n"); + fprintf(ofp, "Please refer to the man page (lttng(1)) for more information on network\n"); + fprintf(ofp, "streaming mechanisms and explanation of the control and data port\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "URL format is has followed:\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " proto://[HOST|IP][:PORT1[:PORT2]][/TRACE_PATH]\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " Supported protocols are (proto):\n"); + fprintf(ofp, " > file://...\n"); + fprintf(ofp, " Local filesystem full path.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " > net[4|6]://...\n"); + fprintf(ofp, " This will use the default network transport layer which is\n"); + fprintf(ofp, " TCP for both control (PORT1) and data port (PORT2).\n"); + fprintf(ofp, " The default ports are respectively 5342 and 5343.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " > tcp[4|6]://...\n"); + fprintf(ofp, " Can only be used with -C and -D together\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "NOTE: IPv6 address MUST be enclosed in brackets '[]' (rfc2732)\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Examples:\n"); + fprintf(ofp, " # lttng enable-consumer -u net://192.168.1.42\n"); + fprintf(ofp, " Uses TCP and default ports for user space tracing (-u).\n"); + fprintf(ofp, "\n"); } /* @@ -224,9 +130,7 @@ static int enable_consumer(char *session_name) { int ret = CMD_SUCCESS; int run_enable_cmd = 1; - ssize_t size; struct lttng_domain dom; - struct lttng_uri *uri = NULL; memset(&dom, 0, sizeof(dom)); @@ -236,9 +140,14 @@ static int enable_consumer(char *session_name) } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; } else { - ERR("Please specify a tracer (-k/--kernel or -u/--userspace)"); - ret = CMD_ERROR; - goto error; + /* + * Set handle with domain set to 0. This means to the session daemon + * that the next action applies on the tracing session rather then the + * domain specific session. + * + * XXX: This '0' value should be a domain enum value. + */ + dom.type = 0; } handle = lttng_create_handle(session_name, &dom); @@ -248,88 +157,49 @@ static int enable_consumer(char *session_name) } /* Handle trailing arguments */ - if (opt_uris_arg) { - size = parse_uri_from_str(opt_uris_arg, &uri); - if (size < 1) { - ret = CMD_ERROR; + if (opt_url_arg) { + ret = lttng_set_consumer_url(handle, opt_url_arg, NULL); + if (ret < 0) { + ERR("%s", lttng_strerror(ret)); goto error; } - ret = set_consumer_arg_uris(uri, size); - if (ret < 0) { - goto free_uri; - } + MSG("URL %s set for session %s.", opt_url_arg, session_name); } - /* Handling URIs (-U opt) */ - if (opt_uris) { - size = parse_uri_from_str(opt_uris, &uri); - if (size < 1) { - ret = CMD_ERROR; - goto error; - } - - ret = set_consumer_arg_uris(uri, size); + /* Handling URLs (-U opt) */ + if (opt_url) { + ret = lttng_set_consumer_url(handle, opt_url, NULL); if (ret < 0) { - goto free_uri; + ERR("%s", lttng_strerror(ret)); + goto error; } /* opt_enable will tell us to run or not the enable_consumer cmd. */ run_enable_cmd = 0; - } - - /* Setting up control URI (-C opt) */ - if (opt_ctrl_uris) { - size = parse_uri_from_str(opt_ctrl_uris, &uri); - if (size < 1) { - ret = CMD_ERROR; - goto error; - } - /* Set default port if none specified */ - if (uri[0].port == 0) { - uri[0].port = DEFAULT_NETWORK_CONTROL_PORT; - } - - uri[0].stype = LTTNG_STREAM_CONTROL; + MSG("URL %s set for session %s.", opt_url, session_name); + } - ret = lttng_set_consumer_uri(handle, &uri[0]); + /* Setting up control URL (-C or/and -D opt) */ + if (opt_ctrl_url || opt_data_url) { + ret = lttng_set_consumer_url(handle, opt_ctrl_url, opt_data_url); if (ret < 0) { - ERR("Failed to set control URI %s: %s", opt_ctrl_uris, - lttng_strerror(ret)); - goto free_uri; + ERR("%s", lttng_strerror(ret)); + goto error; } - print_uri_msg(&uri[0]); /* opt_enable will tell us to run or not the enable_consumer cmd. */ run_enable_cmd = 0; - } - /* Setting up data URI (-D opt) */ - if (opt_data_uris) { - size = parse_uri_from_str(opt_data_uris, &uri); - if (size < 1) { - ret = CMD_ERROR; - goto error; + if (opt_ctrl_url) { + MSG("Control URL %s set for session %s.", opt_ctrl_url, + session_name); } - /* Set default port if none specified */ - if (uri[0].port == 0) { - uri[0].port = DEFAULT_NETWORK_DATA_PORT; + if (opt_data_url) { + MSG("Data URL %s set for session %s.", opt_data_url, session_name); } - - uri[0].stype = LTTNG_STREAM_DATA; - - ret = lttng_set_consumer_uri(handle, &uri[0]); - if (ret < 0) { - ERR("Failed to set data URI %s: %s", opt_data_uris, - lttng_strerror(ret)); - goto free_uri; - } - print_uri_msg(&uri[0]); - - /* opt_enable will tell us to run or not the enable_consumer cmd. */ - run_enable_cmd = 0; } /* Enable consumer (-e opt) */ @@ -341,15 +211,12 @@ static int enable_consumer(char *session_name) if (ret == -LTTCOMM_ENABLE_CONSUMER_FAIL) { ERR("Perhaps the session was previously started?"); } - goto free_uri; + goto error; } MSG("Consumer enabled successfully"); } -free_uri: - free(uri); - error: lttng_destroy_handle(handle); return ret; @@ -384,8 +251,8 @@ int cmd_enable_consumer(int argc, const char **argv) } } - opt_uris_arg = (char *) poptGetArg(pc); - DBG("URIs: %s", opt_uris_arg); + opt_url_arg = (char *) poptGetArg(pc); + DBG("URLs: %s", opt_url_arg); /* Get session name */ if (!opt_session_name) { diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 131fda8e5..84bed094f 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -9,8 +9,7 @@ noinst_HEADERS = lttng-kernel.h defaults.h macros.h error.h futex.h uri.h utils. # Common library noinst_LTLIBRARIES = libcommon.la -libcommon_la_SOURCES = runas.c runas.h common.h futex.c futex.h uri.c uri.h \ - utils.c utils.h +libcommon_la_SOURCES = utils.c utils.h runas.c runas.h common.h futex.c futex.h uri.c uri.h # Consumer library noinst_LTLIBRARIES += libconsumer.la diff --git a/src/common/consumer.c b/src/common/consumer.c index 0e33bea72..deebd2e2b 100644 --- a/src/common/consumer.c +++ b/src/common/consumer.c @@ -278,8 +278,12 @@ void consumer_del_stream(struct lttng_consumer_stream *stream) stream->relayd_stream_id, stream->next_net_seq_num - 1); if (ret < 0) { - ERR("Unable to close stream on the relayd. Continuing"); - /* Continue here. There is nothing we can do for the relayd.*/ + DBG("Unable to close stream on the relayd. Continuing"); + /* + * Continue here. There is nothing we can do for the relayd. + * Chances are that the relayd has closed the socket so we just + * continue cleaning up. + */ } /* Both conditions are met, we destroy the relayd. */ diff --git a/src/common/defaults.h b/src/common/defaults.h index 5ab63d050..0303c02ae 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -44,6 +44,12 @@ #define DEFAULT_KERNEL_TRACE_DIR "/kernel" #define DEFAULT_UST_TRACE_DIR "/ust" +/* + * 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-" + /* Default consumer paths */ #define DEFAULT_CONSUMERD_RUNDIR "%s" diff --git a/src/common/sessiond-comm/sessiond-comm.c b/src/common/sessiond-comm/sessiond-comm.c index 432cf4cff..aee9458b4 100644 --- a/src/common/sessiond-comm/sessiond-comm.c +++ b/src/common/sessiond-comm/sessiond-comm.c @@ -138,14 +138,15 @@ static const char *lttcomm_readable_code[] = { [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_USTCONSUMERD) ] = "No UST consumer detected", [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_KERNCONSUMERD) ] = "No kernel consumer detected", [ LTTCOMM_ERR_INDEX(LTTCOMM_EVENT_EXIST_LOGLEVEL) ] = "Event already enabled with different loglevel", - [ LTTCOMM_ERR_INDEX(LTTCOMM_URI_DATA_MISS) ] = "Missing data path URI", - [ LTTCOMM_ERR_INDEX(LTTCOMM_URI_CTRL_MISS) ] = "Missing control data path URI", + [ LTTCOMM_ERR_INDEX(LTTCOMM_URL_DATA_MISS) ] = "Missing data path URL", + [ LTTCOMM_ERR_INDEX(LTTCOMM_URL_CTRL_MISS) ] = "Missing control data path URL", [ LTTCOMM_ERR_INDEX(LTTCOMM_ENABLE_CONSUMER_FAIL) ] = "Enabling consumer failed", [ LTTCOMM_ERR_INDEX(LTTCOMM_RELAYD_SESSION_FAIL) ] = "Unable to create session on lttng-relayd", [ LTTCOMM_ERR_INDEX(LTTCOMM_RELAYD_VERSION_FAIL) ] = "Relay daemon not compatible", [ LTTCOMM_ERR_INDEX(LTTCOMM_FILTER_INVAL) ] = "Invalid filter bytecode", [ LTTCOMM_ERR_INDEX(LTTCOMM_FILTER_NOMEM) ] = "Not enough memory for filter bytecode", [ LTTCOMM_ERR_INDEX(LTTCOMM_FILTER_EXIST) ] = "Filter already exist", + [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_CONSUMER) ] = "Consumer not found for tracing session", }; /* diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 8d1400cdb..e544bf545 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,6 @@ enum lttcomm_sessiond_command { LTTNG_ENABLE_ALL_EVENT, /* Session daemon command */ LTTNG_CREATE_SESSION, - LTTNG_CREATE_SESSION_URI, LTTNG_DESTROY_SESSION, LTTNG_LIST_CHANNELS, LTTNG_LIST_DOMAINS, @@ -185,14 +185,15 @@ enum lttcomm_return_code { LTTCOMM_NO_USTCONSUMERD, /* No UST consumer detected */ LTTCOMM_NO_KERNCONSUMERD, /* No Kernel consumer detected */ LTTCOMM_EVENT_EXIST_LOGLEVEL, /* Event already enabled with different loglevel */ - LTTCOMM_URI_DATA_MISS, /* Missing network data URI */ - LTTCOMM_URI_CTRL_MISS, /* Missing network control URI */ + LTTCOMM_URL_DATA_MISS, /* Missing network data URL */ + LTTCOMM_URL_CTRL_MISS, /* Missing network control URL */ LTTCOMM_ENABLE_CONSUMER_FAIL, /* Enabling consumer failed */ LTTCOMM_RELAYD_SESSION_FAIL, /* lttng-relayd create session failed */ LTTCOMM_RELAYD_VERSION_FAIL, /* lttng-relayd not compatible */ LTTCOMM_FILTER_INVAL, /* Invalid filter bytecode */ LTTCOMM_FILTER_NOMEM, /* Lack of memory for filter bytecode */ LTTCOMM_FILTER_EXIST, /* Filter already exist */ + LTTCOMM_NO_CONSUMER, /* No consumer exist for the tracing session */ /* MUST be last element */ LTTCOMM_NR, /* Last element */ @@ -280,13 +281,11 @@ struct lttcomm_session_msg { char channel_name[NAME_MAX]; } list; struct lttng_calibrate calibrate; - /* Used by the set_consumer_uri call */ - struct lttng_uri uri; + /* Used by the set_consumer_url and used by create_session also call */ struct { - uint32_t enable_consumer; - struct lttng_uri ctrl_uri; - struct lttng_uri data_uri; - } create_uri; + /* Number of lttng_uri following */ + uint32_t size; + } uri; struct { char channel_name[NAME_MAX]; char event_name[NAME_MAX]; diff --git a/src/common/uri.c b/src/common/uri.c index 6ca46474f..3581e307d 100644 --- a/src/common/uri.c +++ b/src/common/uri.c @@ -24,6 +24,7 @@ #include #include +#include #include "uri.h" @@ -32,7 +33,8 @@ enum uri_proto_code { }; struct uri_proto { - char *name; + const char *name; + const char *leading_string; enum uri_proto_code code; enum lttng_proto_type type; enum lttng_dst_type dtype; @@ -40,29 +42,46 @@ struct uri_proto { /* Supported protocols */ static const struct uri_proto proto_uri[] = { - { .name = "file", .code = P_FILE, .type = 0, .dtype = LTTNG_DST_PATH}, - { .name = "net", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 }, - { .name = "net6", .code = P_NET6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 }, - { .name = "tcp", .code = P_TCP, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 }, - { .name = "tcp6", .code = P_TCP6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 }, - { .name = NULL } + { .name = "file", .leading_string = "file://", .code = P_FILE, .type = 0, .dtype = LTTNG_DST_PATH }, + { .name = "net", .leading_string = "net://", .code = P_NET, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 }, + { .name = "net6", .leading_string = "net6://", .code = P_NET6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 }, + { .name = "tcp", .leading_string = "tcp://", .code = P_TCP, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV4 }, + { .name = "tcp6", .leading_string = "tcp6://", .code = P_TCP6, .type = LTTNG_TCP, .dtype = LTTNG_DST_IPV6 }, + /* Invalid proto marking the end of the array. */ + { NULL, NULL, 0, 0, 0 } }; +/* + * Return pointer to the character in s matching one of the characters in + * accept. If nothing is found, return pointer to the end of string (eos). + */ +const inline char *strpbrk_or_eos(const char *s, const char *accept) +{ + char *p = strpbrk(s, accept); + if (p == NULL) { + p = strchr(s, '\0'); + } + + return p; +} + + /* * Validate if proto is a supported protocol from proto_uri array. */ -static const struct uri_proto *validate_protocol(char *proto) +static const struct uri_proto *get_uri_proto(const char *uri_str) { - const struct uri_proto *supported; + const struct uri_proto *supported = NULL; /* Safety net */ - if (proto == NULL) { + if (uri_str == NULL) { goto end; } for (supported = &proto_uri[0]; - supported->name != NULL; ++supported) { - if (strncmp(proto, supported->name, strlen(proto)) == 0) { + supported->leading_string != NULL; ++supported) { + if (strncasecmp(uri_str, supported->leading_string, + strlen(supported->leading_string)) == 0) { goto end; } } @@ -101,6 +120,8 @@ static int set_ip_address(const char *addr, int af, char *dst, size_t size) memcpy(dst, addr, size); } + DBG2("IP address resolved to %s", dst); + return 0; error: @@ -152,18 +173,26 @@ struct lttng_uri *uri_create(void) * make sure the correct type (stype) is set on the return URI(s). The default * port must also be set by the caller if the returned URI has its port set to * zero. + * + * NOTE: A good part of the following code was inspired from the "wget" source + * tree from the src/url.c file and url_parse() function. Also, the + * strpbrk_or_eos() function found above is also inspired by the same code. + * This code was originally licensed GPLv2 so we acknolwedge the Free Software + * Foundation here for the work and to make sure we are compliant with it. */ ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris) { - int ret; - size_t str_offset = 0; + int ret, i = 0; /* Size of the uris array. Default is 1 */ ssize_t size = 1; - char net[6], dst[LTTNG_MAX_DNNAME + 1], subdir[PATH_MAX]; + char subdir[PATH_MAX]; unsigned int ctrl_port = 0; unsigned int data_port = 0; - struct lttng_uri *uri; + struct lttng_uri *tmp_uris; + char *addr_f = NULL; const struct uri_proto *proto; + const char *purl, *addr_e, *addr_b, *subdir_b = NULL; + const char *seps = ":/\0"; /* * The first part is the protocol portion of a maximum of 5 bytes for now. @@ -173,110 +202,208 @@ ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris) * protocol, two ports CAN be specified. */ - ret = sscanf(str_uri, "%5[^:]://", net); - if (ret < 1) { - ERR("URI parse bad protocol %s", str_uri); - goto error; - } - DBG3("URI string: %s", str_uri); - proto = validate_protocol(net); + proto = get_uri_proto(str_uri); if (proto == NULL) { - ERR("URI parse unknown protocol %s", net); - ret = -1; + ERR("URI parse unknown protocol %s", str_uri); goto error; } + purl = str_uri; + if (proto->code == P_NET || proto->code == P_NET6) { - /* Special case for net:// which requires two URI object */ + /* Special case for net:// which requires two URI objects */ size = 2; } + /* Allocate URI array */ + tmp_uris = zmalloc(sizeof(struct lttng_uri) * size); + if (tmp_uris == NULL) { + PERROR("zmalloc uri"); + goto error; + } + memset(subdir, 0, sizeof(subdir)); - str_offset += strlen(net); - - /* Parse the rest of the URI */ - if (sscanf(str_uri + str_offset, "://%255[^:]:%u:%u/%s", dst, &ctrl_port, - &data_port, subdir) == 4) { - /* All set */ - } else if (sscanf(str_uri + str_offset, "://%255[^:]:%u:%u", dst, - &ctrl_port, &data_port) == 3) { - } else if (sscanf(str_uri + str_offset, "://%255[^:]:%u/%s", dst, - &ctrl_port, subdir) == 3) { - } else if (sscanf(str_uri + str_offset, "://%255[^:]:%u", dst, - &ctrl_port) == 2) { - } else if (sscanf(str_uri + str_offset, "://%255[^/]/%s", dst, - subdir) == 2) { - } else { - ret = sscanf(str_uri + str_offset, "://%255[^:]", dst); - if (ret < 0) { - ERR("Bad URI"); - goto error; + purl += strlen(proto->leading_string); + + /* Copy known value to the first URI. */ + tmp_uris[0].dtype = proto->dtype; + tmp_uris[0].proto = proto->type; + + if (proto->code == P_FILE) { + if (*purl != '/') { + ERR("Missing destination full path."); + goto free_error; } + + strncpy(tmp_uris[0].dst.path, purl, sizeof(tmp_uris[0].dst.path)); + tmp_uris[0].dst.path[sizeof(tmp_uris[0].dst.path) - 1] = '\0'; + DBG3("URI file destination: %s", purl); + goto end; } - /* We have enough valid information to create URI(s) object */ + /* Assume we are at the beginning of an address or host of some sort. */ + addr_b = purl; - /* Allocate URI array */ - uri = zmalloc(sizeof(struct lttng_uri) * size); - if (uri == NULL) { - PERROR("zmalloc uri"); - goto error; + /* + * Handle IPv6 address inside square brackets as mention by RFC 2732. IPv6 + * address that does not start AND end with brackets will be rejected even + * if valid. + * + * proto://[]... + * ^ + */ + if (*purl == '[') { + /* Address begins after '[' */ + addr_b = purl + 1; + addr_e = strchr(addr_b, ']'); + if (addr_e == NULL || addr_b == addr_e) { + ERR("Broken IPv6 address %s", addr_b); + goto free_error; + } + + /* Moving parsed URL pointer after the final bracket ']' */ + purl = addr_e + 1; + + /* + * The closing bracket must be followed by a seperator or NULL char. + */ + if (strchr(seps, *purl) == NULL) { + ERR("Unknown symbol after IPv6 address: %s", purl); + goto free_error; + } + } else { + purl = strpbrk_or_eos(purl, seps); + addr_e = purl; + } + + /* Check if we at least have a char for the addr or hostname. */ + if (addr_b == addr_e) { + ERR("No address or hostname detected."); + goto free_error; + } + + addr_f = utils_strdupdelim(addr_b, addr_e); + if (addr_f == NULL) { + goto free_error; } + /* + * Detect PORT after address. The net/net6 protocol allows up to two port + * so we can define the control and data port. + */ + while (*purl == ':') { + int port; + const char *port_b, *port_e; + char *port_f; + + /* Update pass counter */ + i++; + + /* + * Maximum of two ports is possible if P_NET/NET6. Bigger than that, + * two much stuff. + */ + if ((i == 2 && (proto->code != P_NET && proto->code != P_NET6)) + || i > 2) { + break; + } + + /* + * Move parsed URL to port value. + * proto://addr_host:PORT1:PORT2/foo/bar + * ^ + */ + ++purl; + port_b = purl; + purl = strpbrk_or_eos(purl, seps); + port_e = purl; + + if (port_b != port_e) { + port_f = utils_strdupdelim(port_b, port_e); + if (port_f == NULL) { + goto free_error; + } + + port = atoi(port_f); + if (port > 0xffff || port <= 0x0) { + ERR("Invalid port number %d", port); + free(port_f); + goto free_error; + } + free(port_f); + + if (i == 1) { + ctrl_port = port; + } else { + data_port = port; + } + } + }; + + /* Check for a valid subdir or trailing garbage */ + if (*purl == '/') { + /* + * Move to subdir value. + * proto://addr_host:PORT1:PORT2/foo/bar + * ^ + */ + ++purl; + subdir_b = purl; + } else if (*purl != '\0') { + ERR("Trailing characters not recognized: %s", purl); + goto free_error; + } + + /* We have enough valid information to create URI(s) object */ + /* Copy generic information */ - uri[0].dtype = proto->dtype; - uri[0].proto = proto->type; - uri[0].port = ctrl_port; - strncpy(uri[0].subdir, subdir, sizeof(uri[0].subdir)); + tmp_uris[0].port = ctrl_port; - DBG3("URI dtype: %d, proto: %d, host: %s, subdir: %s, ctrl: %d, data: %d", - proto->dtype, proto->type, dst, subdir, ctrl_port, data_port); + /* Copy subdirectory if one. */ + if (subdir_b) { + strncpy(tmp_uris[0].subdir, subdir_b, sizeof(tmp_uris[0].subdir)); + tmp_uris[0].subdir[sizeof(tmp_uris[0].subdir) - 1] = '\0'; + } switch (proto->code) { - case P_FILE: - memcpy(uri[0].dst.path, dst, sizeof(uri[0].dst.path)); - /* Reset port for the file:// URI */ - uri[0].port = 0; - DBG3("URI file destination: %s", dst); - break; case P_NET: - ret = set_ip_address(dst, AF_INET, uri[0].dst.ipv4, - sizeof(uri[0].dst.ipv4)); + ret = set_ip_address(addr_f, AF_INET, tmp_uris[0].dst.ipv4, + sizeof(tmp_uris[0].dst.ipv4)); if (ret < 0) { goto free_error; } - memcpy(uri[1].dst.ipv4, uri[0].dst.ipv4, sizeof(uri[1].dst.ipv4)); + memcpy(tmp_uris[1].dst.ipv4, tmp_uris[0].dst.ipv4, sizeof(tmp_uris[1].dst.ipv4)); - uri[1].dtype = proto->dtype; - uri[1].proto = proto->type; - uri[1].port = data_port; + tmp_uris[1].dtype = proto->dtype; + tmp_uris[1].proto = proto->type; + tmp_uris[1].port = data_port; break; case P_NET6: - ret = set_ip_address(dst, AF_INET6, uri[0].dst.ipv6, - sizeof(uri[0].dst.ipv6)); + ret = set_ip_address(addr_f, AF_INET6, tmp_uris[0].dst.ipv6, + sizeof(tmp_uris[0].dst.ipv6)); if (ret < 0) { goto free_error; } - memcpy(uri[1].dst.ipv6, uri[0].dst.ipv6, sizeof(uri[1].dst.ipv6)); + memcpy(tmp_uris[1].dst.ipv6, tmp_uris[0].dst.ipv6, sizeof(tmp_uris[1].dst.ipv6)); - uri[1].dtype = proto->dtype; - uri[1].proto = proto->type; - uri[1].port = data_port; + tmp_uris[1].dtype = proto->dtype; + tmp_uris[1].proto = proto->type; + tmp_uris[1].port = data_port; break; case P_TCP: - ret = set_ip_address(dst, AF_INET, uri[0].dst.ipv4, - sizeof(uri[0].dst.ipv4)); + ret = set_ip_address(addr_f, AF_INET, tmp_uris[0].dst.ipv4, + sizeof(tmp_uris[0].dst.ipv4)); if (ret < 0) { goto free_error; } break; case P_TCP6: - ret = set_ip_address(dst, AF_INET6, uri[0].dst.ipv6, - sizeof(uri[0].dst.ipv6)); + ret = set_ip_address(addr_f, AF_INET6, tmp_uris[0].dst.ipv6, + sizeof(tmp_uris[0].dst.ipv6)); if (ret < 0) { goto free_error; } @@ -285,12 +412,19 @@ ssize_t uri_parse(const char *str_uri, struct lttng_uri **uris) goto free_error; } - *uris = uri; +end: + DBG3("URI dtype: %d, proto: %d, host: %s, subdir: %s, ctrl: %d, data: %d", + proto->dtype, proto->type, (addr_f == NULL) ? "" : addr_f, + (subdir_b == NULL) ? "" : subdir_b, ctrl_port, data_port); + + free(addr_f); + *uris = tmp_uris; return size; free_error: - free(uri); + free(addr_f); + free(tmp_uris); error: return -1; } diff --git a/src/common/uri.h b/src/common/uri.h index 959b9a66c..d768e8724 100644 --- a/src/common/uri.h +++ b/src/common/uri.h @@ -15,11 +15,65 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef _LTT_URI_H -#define _LTT_URI_H +#ifndef URI_H +#define URI_H +#include #include +/* Destination type of lttng URI */ +enum lttng_dst_type { + LTTNG_DST_IPV4 = 1, + LTTNG_DST_IPV6 = 2, + LTTNG_DST_PATH = 3, +}; + +/* Type of lttng URI where it is a final destination or a hop */ +enum lttng_uri_type { + LTTNG_URI_DST, /* The URI is a final destination */ + /* + * Hops are not supported yet but planned for a future release. + * + LTTNG_URI_HOP, + */ +}; + +/* Communication stream type of a lttng URI */ +enum lttng_stream_type { + LTTNG_STREAM_CONTROL, + LTTNG_STREAM_DATA, +}; + +/* + * Protocol type of a lttng URI. The value 0 indicate that the proto_type field + * should be ignored. + */ +enum lttng_proto_type { + LTTNG_TCP = 1, + /* + * UDP protocol is not supported for now. + * + LTTNG_UDP = 2, + */ +}; + +/* + * Structure representing an URI supported by lttng. + */ +struct lttng_uri { + enum lttng_dst_type dtype; + enum lttng_uri_type utype; + enum lttng_stream_type stype; + enum lttng_proto_type proto; + in_port_t port; + char subdir[PATH_MAX]; + union { + char ipv4[INET_ADDRSTRLEN]; + char ipv6[INET6_ADDRSTRLEN]; + char path[PATH_MAX]; + } dst; +}; + 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); diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 1fed58bdc..c92d59d02 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -483,7 +483,7 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream, * display the error but continue processing to try * to release the subbuffer */ - ERR("Error writing to tracefile"); + ERR("Error writing to tracefile (expected: %ld, got: %ld)", ret, len); } err = ustctl_put_next_subbuf(handle, buf); assert(err == 0); diff --git a/src/common/utils.c b/src/common/utils.c index bc9b2db3f..0494b23bd 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -154,3 +154,23 @@ void utils_close_pipe(int *src) } } } + +/* + * Create a new string using two strings range. + */ +char *utils_strdupdelim(const char *begin, const char *end) +{ + char *str; + + str = zmalloc(end - begin + 1); + if (str == NULL) { + PERROR("zmalloc strdupdelim"); + goto error; + } + + memcpy(str, begin, end - begin); + str[end - begin] = '\0'; + +error: + return str; +} diff --git a/src/common/utils.h b/src/common/utils.h index 87d090245..d47d44889 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -22,5 +22,6 @@ char *utils_expand_path(const char *path); int utils_create_pipe(int *dst); int utils_create_pipe_cloexec(int *dst); void utils_close_pipe(int *src); +char *utils_strdupdelim(const char *begin, const char *end); #endif /* _COMMON_UTILS_H */ diff --git a/src/lib/lttng-ctl/Makefile.am b/src/lib/lttng-ctl/Makefile.am index a5f6851ca..e00a88026 100644 --- a/src/lib/lttng-ctl/Makefile.am +++ b/src/lib/lttng-ctl/Makefile.am @@ -23,4 +23,6 @@ filter_grammar_test_SOURCES = filter-grammar-test.c filter_grammar_test_LDADD = liblttng-ctl.la liblttng_ctl_la_LIBADD = \ - $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la + $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \ + $(top_builddir)/src/common/libcommon.la \ + $(top_builddir)/src/common/hashtable/libhashtable.la diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index ba0c4c826..064f739aa 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "filter-ast.h" @@ -74,6 +75,134 @@ static int connected; int lttng_opt_quiet; int lttng_opt_verbose; +static void set_default_url_attr(struct lttng_uri *uri, + enum lttng_stream_type stype) +{ + uri->stype = stype; + if (uri->dtype != LTTNG_DST_PATH && uri->port == 0) { + uri->port = (stype == LTTNG_STREAM_CONTROL) ? + DEFAULT_NETWORK_CONTROL_PORT : DEFAULT_NETWORK_DATA_PORT; + } +} + +/* + * Parse a string URL and creates URI(s) returning the size of the populated + * array. + */ +static ssize_t parse_str_urls_to_uri(const char *ctrl_url, const char *data_url, + struct lttng_uri **uris) +{ + int ret; + unsigned int equal = 1, idx = 0; + /* Add the "file://" size to the URL maximum size */ + char url[PATH_MAX + 7]; + ssize_t size_ctrl = 0, size_data = 0, size; + struct lttng_uri *ctrl_uris = NULL, *data_uris = NULL; + struct lttng_uri *tmp_uris = NULL; + + /* No URL(s) is allowed. This means that the consumer will be disabled. */ + if (ctrl_url == NULL && data_url == NULL) { + return 0; + } + + /* Check if URLs are equal and if so, only use the control URL */ + if (ctrl_url && data_url) { + equal = !strcmp(ctrl_url, data_url); + } + + /* + * Since we allow the str_url to be a full local filesystem path, we are + * going to create a valid file:// URL if it's the case. + * + * Check if first character is a '/' or else reject the URL. + */ + if (ctrl_url && ctrl_url[0] == '/') { + ret = snprintf(url, sizeof(url), "file://%s", ctrl_url); + if (ret < 0) { + PERROR("snprintf file url"); + goto parse_error; + } + ctrl_url = url; + } + + /* Parse the control URL if there is one */ + if (ctrl_url) { + size_ctrl = uri_parse(ctrl_url, &ctrl_uris); + if (size_ctrl < 1) { + ERR("Unable to parse the URL %s", ctrl_url); + goto parse_error; + } + + /* At this point, we know there is at least one URI in the array */ + set_default_url_attr(&ctrl_uris[0], LTTNG_STREAM_CONTROL); + + if (ctrl_uris[0].dtype == LTTNG_DST_PATH && data_url) { + ERR("Can not have a data URL when destination is file://"); + goto error; + } + + /* URL are not equal but the control URL uses a net:// protocol */ + if (size_ctrl == 2) { + if (!equal) { + ERR("Control URL uses the net:// protocol and the data URL is " + "different. Not allowed."); + goto error; + } else { + set_default_url_attr(&ctrl_uris[1], LTTNG_STREAM_DATA); + /* + * The data_url and ctrl_url are equal and the ctrl_url + * contains a net:// protocol so we just skip the data part. + */ + data_url = NULL; + } + } + } + + if (data_url) { + /* We have to parse the data URL in this case */ + size_data = uri_parse(data_url, &data_uris); + if (size_data < 1) { + ERR("Unable to parse the URL %s", data_url); + goto error; + } else if (size_data == 2) { + ERR("Data URL can not be set with the net[4|6]:// protocol"); + goto error; + } + + set_default_url_attr(&data_uris[0], LTTNG_STREAM_DATA); + } + + /* Compute total size */ + size = size_ctrl + size_data; + + tmp_uris = zmalloc(sizeof(struct lttng_uri) * size); + if (tmp_uris == NULL) { + PERROR("zmalloc uris"); + goto error; + } + + if (ctrl_uris) { + /* It's possible the control URIs array contains more than one URI */ + memcpy(tmp_uris, ctrl_uris, sizeof(struct lttng_uri) * size_ctrl); + ++idx; + } + + if (data_uris) { + memcpy(&tmp_uris[idx], data_uris, sizeof(struct lttng_uri)); + } + + *uris = tmp_uris; + + return size; + +error: + free(ctrl_uris); + free(data_uris); + free(tmp_uris); +parse_error: + return -1; +} + /* * Copy string from src to dst and enforce null terminated byte. */ @@ -108,7 +237,6 @@ static void copy_lttng_domain(struct lttng_domain *dst, struct lttng_domain *src break; default: memset(dst, 0, sizeof(struct lttng_domain)); - dst->type = LTTNG_DOMAIN_KERNEL; break; } } @@ -129,6 +257,8 @@ static int send_session_msg(struct lttcomm_session_msg *lsm) goto end; } + DBG("LSM cmd type : %d", lsm->cmd_type); + ret = lttcomm_send_creds_unix_sock(sessiond_socket, lsm, sizeof(struct lttcomm_session_msg)); @@ -150,6 +280,7 @@ static int send_session_varlen(void *data, size_t len) ret = -ENOTCONN; goto end; } + if (!data || !len) { ret = 0; goto end; @@ -363,9 +494,7 @@ static int disconnect_sessiond(void) * Return size of data (only payload, not header) or a negative error code. */ static int ask_sessiond_varlen(struct lttcomm_session_msg *lsm, - void *vardata, - size_t varlen, - void **buf) + void *vardata, size_t varlen, void **buf) { int ret; size_t size; @@ -921,51 +1050,35 @@ const char *lttng_strerror(int code) } /* - * Create a brand new session using name and path. - * Returns size of returned session payload data or a negative error code. - */ -int lttng_create_session(const char *name, const char *path) -{ - struct lttcomm_session_msg lsm; - - lsm.cmd_type = LTTNG_CREATE_SESSION; - copy_string(lsm.session.name, name, sizeof(lsm.session.name)); - copy_string(lsm.session.path, path, sizeof(lsm.session.path)); - - return ask_sessiond(&lsm, NULL); -} - -/* - * Create a new tracing session using a name, URIs and a consumer enable flag. + * Create a brand new session using name and url for destination. + * + * Returns LTTCOMM_OK on success or a negative error code. */ -int lttng_create_session_uri(const char *name, struct lttng_uri *ctrl_uri, - struct lttng_uri *data_uri, unsigned int enable_consumer) +int lttng_create_session(const char *name, const char *url) { + ssize_t size; struct lttcomm_session_msg lsm; + struct lttng_uri *uris = NULL; - /* Name and ctrl_uri are mandatory */ - if (name == NULL || ctrl_uri == NULL) { + if (name == NULL) { return -1; } - lsm.cmd_type = LTTNG_CREATE_SESSION_URI; + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_CREATE_SESSION; copy_string(lsm.session.name, name, sizeof(lsm.session.name)); - /* Anything bigger than zero, the consumer(s) will be enabled */ - lsm.u.create_uri.enable_consumer = enable_consumer; - memcpy(&lsm.u.create_uri.ctrl_uri, ctrl_uri, - sizeof(lsm.u.create_uri.ctrl_uri)); - if (data_uri) { - /* - * The only possible scenario where data_uri is NULL is for a local - * consumer where the output is at a specified path name on the - * filesystem. - */ - memcpy(&lsm.u.create_uri.data_uri, data_uri, - sizeof(lsm.u.create_uri.data_uri)); + + /* There should never be a data URL */ + size = parse_str_urls_to_uri(url, NULL, &uris); + if (size < 0) { + return LTTCOMM_INVALID; } - return ask_sessiond(&lsm, NULL); + lsm.u.uri.size = size; + + return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + NULL); } /* @@ -1213,27 +1326,38 @@ int lttng_session_daemon_alive(void) } /* - * Set URI for a consumer for a session and domain. + * Set URL for a consumer for a session and domain. * * Return 0 on success, else a negative value. */ -int lttng_set_consumer_uri(struct lttng_handle *handle, struct lttng_uri *uri) +int lttng_set_consumer_url(struct lttng_handle *handle, + const char *control_url, const char *data_url) { + ssize_t size; struct lttcomm_session_msg lsm; + struct lttng_uri *uris = NULL; - if (handle == NULL || uri == NULL) { + if (handle == NULL || (control_url == NULL && data_url == NULL)) { return -1; } + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_SET_CONSUMER_URI; copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); copy_lttng_domain(&lsm.domain, &handle->domain); - memcpy(&lsm.u.uri, uri, sizeof(lsm.u.uri)); + size = parse_str_urls_to_uri(control_url, data_url, &uris); + if (size < 0) { + return LTTCOMM_INVALID; + } + + lsm.u.uri.size = size; - return ask_sessiond(&lsm, NULL); + return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + NULL); } /* diff --git a/tests/tools/Makefile.am b/tests/tools/Makefile.am index 5cad1fb05..f4cfe57b9 100644 --- a/tests/tools/Makefile.am +++ b/tests/tools/Makefile.am @@ -11,7 +11,8 @@ UTILS=../utils.h SESSIONS=$(top_srcdir)/src/bin/lttng-sessiond/session.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 + $(top_srcdir)/src/common/uri.c \ + $(top_srcdir)/src/common/utils.c COMMON=$(top_builddir)/src/common/libcommon.la HASHTABLE=$(top_builddir)/src/common/hashtable/libhashtable.la SESSIOND_COMM=$(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la @@ -28,7 +29,8 @@ if HAVE_LIBLTTNG_UST_CTL noinst_PROGRAMS += test_ust_data_trace UST_DATA_TRACE=$(top_srcdir)/src/bin/lttng-sessiond/trace-ust.c \ $(top_srcdir)/src/bin/lttng-sessiond/consumer.c \ - $(top_srcdir)/src/common/uri.c + $(top_srcdir)/src/common/uri.c \ + $(top_srcdir)/src/common/utils.c # UST trace data unit tests test_ust_data_trace_SOURCES = test_ust_data_trace.c $(UTILS) $(UST_DATA_TRACE) test_ust_data_trace_LDADD = $(COMMON) $(HASHTABLE) $(SESSIOND_COMM) diff --git a/tests/tools/streaming/unit_tests.c b/tests/tools/streaming/unit_tests.c index 6fea139c3..915e7d1ad 100644 --- a/tests/tools/streaming/unit_tests.c +++ b/tests/tools/streaming/unit_tests.c @@ -37,7 +37,7 @@ /* For lttngerr.h */ int lttng_opt_quiet = 1; -int lttng_opt_verbose = 0; +int lttng_opt_verbose = 3; /* * Test string URI and if uri_parse works well. @@ -138,7 +138,7 @@ int test_uri(void) assert(strcmp(uri[0].dst.ipv4, "42.42.42.42") == 0); PRINT_OK(); - s_uri1 = "tcp6://fe80::f66d:4ff:fe53:d220/my/test/path"; + s_uri1 = "tcp6://[fe80::f66d:4ff:fe53:d220]/my/test/path"; fprintf(stdout, " [+] URI set to %s ", s_uri1); size = uri_parse(s_uri1, &uri); assert(size == 1); @@ -174,12 +174,6 @@ int test_uri(void) assert(size == -1); PRINT_OK(); - s_uri1 = "net://localhost/"; - fprintf(stdout, " [+] Bad URI set to %s ", s_uri1); - size = uri_parse(s_uri1, &uri); - assert(size == -1); - PRINT_OK(); - return 0; } diff --git a/tests/tools/test_kernel_data_trace.c b/tests/tools/test_kernel_data_trace.c index 8bd62875a..c49d7ce54 100644 --- a/tests/tools/test_kernel_data_trace.c +++ b/tests/tools/test_kernel_data_trace.c @@ -89,7 +89,7 @@ static void create_kernel_metadata(void) assert(kern != NULL); printf("Create kernel metadata: "); - kern->metadata = trace_kernel_create_metadata(PATH1); + kern->metadata = trace_kernel_create_metadata(); assert(kern->metadata != NULL); PRINT_OK(); diff --git a/tests/tools/test_sessions.c b/tests/tools/test_sessions.c index fc3fbc1eb..cd8003dda 100644 --- a/tests/tools/test_sessions.c +++ b/tests/tools/test_sessions.c @@ -196,12 +196,6 @@ static int fuzzing_create_args(void) return -1; } - ret = create_one_session(SESSION1, NULL); - if (ret > 0) { - printf("Session created with %s, (null)\n", SESSION1); - return -1; - } - /* Session list must be 0 */ assert(!session_list_count());