#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include <common/defaults.h>
#include <common/error.h>
const char * const config_element_tracefile_size = "tracefile_size";
const char * const config_element_tracefile_count = "tracefile_count";
const char * const config_element_live_timer_interval = "live_timer_interval";
-const char * const config_element_discarded_events = "discarded_events";
-const char * const config_element_lost_packets = "lost_packets";
+LTTNG_HIDDEN const char * const config_element_discarded_events = "discarded_events";
+LTTNG_HIDDEN const char * const config_element_lost_packets = "lost_packets";
const char * const config_element_type = "type";
const char * const config_element_buffer_type = "buffer_type";
const char * const config_element_session = "session";
const char * const config_element_sessions = "sessions";
-const char * const config_element_context_perf = "perf";
-const char * const config_element_context_app = "app";
-const char * const config_element_context_app_provider_name = "provider_name";
-const char * const config_element_context_app_ctx_name = "ctx_name";
+LTTNG_HIDDEN const char * const config_element_context_perf = "perf";
+LTTNG_HIDDEN const char * const config_element_context_app = "app";
+LTTNG_HIDDEN const char * const config_element_context_app_provider_name = "provider_name";
+LTTNG_HIDDEN const char * const config_element_context_app_ctx_name = "ctx_name";
const char * const config_element_config = "config";
const char * const config_element_started = "started";
const char * const config_element_snapshot_mode = "snapshot_mode";
const char * const config_element_loglevel = "loglevel";
const char * const config_element_loglevel_type = "loglevel_type";
const char * const config_element_filter = "filter";
-const char * const config_element_filter_expression = "filter_expression";
+LTTNG_HIDDEN const char * const config_element_filter_expression = "filter_expression";
const char * const config_element_snapshot_outputs = "snapshot_outputs";
const char * const config_element_consumer_output = "consumer_output";
const char * const config_element_destination = "destination";
const char * const config_event_context_hostname = "HOSTNAME";
const char * const config_event_context_ip = "IP";
const char * const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
-const char * const config_event_context_app = "APP";
-
+LTTNG_HIDDEN const char * const config_event_context_app = "APP";
+LTTNG_HIDDEN const char * const config_event_context_interruptible = "INTERRUPTIBLE";
+LTTNG_HIDDEN const char * const config_event_context_preemptible = "PREEMPTIBLE";
+LTTNG_HIDDEN const char * const config_event_context_need_reschedule = "NEED_RESCHEDULE";
+LTTNG_HIDDEN const char * const config_event_context_migratable = "MIGRATABLE";
+
+/* Deprecated symbols */
+const char * const config_element_perf;
+
+enum process_event_node_phase {
+ CREATION = 0,
+ ENABLE = 1,
+};
struct consumer_output {
int enabled;
} else if (!strcmp((char *) context_type,
config_event_context_ip)) {
ret = LTTNG_EVENT_CONTEXT_IP;
+ } else if (!strcmp((char *) context_type,
+ config_event_context_interruptible)) {
+ ret = LTTNG_EVENT_CONTEXT_INTERRUPTIBLE;
+ } else if (!strcmp((char *) context_type,
+ config_event_context_preemptible)) {
+ ret = LTTNG_EVENT_CONTEXT_PREEMPTIBLE;
+ } else if (!strcmp((char *) context_type,
+ config_event_context_need_reschedule)) {
+ ret = LTTNG_EVENT_CONTEXT_NEED_RESCHEDULE;
+ } else if (!strcmp((char *) context_type,
+ config_event_context_migratable)) {
+ ret = LTTNG_EVENT_CONTEXT_MIGRATABLE;
} else {
goto error;
}
}
static
-int create_session_net_output(const char *name, struct lttng_domain *domain,
- const char *control_uri, const char *data_uri)
+int create_session_net_output(const char *name, const char *control_uri,
+ const char *data_uri)
{
int ret;
struct lttng_handle *handle;
const char *uri = NULL;
assert(name);
- assert(domain);
- handle = lttng_create_handle(name, domain);
+ handle = lttng_create_handle(name, NULL);
if (!handle) {
ret = -LTTNG_ERR_NOMEM;
goto end;
}
static
-int create_snapshot_session(const char *session_name, xmlNodePtr output_node)
+int create_snapshot_session(const char *session_name, xmlNodePtr output_node,
+ const struct config_load_session_override_attr *overrides)
{
int ret;
xmlNodePtr node = NULL;
uint64_t max_size = UINT64_MAX;
struct consumer_output output = { 0 };
struct lttng_snapshot_output *snapshot_output = NULL;
+ const char *control_uri = NULL;
+ const char *data_uri = NULL;
+ const char *path = NULL;
for (node = xmlFirstElementChild(snapshot_output_node); node;
node = xmlNextElementSibling(node)) {
}
}
+ control_uri = output.control_uri;
+ data_uri = output.data_uri;
+ path = output.path;
+
+ if (overrides) {
+ if (overrides->path_url) {
+ path = overrides->path_url;
+ /* Control/data_uri are null */
+ control_uri = NULL;
+ data_uri = NULL;
+ } else {
+ if (overrides->ctrl_url) {
+ control_uri = overrides->ctrl_url;
+ /* path is null */
+ path = NULL;
+ }
+ if (overrides->data_url) {
+ data_uri = overrides->data_url;
+ /* path is null */
+ path = NULL;
+ }
+ }
+ }
+
snapshot_output = lttng_snapshot_output_create();
if (!snapshot_output) {
ret = -LTTNG_ERR_NOMEM;
goto error_snapshot_output;
}
- if (output.path) {
- ret = lttng_snapshot_output_set_ctrl_url(output.path,
+ if (path) {
+ ret = lttng_snapshot_output_set_ctrl_url(path,
snapshot_output);
if (ret) {
goto error_snapshot_output;
}
} else {
- if (output.control_uri) {
- ret = lttng_snapshot_output_set_ctrl_url(output.control_uri,
+ if (control_uri) {
+ ret = lttng_snapshot_output_set_ctrl_url(control_uri,
snapshot_output);
if (ret) {
goto error_snapshot_output;
}
}
- if (output.data_uri) {
- ret = lttng_snapshot_output_set_data_url(output.data_uri,
+ if (data_uri) {
+ ret = lttng_snapshot_output_set_data_url(data_uri,
snapshot_output);
if (ret) {
goto error_snapshot_output;
struct lttng_domain *jul_domain,
struct lttng_domain *log4j_domain,
xmlNodePtr output_node,
- uint64_t live_timer_interval)
+ uint64_t live_timer_interval,
+ const struct config_load_session_override_attr *overrides)
{
int ret;
struct consumer_output output = { 0 };
xmlNodePtr consumer_output_node;
+ const char *control_uri = NULL;
+ const char *data_uri = NULL;
+ const char *path = NULL;
assert(name);
}
}
- if (live_timer_interval != UINT64_MAX &&
- !output.control_uri && !output.data_uri) {
+ control_uri = output.control_uri;
+ data_uri = output.data_uri;
+ path = output.path;
+
+ /* Check for override and apply them */
+ if (overrides) {
+ if (overrides->path_url) {
+ path = overrides->path_url;
+ /* control/data_uri are null */;
+ control_uri = NULL;
+ data_uri = NULL;
+ } else {
+ if (overrides->ctrl_url) {
+ control_uri = overrides->ctrl_url;
+ /* path is null */
+ path = NULL;
+ }
+ if (overrides->data_url) {
+ data_uri = overrides->data_url;
+ /* path is null */
+ path = NULL;
+ }
+ }
+ }
+
+
+ if (live_timer_interval != UINT64_MAX && !control_uri && !data_uri) {
ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
goto end;
}
- if (output.control_uri || output.data_uri) {
- int i;
- struct lttng_domain *domain;
- struct lttng_domain *domains[] =
- { kernel_domain, ust_domain, jul_domain, log4j_domain };
-
+ if (control_uri || data_uri) {
/* network destination */
if (live_timer_interval && live_timer_interval != UINT64_MAX) {
/*
goto end;
}
- for (i = 0; i < (sizeof(domains) / sizeof(domains[0])); i++) {
- domain = domains[i];
- if (!domain) {
- continue;
- }
-
- ret = create_session_net_output(name, domain, output.control_uri,
- output.data_uri);
- if (ret) {
- goto end;
- }
+ ret = create_session_net_output(name, control_uri, data_uri);
+ if (ret) {
+ goto end;
}
+
} else {
/* either local output or no output */
- ret = lttng_create_session(name, output.path);
+ ret = lttng_create_session(name, path);
if (ret) {
goto end;
}
static
int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle,
- const char *channel_name)
+ const char *channel_name, const enum process_event_node_phase phase)
{
- int ret, i;
+ int ret = 0, i;
xmlNodePtr node;
struct lttng_event event;
char **exclusions = NULL;
goto end;
}
+ free(filter_expression);
filter_expression = strdup((char *) content);
free(content);
if (!filter_expression) {
}
}
- ret = lttng_enable_event_with_exclusions(handle, &event, channel_name,
- filter_expression, exclusion_count, exclusions);
- if (ret) {
- goto end;
- }
-
- if (!event.enabled) {
- /*
- * Note that we should use lttng_disable_event_ext() (2.6+) to
- * eliminate the risk of clashing on events of the same
- * name (with different event types and loglevels).
- *
- * Unfortunately, lttng_disable_event_ext() only performs a
- * match on the name and event type and errors out if any other
- * event attribute is not set to its default value.
- *
- * This will disable all events that match this name.
- */
- ret = lttng_disable_event(handle, event.name, channel_name);
+ if ((event.enabled && phase == ENABLE) || phase == CREATION) {
+ ret = lttng_enable_event_with_exclusions(handle, &event, channel_name,
+ filter_expression, exclusion_count, exclusions);
+ if (ret < 0) {
+ WARN("Enabling event (name:%s) on load failed.", event.name);
+ ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto end;
+ }
}
end:
for (i = 0; i < exclusion_count; i++) {
const char *channel_name)
{
int ret = 0;
+ struct lttng_event event;
xmlNodePtr node;
assert(events_node);
for (node = xmlFirstElementChild(events_node); node;
node = xmlNextElementSibling(node)) {
- ret = process_event_node(node, handle, channel_name);
+ ret = process_event_node(node, handle, channel_name, CREATION);
if (ret) {
goto end;
}
}
+
+ /*
+ * Disable all events to enable only the necessary events.
+ * Limitations regarding lttng_disable_events and tuple descriptor
+ * force this approach.
+ */
+ memset(&event, 0, sizeof(event));
+ event.loglevel = -1;
+ event.type = LTTNG_EVENT_ALL;
+ ret = lttng_disable_event_ext(handle, &event, channel_name, NULL);
+ if (ret) {
+ goto end;
+ }
+
+ for (node = xmlFirstElementChild(events_node); node;
+ node = xmlNextElementSibling(node)) {
+ ret = process_event_node(node, handle, channel_name, ENABLE);
+ if (ret) {
+ goto end;
+ }
+ }
+
end:
return ret;
}
static
int process_session_node(xmlNodePtr session_node, const char *session_name,
- int override)
+ int overwrite,
+ const struct config_load_session_override_attr *overrides)
{
int ret, started = -1, snapshot_mode = -1;
uint64_t live_timer_interval = UINT64_MAX;
goto error;
}
- if (override) {
+ /* Apply overrides */
+ if (overrides) {
+ if (overrides->session_name) {
+ xmlChar *name_override = xmlStrdup(BAD_CAST(overrides->session_name));
+ if (!name_override) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ /* Overrides the session name to the provided name */
+ xmlFree(name);
+ name = name_override;
+ }
+ }
+
+ if (overwrite) {
/* Destroy session if it exists */
ret = lttng_destroy_session((const char *) name);
if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
/* Create session type depending on output type */
if (snapshot_mode && snapshot_mode != -1) {
- ret = create_snapshot_session((const char *) name, output_node);
+ ret = create_snapshot_session((const char *) name, output_node,
+ overrides);
} else if (live_timer_interval &&
live_timer_interval != UINT64_MAX) {
ret = create_session((const char *) name, kernel_domain,
ust_domain, jul_domain, log4j_domain,
- output_node, live_timer_interval);
+ output_node, live_timer_interval, overrides);
} else {
/* regular session */
ret = create_session((const char *) name, kernel_domain,
ust_domain, jul_domain, log4j_domain,
- output_node, UINT64_MAX);
+ output_node, UINT64_MAX, overrides);
}
if (ret) {
goto error;
static
int load_session_from_file(const char *path, const char *session_name,
- struct session_config_validation_ctx *validation_ctx, int override)
+ struct session_config_validation_ctx *validation_ctx, int overwrite,
+ const struct config_load_session_override_attr *overrides)
{
int ret, session_found = !session_name;
xmlDocPtr doc = NULL;
session_node; session_node =
xmlNextElementSibling(session_node)) {
ret = process_session_node(session_node,
- session_name, override);
+ session_name, overwrite, overrides);
if (session_name && ret == 0) {
/* Target session found and loaded */
session_found = 1;
static
int load_session_from_path(const char *path, const char *session_name,
- struct session_config_validation_ctx *validation_ctx, int override)
+ struct session_config_validation_ctx *validation_ctx, int overwrite,
+ const struct config_load_session_override_attr *overrides)
{
int ret, session_found = !session_name;
DIR *directory = NULL;
file_path[path_len + file_name_len] = '\0';
ret = load_session_from_file(file_path, session_name,
- validation_ctx, override);
+ validation_ctx, overwrite, overrides);
if (session_name && !ret) {
session_found = 1;
break;
free(file_path);
} else {
ret = load_session_from_file(path, session_name,
- validation_ctx, override);
+ validation_ctx, overwrite, overrides);
if (ret) {
goto end;
} else {
}
}
- if (!session_found) {
- ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
+ if (session_found && !ret) {
+ ret = 0;
}
return ret;
LTTNG_HIDDEN
int config_load_session(const char *path, const char *session_name,
- int override, unsigned int autoload)
+ int overwrite, unsigned int autoload,
+ const struct config_load_session_override_attr *overrides)
{
int ret;
+ bool session_loaded = false;
const char *path_ptr = NULL;
struct session_config_validation_ctx validation_ctx = { 0 };
}
if (path_ptr) {
ret = load_session_from_path(path_ptr, session_name,
- &validation_ctx, override);
+ &validation_ctx, overwrite, overrides);
if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
goto end;
}
* Continue even if the session was found since we have to try
* the system wide sessions.
*/
+ session_loaded = true;
}
}
if (path_ptr) {
ret = load_session_from_path(path_ptr, session_name,
- &validation_ctx, override);
+ &validation_ctx, overwrite, overrides);
+ if (!ret) {
+ session_loaded = true;
+ }
}
} else {
ret = access(path, F_OK);
}
ret = load_session_from_path(path, session_name,
- &validation_ctx, override);
+ &validation_ctx, overwrite, overrides);
}
end:
fini_session_config_validation_ctx(&validation_ctx);
*/
ret = 0;
}
+
+ if (session_loaded && ret == -LTTNG_ERR_LOAD_SESSION_NOENT) {
+ /* A matching session was found in one of the search paths. */
+ ret = 0;
+ }
return ret;
}
+
+static
+void __attribute__((destructor)) session_config_exit(void)
+{
+ xmlCleanupParser();
+}