#include <common/utils.h>
#include <lttng/lttng.h>
#include <lttng/health-internal.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/endpoint.h>
+#include <lttng/channel-internal.h>
#include "filter/filter-ast.h"
#include "filter/filter-parser.h"
{
struct lttng_handle *handle = NULL;
- if (domain == NULL) {
- goto end;
- }
-
handle = zmalloc(sizeof(struct lttng_handle));
if (handle == NULL) {
PERROR("malloc handle");
lttng_ctl_copy_string(handle->session_name, session_name,
sizeof(handle->session_name));
- /* Copy lttng domain */
- lttng_ctl_copy_lttng_domain(&handle->domain, domain);
+ /* Copy lttng domain or leave initialized to 0. */
+ if (domain) {
+ lttng_ctl_copy_lttng_domain(&handle->domain, domain);
+ }
end:
return handle;
assert(ev);
/* Don't add filter for the '*' event. */
- if (ev->name[0] != '*') {
+ if (strcmp(ev->name, "*") != 0) {
if (filter) {
err = asprintf(&agent_filter, "(%s) && (logger_name == \"%s\")", filter,
ev->name);
ret = -LTTNG_ERR_FILTER_INVAL;
goto parse_error;
}
- ret = filter_visitor_set_parent(ctx);
- if (ret) {
- fprintf(stderr, "Set parent error\n");
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
if (print_xml) {
ret = filter_visitor_print_xml(ctx, stdout, 0);
if (ret) {
ret = -LTTNG_ERR_FILTER_INVAL;
goto parse_error;
}
+
+ /* Normalize globbing patterns in the expression. */
+ ret = filter_visitor_ir_normalize_glob_patterns(ctx);
+ if (ret) {
+ ret = -LTTNG_ERR_FILTER_INVAL;
+ goto parse_error;
+ }
+
/* Validate strings used as literals in the expression. */
ret = filter_visitor_ir_validate_string(ctx);
if (ret) {
ret = -LTTNG_ERR_FILTER_INVAL;
goto parse_error;
}
+
+ /* Validate globbing patterns in the expression. */
+ ret = filter_visitor_ir_validate_globbing(ctx);
+ if (ret) {
+ ret = -LTTNG_ERR_FILTER_INVAL;
+ goto parse_error;
+ }
+
dbg_printf("done\n");
dbg_printf("Generating bytecode... ");
return lttng_disable_event_ext(handle, &ev, channel_name, NULL);
}
+struct lttng_channel *lttng_channel_create(struct lttng_domain *domain)
+{
+ struct lttng_channel *channel = NULL;
+ struct lttng_channel_extended *extended = NULL;
+
+ if (!domain) {
+ goto error;
+ }
+
+ /* Validate domain. */
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST:
+ switch (domain->buf_type) {
+ case LTTNG_BUFFER_PER_UID:
+ case LTTNG_BUFFER_PER_PID:
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case LTTNG_DOMAIN_KERNEL:
+ if (domain->buf_type != LTTNG_BUFFER_GLOBAL) {
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ channel = zmalloc(sizeof(*channel));
+ if (!channel) {
+ goto error;
+ }
+
+ extended = zmalloc(sizeof(*extended));
+ if (!extended) {
+ goto error;
+ }
+
+ channel->attr.extended.ptr = extended;
+
+ lttng_channel_set_default_attr(domain, &channel->attr);
+ return channel;
+error:
+ free(channel);
+ free(extended);
+ return NULL;
+}
+
+void lttng_channel_destroy(struct lttng_channel *channel)
+{
+ if (!channel) {
+ return;
+ }
+
+ if (channel->attr.extended.ptr) {
+ free(channel->attr.extended.ptr);
+ }
+ free(channel);
+}
+
/*
* Enable channel per domain
* Returns size of returned session payload data or a negative error code.
*/
int lttng_enable_channel(struct lttng_handle *handle,
- struct lttng_channel *chan)
+ struct lttng_channel *in_chan)
{
struct lttcomm_session_msg lsm;
/* NULL arguments are forbidden. No default values. */
- if (handle == NULL || chan == NULL) {
+ if (handle == NULL || in_chan == NULL) {
return -LTTNG_ERR_INVALID;
}
memset(&lsm, 0, sizeof(lsm));
+ memcpy(&lsm.u.channel.chan, in_chan, sizeof(lsm.u.channel.chan));
+ lsm.u.channel.chan.attr.extended.ptr = NULL;
- memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan));
+ if (!in_chan->attr.extended.ptr) {
+ struct lttng_channel *channel;
+ struct lttng_channel_extended *extended;
- lsm.cmd_type = LTTNG_ENABLE_CHANNEL;
+ channel = lttng_channel_create(&handle->domain);
+ if (!channel) {
+ return -LTTNG_ERR_NOMEM;
+ }
+
+ /*
+ * Create a new channel in order to use default extended
+ * attribute values.
+ */
+ extended = (struct lttng_channel_extended *)
+ channel->attr.extended.ptr;
+ memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
+ lttng_channel_destroy(channel);
+ } else {
+ struct lttng_channel_extended *extended;
+
+ extended = (struct lttng_channel_extended *)
+ in_chan->attr.extended.ptr;
+ memcpy(&lsm.u.channel.extended, extended, sizeof(*extended));
+ }
+ lsm.cmd_type = LTTNG_ENABLE_CHANNEL;
lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
lttng_ctl_copy_string(lsm.session.name, handle->session_name,
* Destroy session using name.
* Returns size of returned session payload data or a negative error code.
*/
+static
int _lttng_destroy_session(const char *session_name)
{
struct lttcomm_session_msg lsm;
int ret;
size_t channel_count, i;
const size_t channel_size = sizeof(struct lttng_channel) +
- sizeof(struct lttcomm_channel_extended);
+ sizeof(struct lttng_channel_extended);
struct lttcomm_session_msg lsm;
void *extended_at;
struct lttng_channel *chan = &(*channels)[i];
chan->attr.extended.ptr = extended_at;
- extended_at += sizeof(struct lttcomm_channel_extended);
+ extended_at += sizeof(struct lttng_channel_extended);
}
ret = (int) channel_count;
return 0;
}
-/*
- * Returns size of returned session payload data or a negative error code.
- */
int lttng_calibrate(struct lttng_handle *handle,
struct lttng_calibrate *calibrate)
{
- struct lttcomm_session_msg lsm;
-
- /* Safety check. NULL pointer are forbidden */
- if (handle == NULL || calibrate == NULL) {
- return -LTTNG_ERR_INVALID;
- }
-
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_CALIBRATE;
- lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
-
- memcpy(&lsm.u.calibrate, calibrate, sizeof(lsm.u.calibrate));
-
- return lttng_ctl_ask_sessiond(&lsm, NULL);
+ /*
+ * This command was removed in LTTng 2.9.
+ */
+ return -LTTNG_ERR_UND;
}
/*
void lttng_channel_set_default_attr(struct lttng_domain *domain,
struct lttng_channel_attr *attr)
{
+ struct lttng_channel_extended *extended;
+
/* Safety check */
if (attr == NULL || domain == NULL) {
return;
}
+ extended = (struct lttng_channel_extended *) attr->extended.ptr;
memset(attr, 0, sizeof(struct lttng_channel_attr));
/* Same for all domains. */
attr->subbuf_size = default_get_kernel_channel_subbuf_size();
attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
+ }
break;
case LTTNG_DOMAIN_UST:
switch (domain->buf_type) {
DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
attr->read_timer_interval =
DEFAULT_UST_UID_CHANNEL_READ_TIMER;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
+ }
break;
case LTTNG_BUFFER_PER_PID:
default:
DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
attr->read_timer_interval =
DEFAULT_UST_PID_CHANNEL_READ_TIMER;
+ if (extended) {
+ extended->monitor_timer_interval =
+ DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
+ extended->blocking_timeout =
+ DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
+ }
break;
}
default:
/* Default behavior: leave set to 0. */
break;
}
+
+ attr->extended.ptr = extended;
}
int lttng_channel_get_discarded_event_count(struct lttng_channel *channel,
uint64_t *discarded_events)
{
int ret = 0;
- struct lttcomm_channel_extended *chan_ext;
+ struct lttng_channel_extended *chan_ext;
if (!channel || !discarded_events) {
ret = -LTTNG_ERR_INVALID;
uint64_t *lost_packets)
{
int ret = 0;
- struct lttcomm_channel_extended *chan_ext;
+ struct lttng_channel_extended *chan_ext;
if (!channel || !lost_packets) {
ret = -LTTNG_ERR_INVALID;
return ret;
}
+int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
+ uint64_t *monitor_timer_interval)
+{
+ int ret = 0;
+
+ if (!chan || !monitor_timer_interval) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *monitor_timer_interval = ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->monitor_timer_interval;
+end:
+ return ret;
+}
+
+int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
+ uint64_t monitor_timer_interval)
+{
+ int ret = 0;
+
+ if (!chan || !chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->monitor_timer_interval =
+ monitor_timer_interval;
+end:
+ return ret;
+}
+
+int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
+ int64_t *blocking_timeout)
+{
+ int ret = 0;
+
+ if (!chan || !blocking_timeout) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *blocking_timeout = ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->blocking_timeout;
+end:
+ return ret;
+}
+
+int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
+ int64_t blocking_timeout)
+{
+ int ret = 0;
+ int64_t msec_timeout;
+
+ if (!chan || !chan->attr.extended.ptr) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (blocking_timeout < 0 && blocking_timeout != -1) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /*
+ * LTTng-ust's use of poll() to implement this timeout mechanism forces
+ * us to accept a narrower range of values (msecs expressed as a signed
+ * 32-bit integer).
+ */
+ msec_timeout = blocking_timeout / 1000;
+ if (msec_timeout != (int32_t) msec_timeout) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ((struct lttng_channel_extended *)
+ chan->attr.extended.ptr)->blocking_timeout =
+ blocking_timeout;
+end:
+ return ret;
+}
+
/*
* Check if session daemon is alive.
*
lsm.u.uri.size = size;
+ /*
+ * If the user does not specify a custom subdir, use the session name.
+ */
+ if (size > 0 && uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) {
+ ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s", name);
+ if (ret < 0) {
+ PERROR("snprintf uri subdir");
+ ret = -LTTNG_ERR_FATAL;
+ goto error;
+ }
+ }
+
ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, uris,
sizeof(struct lttng_uri) * size, NULL);
+error:
free(uris);
return ret;
}
* Regenerate the metadata for a session.
* Return 0 on success, a negative error code on error.
*/
+int lttng_regenerate_metadata(const char *session_name)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+
+ if (!session_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGENERATE_METADATA;
+
+ lttng_ctl_copy_string(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+/*
+ * Deprecated, replaced by lttng_regenerate_metadata.
+ */
int lttng_metadata_regenerate(const char *session_name)
+{
+ return lttng_regenerate_metadata(session_name);
+}
+
+/*
+ * Regenerate the statedump of a session.
+ * Return 0 on success, a negative error code on error.
+ */
+int lttng_regenerate_statedump(const char *session_name)
{
int ret;
struct lttcomm_session_msg lsm;
}
memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_METADATA_REGENERATE;
+ lsm.cmd_type = LTTNG_REGENERATE_STATEDUMP;
lttng_ctl_copy_string(lsm.session.name, session_name,
sizeof(lsm.session.name));
return ret;
}
+int lttng_register_trigger(struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ char *trigger_buf = NULL;
+ ssize_t trigger_size;
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ trigger_size = lttng_trigger_serialize(trigger, NULL);
+ if (trigger_size < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ trigger_buf = zmalloc(trigger_size);
+ if (!trigger_buf) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_REGISTER_TRIGGER;
+ if (lttng_trigger_serialize(trigger, trigger_buf) < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lsm.u.trigger.length = (uint32_t) trigger_size;
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, trigger_buf,
+ trigger_size, NULL);
+end:
+ free(trigger_buf);
+ return ret;
+}
+
+int lttng_unregister_trigger(struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ char *trigger_buf = NULL;
+ ssize_t trigger_size;
+
+ if (!trigger) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ if (!lttng_trigger_validate(trigger)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ trigger_size = lttng_trigger_serialize(trigger, NULL);
+ if (trigger_size < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ trigger_buf = zmalloc(trigger_size);
+ if (!trigger_buf) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
+ if (lttng_trigger_serialize(trigger, trigger_buf) < 0) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ lsm.u.trigger.length = (uint32_t) trigger_size;
+ ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, trigger_buf,
+ trigger_size, NULL);
+end:
+ free(trigger_buf);
+ return ret;
+}
+
+int lttng_session_get_current_archive_location(const char *session_name,
+ char **chunk_path)
+{
+ struct lttcomm_session_msg lsm;
+ struct lttng_session_get_current_output_return *output_return = NULL;
+ int ret;
+ size_t path_len;
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_SESSION_GET_CURRENT_OUTPUT;
+ ret = lttng_strncpy(lsm.session.name, session_name,
+ sizeof(lsm.session.name));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_ctl_ask_sessiond(&lsm, (void **) &output_return);
+ if (ret < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ path_len = lttng_strnlen(output_return->path,
+ sizeof(output_return->path));
+ if (path_len == 0 || path_len == sizeof(output_return->path)) {
+ ret = -LTTNG_ERR_NO_SESSION_OUTPUT;
+ goto end;
+ }
+
+ *chunk_path = zmalloc(path_len + 1);
+ if (!*chunk_path) {
+ ret = -1;
+ goto end;
+ }
+ memcpy(*chunk_path, output_return->path, path_len);
+
+ ret = 0;
+
+end:
+ free(output_return);
+ return ret;
+}
+
/*
* lib constructor.
*/
-static void __attribute__((constructor)) init()
+static void __attribute__((constructor)) init(void)
{
/* Set default session group */
lttng_set_tracing_group(DEFAULT_TRACING_GROUP);
/*
* lib destructor.
*/
-static void __attribute__((destructor)) lttng_ctl_exit()
+static void __attribute__((destructor)) lttng_ctl_exit(void)
{
free(tracing_group);
}