+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 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);
+
+
+ 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;
+ }
+
+ printed_bytes = asprintf(&loglevel_value_str, "%d", loglevel_value);
+ if (printed_bytes <= 0 ) {
+ ERR("Asprintf loglevel");
+ ret = 1;
+ goto end;
+ }
+
+ 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 {
+ 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;
+}
+