X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=6bf19a46acadc97ee3815a91189835daa8e307ba;hb=3dd05a854fd61d14a2c395c0c82678abd63798e9;hp=edaebf59c8654515ac7872d0888e4a84dd6ab0ad;hpb=2f70b271351fe2b7befc4e327503f7c13a57dcd5;p=lttng-tools.git diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index edaebf59c..6bf19a46a 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -69,8 +69,6 @@ static int connected; * Those two variables are used by error.h to silent or control the verbosity of * error message. They are global to the library so application linking with it * are able to compile correctly and also control verbosity of the library. - * - * Note that it is *not* possible to silent ERR() and PERROR() macros. */ int lttng_opt_quiet; int lttng_opt_verbose; @@ -92,7 +90,6 @@ static void set_default_url_attr(struct lttng_uri *uri, 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]; @@ -117,6 +114,8 @@ static ssize_t parse_str_urls_to_uri(const char *ctrl_url, const char *data_url, * Check if first character is a '/' or else reject the URL. */ if (ctrl_url && ctrl_url[0] == '/') { + int ret; + ret = snprintf(url, sizeof(url), "file://%s", ctrl_url); if (ret < 0) { PERROR("snprintf file url"); @@ -185,10 +184,12 @@ static ssize_t parse_str_urls_to_uri(const char *ctrl_url, const char *data_url, /* It's possible the control URIs array contains more than one URI */ memcpy(tmp_uris, ctrl_uris, sizeof(struct lttng_uri) * size_ctrl); ++idx; + free(ctrl_uris); } if (data_uris) { memcpy(&tmp_uris[idx], data_uris, sizeof(struct lttng_uri)); + free(data_uris); } *uris = tmp_uris; @@ -416,7 +417,6 @@ error: */ static int set_session_daemon_path(void) { - int ret; int in_tgroup = 0; /* In tracing group */ uid_t uid; @@ -433,6 +433,8 @@ static int set_session_daemon_path(void) } if (uid != 0) { + int ret; + if (in_tgroup) { /* Tracing group */ ret = try_connect_sessiond(sessiond_sock_path); @@ -682,11 +684,11 @@ int lttng_start_tracing(const char *session_name) } /* - * Stop tracing for all traces of the session. - * Returns size of returned session payload data or a negative error code. + * Stop tracing for all traces of the session. */ -int lttng_stop_tracing(const char *session_name) +static int _lttng_stop_tracing(const char *session_name, int wait) { + int ret, data_ret; struct lttcomm_session_msg lsm; if (session_name == NULL) { @@ -697,14 +699,64 @@ int lttng_stop_tracing(const char *session_name) copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); - return ask_sessiond(&lsm, NULL); + ret = ask_sessiond(&lsm, NULL); + if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) { + goto error; + } + + if (!wait) { + goto end; + } + + _MSG("Waiting for data availability"); + + /* Check for data availability */ + do { + data_ret = lttng_data_pending(session_name); + if (data_ret < 0) { + /* Return the data available call error. */ + ret = data_ret; + goto error; + } + + /* + * Data sleep time before retrying (in usec). Don't sleep if the call + * returned value indicates availability. + */ + if (data_ret) { + usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME); + _MSG("."); + } + } while (data_ret != 0); + + MSG(""); + +end: +error: + return ret; +} + +/* + * Stop tracing and wait for data availability. + */ +int lttng_stop_tracing(const char *session_name) +{ + return _lttng_stop_tracing(session_name, 1); } /* - * Add context to event and/or channel. - * If event_name is NULL, the context is applied to all events of the channel. - * If channel_name is NULL, a lookup of the event's channel is done. - * If both are NULL, the context is applied to all events of all channels. + * Stop tracing but _don't_ wait for data availability. + */ +int lttng_stop_tracing_no_wait(const char *session_name) +{ + return _lttng_stop_tracing(session_name, 0); +} + +/* + * Add context to a channel. + * + * If the given channel is NULL, add the contexts to all channels. + * The event_name param is ignored. * * Returns the size of the returned payload data or a negative error code. */ @@ -726,9 +778,6 @@ int lttng_add_context(struct lttng_handle *handle, /* Copy channel name */ copy_string(lsm.u.context.channel_name, channel_name, sizeof(lsm.u.context.channel_name)); - /* Copy event name */ - copy_string(lsm.u.context.event_name, event_name, - sizeof(lsm.u.context.event_name)); copy_lttng_domain(&lsm.domain, &handle->domain); @@ -782,13 +831,13 @@ int lttng_enable_event(struct lttng_handle *handle, } /* - * set filter for an event + * Create or enable an event with a filter expression. + * * Return negative error value on error. * Return size of returned session payload data if OK. */ - -int lttng_set_event_filter(struct lttng_handle *handle, - const char *event_name, const char *channel_name, +int lttng_enable_event_with_filter(struct lttng_handle *handle, + struct lttng_event *event, const char *channel_name, const char *filter_expression) { struct lttcomm_session_msg lsm; @@ -796,13 +845,21 @@ int lttng_set_event_filter(struct lttng_handle *handle, FILE *fmem; int ret = 0; - /* Safety check. */ - if (handle == NULL) { - return -LTTNG_ERR_INVALID; + if (!filter_expression) { + /* + * Fall back to normal event enabling if no filter + * specified. + */ + return lttng_enable_event(handle, event, channel_name); } - if (!filter_expression) { - return 0; + /* + * Empty filter string will always be rejected by the parser + * anyway, so treat this corner-case early to eliminate + * lttng_fmemopen error for 0-byte allocation. + */ + if (handle == NULL || filter_expression[0] == '\0') { + return -LTTNG_ERR_INVALID; } /* @@ -876,15 +933,17 @@ int lttng_set_event_filter(struct lttng_handle *handle, memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_SET_FILTER; + lsm.cmd_type = LTTNG_ENABLE_EVENT_WITH_FILTER; /* Copy channel name */ - copy_string(lsm.u.filter.channel_name, channel_name, - sizeof(lsm.u.filter.channel_name)); + copy_string(lsm.u.enable.channel_name, channel_name, + sizeof(lsm.u.enable.channel_name)); /* Copy event name */ - copy_string(lsm.u.filter.event_name, event_name, - sizeof(lsm.u.filter.event_name)); - lsm.u.filter.bytecode_len = sizeof(ctx->bytecode->b) + if (event) { + memcpy(&lsm.u.enable.event, event, sizeof(lsm.u.enable.event)); + } + + lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b) + bytecode_get_len(&ctx->bytecode->b); copy_lttng_domain(&lsm.domain, &handle->domain); @@ -893,7 +952,7 @@ int lttng_set_event_filter(struct lttng_handle *handle, sizeof(lsm.session.name)); ret = ask_sessiond_varlen(&lsm, &ctx->bytecode->b, - lsm.u.filter.bytecode_len, NULL); + lsm.u.enable.bytecode_len, NULL); filter_bytecode_free(ctx); filter_ir_free(ctx); @@ -1082,6 +1141,7 @@ const char *lttng_strerror(int code) */ int lttng_create_session(const char *name, const char *url) { + int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; @@ -1103,8 +1163,11 @@ int lttng_create_session(const char *name, const char *url) lsm.u.uri.size = size; - return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); + + free(uris); + return ret; } /* @@ -1296,7 +1359,7 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; - attr->subbuf_size = DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE; + attr->subbuf_size = default_get_kernel_channel_subbuf_size(); attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT; break; @@ -1310,7 +1373,7 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; - attr->subbuf_size = DEFAULT_UST_CHANNEL_SUBBUF_SIZE; + attr->subbuf_size = default_get_ust_channel_subbuf_size(); attr->num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM; attr->output = DEFAULT_UST_CHANNEL_OUTPUT; break; @@ -1362,6 +1425,7 @@ int lttng_session_daemon_alive(void) int lttng_set_consumer_url(struct lttng_handle *handle, const char *control_url, const char *data_url) { + int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; @@ -1385,8 +1449,11 @@ int lttng_set_consumer_url(struct lttng_handle *handle, lsm.u.uri.size = size; - return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); + + free(uris); + return ret; } /* @@ -1441,7 +1508,6 @@ int lttng_disable_consumer(struct lttng_handle *handle) */ static int set_health_socket_path(void) { - int ret; int in_tgroup = 0; /* In tracing group */ uid_t uid; const char *home; @@ -1459,6 +1525,8 @@ static int set_health_socket_path(void) } if (uid != 0) { + int ret; + /* * With GNU C < 2.1, snprintf returns -1 if the target buffer is too small; * With GNU C >= 2.1, snprintf returns the required size (excluding closing null) @@ -1558,36 +1626,65 @@ int _lttng_create_session_ext(const char *name, const char *url, memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION; - if (!strncmp(name, DEFAULT_SESSION_NAME, strlen(DEFAULT_SESSION_NAME))) { - ret = snprintf(lsm.session.name, sizeof(lsm.session.name), "%s-%s", - name, datetime); - if (ret < 0) { - PERROR("snprintf session name datetime"); - return -LTTNG_ERR_FATAL; - } - } else { - copy_string(lsm.session.name, name, sizeof(lsm.session.name)); - } + copy_string(lsm.session.name, name, sizeof(lsm.session.name)); /* There should never be a data URL */ size = parse_str_urls_to_uri(url, NULL, &uris); if (size < 0) { - return -LTTNG_ERR_INVALID; + ret = -LTTNG_ERR_INVALID; + goto error; } lsm.u.uri.size = size; - if (uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) { + if (size > 0 && uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) { ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s-%s", name, datetime); if (ret < 0) { PERROR("snprintf uri subdir"); - return -LTTNG_ERR_FATAL; + ret = -LTTNG_ERR_FATAL; + goto error; } } - return ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, + ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); + +error: + free(uris); + return ret; +} + +/* + * For a given session name, this call checks if the data is ready to be read + * or is still being extracted by the consumer(s) hence not ready to be used by + * any readers. + */ +int lttng_data_pending(const char *session_name) +{ + int ret; + struct lttcomm_session_msg lsm; + + if (session_name == NULL) { + return -LTTNG_ERR_INVALID; + } + + lsm.cmd_type = LTTNG_DATA_PENDING; + + copy_string(lsm.session.name, session_name, sizeof(lsm.session.name)); + + ret = ask_sessiond(&lsm, NULL); + + /* + * The ask_sessiond function negate the return code if it's not LTTNG_OK so + * getting -1 means that the reply ret_code was 1 thus meaning that the + * data is available. Yes it is hackish but for now this is the only way. + */ + if (ret == -1) { + ret = 1; + } + + return ret; } /* @@ -1600,3 +1697,11 @@ static void __attribute__((constructor)) init() /* Set socket for health check */ (void) set_health_socket_path(); } + +/* + * lib destructor + */ +static void __attribute__((destructor)) lttng_ctl_exit() +{ + free(tracing_group); +}