* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#define _GNU_SOURCE
+#define _LGPL_SOURCE
#include <assert.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <src/common/sessiond-comm/sessiond-comm.h>
+#include <common/compat/string.h>
/* Mi dependancy */
#include <common/mi-lttng.h>
static char *opt_event_list;
static int opt_event_type;
-static const char *opt_loglevel;
+static char *opt_loglevel;
static int opt_loglevel_type;
static int opt_kernel;
static char *opt_session_name;
-static int opt_userspace;
-static int opt_jul;
-static int opt_log4j;
+static int opt_domain;
static int opt_enable_all;
static char *opt_probe;
static char *opt_function;
-static char *opt_function_entry_symbol;
static char *opt_channel_name;
static char *opt_filter;
static char *opt_exclude;
-#if 0
-/* Not implemented yet */
-static char *opt_cmd_name;
-static pid_t opt_pid;
-#endif
+static char *opt_template_path;
enum {
OPT_HELP = 1,
OPT_TRACEPOINT,
OPT_PROBE,
OPT_FUNCTION,
- OPT_FUNCTION_ENTRY,
OPT_SYSCALL,
- OPT_USERSPACE,
OPT_LOGLEVEL,
OPT_LOGLEVEL_ONLY,
OPT_LIST_OPTIONS,
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
- {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
- {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
{"all", 'a', POPT_ARG_VAL, &opt_enable_all, 1, 0, 0},
{"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
- {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
- {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
- {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
- {"log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0},
+ {"kernel", 'k', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_KERNEL, 0, 0},
+ {"userspace", 'u', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_UST, 0, 0},
+ {"jul", 'j', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_JUL, 0, 0},
+ {"log4j", 'l', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_LOG4J, 0, 0},
+ {"python", 'p', POPT_ARG_VAL, &opt_domain, LTTNG_DOMAIN_PYTHON, 0, 0},
{"tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0},
{"probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0},
{"function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0},
-#if 0
- /*
- * Currently removed from lttng kernel tracer. Removed from
- * lttng UI to discourage its use.
- */
- {"function:entry", 0, POPT_ARG_STRING, &opt_function_entry_symbol, OPT_FUNCTION_ENTRY, 0, 0},
-#endif
{"syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0},
{"loglevel", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL, 0, 0},
{"loglevel-only", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL_ONLY, 0, 0},
- {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
{"filter", 'f', POPT_ARG_STRING, &opt_filter, OPT_FILTER, 0, 0},
{"exclude", 'x', POPT_ARG_STRING, &opt_exclude, OPT_EXCLUDE, 0, 0},
+ /* No op */
+ {"session", 's', POPT_ARG_NONE, 0, 0, 0, 0},
+ {"template-path", 't', POPT_ARG_NONE, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0}
};
-/*
- * usage
- */
-static void usage(FILE *ofp)
-{
- fprintf(ofp, "usage: lttng enable-event NAME[,NAME2,...] [-k|-u] [OPTIONS] \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, " -c, --channel NAME Apply to this channel\n");
- fprintf(ofp, " -a, --all Enable all tracepoints and syscalls\n");
- fprintf(ofp, " -k, --kernel Apply for the kernel tracer\n");
- fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
- fprintf(ofp, " -j, --jul Apply for Java application using JUL\n");
- fprintf(ofp, " -l, --log4j Apply for Java application using LOG4j\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Event options:\n");
- fprintf(ofp, " --tracepoint Tracepoint event (default)\n");
- fprintf(ofp, " - userspace tracer supports wildcards at end of string.\n");
- fprintf(ofp, " Don't forget to quote to deal with bash expansion.\n");
- fprintf(ofp, " e.g.:\n");
- fprintf(ofp, " \"*\"\n");
- fprintf(ofp, " \"app_component:na*\"\n");
- fprintf(ofp, " --probe (addr | symbol | symbol+offset)\n");
- fprintf(ofp, " Dynamic probe.\n");
- fprintf(ofp, " Addr and offset can be octal (0NNN...),\n");
- fprintf(ofp, " decimal (NNN...) or hexadecimal (0xNNN...)\n");
- fprintf(ofp, " --function (addr | symbol | symbol+offset)\n");
- fprintf(ofp, " Dynamic function entry/return probe.\n");
- fprintf(ofp, " Addr and offset can be octal (0NNN...),\n");
- fprintf(ofp, " decimal (NNN...) or hexadecimal (0xNNN...)\n");
-#if 0
- fprintf(ofp, " --function:entry symbol\n");
- fprintf(ofp, " Function tracer event\n");
-#endif
- fprintf(ofp, " --syscall System call event\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " --loglevel name\n");
- fprintf(ofp, " Tracepoint loglevel range from 0 to loglevel.\n");
- fprintf(ofp, " For JUL/LOG4j domain, see the table below for the range values.\n");
- fprintf(ofp, " --loglevel-only name\n");
- fprintf(ofp, " Tracepoint loglevel (only this loglevel)\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " The loglevel or loglevel-only options should be\n");
- fprintf(ofp, " combined with a tracepoint name or tracepoint\n");
- fprintf(ofp, " wildcard.\n");
- fprintf(ofp, " Available loglevels:\n");
- fprintf(ofp, " (higher value is more verbose)\n");
- fprintf(ofp, " TRACE_EMERG = 0\n");
- fprintf(ofp, " TRACE_ALERT = 1\n");
- fprintf(ofp, " TRACE_CRIT = 2\n");
- fprintf(ofp, " TRACE_ERR = 3\n");
- fprintf(ofp, " TRACE_WARNING = 4\n");
- fprintf(ofp, " TRACE_NOTICE = 5\n");
- fprintf(ofp, " TRACE_INFO = 6\n");
- fprintf(ofp, " TRACE_DEBUG_SYSTEM = 7\n");
- fprintf(ofp, " TRACE_DEBUG_PROGRAM = 8\n");
- fprintf(ofp, " TRACE_DEBUG_PROCESS = 9\n");
- fprintf(ofp, " TRACE_DEBUG_MODULE = 10\n");
- fprintf(ofp, " TRACE_DEBUG_UNIT = 11\n");
- fprintf(ofp, " TRACE_DEBUG_FUNCTION = 12\n");
- fprintf(ofp, " TRACE_DEBUG_LINE = 13\n");
- fprintf(ofp, " TRACE_DEBUG = 14\n");
- fprintf(ofp, " (shortcuts such as \"system\" are allowed)\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " Available JUL domain loglevels:\n");
- fprintf(ofp, " JUL_OFF = INT32_MAX\n");
- fprintf(ofp, " JUL_SEVERE = %d\n", LTTNG_LOGLEVEL_JUL_SEVERE);
- fprintf(ofp, " JUL_WARNING = %d\n", LTTNG_LOGLEVEL_JUL_WARNING);
- fprintf(ofp, " JUL_INFO = %d\n", LTTNG_LOGLEVEL_JUL_INFO);
- fprintf(ofp, " JUL_CONFIG = %d\n", LTTNG_LOGLEVEL_JUL_CONFIG);
- fprintf(ofp, " JUL_FINE = %d\n", LTTNG_LOGLEVEL_JUL_FINE);
- fprintf(ofp, " JUL_FINER = %d\n", LTTNG_LOGLEVEL_JUL_FINER);
- fprintf(ofp, " JUL_FINEST = %d\n", LTTNG_LOGLEVEL_JUL_FINEST);
- fprintf(ofp, " JUL_ALL = INT32_MIN\n");
- fprintf(ofp, " (shortcuts such as \"severe\" are allowed)\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " Available LOG4j domain loglevels:\n");
- fprintf(ofp, " LOG4J_OFF = INT32_MAX\n");
- fprintf(ofp, " LOG4J_FATAL = %d\n", LTTNG_LOGLEVEL_LOG4J_FATAL);
- fprintf(ofp, " LOG4J_ERROR = %d\n", LTTNG_LOGLEVEL_LOG4J_ERROR);
- fprintf(ofp, " LOG4J_WARN = %d\n", LTTNG_LOGLEVEL_LOG4J_WARN);
- fprintf(ofp, " LOG4J_INFO = %d\n", LTTNG_LOGLEVEL_LOG4J_INFO);
- fprintf(ofp, " LOG4J_DEBUG = %d\n", LTTNG_LOGLEVEL_LOG4J_DEBUG);
- fprintf(ofp, " LOG4J_TRACE = %d\n", LTTNG_LOGLEVEL_LOG4J_TRACE);
- fprintf(ofp, " LOG4J_ALL = INT32_MIN\n");
- fprintf(ofp, " (shortcuts such as \"severe\" are allowed)\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " -f, --filter \'expression\'\n");
- fprintf(ofp, " Filter expression on event fields and context.\n");
- fprintf(ofp, " Event recording depends on evaluation.\n");
- fprintf(ofp, " Only specify on first activation of\n");
- fprintf(ofp, " a given event within a session.\n");
- fprintf(ofp, " Filter only allowed when enabling\n");
- fprintf(ofp, " events within a session before tracing\n");
- fprintf(ofp, " is started. If the filter fails to link\n");
- fprintf(ofp, " with the event within the traced domain,\n");
- fprintf(ofp, " the event will be discarded. Currently,\n");
- fprintf(ofp, " filter is only implemented for the user-space\n");
- fprintf(ofp, " tracer.\n");
- fprintf(ofp, " Expression examples:.\n");
- fprintf(ofp, " \n");
- fprintf(ofp, " 'intfield > 500 && intfield < 503'\n");
- fprintf(ofp, " '(strfield == \"test\" || intfield != 10) && intfield > 33'\n");
- fprintf(ofp, " 'doublefield > 1.1 && intfield < 5.3'\n");
- fprintf(ofp, " \n");
- fprintf(ofp, " Wildcards are allowed at the end of strings:\n");
- fprintf(ofp, " 'seqfield1 == \"te*\"'\n");
- fprintf(ofp, " In string literals, the escape character is '\\'.\n");
- fprintf(ofp, " Use '\\*' for the '*' character, and '\\\\' for\n");
- fprintf(ofp, " the '\\' character. Wildcard match any sequence of,\n");
- fprintf(ofp, " characters including an empty sub-string (match 0 or\n");
- fprintf(ofp, " more characters).\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " Context information can be used for filtering. The\n");
- fprintf(ofp, " examples below show usage of context filtering on\n");
- fprintf(ofp, " process name (with a wildcard), process ID range, and\n");
- fprintf(ofp, " unique thread ID for filtering. The process and\n");
- fprintf(ofp, " thread ID of running applications can be found under\n");
- fprintf(ofp, " columns \"PID\" and \"LWP\" of the \"ps -eLf\" command.\n");
- fprintf(ofp, "\n");
- fprintf(ofp, " '$ctx.procname == \"demo*\"'\n");
- fprintf(ofp, " '$ctx.vpid >= 4433 && $ctx.vpid < 4455'\n");
- fprintf(ofp, " '$ctx.vtid == 1234'\n");
- fprintf(ofp, " -x, --exclude LIST\n");
- fprintf(ofp, " Add exclusions to UST tracepoints:\n");
- fprintf(ofp, " Events that match any of the items\n");
- fprintf(ofp, " in the comma-separated LIST are not\n");
- fprintf(ofp, " enabled, even if they match a wildcard\n");
- fprintf(ofp, " definition of the event.\n");
- fprintf(ofp, "\n");
-}
-
+static struct poptOption global_long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
+ {"template-path", 't', POPT_ARG_STRING, &opt_template_path, 0, 0, 0},
+ {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
+ {0, 0, 0, 0, 0, 0, 0}
+};
/*
* Parse probe options.
*/
int i = 0;
char str[LTTNG_SYMBOL_NAME_LEN];
+ if (!inputstr || strlen(inputstr) == 0) {
+ return -1;
+ }
+
/*
* Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
* added at the end of the loop so a the upper bound we avoid the overflow.
int i = 0;
char str[LTTNG_SYMBOL_NAME_LEN];
+ if (!inputstr || strlen(inputstr) == 0) {
+ return -1;
+ }
+
/*
* Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
* added at the end of the loop so a the upper bound we avoid the overflow.
}
}
+/*
+ * Maps Python loglevel from string to value
+ */
+static int loglevel_python_str_to_value(const char *inputstr)
+{
+ int i = 0;
+ char str[LTTNG_SYMBOL_NAME_LEN];
+
+ if (!inputstr || strlen(inputstr) == 0) {
+ return -1;
+ }
+
+ /*
+ * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+ * added at the end of the loop so a the upper bound we avoid the overflow.
+ */
+ while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+ str[i] = toupper(inputstr[i]);
+ i++;
+ }
+ str[i] = '\0';
+
+ if (!strcmp(str, "PYTHON_CRITICAL") || !strcmp(str, "CRITICAL")) {
+ return LTTNG_LOGLEVEL_PYTHON_CRITICAL;
+ } else if (!strcmp(str, "PYTHON_ERROR") || !strcmp(str, "ERROR")) {
+ return LTTNG_LOGLEVEL_PYTHON_ERROR;
+ } else if (!strcmp(str, "PYTHON_WARNING") || !strcmp(str, "WARNING")) {
+ return LTTNG_LOGLEVEL_PYTHON_WARNING;
+ } else if (!strcmp(str, "PYTHON_INFO") || !strcmp(str, "INFO")) {
+ return LTTNG_LOGLEVEL_PYTHON_INFO;
+ } else if (!strcmp(str, "PYTNON_DEBUG") || !strcmp(str, "DEBUG")) {
+ return LTTNG_LOGLEVEL_PYTHON_DEBUG;
+ } else if (!strcmp(str, "PYTHON_NOTSET") || !strcmp(str, "NOTSET")) {
+ return LTTNG_LOGLEVEL_PYTHON_NOTSET;
+ } else {
+ return -1;
+ }
+}
+
/*
* Maps loglevel from string to value
*/
static
-int loglevel_str_to_value(const char *inputstr)
+int loglevel_ust_str_to_value(const char *inputstr)
{
int i = 0;
char str[LTTNG_SYMBOL_NAME_LEN];
+ if (!inputstr || strlen(inputstr) == 0) {
+ return -1;
+ }
+
/*
* Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
* added at the end of the loop so a the upper bound we avoid the overflow.
}
}
+/*
+ * Map a userspace agent loglevel to it's value based on the domain type.
+ *
+ * Assert when loglevel is NULL and domain type is LTTNG_DOMAIN_NONE ||
+ * LTTNG_DOMAIN_KERNEL.
+ *
+ * return -1 on invalid loglevel.
+ */
+static int loglevel_str_to_value(const char* loglevel, enum lttng_domain_type type)
+{
+ int ret = -1;
+ switch (type) {
+ case LTTNG_DOMAIN_UST:
+ ret = loglevel_ust_str_to_value(loglevel);
+ break;
+ case LTTNG_DOMAIN_JUL:
+ ret = loglevel_jul_str_to_value(loglevel);
+ break;
+ case LTTNG_DOMAIN_LOG4J:
+ ret = loglevel_log4j_str_to_value(loglevel);
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ ret = loglevel_python_str_to_value(loglevel);
+ break;
+ default:
+ assert(0);
+ }
+
+ return ret;
+}
+
static
const char *print_channel_name(const char *name)
{
/* add length of preamble + one for NUL - one for last (missing) comma */
length += strlen(preamble);
- ret = malloc(length);
+ ret = zmalloc(length);
+ if (!ret) {
+ return NULL;
+ }
strncpy(ret, preamble, length);
for (i = 0; i < count; i++) {
strcat(ret, names[i]);
return ret;
}
+/*
+ * Return an allocated string for pretty printing of exclusion of an event from
+ * a config_element.
+ *
+ * e.g: test,test1,test2
+ */
+static
+char *print_exclusions_config(const struct config_element *event)
+{
+ const char *path = "/event/exclusions/exclusion";
+ struct config_element **element_array = NULL;
+ int element_array_size = 0;
+ char **exclusion_str_array = NULL;
+ char *return_string = NULL;
+ int length = 0;
+
+ config_element_get_element_array(event, path, &element_array, &element_array_size);
+ if (element_array_size == 0) {
+ return_string = strdup("");
+ goto end;
+ }
+
+ exclusion_str_array = calloc(element_array_size, sizeof(char *));
+ if (!exclusion_str_array) {
+ ERR("calloc exclusion string array");
+ return_string = NULL;
+ goto end;
+ }
+
+ /* Fetch data and get full length */
+ for (int i = 0; i < element_array_size; i++) {
+ exclusion_str_array[i] = config_element_get_element_value(element_array[i], "/exclusion");
+ if (!exclusion_str_array[i]) {
+ ERR("Fecthing exlusion %d of event config element", i);
+ continue;
+ }
+ length += strlen(exclusion_str_array[i]) + 1;
+ }
+
+ return_string = zmalloc(length);
+ if (!return_string) {
+ return_string = NULL;
+ goto end;
+ }
+
+ /* Construct string */
+ for (int i = 0; i < element_array_size; i++) {
+ if (!exclusion_str_array[i]) {
+ continue;
+ }
+
+ strcat(return_string, exclusion_str_array[i]);
+ if (i != element_array_size - 1) {
+ strcat(return_string, ",");
+ }
+ }
+
+end:
+ config_element_free_array(element_array, element_array_size);
+ if (exclusion_str_array) {
+ for (int i = 0; i < element_array_size; i++) {
+ free(exclusion_str_array[i]);
+ }
+ }
+ free(exclusion_str_array);
+
+ return return_string;
+}
+
/*
* Compare list of exclusions against an event name.
* Return a list of legal exclusion names.
goto error;
}
if (e == '*') {
+ char *string;
+ char **new_exclusion_list;
+
/* Excluder is a proper subset of event */
+ string = lttng_strndup(next_excluder, excluder_length);
+ if (!string) {
+ PERROR("lttng_strndup error");
+ goto error;
+ }
+ new_exclusion_list = realloc(exclusion_list,
+ sizeof(char *) * (exclusion_count + 1));
+ if (!new_exclusion_list) {
+ PERROR("realloc");
+ free(string);
+ goto error;
+ }
+ exclusion_list = new_exclusion_list;
exclusion_count++;
- exclusion_list = realloc(exclusion_list, sizeof(char **) * exclusion_count);
- exclusion_list[exclusion_count - 1] = strndup(next_excluder, excluder_length);
-
+ exclusion_list[exclusion_count - 1] = string;
break;
}
if (x != e) {
*exclusion_list_ptr = exclusion_list;
return ret;
}
+
+static void warn_on_truncated_exclusion_names(char **exclusion_list,
+ int exclusion_count, int *warn)
+{
+ size_t i = 0;
+
+ for (i = 0; i < exclusion_count; ++i) {
+ const char *name = exclusion_list[i];
+ size_t len = strlen(name);
+
+ if (len >= LTTNG_SYMBOL_NAME_LEN) {
+ WARN("Event exclusion \"%s\" will be truncated",
+ name);
+ *warn = 1;
+ }
+ }
+}
+
+struct domain_configuration {
+ int enable_all;
+ int event_type;
+ char *event_list;
+ char *loglevel;
+ int loglevel_type;
+ enum lttng_domain_type domain_type;
+ char *probe;
+ char *function;
+ char *channel_name;
+ char *filter;
+ char *exclude;
+};
+
/*
* Enabling event using the lttng API.
* Note: in case of error only the last error code will be return.
*/
-static int enable_events(char *session_name)
+static int enable_events(char *session_name, struct domain_configuration *config)
{
int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1;
int exclusion_count = 0;
char **exclusion_list = NULL;
+ int config_enable_all;
+ int config_event_type;
+ char *config_event_list;
+ char *config_loglevel;
+ int config_loglevel_type;
+ enum lttng_domain_type config_domain_type;
+ char *config_probe;
+ char *config_function;
+ char *config_channel_name;
+ char *config_filter;
+ char *config_exclude;
+
+ assert(config);
+
memset(&ev, 0, sizeof(ev));
memset(&dom, 0, sizeof(dom));
- if (opt_kernel) {
- if (opt_filter) {
- ERR("Filter not implement for kernel tracing yet");
- ret = CMD_ERROR;
- goto error;
- }
- if (opt_loglevel) {
- WARN("Kernel loglevels are not supported.");
- }
- }
+ config_enable_all = config->enable_all;
+ config_event_type = config->event_type;
+ config_event_list = config->event_list;
+ config_loglevel = config->loglevel;
+ config_loglevel_type = config->loglevel_type;
+ config_domain_type = config->domain_type;
+ config_probe = config->probe;
+ config_function = config->function;
+ config_channel_name = config->channel_name;
+ config_filter = config->filter;
+ config_exclude = config->exclude;
+
/* Create lttng domain */
- if (opt_kernel) {
- dom.type = LTTNG_DOMAIN_KERNEL;
+ dom.type = config_domain_type;
+ switch (config_domain_type) {
+ case LTTNG_DOMAIN_KERNEL:
dom.buf_type = LTTNG_BUFFER_GLOBAL;
- } else if (opt_userspace) {
- dom.type = LTTNG_DOMAIN_UST;
- /* Default. */
- dom.buf_type = LTTNG_BUFFER_PER_UID;
- } else if (opt_jul) {
- dom.type = LTTNG_DOMAIN_JUL;
- /* Default. */
- dom.buf_type = LTTNG_BUFFER_PER_UID;
- } else if (opt_log4j) {
- dom.type = LTTNG_DOMAIN_LOG4J;
- /* Default. */
+ break;
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
dom.buf_type = LTTNG_BUFFER_PER_UID;
- } else {
- print_missing_domain();
- ret = CMD_ERROR;
- goto error;
+ break;
+ case LTTNG_DOMAIN_NONE:
+ default:
+ assert(0);
}
- if (opt_kernel && opt_exclude) {
- ERR("Event name exclusions are not yet implemented for kernel events");
- ret = CMD_ERROR;
- goto error;
- }
- channel_name = opt_channel_name;
+
+ channel_name = config_channel_name;
handle = lttng_create_handle(session_name, &dom);
if (handle == NULL) {
/* Prepare Mi */
if (lttng_opt_mi) {
+ /* Open a domain element */
+ ret = mi_lttng_writer_open_element(writer, config_element_domain);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+
+ /* Specify the domain type */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_type,
+ mi_lttng_domaintype_string(config_domain_type));
+ if (ret) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+
/* Open a events element */
ret = mi_lttng_writer_open_element(writer, config_element_events);
if (ret) {
}
}
- if (opt_enable_all) {
+ if (config_enable_all) {
/* Default setup for enable all */
- if (opt_kernel) {
- ev.type = opt_event_type;
- ev.name[0] = '\0';
+ if (config_domain_type == LTTNG_DOMAIN_KERNEL) {
+ ev.type = config_event_type;
+ strcpy(ev.name, "*");
/* kernel loglevels not implemented */
ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
} else {
ev.type = LTTNG_EVENT_TRACEPOINT;
strcpy(ev.name, "*");
- ev.loglevel_type = opt_loglevel_type;
- if (opt_loglevel) {
- assert(opt_userspace || opt_jul || opt_log4j);
- if (opt_userspace) {
- ev.loglevel = loglevel_str_to_value(opt_loglevel);
- } else if (opt_jul) {
- ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
- } else if (opt_log4j) {
- ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel);
- }
+ ev.loglevel_type = config_loglevel_type;
+ if (config_loglevel) {
+ ev.loglevel = loglevel_str_to_value(config_loglevel, config_domain_type);
if (ev.loglevel == -1) {
- ERR("Unknown loglevel %s", opt_loglevel);
+ ERR("Unknown loglevel %s", config_loglevel);
ret = -LTTNG_ERR_INVALID;
goto error;
}
} else {
- assert(opt_userspace || opt_jul || opt_log4j);
- if (opt_userspace) {
+ assert(config_domain_type != LTTNG_DOMAIN_NONE || config_domain_type != LTTNG_DOMAIN_KERNEL);
+ switch (config_domain_type) {
+ case LTTNG_DOMAIN_UST:
ev.loglevel = -1;
- } else if (opt_jul || opt_log4j) {
+ break;
+ case LTTNG_DOMAIN_JUL:
ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+ break;
+ case LTTNG_DOMAIN_LOG4J:
+ ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
+ break;
+ default:
+ assert(0);
}
}
}
- if (opt_exclude) {
- ret = check_exclusion_subsets("*", opt_exclude,
+ if (config_exclude) {
+ ret = check_exclusion_subsets("*", config_exclude,
&exclusion_count, &exclusion_list);
if (ret == CMD_ERROR) {
goto error;
}
ev.exclusion = 1;
+
+ warn_on_truncated_exclusion_names(exclusion_list,
+ exclusion_count, &warn);
}
- if (!opt_filter) {
+ if (!config_filter) {
ret = lttng_enable_event_with_exclusions(handle,
&ev, channel_name,
NULL,
print_channel_name(channel_name), session_name);
warn = 1;
break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ {
+ const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
+ ERR("Events: %s (domain %s, channel %s, session %s)",
+ msg,
+ get_domain_str(dom.type),
+ print_channel_name(channel_name),
+ session_name);
+ error = 1;
+ break;
+ }
default:
- ERR("Events: %s (channel %s, session %s)",
+ ERR("Events: %s (domain %s, channel %s, session %s)",
lttng_strerror(ret),
+ get_domain_str(dom.type),
ret == -LTTNG_ERR_NEED_CHANNEL_NAME
? print_raw_channel_name(channel_name)
: print_channel_name(channel_name),
goto end;
}
- switch (opt_event_type) {
+ switch (config_event_type) {
case LTTNG_EVENT_TRACEPOINT:
- if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
+ if (config_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);
+
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
get_domain_str(dom.type),
exclusion_string,
print_channel_name(channel_name),
- opt_loglevel);
+ config_loglevel);
free(exclusion_string);
} else {
char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);
+
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
MSG("All %s tracepoints%s are enabled in channel %s",
get_domain_str(dom.type),
exclusion_string,
break;
case LTTNG_EVENT_SYSCALL:
if (opt_kernel) {
- MSG("All kernel system calls are enabled in channel %s",
+ MSG("All %s system calls are enabled in channel %s",
+ get_domain_str(dom.type),
print_channel_name(channel_name));
}
break;
case LTTNG_EVENT_ALL:
- if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
+ if (config_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);
+
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
MSG("All %s events%s are enabled in channel %s for loglevel %s",
get_domain_str(dom.type),
exclusion_string,
print_channel_name(channel_name),
- opt_loglevel);
+ config_loglevel);
free(exclusion_string);
} else {
char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);
+
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
MSG("All %s events%s are enabled in channel %s",
get_domain_str(dom.type),
exclusion_string,
}
}
- if (opt_filter) {
+ if (config_filter) {
command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
- opt_filter, exclusion_count, exclusion_list);
+ config_filter, exclusion_count, exclusion_list);
if (command_ret < 0) {
switch (-command_ret) {
case LTTNG_ERR_FILTER_EXIST:
WARN("Filter on all events is already enabled"
- " (channel %s, session %s)",
+ " (domain %s, channel %s, session %s)",
+ get_domain_str(dom.type),
print_channel_name(channel_name), session_name);
warn = 1;
break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ {
+ const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
+ ERR("All events: %s (domain %s, channel %s, session %s, filter \'%s\')",
+ msg,
+ get_domain_str(dom.type),
+ print_channel_name(channel_name),
+ session_name, config_filter);
+ error = 1;
+ break;
+ }
default:
- ERR("All events: %s (channel %s, session %s, filter \'%s\')",
+ ERR("All events: %s (domain %s, channel %s, session %s, filter \'%s\')",
lttng_strerror(command_ret),
+ get_domain_str(dom.type),
command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
? print_raw_channel_name(channel_name)
: print_channel_name(channel_name),
- session_name, opt_filter);
+ session_name, config_filter);
error = 1;
break;
}
error_holder = command_ret;
} else {
ev.filter = 1;
- MSG("Filter '%s' successfully set", opt_filter);
+ MSG("Filter '%s' successfully set", config_filter);
}
}
ev.enabled = 0;
success = 0;
}
- ret = mi_lttng_event(writer, &ev, 1);
+ ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
if (ret) {
ret = CMD_ERROR;
goto error;
}
/* Strip event list */
- event_name = strtok(opt_event_list, ",");
+ event_name = strtok(config_event_list, ",");
while (event_name != NULL) {
/* Copy name and type of the event */
strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
- ev.type = opt_event_type;
+ ev.type = config_event_type;
/* Kernel tracer action */
- if (opt_kernel) {
+ switch (config_domain_type) {
+ case LTTNG_DOMAIN_KERNEL:
DBG("Enabling kernel event %s for channel %s",
event_name,
print_channel_name(channel_name));
- switch (opt_event_type) {
- case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */
- ev.type = LTTNG_EVENT_TRACEPOINT;
- /* Fall-through */
+ switch (config_event_type) {
+ case LTTNG_EVENT_ALL: /* Enable tracepoints and syscalls */
+ /* If event name differs from *, select tracepoint. */
+ if (strcmp(ev.name, "*")) {
+ ev.type = LTTNG_EVENT_TRACEPOINT;
+ }
+ break;
case LTTNG_EVENT_TRACEPOINT:
break;
case LTTNG_EVENT_PROBE:
- ret = parse_probe_opts(&ev, opt_probe);
+ ret = parse_probe_opts(&ev, config_probe);
if (ret) {
ERR("Unable to parse probe options");
ret = 0;
}
break;
case LTTNG_EVENT_FUNCTION:
- ret = parse_probe_opts(&ev, opt_function);
+ ret = parse_probe_opts(&ev, config_function);
if (ret) {
ERR("Unable to parse function probe options");
ret = 0;
goto error;
}
break;
- case LTTNG_EVENT_FUNCTION_ENTRY:
- strncpy(ev.attr.ftrace.symbol_name, opt_function_entry_symbol,
- LTTNG_SYMBOL_NAME_LEN);
- ev.attr.ftrace.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
- break;
case LTTNG_EVENT_SYSCALL:
ev.type = LTTNG_EVENT_SYSCALL;
break;
/* kernel loglevels not implemented */
ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
- } else if (opt_userspace) { /* User-space tracer action */
-#if 0
- if (opt_cmd_name != NULL || opt_pid) {
- MSG("Only supporting tracing all UST processes (-u) for now.");
- ret = CMD_UNDEFINED;
- goto error;
- }
-#endif
-
+ break;
+ case LTTNG_DOMAIN_UST:
+ /* User-space tracer action */
DBG("Enabling UST event %s for channel %s, loglevel %s", event_name,
- print_channel_name(channel_name), opt_loglevel ? : "<all>");
+ print_channel_name(channel_name), config_loglevel ? : "<all>");
- switch (opt_event_type) {
+ switch (config_event_type) {
case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */
/* Fall-through */
case LTTNG_EVENT_TRACEPOINT:
break;
case LTTNG_EVENT_PROBE:
case LTTNG_EVENT_FUNCTION:
- case LTTNG_EVENT_FUNCTION_ENTRY:
case LTTNG_EVENT_SYSCALL:
default:
ERR("Event type not available for user-space tracing");
goto error;
}
- if (opt_exclude) {
+ if (config_exclude) {
ev.exclusion = 1;
- if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) {
+ if (config_event_type != LTTNG_EVENT_ALL && config_event_type != LTTNG_EVENT_TRACEPOINT) {
ERR("Exclusion option can only be used with tracepoint events");
ret = CMD_ERROR;
goto error;
exclusion_list = NULL;
}
/* Check for proper subsets */
- ret = check_exclusion_subsets(event_name, opt_exclude,
+ ret = check_exclusion_subsets(event_name, config_exclude,
&exclusion_count, &exclusion_list);
if (ret == CMD_ERROR) {
goto error;
}
+
+ warn_on_truncated_exclusion_names(
+ exclusion_list, exclusion_count, &warn);
}
- ev.loglevel_type = opt_loglevel_type;
- if (opt_loglevel) {
- ev.loglevel = loglevel_str_to_value(opt_loglevel);
+ ev.loglevel_type = config_loglevel_type;
+ if (config_loglevel) {
+ ev.loglevel = loglevel_ust_str_to_value(config_loglevel);
if (ev.loglevel == -1) {
- ERR("Unknown loglevel %s", opt_loglevel);
+ ERR("Unknown loglevel %s", config_loglevel);
ret = -LTTNG_ERR_INVALID;
goto error;
}
} else {
ev.loglevel = -1;
}
- } else if (opt_jul || opt_log4j) {
- if (opt_event_type != LTTNG_EVENT_ALL &&
- opt_event_type != LTTNG_EVENT_TRACEPOINT) {
+ break;
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ if (config_event_type != LTTNG_EVENT_ALL &&
+ config_event_type != LTTNG_EVENT_TRACEPOINT) {
ERR("Event type not supported for domain.");
ret = CMD_UNSUPPORTED;
goto error;
}
- ev.loglevel_type = opt_loglevel_type;
- if (opt_loglevel) {
- if (opt_jul) {
- ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
- } else if (opt_log4j) {
- ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel);
- }
+ ev.loglevel_type = config_loglevel_type;
+ if (config_loglevel) {
+ ev.loglevel = loglevel_str_to_value(config_loglevel, config_domain_type);
if (ev.loglevel == -1) {
- ERR("Unknown loglevel %s", opt_loglevel);
+ ERR("Unknown loglevel %s", config_loglevel);
ret = -LTTNG_ERR_INVALID;
goto error;
}
} else {
- if (opt_jul) {
+ switch (config_domain_type) {
+ case LTTNG_DOMAIN_JUL:
ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
- } else if (opt_log4j) {
+ break;
+ case LTTNG_DOMAIN_LOG4J:
ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
+ break;
+ default:
+ assert(0);
+ break;
}
}
ev.type = LTTNG_EVENT_TRACEPOINT;
strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
- } else {
- print_missing_domain();
- ret = CMD_ERROR;
- goto error;
+ break;
+ default:
+ assert(0);
}
- if (!opt_filter) {
+ if (!config_filter) {
char *exclusion_string;
command_ret = lttng_enable_event_with_exclusions(handle,
&ev, channel_name,
NULL, exclusion_count, exclusion_list);
exclusion_string = print_exclusions(exclusion_count, exclusion_list);
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
if (command_ret < 0) {
/* Turn ret to positive value to handle the positive error code */
switch (-command_ret) {
print_channel_name(channel_name), session_name);
warn = 1;
break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ {
+ const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
+ ERR("Event %s%s: %s (domain %s,channel %s, session %s)", event_name,
+ exclusion_string,
+ msg,
+ get_domain_str(dom.type),
+ print_channel_name(channel_name),
+ session_name);
+ error = 1;
+ break;
+ }
default:
- ERR("Event %s%s: %s (channel %s, session %s)", event_name,
+ ERR("Event %s%s: %s (domain %s, channel %s, session %s)", event_name,
exclusion_string,
lttng_strerror(command_ret),
+ get_domain_str(dom.type),
command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
? print_raw_channel_name(channel_name)
: print_channel_name(channel_name),
}
error_holder = command_ret;
} else {
- /* So we don't print the default channel name for agent domain. */
- if (dom.type == LTTNG_DOMAIN_JUL ||
- dom.type == LTTNG_DOMAIN_LOG4J) {
- MSG("%s event %s%s enabled.",
- get_domain_str(dom.type), event_name,
- exclusion_string);
- } else {
+ switch (dom.type) {
+ case LTTNG_DOMAIN_KERNEL:
+ case LTTNG_DOMAIN_UST:
MSG("%s event %s%s created in channel %s",
- get_domain_str(dom.type), event_name,
- exclusion_string,
- print_channel_name(channel_name));
+ get_domain_str(dom.type),
+ event_name,
+ exclusion_string,
+ print_channel_name(channel_name));
+ break;
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ /*
+ * Don't print the default channel
+ * name for agent domains.
+ */
+ MSG("%s event %s%s enabled",
+ get_domain_str(dom.type),
+ event_name,
+ exclusion_string);
+ break;
+ default:
+ assert(0);
}
}
free(exclusion_string);
}
- if (opt_filter) {
+ if (config_filter) {
char *exclusion_string;
/* Filter present */
ev.filter = 1;
command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
- opt_filter, exclusion_count, exclusion_list);
+ config_filter, exclusion_count, exclusion_list);
exclusion_string = print_exclusions(exclusion_count, exclusion_list);
-
+ if (!exclusion_string) {
+ PERROR("Cannot allocate exclusion_string");
+ error = 1;
+ goto end;
+ }
if (command_ret < 0) {
switch (-command_ret) {
case LTTNG_ERR_FILTER_EXIST:
WARN("Filter on event %s%s is already enabled"
- " (channel %s, session %s)",
+ " (domain %s, channel %s, session %s)",
event_name,
exclusion_string,
+ get_domain_str(dom.type),
print_channel_name(channel_name), session_name);
warn = 1;
break;
+ case LTTNG_ERR_TRACE_ALREADY_STARTED:
+ {
+ const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
+ ERR("Event %s%s: %s (domain %s, channel %s, session %s, filter \'%s\')", ev.name,
+ exclusion_string,
+ msg,
+ get_domain_str(dom.type),
+ print_channel_name(channel_name),
+ session_name, config_filter);
+ error = 1;
+ break;
+ }
default:
- ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name,
+ ERR("Event %s%s: %s (domain %s, channel %s, session %s, filter \'%s\')", ev.name,
exclusion_string,
lttng_strerror(command_ret),
+ get_domain_str(dom.type),
command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
? print_raw_channel_name(channel_name)
: print_channel_name(channel_name),
- session_name, opt_filter);
+ session_name, config_filter);
error = 1;
break;
}
error_holder = command_ret;
} else {
- MSG("Event %s%s: Filter '%s' successfully set",
+ MSG("Event %s%s: Filter '%s' for domain %s successfully set",
event_name, exclusion_string,
- opt_filter);
+ config_filter,
+ get_domain_str(dom.type));
}
free(exclusion_string);
}
ev.enabled = 1;
}
- ret = mi_lttng_event(writer, &ev, 1);
+ ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
if (ret) {
ret = CMD_ERROR;
goto error;
end:
/* Close Mi */
if (lttng_opt_mi) {
- /* Close events element */
- ret = mi_lttng_writer_close_element(writer);
+ /* Close events and domain element */
+ ret = mi_lttng_close_multi_element(writer, 2);
if (ret) {
ret = CMD_ERROR;
goto error;
return ret;
}
-/*
- * Add event to trace session
- */
-int cmd_enable_events(int argc, const char **argv)
+struct exclusions_tuple {
+ char **exclusion_list;
+ int exclusion_count;
+};
+
+static int enable_event_template_per_domain(const struct config_document *document,
+ const char* session_name,
+ const struct domain_configuration *config)
{
- int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
- static poptContext pc;
- char *session_name = NULL;
- int event_type = -1;
+ int ret = 0;
+ int warn = 0;
+ int error = 0;
+ int printed_bytes = 0;
+ char *query = NULL;
+ struct config_element **element_array = NULL;
+ int element_array_size = 0;
+ struct config_element *config_loglevel_type = NULL;
+ struct config_element *config_loglevel = NULL;
+ struct config_element *config_filter = NULL;
+ struct exclusions_tuple *event_exclusion_array = NULL;
+
+ assert(document);
+ assert(config);
+
+
+ /* Fetch contexts element */
+ printed_bytes = asprintf(&query, "//sessions/session/domains/domain[./type = '%s']/channels/channel/contexts", config_get_domain_str(config->domain_type));
+ if (printed_bytes <= 0) {
+ ERR("Asprintf template events query");
+ ret = -1;
+ goto end;
+ }
- pc = poptGetContext(NULL, argc, argv, long_options, 0);
- poptReadDefaultConfig(pc, 0);
+ config_document_get_element_array(document, query, &element_array, &element_array_size);
+ if (element_array) {
+ if (element_array_size != 1) {
+ ERR("Invalid document");
+ goto end;
+ }
+ ret = config_process_contexts_element(element_array[0], session_name, config->domain_type, config->channel_name);
+ if (ret) {
+ ERR("Contexts processing for domain %s channel %s : %s", config_get_domain_str(config->domain_type), config->channel_name, lttng_strerror(ret));
+ goto end;
+ }
+ config_element_free_array(element_array, element_array_size);
+ element_array = NULL;
+ element_array_size = 0;
+ }
- /* Default event type */
- opt_event_type = LTTNG_EVENT_ALL;
- while ((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case OPT_HELP:
- usage(stdout);
- goto end;
- case OPT_TRACEPOINT:
- opt_event_type = LTTNG_EVENT_TRACEPOINT;
- break;
- case OPT_PROBE:
- opt_event_type = LTTNG_EVENT_PROBE;
- break;
- case OPT_FUNCTION:
- opt_event_type = LTTNG_EVENT_FUNCTION;
- break;
- case OPT_FUNCTION_ENTRY:
- opt_event_type = LTTNG_EVENT_FUNCTION_ENTRY;
- break;
- case OPT_SYSCALL:
- opt_event_type = LTTNG_EVENT_SYSCALL;
- break;
- case OPT_USERSPACE:
- opt_userspace = 1;
- break;
- case OPT_LOGLEVEL:
- opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
- opt_loglevel = poptGetOptArg(pc);
- break;
- case OPT_LOGLEVEL_ONLY:
- opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
- opt_loglevel = poptGetOptArg(pc);
- break;
- case OPT_LIST_OPTIONS:
- list_cmd_options(stdout, long_options);
+ /* Fetch event element */
+ printed_bytes = asprintf(&query, "//sessions/session/domains/domain[./type = '%s']/channels/channel/events/event[./enabled = 'true']", config_get_domain_str(config->domain_type));
+ if (printed_bytes <= 0) {
+ ERR("Asprintf template events query");
+ ret = -1;
+ goto end;
+ }
+
+ config_document_get_element_array(document, query, &element_array, &element_array_size);
+ if (!element_array) {
+ /* No event */
+ goto end;
+ }
+
+ /*
+ * Handle log_level
+ * Only userspace domain accept loglevel.
+ *
+ * config-> loglevel is only set when the user pass --logleve/
+ * --loglevel-only on the command line so use it as a way to
+ * know if a loglevel override is necessary
+ */
+ if (config->domain_type != LTTNG_DOMAIN_KERNEL && config->loglevel) {
+ char *loglevel_value_str = NULL;
+ int loglevel_value = -1;
+
+ loglevel_value = loglevel_str_to_value(config->loglevel, config->domain_type);
+ if (loglevel_value == -1) {
+ ERR("Unknown loglevel %s", config->loglevel);
+ ret = 1;
goto end;
- case OPT_FILTER:
- break;
- case OPT_EXCLUDE:
- break;
- default:
- usage(stderr);
- ret = CMD_UNDEFINED;
+ }
+
+ printed_bytes = asprintf(&loglevel_value_str, "%d", loglevel_value);
+ if (printed_bytes <= 0 ) {
+ ERR("Asprintf loglevel");
+ ret = 1;
goto end;
}
- /* Validate event type. Multiple event type are not supported. */
- if (event_type == -1) {
- event_type = opt_event_type;
+ config_loglevel = config_element_create(config_element_loglevel, loglevel_value_str);
+ free(loglevel_value_str);
+ if (!config_loglevel) {
+ ERR("Loglevel config creation failed");
+ ret = 1;
+ goto end;
+ }
+
+ config_loglevel_type = config_element_create(config_element_loglevel_type, config_get_loglevel_type_string(config->loglevel_type));
+ if (!config_loglevel_type) {
+ ERR("Loglevel type config creattion failed");
+ ret = 1;
+ goto end;
+ }
+ }
+
+ /* Handle the filter */
+ if (config->filter) {
+ config_filter = config_element_create(config_element_filter, config->filter);
+ if (!config_filter) {
+ ERR("Filter config creattion failed");
+ ret = 1;
+ goto end;
+ }
+ }
+
+ /*
+ * Handle exclusion on a per event base
+ * For now only userspace domains can have exclusions.
+ */
+ event_exclusion_array = calloc(element_array_size, sizeof(struct exclusions_tuple));
+ if (!event_exclusion_array) {
+ ERR("Calloc exclusion list array");
+ ret = 1;
+ goto end;
+ }
+
+
+ if (config->domain_type != LTTNG_DOMAIN_KERNEL && config->exclude) {
+ for (int i = 0; i < element_array_size; i++) {
+ struct config_element *cur_event = element_array[i];
+ char ***exclusion_list = &(event_exclusion_array[i].exclusion_list);
+ int *exclusion_count = &(event_exclusion_array[i].exclusion_count);
+ char *event_type_str = NULL;
+ int event_type;
+ char *event_name = NULL;
+
+ *exclusion_list = NULL;
+ *exclusion_count = 0;
+
+ /* Get event name */
+ event_name = config_element_get_element_value(cur_event, "/event/name");
+ if (!event_name) {
+ ERR("Reading event name from config element");
+ continue;
+ }
+ event_type_str = config_element_get_element_value(cur_event, "/event/type");
+ if (!event_type_str) {
+ ERR("Reading event type from config element");
+ free(event_name);
+ continue;
+ }
+
+ event_type = config_get_event_type(event_type_str);
+ if (event_type != LTTNG_EVENT_ALL && event_type != LTTNG_EVENT_TRACEPOINT) {
+ const char *msg = "Exclusions do not apply to this event";
+ WARN("Event %s: %s exclusions: %s (domain %s, channel %s, session %s)",
+ event_name, msg, config->exclude,
+ get_domain_str(config->domain_type),
+ print_channel_name(config->channel_name),
+ session_name);
+ free(event_type_str);
+ free(event_name);
+ goto end;
+ }
+
+ /* Check for proper subsets */
+ ret = check_exclusion_subsets(event_name, config->exclude,
+ exclusion_count, exclusion_list);
+
+ warn_on_truncated_exclusion_names(
+ *exclusion_list, *exclusion_count, &warn);
+ free(event_type_str);
+ free(event_name);
+ }
+ }
+
+ /*
+ * Create valid events config_element and try to enable them one by one
+ */
+ for (int i = 0; i < element_array_size; i++) {
+ const char *sub_msg = NULL;
+ bool success = false;
+ bool warn = false;
+
+ struct config_element *cur_event = element_array[i];
+ struct config_element *success_element = NULL;
+ char *msg = NULL;
+ char *exclusions_string = NULL;
+ char *filter_string = NULL;
+ char *event_name = NULL;
+
+ event_name = config_element_get_element_value(cur_event, "/event/name");
+ if (!event_name) {
+ sub_msg = "event name not present abort event creation ";
+ event_name = strdup("<Error fetching event name>");
+ goto enable_event_continue;
+ }
+
+ /* Add the loglevel */
+ if (config_loglevel && config_loglevel_type) {
+ config_element_add_or_replace_child(cur_event, config_loglevel);
+ config_element_add_or_replace_child(cur_event, config_loglevel_type);
+ }
+ if (config_filter) {
+ config_element_add_or_replace_child(cur_event, config_filter);
+ }
+
+ if (event_exclusion_array[i].exclusion_list) {
+ char **exclusion_list = event_exclusion_array[i].exclusion_list;
+ const int exclusion_count = event_exclusion_array[i].exclusion_count;
+ struct config_element *config_exclusions = NULL;
+ struct config_element *exclusion = NULL;
+
+ config_exclusions = config_element_create(config_element_exclusions, NULL);
+ if (!config_exclusions) {
+ sub_msg = "Exclusions config element ration failed abort event creation";
+ goto enable_event_continue;
+ }
+
+ for (int j = 0; j < exclusion_count; j++) {
+ exclusion = config_element_create(config_element_exclusion, exclusion_list[j]);
+ if (!exclusion) {
+ sub_msg = "Exclusion config element creation failed abort event creation";
+ config_element_free(config_exclusions);
+ goto enable_event_continue;
+ }
+ ret = config_element_add_child(config_exclusions, exclusion);
+ if (ret) {
+ sub_msg = "Exclusion config element child addition failed abort event creation";
+ config_element_free(config_exclusions);
+ config_element_free(exclusion);
+ goto enable_event_continue;
+ }
+
+ config_element_free(exclusion);
+ }
+
+ ret = config_element_add_or_replace_child(cur_event, config_exclusions);
+ if (ret) {
+ sub_msg = "Exclusions config element child addition failed abort event creation";
+ config_element_free(config_exclusions);
+ goto enable_event_continue;
+ }
+ config_element_free(config_exclusions);
+ }
+
+
+ ret = config_process_event_element(cur_event, session_name, config->domain_type, config->channel_name);
+ if (!ret) {
+ success = true;
+ sub_msg = "created";
+
+ /* Mi element insertion */
+ success_element = config_element_create(mi_lttng_element_command_success, "true");
+ if (success_element) {
+ ret = config_element_add_or_replace_child(cur_event, success_element);
+ if (ret) {
+ error = 1;
+ }
+ } else {
+ error = 1;
+ }
+
} else {
- if (event_type != opt_event_type) {
- ERR("Multiple event type not supported.");
- ret = CMD_ERROR;
+ success = false;
+ if (ret < 0) {
+ sub_msg = lttng_strerror(ret);
+ if (-ret == LTTNG_ERR_UST_EVENT_ENABLED || -ret == LTTNG_ERR_KERN_EVENT_EXIST) {
+ /*This is not an error */
+ warn = true;
+ }
+ } else {
+ sub_msg = "creation failed";
+ }
+
+ /* Mi related insertion */
+ success_element = config_element_create(mi_lttng_element_command_success, "false");
+ if (success_element) {
+ ret = config_element_add_or_replace_child(cur_event, success_element);
+ if (ret) {
+ error = 1;
+ }
+ } else {
+ error = 1;
+ }
+ }
+
+enable_event_continue:
+
+ /* Get exclusions string for printing */
+ exclusions_string = print_exclusions_config(cur_event);
+ filter_string = config_element_get_element_value(cur_event, "/event/filter");
+
+
+ /* Domain is already present inside the error or msg */
+ printed_bytes = asprintf(&msg,"%s%sEvent %s: %s (exclusions: [%s] filter: [%s] session %s, channel %s)",
+ success ? get_domain_str(config->domain_type): "",
+ success ? " " : "",
+ event_name,
+ sub_msg,
+ /*
+ * TODO: print actual exclusion of loaded event
+ */
+ exclusions_string ? : "",
+ /*
+ * TODO: print actual exclusion of loaded event
+ */
+ filter_string ? : "",
+ session_name,
+ print_channel_name(config->channel_name));
+
+ if (printed_bytes > 0 && success) {
+ MSG("%s", msg);
+ } else if (printed_bytes > 0 && warn) {
+ WARN("%s", msg);
+ /* At least one event failed */
+ error = 1;
+ } else if (printed_bytes > 0) {
+ ERR("%s", msg);
+ } else {
+ ERR("Asprintf enable event message");
+ /* At least one event failed */
+ error = 1;
+ }
+ config_element_free(success_element);
+ free(exclusions_string);
+ free(event_name);
+ free(filter_string);
+ free(msg);
+ continue;
+ }
+
+ /* Prepare Mi */
+ if (lttng_opt_mi) {
+ /* Open a domain element */
+ ret = mi_lttng_writer_open_element(writer, config_element_domain);
+ if (ret) {
+ ret = 1;
+ goto end;
+ }
+
+ /* Specify the domain type */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_type,
+ mi_lttng_domaintype_string(config->domain_type));
+ if (ret) {
+ ret = 1;
+ goto end;
+ }
+
+ /* Open a events element */
+ ret = mi_lttng_writer_open_element(writer, config_element_events);
+ if (ret) {
+ ret = 1;
+ goto end;
+ }
+
+ for (int i = 0; i < element_array_size; i++) {
+ ret = mi_lttng_writer_write_config_element(writer,
+ element_array[i]);
+ if (ret) {
+ ret = 1;
goto end;
}
}
+
+ ret = mi_lttng_close_multi_element(writer, 2);
+ if (ret) {
+ ret = 1;
+ goto end;
+ }
+ }
+
+
+end:
+ /* Free exclusion allocated items */
+ if (event_exclusion_array != NULL) {
+ for (int i = 0; i < element_array_size; i++) {
+ char **exclusion_list = event_exclusion_array[i].exclusion_list;
+ int exclusion_count = event_exclusion_array[i].exclusion_count;
+ if (exclusion_list != NULL) {
+ while (exclusion_count--) {
+ free(exclusion_list[exclusion_count]);
+ }
+ }
+ free(exclusion_list);
+ exclusion_list = NULL;
+ }
+ free(event_exclusion_array);
+ }
+ config_element_free_array(element_array, element_array_size);
+ config_element_free(config_loglevel);
+ config_element_free(config_loglevel_type);
+ config_element_free(config_filter);
+ free(query);
+ if (error) {
+ ret = 1;
+ }
+ return ret;
+}
+
+
+static int enable_event_from_template(const struct config_document *document,
+ const char* session_name,
+ const struct domain_configuration *kernel_config,
+ const struct domain_configuration *ust_config,
+ const struct domain_configuration *jul_config,
+ const struct domain_configuration *log4j_config,
+ const struct domain_configuration *python_config)
+{
+ int ret = 0;
+ int error = 0;
+
+ ret = enable_event_template_per_domain(document, session_name, kernel_config);
+ if (ret) {
+ error = ret;
+ }
+ ret = enable_event_template_per_domain(document, session_name, ust_config);
+ if (ret) {
+ error = ret;
+ }
+ ret = enable_event_template_per_domain(document, session_name, jul_config);
+ if (ret) {
+ error = ret;
+ }
+ ret = enable_event_template_per_domain(document, session_name, log4j_config);
+ if (ret) {
+ error = ret;
+ }
+ ret = enable_event_template_per_domain(document, session_name, python_config);
+ if (ret) {
+ error = ret;
+ }
+
+ return error;
+}
+
+/*
+ * Add event to trace session
+ */
+
+struct args_tuple {
+ int argv_index_start;
+ int argv_index_end;
+};
+
+
+static struct domain_configuration *initialize_domain_configuration(enum lttng_domain_type type)
+{
+
+ struct domain_configuration *config = malloc(sizeof(struct domain_configuration));
+
+ if (!config) {
+ goto end;
}
+ switch(type) {
+ case LTTNG_DOMAIN_KERNEL:
+ config->domain_type = LTTNG_DOMAIN_KERNEL;
+ break;
+ case LTTNG_DOMAIN_UST:
+ config->domain_type = LTTNG_DOMAIN_UST;
+ break;
+ case LTTNG_DOMAIN_JUL:
+ config->domain_type = LTTNG_DOMAIN_JUL;
+ break;
+ case LTTNG_DOMAIN_LOG4J:
+ config->domain_type = LTTNG_DOMAIN_LOG4J;
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ config->domain_type = LTTNG_DOMAIN_PYTHON;
+ break;
+ case LTTNG_DOMAIN_NONE:
+ default:
+ free(config);
+ config=NULL;
+ goto end;
+ };
+
+ config->event_type = LTTNG_EVENT_ALL ;
+ config->enable_all = 0;
+ config->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+ config->loglevel = NULL;
+ config->probe = NULL;
+ config->function = NULL;
+ config->channel_name = NULL;
+ config->filter = NULL;
+ config->exclude = NULL;
+ config->event_list = NULL;
+end:
+ return config;
+}
+
+int cmd_enable_events(int argc, const char **argv)
+{
+ int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
+ static poptContext pc;
+ char *session_name = NULL;
+ int event_type = -1;
+ int i;
+ int args_tuple_count = 0;
+ int arg_state_looking_for_end = 0;
+ struct args_tuple *args_tuple_list = NULL;
+ struct domain_configuration *tmp_config = NULL;
+
+ struct config_document *template = NULL;
+
+ struct domain_configuration *jul_config = NULL;
+ struct domain_configuration *kernel_config = NULL;
+ struct domain_configuration *log4j_config = NULL;
+ struct domain_configuration *python_config = NULL;
+ struct domain_configuration *ust_config = NULL;
+
/* Mi check */
if (lttng_opt_mi) {
writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
ret = CMD_ERROR;
goto end;
}
+
+ /* Open the domains element */
+ ret = mi_lttng_domains_open(writer);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+
}
- opt_event_list = (char*) poptGetArg(pc);
- if (opt_event_list == NULL && opt_enable_all == 0) {
- ERR("Missing event name(s).\n");
- usage(stderr);
- ret = CMD_ERROR;
- goto end;
+ /* Parse global arguments */
+ pc = poptGetContext(NULL, argc, argv, global_long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ SHOW_HELP();
+ goto end;
+ case OPT_LIST_OPTIONS:
+ list_cmd_options(stdout, long_options);
+ goto end;
+ default:
+ break;
+ }
}
+ /* Dispose the global arguments context */
+ poptFreeContext(pc);
+ pc = NULL;
+
if (!opt_session_name) {
session_name = get_session_name();
if (session_name == NULL) {
session_name = opt_session_name;
}
- command_ret = enable_events(session_name);
- if (command_ret) {
- success = 0;
- goto mi_closing;
+ /* Find the number of domain based on the passed arguments */
+ for (i = 1; i < argc ; i++) {
+
+ if (strcmp("-u", argv[i]) && strcmp("--userspace", argv[i]) &&
+ strcmp("-j", argv[i]) && strcmp("--jul", argv[i]) &&
+ strcmp("-l", argv[i]) && strcmp("--log4j", argv[i]) &&
+ strcmp("-p", argv[i]) && strcmp("--python", argv[i]) &&
+ strcmp("-k", argv[i]) && strcmp("--kernel", argv[i])) {
+ continue;
+ }
+
+
+ struct args_tuple *tmp_pointer = NULL;
+ args_tuple_count++;
+ tmp_pointer = realloc(args_tuple_list, sizeof(struct args_tuple) * args_tuple_count);
+ if (!tmp_pointer) {
+ ERR("Realoc of args tuple failed");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ args_tuple_list = tmp_pointer;
+
+ if (!arg_state_looking_for_end) {
+ if (args_tuple_count -1 < 0) {
+ ERR("Args parsing illegal state");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ args_tuple_list[args_tuple_count-1].argv_index_start = i;
+ arg_state_looking_for_end = 1;
+ } else {
+ if (args_tuple_count - 2 < 0 || args_tuple_count -1 < 0) {
+ ERR("Args parsing illegal state");
+ ret = CMD_ERROR;
+ goto end;
+ }
+
+ /* Close the previous tuple */
+ args_tuple_list[args_tuple_count-2].argv_index_end = i - 1;
+
+ /* Start the new tuple */
+ args_tuple_list[args_tuple_count-1].argv_index_start = i;
+ }
+ }
+
+ if (args_tuple_count == 0 && !opt_template_path) {
+ ret = print_missing_or_multiple_domains(0);
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ goto end;
+ } else if (args_tuple_count > 0) {
+ /* Close the last tuple */
+ args_tuple_list[args_tuple_count-1].argv_index_end = i - 1;
+
+ if (args_tuple_count == 1) {
+ /* Preserve the old way with a domain flag that can be anywhere */
+ args_tuple_list[0].argv_index_start = 1;
+ }
+ }
+
+ for (i = 0; i < args_tuple_count; i++) {
+ struct args_tuple *tuple = &args_tuple_list[i];
+ int cur_argc = tuple->argv_index_end - tuple-> argv_index_start + 1;
+ const char **cur_argv = &argv[tuple->argv_index_start];
+
+ /* Default options */
+
+ /* Domain */
+ opt_domain = LTTNG_DOMAIN_NONE;
+
+ /* Event options */
+ opt_enable_all = 0;
+ opt_event_type = LTTNG_EVENT_ALL;
+ opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+ opt_event_list = NULL;
+ opt_loglevel = NULL;
+ opt_probe = NULL;
+ opt_function = NULL;
+ opt_channel_name = NULL;
+ opt_filter = NULL;
+ opt_exclude = NULL;
+
+ pc = poptGetContext(NULL, cur_argc, cur_argv, long_options, POPT_CONTEXT_KEEP_FIRST);
+ poptReadDefaultConfig(pc, 0);
+
+ /* Default event type */
+ opt_event_type = LTTNG_EVENT_ALL;
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ SHOW_HELP();
+ goto end;
+ case OPT_TRACEPOINT:
+ opt_event_type = LTTNG_EVENT_TRACEPOINT;
+ break;
+ case OPT_PROBE:
+ opt_event_type = LTTNG_EVENT_PROBE;
+ break;
+ case OPT_FUNCTION:
+ opt_event_type = LTTNG_EVENT_FUNCTION;
+ break;
+ case OPT_SYSCALL:
+ opt_event_type = LTTNG_EVENT_SYSCALL;
+ break;
+ case OPT_LOGLEVEL:
+ opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+ opt_loglevel = poptGetOptArg(pc);
+ break;
+ case OPT_LOGLEVEL_ONLY:
+ opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
+ opt_loglevel = poptGetOptArg(pc);
+ break;
+ case OPT_LIST_OPTIONS:
+ list_cmd_options(stdout, long_options);
+ goto end;
+ case OPT_FILTER:
+ break;
+ case OPT_EXCLUDE:
+ break;
+ default:
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+
+ /* Validate event type. Multiple event type are not supported. */
+ if (event_type == -1) {
+ event_type = opt_event_type;
+ } else {
+ if (event_type != opt_event_type) {
+ ERR("Multiple event type not supported.");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+ }
+
+ tmp_config = initialize_domain_configuration(opt_domain);
+
+ opt_event_list = (char*) poptGetArg(pc);
+ if (opt_event_list == NULL && opt_enable_all == 0 && !opt_template_path) {
+ ERR("Missing event name(s).\n");
+ ret = CMD_ERROR;
+ goto end;
+ }
+
+ /* Option check */
+ if (opt_domain == LTTNG_DOMAIN_KERNEL) {
+ if (opt_loglevel) {
+ WARN("Kernel loglevels are not supported.");
+ }
+ }
+
+ if (opt_exclude) {
+ switch (opt_domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ ERR("Event name exclusions are not yet implemented for %s events",
+ get_domain_str(opt_domain));
+ ret = CMD_ERROR;
+ goto end;
+ case LTTNG_DOMAIN_UST:
+ /* Exclusions supported */
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ if (opt_template_path) {
+ if (event_type != LTTNG_EVENT_ALL) {
+ WARN("Type options for events while using a template have no effect (--function,--probe,--syscall,--tracepoint).");
+ }
+ if (opt_enable_all) {
+ WARN("The all (-a) shortcut for enabling all events while using a template have no effect.");
+ }
+ }
+
+ tmp_config->event_type = event_type ;
+ tmp_config->enable_all = opt_enable_all;
+ tmp_config->loglevel_type = opt_loglevel_type;
+ tmp_config->loglevel = opt_loglevel;
+ tmp_config->probe = opt_probe;
+ tmp_config->function = opt_function;
+ tmp_config->channel_name = opt_channel_name;
+ tmp_config->filter = opt_filter;
+ tmp_config->exclude = opt_exclude;
+ tmp_config->event_list = opt_event_list;
+
+
+ switch(opt_domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ if (kernel_config) {
+ ERR("Only one -k option is permitted per command");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ kernel_config = tmp_config;
+ break;
+ case LTTNG_DOMAIN_UST:
+ if (ust_config) {
+ ERR("Only one -u option is permitted per command");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ ust_config = tmp_config;
+ break;
+ case LTTNG_DOMAIN_JUL:
+ if (jul_config) {
+ ERR("Only one -j option is permitted per command");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ jul_config = tmp_config;
+ break;
+ case LTTNG_DOMAIN_LOG4J:
+ if (log4j_config) {
+ ERR("Only one -l option is permitted per command");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ log4j_config = tmp_config;
+ break;
+ case LTTNG_DOMAIN_PYTHON:
+ if (python_config) {
+ ERR("Only one -p option is permitted per command");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ python_config = tmp_config;
+ break;
+ case LTTNG_DOMAIN_NONE:
+ default:
+ ret = CMD_ERROR;
+ goto end;
+ }
+
+ tmp_config = NULL;
+
+ poptFreeContext(pc);
+ pc = NULL;
+ }
+
+
+ if (opt_template_path) {
+ /* validate template */
+ template = config_document_get(opt_template_path, 0);
+ if (!template) {
+ ERR("Could not load the template");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ /* TODO: validate the xml */
+ /* Only one session, only one channel per domain */
+ if (!kernel_config) {
+ kernel_config = initialize_domain_configuration(LTTNG_DOMAIN_KERNEL);
+ if (!kernel_config) {
+ ERR("Default initialization for kernel domain configuration");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
+ if (!ust_config) {
+ ust_config = initialize_domain_configuration(LTTNG_DOMAIN_UST);
+ if (!ust_config) {
+ ERR("Default initialization for ust domain configuration");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
+ if (!jul_config) {
+ jul_config = initialize_domain_configuration(LTTNG_DOMAIN_JUL);
+ if (!jul_config) {
+ ERR("Default initialization for jul domain configuration");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
+ if (!log4j_config) {
+ log4j_config = initialize_domain_configuration(LTTNG_DOMAIN_LOG4J);
+ if (!log4j_config) {
+ ERR("Default initialization for log4j domain configuration");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
+ if (!python_config) {
+ python_config = initialize_domain_configuration(LTTNG_DOMAIN_PYTHON);
+ if (!python_config) {
+ ERR("Default initialization for python domain configuration");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
+ command_ret = enable_event_from_template(template, session_name, kernel_config, ust_config,
+ jul_config, log4j_config, python_config);
+
+ goto end;
+ }
+
+ if (kernel_config) {
+ command_ret = enable_events(session_name, kernel_config);
+ if (command_ret) {
+ success = 0;
+ }
+ }
+
+ if (ust_config) {
+ command_ret = enable_events(session_name, ust_config);
+ if (command_ret) {
+ success = 0;
+ }
+ }
+
+ if (jul_config) {
+ command_ret = enable_events(session_name, jul_config);
+ if (command_ret) {
+ success = 0;
+ }
+ }
+
+ if (log4j_config) {
+ command_ret = enable_events(session_name, log4j_config);
+ if (command_ret) {
+ success = 0;
+ }
+ }
+
+ if (python_config) {
+ command_ret = enable_events(session_name, python_config);
+ if (command_ret) {
+ success = 0;
+ }
}
mi_closing:
/* Mi closing */
if (lttng_opt_mi) {
- /* Close output element */
- ret = mi_lttng_writer_close_element(writer);
+ /* Close domains and output element */
+ ret = mi_lttng_close_multi_element(writer, 2);
if (ret) {
ret = CMD_ERROR;
goto end;
/* Overwrite ret if an error occurred in enable_events */
ret = command_ret ? command_ret : ret;
+ config_document_free(template);
+ free(args_tuple_list);
+ free(tmp_config);
+ free(jul_config);
+ free(kernel_config);
+ free(log4j_config);
+ free(python_config);
+ free(ust_config);
poptFreeContext(pc);
return ret;
}