+
+LTTNG_HIDDEN
+int mi_lttng_domains_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(writer, config_element_domains);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_domain(struct mi_writer *writer,
+ struct lttng_domain *domain, int is_open)
+{
+ int ret = 0;
+ const char *str_domain;
+ const char *str_buffer;
+
+ assert(domain);
+
+ /* Open domain element */
+ ret = mi_lttng_writer_open_element(writer, config_element_domain);
+ if (ret) {
+ goto end;
+ }
+
+ /* Domain Type */
+ str_domain = mi_lttng_domaintype_string(domain->type);
+ ret = mi_lttng_writer_write_element_string(writer, config_element_type,
+ str_domain);
+ if (ret) {
+ goto end;
+ }
+
+ /* Buffer Type */
+ str_buffer= mi_lttng_buffertype_string(domain->buf_type);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_buffer_type, str_buffer);
+ if (ret) {
+ goto end;
+ }
+
+ /* TODO: union attr
+ * This union is not currently used and was added for
+ * future ust domain support.
+ * Date: 25-06-2014
+ * */
+
+ if (!is_open) {
+ /* Closing domain element */
+ ret = mi_lttng_writer_close_element(writer);
+ }
+
+end:
+ return ret;
+
+}
+
+LTTNG_HIDDEN
+int mi_lttng_channels_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(writer, config_element_channels);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_channel(struct mi_writer *writer,
+ struct lttng_channel *channel, int is_open)
+{
+ int ret = 0;
+
+ assert(channel);
+
+ /* Opening channel element */
+ ret = mi_lttng_writer_open_element(writer, config_element_channel);
+ if (ret) {
+ goto end;
+ }
+
+ /* Name */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ channel->name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Enabled ? */
+ ret = mi_lttng_writer_write_element_bool(writer,
+ config_element_enabled, channel->enabled);
+ if (ret) {
+ goto end;
+ }
+
+ /* Attribute */
+ ret = mi_lttng_channel_attr(writer, &channel->attr);
+ if (ret) {
+ goto end;
+ }
+
+ if (!is_open) {
+ /* Closing channel element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_channel_attr(struct mi_writer *writer,
+ struct lttng_channel_attr *attr)
+{
+ int ret = 0;
+ struct lttng_channel *chan = caa_container_of(attr,
+ struct lttng_channel, attr);
+ uint64_t discarded_events, lost_packets, monitor_timer_interval;
+ int64_t blocking_timeout;
+
+ assert(attr);
+
+ ret = lttng_channel_get_discarded_event_count(chan, &discarded_events);
+ if (ret) {
+ goto end;
+ }
+
+ ret = lttng_channel_get_lost_packet_count(chan, &lost_packets);
+ if (ret) {
+ goto end;
+ }
+
+ ret = lttng_channel_get_monitor_timer_interval(chan,
+ &monitor_timer_interval);
+ if (ret) {
+ goto end;
+ }
+
+ ret = lttng_channel_get_blocking_timeout(chan,
+ &blocking_timeout);
+ if (ret) {
+ goto end;
+ }
+
+ /* Opening Attributes */
+ ret = mi_lttng_writer_open_element(writer, config_element_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ /* Overwrite */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_overwrite_mode,
+ attr->overwrite ? config_overwrite_mode_overwrite :
+ config_overwrite_mode_discard);
+ if (ret) {
+ goto end;
+ }
+
+ /* Sub buffer size in byte */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_subbuf_size, attr->subbuf_size);
+ if (ret) {
+ goto end;
+ }
+
+ /* Number of subbuffer (power of two) */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_num_subbuf,
+ attr->num_subbuf);
+ if (ret) {
+ goto end;
+ }
+
+ /* Switch timer interval in usec */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_switch_timer_interval,
+ attr->switch_timer_interval);
+ if (ret) {
+ goto end;
+ }
+
+ /* Read timer interval in usec */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_read_timer_interval,
+ attr->read_timer_interval);
+ if (ret) {
+ goto end;
+ }
+
+ /* Monitor timer interval in usec */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_monitor_timer_interval,
+ monitor_timer_interval);
+ if (ret) {
+ goto end;
+ }
+
+ /* Retry timeout in usec */
+ ret = mi_lttng_writer_write_element_signed_int(writer,
+ config_element_blocking_timeout,
+ blocking_timeout);
+ if (ret) {
+ goto end;
+ }
+
+ /* Event output */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_output_type,
+ attr->output == LTTNG_EVENT_SPLICE ?
+ config_output_type_splice : config_output_type_mmap);
+ if (ret) {
+ goto end;
+ }
+
+ /* Tracefile size in bytes */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_tracefile_size, attr->tracefile_size);
+ if (ret) {
+ goto end;
+ }
+
+ /* Count of tracefiles */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_tracefile_count,
+ attr->tracefile_count);
+ if (ret) {
+ goto end;
+ }
+
+ /* Live timer interval in usec*/
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_live_timer_interval,
+ attr->live_timer_interval);
+ if (ret) {
+ goto end;
+ }
+
+ /* Discarded events */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_discarded_events,
+ discarded_events);
+ if (ret) {
+ goto end;
+ }
+
+ /* Lost packets */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_lost_packets,
+ lost_packets);
+ if (ret) {
+ goto end;
+ }
+
+ /* Closing attributes */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+end:
+ return ret;
+
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_common_attributes(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ int ret;
+ const char *filter_expression;
+
+ /* Open event element */
+ ret = mi_lttng_writer_open_element(writer, config_element_event);
+ if (ret) {
+ goto end;
+ }
+
+ /* Event name */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_name, event->name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Event type */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_type, mi_lttng_eventtype_string(event->type));
+ if (ret) {
+ goto end;
+ }
+
+ /* Is event enabled */
+ ret = mi_lttng_writer_write_element_bool(writer,
+ config_element_enabled, event->enabled);
+ if (ret) {
+ goto end;
+ }
+
+ /* Event filter expression */
+ ret = lttng_event_get_filter_expression(event, &filter_expression);
+ if (ret) {
+ goto end;
+ }
+
+ if (filter_expression) {
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_filter_expression,
+ filter_expression);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+static int write_event_exclusions(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ int i;
+ int ret;
+ int exclusion_count;
+
+ /* Open event exclusions */
+ ret = mi_lttng_writer_open_element(writer, config_element_exclusions);
+ if (ret) {
+ goto end;
+ }
+
+ exclusion_count = lttng_event_get_exclusion_name_count(event);
+ if (exclusion_count < 0) {
+ ret = exclusion_count;
+ goto end;
+ }
+
+ for (i = 0; i < exclusion_count; i++) {
+ const char *name;
+
+ ret = lttng_event_get_exclusion_name(event, i, &name);
+ if (ret) {
+ /* Close exclusions */
+ mi_lttng_writer_close_element(writer);
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_exclusion, name);
+ if (ret) {
+ /* Close exclusions */
+ mi_lttng_writer_close_element(writer);
+ goto end;
+ }
+ }
+
+ /* Close exclusions */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_tracepoint_loglevel(struct mi_writer *writer,
+ struct lttng_event *event, enum lttng_domain_type domain)
+{
+ int ret;
+
+ /* Event loglevel */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_loglevel,
+ mi_lttng_loglevel_string(event->loglevel, domain));
+ if (ret) {
+ goto end;
+ }
+
+ /* Log level type */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_loglevel_type,
+ mi_lttng_logleveltype_string(event->loglevel_type));
+ if (ret) {
+ goto end;
+ }
+
+ /* Event exclusions */
+ ret = write_event_exclusions(writer, event);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_tracepoint_no_loglevel(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ /* event exclusion filter */
+ return write_event_exclusions(writer, event);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_function_probe(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ int ret;
+
+ ret = mi_lttng_writer_open_element(writer, config_element_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, config_element_probe_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ if (event->attr.probe.addr != 0) {
+ /* event probe address */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_address, event->attr.probe.addr);
+ if (ret) {
+ goto end;
+ }
+ } else {
+ /* event probe offset */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_offset, event->attr.probe.offset);
+ if (ret) {
+ goto end;
+ }
+
+ /* event probe symbol_name */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_symbol_name, event->attr.probe.symbol_name);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close probe_attributes and attributes */
+ ret = mi_lttng_close_multi_element(writer, 2);
+end:
+ return ret;
+}
+
+static
+int mi_lttng_event_userspace_probe(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ int ret;
+ const struct lttng_userspace_probe_location *location;
+ const struct lttng_userspace_probe_location_lookup_method *lookup_method;
+ enum lttng_userspace_probe_location_lookup_method_type lookup_type;
+
+ location = lttng_event_get_userspace_probe_location(event);
+ if (!location) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
+ if (!lookup_method) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
+
+ ret = mi_lttng_writer_open_element(writer, config_element_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ switch (lttng_userspace_probe_location_get_type(location)) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
+ {
+ const char *function_name;
+ const char *binary_path;
+
+ ret = mi_lttng_writer_open_element(writer,
+ config_element_userspace_probe_function_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ switch (lookup_type) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_lookup,
+ config_element_userspace_probe_lookup_function_elf);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_lookup,
+ config_element_userspace_probe_lookup_function_default);
+ if (ret) {
+ goto end;
+ }
+ break;
+ default:
+ goto end;
+ }
+
+ binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_location_binary_path, binary_path);
+ if (ret) {
+ goto end;
+ }
+
+ function_name = lttng_userspace_probe_location_function_get_function_name(location);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_function_location_function_name,
+ function_name);
+ if (ret) {
+ goto end;
+ }
+
+ break;
+ }
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+ {
+ const char *probe_name, *provider_name;
+ const char *binary_path;
+
+ ret = mi_lttng_writer_open_element(writer,
+ config_element_userspace_probe_function_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ switch (lookup_type) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_lookup,
+ config_element_userspace_probe_lookup_tracepoint_sdt);
+ if (ret) {
+ goto end;
+ }
+ break;
+ default:
+ goto end;
+ }
+
+ binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_location_binary_path,
+ binary_path);
+ if (ret) {
+ goto end;
+ }
+
+ provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_tracepoint_location_provider_name,
+ provider_name);
+ if (ret) {
+ goto end;
+ }
+
+ probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_userspace_probe_tracepoint_location_probe_name, probe_name);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ default:
+ ERR("Invalid probe type encountered");
+ }
+ /* Close probe_attributes and attributes */
+ ret = mi_lttng_close_multi_element(writer, 2);
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_function_entry(struct mi_writer *writer,
+ struct lttng_event *event)
+{
+ int ret;
+
+ ret = mi_lttng_writer_open_element(writer, config_element_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, config_element_probe_attributes);
+ if (ret) {
+ goto end;
+ }
+
+ /* event probe symbol_name */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_symbol_name, event->attr.ftrace.symbol_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close function_attributes and attributes */
+ ret = mi_lttng_close_multi_element(writer, 2);
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_events_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(writer, config_element_events);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event(struct mi_writer *writer,
+ struct lttng_event *event, int is_open, enum lttng_domain_type domain)
+{
+ int ret;
+
+ ret = mi_lttng_event_common_attributes(writer, event);
+ if (ret) {
+ goto end;
+ }
+
+ switch (event->type) {
+ case LTTNG_EVENT_TRACEPOINT:
+ {
+ if (event->loglevel != -1) {
+ ret = mi_lttng_event_tracepoint_loglevel(writer, event, domain);
+ } else {
+ ret = mi_lttng_event_tracepoint_no_loglevel(writer, event);
+ }
+ break;
+ }
+ case LTTNG_EVENT_FUNCTION:
+ /* Fallthrough */
+ case LTTNG_EVENT_PROBE:
+ ret = mi_lttng_event_function_probe(writer, event);
+ break;
+ case LTTNG_EVENT_FUNCTION_ENTRY:
+ ret = mi_lttng_event_function_entry(writer, event);
+ break;
+ case LTTNG_EVENT_USERSPACE_PROBE:
+ ret = mi_lttng_event_userspace_probe(writer, event);
+ break;
+ case LTTNG_EVENT_ALL:
+ /* Fallthrough */
+ default:
+ break;
+ }
+
+ if (ret) {
+ goto end;
+ }
+
+ if (!is_open) {
+ ret = mi_lttng_writer_close_element(writer);
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_trackers_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(
+ writer, config_element_process_attr_trackers);
+}
+
+static int get_tracker_elements(enum lttng_process_attr process_attr,
+ const char **element_process_attr_tracker,
+ const char **element_process_attr_value)
+{
+ int ret = 0;
+
+ switch (process_attr) {
+ case LTTNG_PROCESS_ATTR_PROCESS_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_pid;
+ *element_process_attr_value =
+ config_element_process_attr_pid_value;
+ break;
+ case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_vpid;
+ *element_process_attr_value =
+ config_element_process_attr_vpid_value;
+ break;
+ case LTTNG_PROCESS_ATTR_USER_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_uid;
+ *element_process_attr_value =
+ config_element_process_attr_uid_value;
+ break;
+ case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_vuid;
+ *element_process_attr_value =
+ config_element_process_attr_vuid_value;
+ break;
+ case LTTNG_PROCESS_ATTR_GROUP_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_gid;
+ *element_process_attr_value =
+ config_element_process_attr_gid_value;
+ break;
+ case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
+ *element_process_attr_tracker =
+ config_element_process_attr_tracker_vgid;
+ *element_process_attr_value =
+ config_element_process_attr_vgid_value;
+ break;
+ default:
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ }
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_process_attribute_tracker_open(
+ struct mi_writer *writer, enum lttng_process_attr process_attr)
+{
+ int ret;
+ const char *element_tracker, *element_value;
+
+ ret = get_tracker_elements(
+ process_attr, &element_tracker, &element_value);
+ if (ret) {
+ return ret;
+ }
+
+ /* Open process attribute tracker element */
+ ret = mi_lttng_writer_open_element(writer, element_tracker);
+ if (ret) {
+ goto end;
+ }
+
+ /* Open values element */
+ ret = mi_lttng_process_attr_values_open(writer);
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_pids_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(writer, config_element_pids);
+}
+
+/*
+ * TODO: move the listing of pid for user agent to process semantic on
+ * mi api bump. The use of process element break the mi api.
+ */
+LTTNG_HIDDEN
+int mi_lttng_pid(struct mi_writer *writer,
+ pid_t pid,
+ const char *name,
+ int is_open)
+{
+ int ret;
+
+ /* Open pid process */
+ ret = mi_lttng_writer_open_element(writer, config_element_pid);
+ if (ret) {
+ goto end;
+ }
+
+ /* Writing pid number */
+ ret = mi_lttng_writer_write_element_signed_int(writer,
+ mi_lttng_element_pid_id, (int)pid);
+ if (ret) {
+ goto end;
+ }
+
+ /* Writing name of the process */
+ if (name) {
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ name);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ if (!is_open) {
+ /* Closing Pid */
+ ret = mi_lttng_writer_close_element(writer);
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_process_attr_values_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(
+ writer, config_element_process_attr_values);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_all_process_attribute_value(struct mi_writer *writer,
+ enum lttng_process_attr process_attr,
+ bool is_open)
+{
+ int ret;
+ const char *element_id_tracker, *element_target_id;
+
+ ret = get_tracker_elements(
+ process_attr, &element_id_tracker, &element_target_id);
+ if (ret) {
+ return ret;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, element_target_id);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, config_element_type);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_bool(writer, config_element_all, 1);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+
+ if (!is_open) {
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_integral_process_attribute_value(struct mi_writer *writer,
+ enum lttng_process_attr process_attr,
+ int64_t value,
+ bool is_open)
+{
+ int ret;
+ const char *element_id_tracker, *element_target_id;
+
+ ret = get_tracker_elements(
+ process_attr, &element_id_tracker, &element_target_id);
+ if (ret) {
+ return ret;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, element_target_id);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, config_element_type);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_signed_int(
+ writer, config_element_process_attr_id, value);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+
+ if (!is_open) {
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_string_process_attribute_value(struct mi_writer *writer,
+ enum lttng_process_attr process_attr,
+ const char *value,
+ bool is_open)
+
+{
+ int ret;
+ const char *element_id_tracker, *element_target_id;
+
+ ret = get_tracker_elements(
+ process_attr, &element_id_tracker, &element_target_id);
+ if (ret) {
+ return ret;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, element_target_id);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer, config_element_type);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(
+ writer, config_element_name, value);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+
+ if (!is_open) {
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_fields_open(struct mi_writer *writer)
+{
+ return mi_lttng_writer_open_element(writer, mi_lttng_element_event_fields);
+}
+
+LTTNG_HIDDEN
+int mi_lttng_event_field(struct mi_writer *writer,
+ struct lttng_event_field *field)
+{
+ int ret;
+
+ if (!field->field_name[0]) {
+ ret = 0;
+ goto end;
+ }
+
+ /* Open field */
+ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_field);
+ if (ret) {
+ goto end;
+ }
+
+ if (!field->field_name[0]) {
+ goto close;
+ }
+
+ /* Name */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ field->field_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Type */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_type,
+ mi_lttng_eventfieldtype_string(field->type));
+ if (ret) {
+ goto end;
+ }
+
+ /* nowrite */
+ ret = mi_lttng_writer_write_element_signed_int(writer,
+ mi_lttng_element_nowrite, field->nowrite);
+ if (ret) {
+ goto end;
+ }
+
+close:
+ /* Close field element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_perf_counter_context(struct mi_writer *writer,
+ struct lttng_event_perf_counter_ctx *perf_context)
+{
+ int ret;
+
+ /* Open perf_counter_context */
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_perf_counter_context);
+ if (ret) {
+ goto end;
+ }
+
+ /* Type */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_type, perf_context->type);
+ if (ret) {
+ goto end;
+ }
+
+ /* Config */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ config_element_config, perf_context->config);
+ if (ret) {
+ goto end;
+ }
+
+ /* Name of the perf counter */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_name, perf_context->name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close perf_counter_context */
+ ret = mi_lttng_writer_close_element(writer);
+end:
+ return ret;
+}
+
+static
+int mi_lttng_app_context(struct mi_writer *writer,
+ const char *provider_name, const char *ctx_name)
+{
+ int ret;
+
+ /* Open app */
+ ret = mi_lttng_writer_open_element(writer,
+ config_element_context_app);
+ if (ret) {
+ goto end;
+ }
+
+ /* provider_name */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_context_app_provider_name,
+ provider_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* ctx_name */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_context_app_ctx_name, ctx_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close app */
+ ret = mi_lttng_writer_close_element(writer);
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_context(struct mi_writer *writer,
+ struct lttng_event_context *context, int is_open)
+{
+ int ret;
+
+ /* Open context */
+ ret = mi_lttng_writer_open_element(writer , config_element_context);
+ if (ret) {
+ goto end;
+ }
+
+ /* Special case for PERF_*_COUNTER
+ * print the lttng_event_perf_counter_ctx*/
+ switch (context->ctx) {
+ case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+ case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
+ case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+ {
+ struct lttng_event_perf_counter_ctx *perf_context =
+ &context->u.perf_counter;
+ ret = mi_lttng_perf_counter_context(writer, perf_context);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
+ {
+ ret = mi_lttng_app_context(writer,
+ context->u.app_ctx.provider_name,
+ context->u.app_ctx.ctx_name);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ default:
+ {
+ const char *type_string = mi_lttng_event_contexttype_string(
+ context->ctx);
+ if (!type_string) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* Print context type */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_type, type_string);
+ break;
+ }
+ }
+
+ /* Close context */
+ if (!is_open) {
+ ret = mi_lttng_writer_close_element(writer);
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_snapshot_output_session_name(struct mi_writer *writer,
+ const char *session_name)
+{
+ int ret;
+
+ /* Open session element */
+ ret = mi_lttng_writer_open_element(writer, config_element_session);
+ if (ret) {
+ goto end;
+ }
+
+ /* Snapshot output list for current session name */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ session_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Open element snapshots (sequence one snapshot) */
+ ret = mi_lttng_writer_open_element(writer, mi_lttng_element_snapshots);
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_snapshot_list_output(struct mi_writer *writer,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+
+ /* Open element snapshot output */
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_command_snapshot);
+ if (ret) {
+ goto end;
+ }
+
+ /* ID of the snapshot output */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_id, output->id);
+ if (ret) {
+ goto end;
+ }
+
+ /* Name of the output */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ output->name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Destination of the output (ctrl_url)*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_ctrl_url, output->ctrl_url);
+ if (ret) {
+ goto end;
+ }
+
+ /* Destination of the output (data_url) */
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_data_url, output->data_url);
+ if (ret) {
+ goto end;
+ }
+
+ /* total size of all stream combined */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_snapshot_max_size, output->max_size);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close snapshot output element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_snapshot_del_output(struct mi_writer *writer, int id,
+ const char *name, const char *current_session_name)
+{
+ int ret;
+
+ /* Open element del_snapshot */
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_command_snapshot);
+ if (ret) {
+ goto end;
+ }
+
+
+ if (id != UINT32_MAX) {
+ /* "Snapshot output "id" successfully deleted
+ * for "current_session_name"
+ * ID of the snapshot output
+ */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_id, id);
+ if (ret) {
+ goto end;
+ }
+ } else {
+ /* "Snapshot output "name" successfully deleted
+ * for session "current_session_name"
+ * Name of the output
+ */
+ ret = mi_lttng_writer_write_element_string(writer, config_element_name,
+ name);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Snapshot was deleted for session "current_session_name"*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_session_name,
+ current_session_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close snapshot element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_snapshot_add_output(struct mi_writer *writer,
+ const char *current_session_name, const char *n_ptr,
+ struct lttng_snapshot_output *output)
+{
+ int ret;
+
+ /* Open element snapshot */
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_command_snapshot);
+ if (ret) {
+ goto end;
+ }
+
+ /* Snapshot output id */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_id, output->id);
+ if (ret) {
+ goto end;
+ }
+
+ /* Snapshot output names */
+ ret = mi_lttng_writer_write_element_string(writer,
+ config_element_name, n_ptr);
+ if (ret) {
+ goto end;
+ }
+
+ /* Destination of the output (ctrl_url)*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_ctrl_url, output->ctrl_url);
+ if (ret) {
+ goto end;
+ }
+
+ /* Snapshot added for session "current_session_name"*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_session_name, current_session_name);
+ if (ret) {
+ goto end;
+ }
+
+ /* total size of all stream combined */
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_snapshot_max_size, output->max_size);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close snapshot element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_snapshot_record(struct mi_writer *writer,
+ const char *current_session_name, const char *url,
+ const char *cmdline_ctrl_url, const char *cmdline_data_url)
+{
+ int ret;
+
+ /* Open element snapshot */
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_command_snapshot);
+ if (ret) {
+ goto end;
+ }
+
+ /*
+ * If a valid an URL was given, serialize it,
+ * else take the command line data and ctrl urls*/
+ if (url) {
+ /* Destination of the output (ctrl_url)*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_ctrl_url, url);
+ if (ret) {
+ goto end;
+ }
+ } else if (cmdline_ctrl_url) {
+ /* Destination of the output (ctrl_url)*/
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_ctrl_url, cmdline_ctrl_url);
+ if (ret) {
+ goto end;
+ }
+
+ /* Destination of the output (data_url) */
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_snapshot_data_url, cmdline_data_url);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close record_snapshot element */
+ ret = mi_lttng_writer_close_element(writer);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_rotation_schedule(struct mi_writer *writer,
+ const struct lttng_rotation_schedule *schedule)
+{
+ int ret = 0;
+ enum lttng_rotation_status status;
+ uint64_t value;
+ const char *element_name;
+ const char *value_name;
+ bool empty_schedule = false;
+
+ switch (lttng_rotation_schedule_get_type(schedule)) {
+ case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
+ status = lttng_rotation_schedule_periodic_get_period(schedule,
+ &value);
+ element_name = mi_lttng_element_rotation_schedule_periodic;
+ value_name = mi_lttng_element_rotation_schedule_periodic_time_us;
+ break;
+ case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
+ status = lttng_rotation_schedule_size_threshold_get_threshold(
+ schedule, &value);
+ element_name = mi_lttng_element_rotation_schedule_size_threshold;
+ value_name = mi_lttng_element_rotation_schedule_size_threshold_bytes;
+ break;
+ default:
+ ret = -1;
+ goto end;
+ }
+
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ if (status == LTTNG_ROTATION_STATUS_UNAVAILABLE) {
+ empty_schedule = true;
+ } else {
+ ret = -1;
+ goto end;
+ }
+ }
+
+ ret = mi_lttng_writer_open_element(writer, element_name);
+ if (ret) {
+ goto end;
+ }
+
+ if (!empty_schedule) {
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ value_name, value);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ /* Close schedule descriptor element. */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_rotation_schedule_result(struct mi_writer *writer,
+ const struct lttng_rotation_schedule *schedule,
+ bool success)
+{
+ int ret = 0;
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation_schedule_result);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation_schedule);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_rotation_schedule(writer, schedule);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close rotation_schedule element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_bool(writer,
+ mi_lttng_element_command_success, success);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close rotation_schedule_result element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+end:
+ return ret;
+}
+
+static
+int mi_lttng_location(struct mi_writer *writer,
+ const struct lttng_trace_archive_location *location)
+{
+ int ret = 0;
+ enum lttng_trace_archive_location_type location_type;
+ enum lttng_trace_archive_location_status status;
+
+ location_type = lttng_trace_archive_location_get_type(location);
+
+ switch (location_type) {
+ case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
+ {
+ const char *absolute_path;
+
+ status = lttng_trace_archive_location_local_get_absolute_path(
+ location, &absolute_path);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation_location_local);
+ if (ret) {
+ goto end;
+ }
+
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_rotation_location_local_absolute_path,
+ absolute_path);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close local element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
+ {
+ uint16_t control_port, data_port;
+ const char *host, *relative_path;
+ enum lttng_trace_archive_location_relay_protocol_type protocol;
+
+ /* Fetch all relay location parameters. */
+ status = lttng_trace_archive_location_relay_get_protocol_type(
+ location, &protocol);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_trace_archive_location_relay_get_host(
+ location, &host);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_trace_archive_location_relay_get_control_port(
+ location, &control_port);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_trace_archive_location_relay_get_data_port(
+ location, &data_port);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ status = lttng_trace_archive_location_relay_get_relative_path(
+ location, &relative_path);
+ if (status != LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation_location_relay);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_rotation_location_relay_host,
+ host);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_rotation_location_relay_control_port,
+ control_port);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_unsigned_int(writer,
+ mi_lttng_element_rotation_location_relay_data_port,
+ data_port);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_rotation_location_relay_protocol,
+ mi_lttng_trace_archive_location_relay_protocol_type_string(protocol));
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_rotation_location_relay_relative_path,
+ relative_path);
+ if (ret) {
+ goto end;
+ }
+
+ /* Close relay element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+ break;
+ }
+ default:
+ abort();
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int mi_lttng_rotate(struct mi_writer *writer,
+ const char *session_name,
+ enum lttng_rotation_state rotation_state,
+ const struct lttng_trace_archive_location *location)
+{
+ int ret;
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_session_name,
+ session_name);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_writer_write_element_string(writer,
+ mi_lttng_element_rotation_state,
+ mi_lttng_rotation_state_string(rotation_state));
+ if (ret) {
+ goto end;
+ }
+
+ if (!location) {
+ /* Not a serialization error. */
+ goto close_rotation;
+ }
+
+ ret = mi_lttng_writer_open_element(writer,
+ mi_lttng_element_rotation_location);
+ if (ret) {
+ goto end;
+ }
+
+ ret = mi_lttng_location(writer, location);
+ if (ret) {
+ goto close_location;
+ }
+
+close_location:
+ /* Close location element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+
+close_rotation:
+ /* Close rotation element */
+ ret = mi_lttng_writer_close_element(writer);
+ if (ret) {
+ goto end;
+ }
+end:
+ return ret;
+}