int lttng_opt_quiet;
int lttng_opt_verbose;
+/*
+ * Compare two URL destination.
+ *
+ * Return 0 is equal else is not equal.
+ */
+static int compare_destination(struct lttng_uri *ctrl, struct lttng_uri *data)
+{
+ int ret;
+
+ assert(ctrl);
+ assert(data);
+
+ switch (ctrl->dtype) {
+ case LTTNG_DST_IPV4:
+ ret = strncmp(ctrl->dst.ipv4, data->dst.ipv4, sizeof(ctrl->dst.ipv4));
+ break;
+ case LTTNG_DST_IPV6:
+ ret = strncmp(ctrl->dst.ipv6, data->dst.ipv6, sizeof(ctrl->dst.ipv6));
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
static void set_default_url_attr(struct lttng_uri *uri,
enum lttng_stream_type stype)
{
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];
* 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");
}
if (data_url) {
+ int ret;
+
/* We have to parse the data URL in this case */
size_data = uri_parse(data_url, &data_uris);
if (size_data < 1) {
}
set_default_url_attr(&data_uris[0], LTTNG_STREAM_DATA);
+
+ ret = compare_destination(&ctrl_uris[0], &data_uris[0]);
+ if (ret != 0) {
+ ERR("Control and data destination mismatch");
+ goto error;
+ }
}
/* Compute total size */
/* 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;
*/
static int set_session_daemon_path(void)
{
- int ret;
int in_tgroup = 0; /* In tracing group */
uid_t uid;
}
if (uid != 0) {
+ int ret;
+
if (in_tgroup) {
/* Tracing group */
ret = try_connect_sessiond(sessiond_sock_path);
*/
void lttng_destroy_handle(struct lttng_handle *handle)
{
- if (handle) {
- free(handle);
- }
+ free(handle);
}
/*
/* Check for data availability */
do {
- data_ret = lttng_data_available(session_name);
+ data_ret = lttng_data_pending(session_name);
if (data_ret < 0) {
/* Return the data available call error. */
ret = data_ret;
* Data sleep time before retrying (in usec). Don't sleep if the call
* returned value indicates availability.
*/
- if (!data_ret) {
+ if (data_ret) {
usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
_MSG(".");
}
- } while (data_ret != 1);
+ } while (data_ret != 0);
MSG("");
}
/*
- * 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.
+ * 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.
*/
/* 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);
}
/*
- * 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;
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;
}
/*
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);
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);
*/
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;
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;
}
/*
memset(attr, 0, sizeof(struct lttng_channel_attr));
+ /* Same for all domains. */
+ attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ attr->tracefile_size = DEFAULT_CHANNEL_TRACEFILE_SIZE;
+ attr->tracefile_count = DEFAULT_CHANNEL_TRACEFILE_COUNT;
+
switch (domain->type) {
case LTTNG_DOMAIN_KERNEL:
- attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
- 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->switch_timer_interval = DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
+ attr->subbuf_size = default_get_kernel_channel_subbuf_size();
attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
break;
case LTTNG_DOMAIN_UST:
-#if 0
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
-#endif
- attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
- 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->num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM;
- attr->output = DEFAULT_UST_CHANNEL_OUTPUT;
- break;
+ switch (domain->buf_type) {
+ case LTTNG_BUFFER_PER_UID:
+ attr->subbuf_size = default_get_ust_uid_channel_subbuf_size();
+ attr->num_subbuf = DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM;
+ attr->output = DEFAULT_UST_UID_CHANNEL_OUTPUT;
+ attr->switch_timer_interval = DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval = DEFAULT_UST_UID_CHANNEL_READ_TIMER;
+ break;
+ case LTTNG_BUFFER_PER_PID:
+ default:
+ attr->subbuf_size = default_get_ust_pid_channel_subbuf_size();
+ attr->num_subbuf = DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM;
+ attr->output = DEFAULT_UST_PID_CHANNEL_OUTPUT;
+ attr->switch_timer_interval = DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
+ attr->read_timer_interval = DEFAULT_UST_PID_CHANNEL_READ_TIMER;
+ break;
+ }
default:
/* Default behavior: leave set to 0. */
break;
return ret;
}
- if (strlen(sessiond_sock_path) == 0) {
+ if (*sessiond_sock_path == '\0') {
/*
* No socket path set. Weird error which means the constructor was not
* called.
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;
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;
}
/*
- * Enable consumer for a session and domain.
- *
- * Return 0 on success, else a negative value.
+ * [OBSOLETE]
*/
int lttng_enable_consumer(struct lttng_handle *handle)
{
- struct lttcomm_session_msg lsm;
-
- if (handle == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- lsm.cmd_type = LTTNG_ENABLE_CONSUMER;
-
- copy_string(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- copy_lttng_domain(&lsm.domain, &handle->domain);
-
- return ask_sessiond(&lsm, NULL);
+ return -ENOSYS;
}
/*
- * Disable consumer for a session and domain.
- *
- * Return 0 on success, else a negative value.
+ * [OBSOLETE]
*/
int lttng_disable_consumer(struct lttng_handle *handle)
{
- struct lttcomm_session_msg lsm;
-
- if (handle == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- lsm.cmd_type = LTTNG_DISABLE_CONSUMER;
-
- copy_string(lsm.session.name, handle->session_name,
- sizeof(lsm.session.name));
- copy_lttng_domain(&lsm.domain, &handle->domain);
-
- return ask_sessiond(&lsm, NULL);
+ return -ENOSYS;
}
/*
*/
static int set_health_socket_path(void)
{
- int ret;
int in_tgroup = 0; /* In tracing group */
uid_t uid;
const char *home;
}
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)
ret = reply.ret_code;
close_error:
- close(sock);
+ {
+ int closeret;
+
+ closeret = close(sock);
+ assert(!closeret);
+ }
error:
return ret;
struct lttcomm_session_msg lsm;
struct lttng_uri *uris = NULL;
- if (name == NULL || datetime == NULL) {
+ if (name == NULL || datetime == NULL || url == NULL) {
return -LTTNG_ERR_INVALID;
}
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 (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);
+ /* Don't append datetime if the name was automatically created. */
+ if (strncmp(name, DEFAULT_SESSION_NAME "-",
+ strlen(DEFAULT_SESSION_NAME) + 1)) {
+ ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s-%s",
+ name, datetime);
+ } else {
+ ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s", name);
+ }
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;
}
/*
* or is still being extracted by the consumer(s) hence not ready to be used by
* any readers.
*/
-int lttng_data_available(const char *session_name)
+int lttng_data_pending(const char *session_name)
{
int ret;
struct lttcomm_session_msg lsm;
return -LTTNG_ERR_INVALID;
}
- lsm.cmd_type = LTTNG_DATA_AVAILABLE;
+ lsm.cmd_type = LTTNG_DATA_PENDING;
copy_string(lsm.session.name, session_name, sizeof(lsm.session.name));
/* Set socket for health check */
(void) set_health_socket_path();
}
+
+/*
+ * lib destructor
+ */
+static void __attribute__((destructor)) lttng_ctl_exit()
+{
+ free(tracing_group);
+}