X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fmi-lttng.c;h=69b3cc041de0d42c44333d7ab8c84d5ff7e52473;hp=052b5425e752aaf9bf5ff8a04b8919b7f40f12be;hb=87597c2c3bbaa1502ad2025cbf16704829f3b464;hpb=c7e35b037773dbbfe10178c946ba44feefb226e1 diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index 052b5425e..69b3cc041 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 - Jonathan Rajotte * - Olivier Cotte + * Copyright (C) 2016 - Jérémie Galarneau * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License, version 2 only, as @@ -16,27 +17,510 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include - +#define _LGPL_SOURCE +#include +#include +#include +#include #include "mi-lttng.h" +#include + +#define MI_SCHEMA_MAJOR_VERSION 3 +#define MI_SCHEMA_MINOR_VERSION 0 + +/* Machine interface namespace URI */ +LTTNG_HIDDEN const char * const mi_lttng_xmlns = "xmlns"; +LTTNG_HIDDEN const char * const mi_lttng_xmlns_xsi = "xmlns:xsi"; +LTTNG_HIDDEN const char * const mi_lttng_w3_schema_uri = "http://www.w3.org/2001/XMLSchema-instance"; +LTTNG_HIDDEN const char * const mi_lttng_schema_location = "xsi:schemaLocation"; +LTTNG_HIDDEN const char * const mi_lttng_schema_location_uri = + DEFAULT_LTTNG_MI_NAMESPACE " " + "https://lttng.org/xml/schemas/lttng-mi/" XSTR(MI_SCHEMA_MAJOR_VERSION) + "/lttng-mi-" XSTR(MI_SCHEMA_MAJOR_VERSION) "." + XSTR(MI_SCHEMA_MINOR_VERSION) ".xsd"; +LTTNG_HIDDEN const char * const mi_lttng_schema_version = "schemaVersion"; +LTTNG_HIDDEN const char * const mi_lttng_schema_version_value = XSTR(MI_SCHEMA_MAJOR_VERSION) + "." XSTR(MI_SCHEMA_MINOR_VERSION); + /* Strings related to command */ const char * const mi_lttng_element_command = "command"; -const char * const mi_lttng_element_command_version = "version"; +const char * const mi_lttng_element_command_action = "snapshot_action"; +const char * const mi_lttng_element_command_add_context = "add-context"; +const char * const mi_lttng_element_command_create = "create"; +const char * const mi_lttng_element_command_destroy = "destroy"; +const char * const mi_lttng_element_command_disable_channel = "disable-channel"; +const char * const mi_lttng_element_command_disable_event = "disable-event"; +const char * const mi_lttng_element_command_enable_channels = "enable-channel"; +const char * const mi_lttng_element_command_enable_event = "enable-event"; const char * const mi_lttng_element_command_list = "list"; +const char * const mi_lttng_element_command_load = "load"; +LTTNG_HIDDEN const char * const mi_lttng_element_command_metadata = "metadata"; +LTTNG_HIDDEN const char * const mi_lttng_element_command_metadata_action = "metadata_action"; +LTTNG_HIDDEN const char * const mi_lttng_element_command_regenerate = "regenerate"; +LTTNG_HIDDEN const char * const mi_lttng_element_command_regenerate_action = "regenerate_action"; const char * const mi_lttng_element_command_name = "name"; const char * const mi_lttng_element_command_output = "output"; +const char * const mi_lttng_element_command_save = "save"; +const char * const mi_lttng_element_command_set_session = "set-session"; +const char * const mi_lttng_element_command_snapshot = "snapshot"; +const char * const mi_lttng_element_command_snapshot_add = "add_snapshot"; +const char * const mi_lttng_element_command_snapshot_del = "del_snapshot"; +const char * const mi_lttng_element_command_snapshot_list = "list_snapshot"; +const char * const mi_lttng_element_command_snapshot_record = "record_snapshot"; +const char * const mi_lttng_element_command_start = "start"; +const char * const mi_lttng_element_command_stop = "stop"; +const char * const mi_lttng_element_command_success = "success"; +const char * const mi_lttng_element_command_track = "track"; +const char * const mi_lttng_element_command_untrack = "untrack"; +const char * const mi_lttng_element_command_version = "version"; +const char * const mi_lttng_element_command_rotate = "rotate"; +const char * const mi_lttng_element_command_enable_rotation = "enable-rotation"; +const char * const mi_lttng_element_command_disable_rotation = "disable-rotation"; -/* Strings related to command: version */ +/* Strings related to version command */ const char * const mi_lttng_element_version = "version"; -const char * const mi_lttng_element_version_str = "string"; -const char * const mi_lttng_element_version_web = "url"; +const char * const mi_lttng_element_version_commit = "commit"; +const char * const mi_lttng_element_version_description = "description"; +const char * const mi_lttng_element_version_license = "license"; const char * const mi_lttng_element_version_major = "major"; const char * const mi_lttng_element_version_minor = "minor"; -const char * const mi_lttng_element_version_license = "license"; const char * const mi_lttng_element_version_patch_level = "patchLevel"; -const char * const mi_lttng_element_version_description = "description"; +const char * const mi_lttng_element_version_str = "string"; +const char * const mi_lttng_element_version_web = "url"; + +/* String related to a lttng_event_field */ +const char * const mi_lttng_element_event_field = "event_field"; +const char * const mi_lttng_element_event_fields = "event_fields"; + +/* String related to lttng_event_perf_counter_ctx */ +const char * const mi_lttng_element_perf_counter_context = "perf"; + +/* Strings related to pid */ +const char * const mi_lttng_element_pid_id = "id"; + +/* Strings related to save command */ +const char * const mi_lttng_element_save = "save"; + +/* Strings related to load command */ +const char * const mi_lttng_element_load = "load"; +LTTNG_HIDDEN const char * const mi_lttng_element_load_overrides = "overrides"; +LTTNG_HIDDEN const char * const mi_lttng_element_load_override_url = "url"; + +/* General elements of mi_lttng */ +const char * const mi_lttng_element_empty = ""; +const char * const mi_lttng_element_id = "id"; +const char * const mi_lttng_element_nowrite = "nowrite"; +const char * const mi_lttng_element_success = "success"; +const char * const mi_lttng_element_type_enum = "ENUM"; +const char * const mi_lttng_element_type_float = "FLOAT"; +const char * const mi_lttng_element_type_integer = "INTEGER"; +const char * const mi_lttng_element_type_other = "OTHER"; +const char * const mi_lttng_element_type_string = "STRING"; + +/* String related to loglevel */ +const char * const mi_lttng_loglevel_str_alert = "TRACE_ALERT"; +const char * const mi_lttng_loglevel_str_crit = "TRACE_CRIT"; +const char * const mi_lttng_loglevel_str_debug = "TRACE_DEBUG"; +const char * const mi_lttng_loglevel_str_debug_function = "TRACE_DEBUG_FUNCTION"; +const char * const mi_lttng_loglevel_str_debug_line = "TRACE_DEBUG_LINE"; +const char * const mi_lttng_loglevel_str_debug_module = "TRACE_DEBUG_MODULE"; +const char * const mi_lttng_loglevel_str_debug_process = "TRACE_DEBUG_PROCESS"; +const char * const mi_lttng_loglevel_str_debug_program = "TRACE_DEBUG_PROGRAM"; +const char * const mi_lttng_loglevel_str_debug_system = "TRACE_DEBUG_SYSTEM"; +const char * const mi_lttng_loglevel_str_debug_unit = "TRACE_DEBUG_UNIT"; +const char * const mi_lttng_loglevel_str_emerg = "TRACE_EMERG"; +const char * const mi_lttng_loglevel_str_err = "TRACE_ERR"; +const char * const mi_lttng_loglevel_str_info = "TRACE_INFO"; +const char * const mi_lttng_loglevel_str_notice = "TRACE_NOTICE"; +const char * const mi_lttng_loglevel_str_unknown = "UNKNOWN"; +const char * const mi_lttng_loglevel_str_warning = "TRACE_WARNING"; + +/* String related to loglevel JUL */ +const char * const mi_lttng_loglevel_str_jul_all = "JUL_ALL"; +const char * const mi_lttng_loglevel_str_jul_config = "JUL_CONFIG"; +const char * const mi_lttng_loglevel_str_jul_fine = "JUL_FINE"; +const char * const mi_lttng_loglevel_str_jul_finer = "JUL_FINER"; +const char * const mi_lttng_loglevel_str_jul_finest = "JUL_FINEST"; +const char * const mi_lttng_loglevel_str_jul_info = "JUL_INFO"; +const char * const mi_lttng_loglevel_str_jul_off = "JUL_OFF"; +const char * const mi_lttng_loglevel_str_jul_severe = "JUL_SEVERE"; +const char * const mi_lttng_loglevel_str_jul_warning = "JUL_WARNING"; + +/* String related to loglevel LOG4J */ +const char * const mi_lttng_loglevel_str_log4j_off = "LOG4J_OFF"; +const char * const mi_lttng_loglevel_str_log4j_fatal = "LOG4J_FATAL"; +const char * const mi_lttng_loglevel_str_log4j_error = "LOG4J_ERROR"; +const char * const mi_lttng_loglevel_str_log4j_warn = "LOG4J_WARN"; +const char * const mi_lttng_loglevel_str_log4j_info = "LOG4J_INFO"; +const char * const mi_lttng_loglevel_str_log4j_debug = "LOG4J_DEBUG"; +const char * const mi_lttng_loglevel_str_log4j_trace = "LOG4J_TRACE"; +const char * const mi_lttng_loglevel_str_log4j_all = "LOG4J_ALL"; + +/* String related to loglevel Python */ +const char * const mi_lttng_loglevel_str_python_critical = "PYTHON_CRITICAL"; +const char * const mi_lttng_loglevel_str_python_error = "PYTHON_ERROR"; +const char * const mi_lttng_loglevel_str_python_warning = "PYTHON_WARNING"; +const char * const mi_lttng_loglevel_str_python_info = "PYTHON_INFO"; +const char * const mi_lttng_loglevel_str_python_debug = "PYTHON_DEBUG"; +const char * const mi_lttng_loglevel_str_python_notset = "PYTHON_NOTSET"; + +/* String related to loglevel type */ +const char * const mi_lttng_loglevel_type_all = "ALL"; +const char * const mi_lttng_loglevel_type_range = "RANGE"; +const char * const mi_lttng_loglevel_type_single = "SINGLE"; +const char * const mi_lttng_loglevel_type_unknown = "UNKNOWN"; + +/* String related to a lttng_snapshot_output */ +const char * const mi_lttng_element_snapshot_ctrl_url = "ctrl_url"; +const char * const mi_lttng_element_snapshot_data_url = "data_url"; +const char * const mi_lttng_element_snapshot_max_size = "max_size"; +const char * const mi_lttng_element_snapshot_n_ptr = "n_ptr"; +const char * const mi_lttng_element_snapshot_session_name = "session_name"; +const char * const mi_lttng_element_snapshots = "snapshots"; + +/* String related to track/untrack command */ +const char * const mi_lttng_element_track_untrack_all_wildcard = "*"; + +LTTNG_HIDDEN const char * const mi_lttng_element_session_name = "session_name"; + +/* String related to rotate command */ +LTTNG_HIDDEN const char * const mi_lttng_element_rotation = "rotation"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotate_status = "status"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule = "rotation_schedule"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedules = "rotation_schedules"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_result = "rotation_schedule_result"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_results = "rotation_schedule_results"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_periodic = "periodic"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_periodic_time_us = "time_us"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_size_threshold = "size_threshold"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_schedule_size_threshold_bytes = "bytes"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_state = "state"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location = "location"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_local = "local"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_local_absolute_path = "absolute_path"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay = "relay"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay_host = "host"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay_control_port = "control_port"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay_data_port = "data_port"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay_protocol = "protocol"; +LTTNG_HIDDEN const char * const mi_lttng_element_rotation_location_relay_relative_path = "relative_path"; + +/* String related to enum lttng_rotation_state */ +LTTNG_HIDDEN const char * const mi_lttng_rotation_state_str_ongoing = "ONGOING"; +LTTNG_HIDDEN const char * const mi_lttng_rotation_state_str_completed = "COMPLETED"; +LTTNG_HIDDEN const char * const mi_lttng_rotation_state_str_expired = "EXPIRED"; +LTTNG_HIDDEN const char * const mi_lttng_rotation_state_str_error = "ERROR"; + +/* String related to enum lttng_trace_archive_location_relay_protocol_type */ +LTTNG_HIDDEN const char * const mi_lttng_rotation_location_relay_protocol_str_tcp = "TCP"; + +/* String related to add-context command */ +LTTNG_HIDDEN const char * const mi_lttng_element_context_symbol = "symbol"; + +/* Deprecated symbols preserved for ABI compatibility. */ +const char * const mi_lttng_context_type_perf_counter; +const char * const mi_lttng_context_type_perf_cpu_counter; +const char * const mi_lttng_context_type_perf_thread_counter; +const char * const mi_lttng_element_track_untrack_pid_target; +const char * const mi_lttng_element_track_untrack_targets; +const char * const mi_lttng_element_calibrate; +const char * const mi_lttng_element_calibrate_function; +const char * const mi_lttng_element_command_calibrate; + +/* This is a merge of jul loglevel and regular loglevel + * Those should never overlap by definition + * (see struct lttng_event loglevel) + */ +LTTNG_HIDDEN +const char *mi_lttng_loglevel_string(int value, enum lttng_domain_type domain) +{ + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + case LTTNG_DOMAIN_UST: + switch (value) { + case -1: + return mi_lttng_element_empty; + case LTTNG_LOGLEVEL_EMERG: + return mi_lttng_loglevel_str_emerg; + case LTTNG_LOGLEVEL_ALERT: + return mi_lttng_loglevel_str_alert; + case LTTNG_LOGLEVEL_CRIT: + return mi_lttng_loglevel_str_crit; + case LTTNG_LOGLEVEL_ERR: + return mi_lttng_loglevel_str_err; + case LTTNG_LOGLEVEL_WARNING: + return mi_lttng_loglevel_str_warning; + case LTTNG_LOGLEVEL_NOTICE: + return mi_lttng_loglevel_str_notice; + case LTTNG_LOGLEVEL_INFO: + return mi_lttng_loglevel_str_info; + case LTTNG_LOGLEVEL_DEBUG_SYSTEM: + return mi_lttng_loglevel_str_debug_system; + case LTTNG_LOGLEVEL_DEBUG_PROGRAM: + return mi_lttng_loglevel_str_debug_program; + case LTTNG_LOGLEVEL_DEBUG_PROCESS: + return mi_lttng_loglevel_str_debug_process; + case LTTNG_LOGLEVEL_DEBUG_MODULE: + return mi_lttng_loglevel_str_debug_module; + case LTTNG_LOGLEVEL_DEBUG_UNIT: + return mi_lttng_loglevel_str_debug_unit; + case LTTNG_LOGLEVEL_DEBUG_FUNCTION: + return mi_lttng_loglevel_str_debug_function; + case LTTNG_LOGLEVEL_DEBUG_LINE: + return mi_lttng_loglevel_str_debug_line; + case LTTNG_LOGLEVEL_DEBUG: + return mi_lttng_loglevel_str_debug; + default: + return mi_lttng_loglevel_str_unknown; + } + break; + case LTTNG_DOMAIN_LOG4J: + switch (value) { + case -1: + return mi_lttng_element_empty; + case LTTNG_LOGLEVEL_LOG4J_OFF: + return mi_lttng_loglevel_str_log4j_off; + case LTTNG_LOGLEVEL_LOG4J_FATAL: + return mi_lttng_loglevel_str_log4j_fatal; + case LTTNG_LOGLEVEL_LOG4J_ERROR: + return mi_lttng_loglevel_str_log4j_error; + case LTTNG_LOGLEVEL_LOG4J_WARN: + return mi_lttng_loglevel_str_log4j_warn; + case LTTNG_LOGLEVEL_LOG4J_INFO: + return mi_lttng_loglevel_str_log4j_info; + case LTTNG_LOGLEVEL_LOG4J_DEBUG: + return mi_lttng_loglevel_str_log4j_debug; + case LTTNG_LOGLEVEL_LOG4J_TRACE: + return mi_lttng_loglevel_str_log4j_trace; + case LTTNG_LOGLEVEL_LOG4J_ALL: + return mi_lttng_loglevel_str_log4j_all; + default: + return mi_lttng_loglevel_str_unknown; + } + break; + case LTTNG_DOMAIN_JUL: + switch (value) { + case -1: + return mi_lttng_element_empty; + case LTTNG_LOGLEVEL_JUL_OFF: + return mi_lttng_loglevel_str_jul_off; + case LTTNG_LOGLEVEL_JUL_SEVERE: + return mi_lttng_loglevel_str_jul_severe; + case LTTNG_LOGLEVEL_JUL_WARNING: + return mi_lttng_loglevel_str_jul_warning; + case LTTNG_LOGLEVEL_JUL_INFO: + return mi_lttng_loglevel_str_jul_info; + case LTTNG_LOGLEVEL_JUL_CONFIG: + return mi_lttng_loglevel_str_jul_config; + case LTTNG_LOGLEVEL_JUL_FINE: + return mi_lttng_loglevel_str_jul_fine; + case LTTNG_LOGLEVEL_JUL_FINER: + return mi_lttng_loglevel_str_jul_finer; + case LTTNG_LOGLEVEL_JUL_FINEST: + return mi_lttng_loglevel_str_jul_finest; + case LTTNG_LOGLEVEL_JUL_ALL: + return mi_lttng_loglevel_str_jul_all; + default: + return mi_lttng_loglevel_str_unknown; + } + break; + case LTTNG_DOMAIN_PYTHON: + switch (value) { + case LTTNG_LOGLEVEL_PYTHON_CRITICAL: + return mi_lttng_loglevel_str_python_critical; + case LTTNG_LOGLEVEL_PYTHON_ERROR: + return mi_lttng_loglevel_str_python_error; + case LTTNG_LOGLEVEL_PYTHON_WARNING: + return mi_lttng_loglevel_str_python_warning; + case LTTNG_LOGLEVEL_PYTHON_INFO: + return mi_lttng_loglevel_str_python_info; + case LTTNG_LOGLEVEL_PYTHON_DEBUG: + return mi_lttng_loglevel_str_python_debug; + case LTTNG_LOGLEVEL_PYTHON_NOTSET: + return mi_lttng_loglevel_str_python_notset; + default: + return mi_lttng_loglevel_str_unknown; + } + break; + default: + return mi_lttng_loglevel_str_unknown; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_logleveltype_string(enum lttng_loglevel_type value) +{ + switch (value) { + case LTTNG_EVENT_LOGLEVEL_ALL: + return mi_lttng_loglevel_type_all; + case LTTNG_EVENT_LOGLEVEL_RANGE: + return mi_lttng_loglevel_type_range; + case LTTNG_EVENT_LOGLEVEL_SINGLE: + return mi_lttng_loglevel_type_single; + default: + return mi_lttng_loglevel_type_unknown; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_eventtype_string(enum lttng_event_type value) +{ + switch (value) { + case LTTNG_EVENT_ALL: + return config_event_type_all; + case LTTNG_EVENT_TRACEPOINT: + return config_event_type_tracepoint; + case LTTNG_EVENT_PROBE: + return config_event_type_probe; + case LTTNG_EVENT_USERSPACE_PROBE: + return config_event_type_userspace_probe; + case LTTNG_EVENT_FUNCTION: + return config_event_type_function; + case LTTNG_EVENT_FUNCTION_ENTRY: + return config_event_type_function_entry; + case LTTNG_EVENT_SYSCALL: + return config_event_type_syscall; + case LTTNG_EVENT_NOOP: + return config_event_type_noop; + default: + return mi_lttng_element_empty; + } +} + +static +const char *mi_lttng_event_contexttype_string(enum lttng_event_context_type val) +{ + switch (val) { + case LTTNG_EVENT_CONTEXT_PID: + return config_event_context_pid; + case LTTNG_EVENT_CONTEXT_PROCNAME: + return config_event_context_procname; + case LTTNG_EVENT_CONTEXT_PRIO: + return config_event_context_prio; + case LTTNG_EVENT_CONTEXT_NICE: + return config_event_context_nice; + case LTTNG_EVENT_CONTEXT_VPID: + return config_event_context_vpid; + case LTTNG_EVENT_CONTEXT_TID: + return config_event_context_tid; + case LTTNG_EVENT_CONTEXT_VTID: + return config_event_context_vtid; + case LTTNG_EVENT_CONTEXT_PPID: + return config_event_context_ppid; + case LTTNG_EVENT_CONTEXT_VPPID: + return config_event_context_vppid; + case LTTNG_EVENT_CONTEXT_PTHREAD_ID: + return config_event_context_pthread_id; + case LTTNG_EVENT_CONTEXT_HOSTNAME: + return config_event_context_hostname; + case LTTNG_EVENT_CONTEXT_IP: + return config_event_context_ip; + case LTTNG_EVENT_CONTEXT_INTERRUPTIBLE: + return config_event_context_interruptible; + case LTTNG_EVENT_CONTEXT_PREEMPTIBLE: + return config_event_context_preemptible; + case LTTNG_EVENT_CONTEXT_NEED_RESCHEDULE: + return config_event_context_need_reschedule; + case LTTNG_EVENT_CONTEXT_MIGRATABLE: + return config_event_context_migratable; + case LTTNG_EVENT_CONTEXT_CALLSTACK_USER: + return config_event_context_callstack_user; + case LTTNG_EVENT_CONTEXT_CALLSTACK_KERNEL: + return config_event_context_callstack_kernel; + default: + return NULL; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_eventfieldtype_string(enum lttng_event_field_type val) +{ + switch (val) { + case(LTTNG_EVENT_FIELD_INTEGER): + return mi_lttng_element_type_integer; + case(LTTNG_EVENT_FIELD_ENUM): + return mi_lttng_element_type_enum; + case(LTTNG_EVENT_FIELD_FLOAT): + return mi_lttng_element_type_float; + case(LTTNG_EVENT_FIELD_STRING): + return mi_lttng_element_type_string; + default: + return mi_lttng_element_type_other; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_domaintype_string(enum lttng_domain_type value) +{ + /* Note: This is a *duplicate* of get_domain_str from bin/lttng/utils.c */ + switch (value) { + case LTTNG_DOMAIN_KERNEL: + return config_domain_type_kernel; + case LTTNG_DOMAIN_UST: + return config_domain_type_ust; + case LTTNG_DOMAIN_JUL: + return config_domain_type_jul; + case LTTNG_DOMAIN_LOG4J: + return config_domain_type_log4j; + case LTTNG_DOMAIN_PYTHON: + return config_domain_type_python; + default: + /* Should not have an unknown domain */ + assert(0); + return NULL; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_buffertype_string(enum lttng_buffer_type value) +{ + switch (value) { + case LTTNG_BUFFER_PER_PID: + return config_buffer_type_per_pid; + case LTTNG_BUFFER_PER_UID: + return config_buffer_type_per_uid; + case LTTNG_BUFFER_GLOBAL: + return config_buffer_type_global; + default: + /* Should not have an unknow buffer type */ + assert(0); + return NULL; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_rotation_state_string(enum lttng_rotation_state value) +{ + switch (value) { + case LTTNG_ROTATION_STATE_ONGOING: + return mi_lttng_rotation_state_str_ongoing; + case LTTNG_ROTATION_STATE_COMPLETED: + return mi_lttng_rotation_state_str_completed; + case LTTNG_ROTATION_STATE_EXPIRED: + return mi_lttng_rotation_state_str_expired; + case LTTNG_ROTATION_STATE_ERROR: + return mi_lttng_rotation_state_str_error; + default: + /* Should not have an unknow rotation state. */ + assert(0); + return NULL; + } +} + +LTTNG_HIDDEN +const char *mi_lttng_trace_archive_location_relay_protocol_type_string( + enum lttng_trace_archive_location_relay_protocol_type value) +{ + switch (value) { + case LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP: + return mi_lttng_rotation_location_relay_protocol_str_tcp; + default: + /* Should not have an unknow relay protocol. */ + assert(0); + return NULL; + } +} LTTNG_HIDDEN struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type) @@ -49,7 +533,7 @@ struct mi_writer *mi_lttng_writer_create(int fd_output, int mi_output_type) goto end; } if (mi_output_type == LTTNG_MI_XML) { - mi_writer->writer = config_writer_create(fd_output); + mi_writer->writer = config_writer_create(fd_output, 0); if (!mi_writer->writer) { goto err_destroy; } @@ -91,10 +575,42 @@ int mi_lttng_writer_command_open(struct mi_writer *writer, const char *command) { int ret; - ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command); + /* + * A command is always the MI's root node, it must declare the current + * namespace and schema URIs and the schema's version. + */ + ret = config_writer_open_element(writer->writer, + mi_lttng_element_command); + if (ret) { + goto end; + } + + ret = config_writer_write_attribute(writer->writer, + mi_lttng_xmlns, DEFAULT_LTTNG_MI_NAMESPACE); + if (ret) { + goto end; + } + + ret = config_writer_write_attribute(writer->writer, + mi_lttng_xmlns_xsi, mi_lttng_w3_schema_uri); + if (ret) { + goto end; + } + + ret = config_writer_write_attribute(writer->writer, + mi_lttng_schema_location, + mi_lttng_schema_location_uri); + if (ret) { + goto end; + } + + ret = config_writer_write_attribute(writer->writer, + mi_lttng_schema_version, + mi_lttng_schema_version_value); if (ret) { goto end; } + ret = mi_lttng_writer_write_element_string(writer, mi_lttng_element_command_name, command); end: @@ -120,6 +636,26 @@ int mi_lttng_writer_close_element(struct mi_writer *writer) return config_writer_close_element(writer->writer); } +LTTNG_HIDDEN +int mi_lttng_close_multi_element(struct mi_writer *writer, + unsigned int nb_element) +{ + int ret, i; + + if (nb_element < 1) { + ret = 0; + goto end; + } + for (i = 0; i < nb_element; i++) { + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + } +end: + return ret; +} + LTTNG_HIDDEN int mi_lttng_writer_write_element_unsigned_int(struct mi_writer *writer, const char *element_name, uint64_t value) @@ -166,7 +702,7 @@ int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version *version, /* Version string (contain info like rc etc.) */ ret = mi_lttng_writer_write_element_string(writer, - mi_lttng_element_version_str, VERSION); + mi_lttng_element_version_str, version->version); if (ret) { goto end; } @@ -185,6 +721,13 @@ int mi_lttng_version(struct mi_writer *writer, struct mi_lttng_version *version, goto end; } + /* Commit version number */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_version_commit, version->version_commit); + if (ret) { + goto end; + } + /* Patch number */ ret = mi_lttng_writer_write_element_unsigned_int(writer, mi_lttng_element_version_patch_level, version->version_patchlevel); @@ -227,13 +770,21 @@ end: return ret; } +LTTNG_HIDDEN +int mi_lttng_sessions_open(struct mi_writer *writer) +{ + return mi_lttng_writer_open_element(writer, config_element_sessions); +} + LTTNG_HIDDEN int mi_lttng_session(struct mi_writer *writer, struct lttng_session *session, int is_open) { int ret; - /* open sessions element */ + assert(session); + + /* Open sessions element */ ret = mi_lttng_writer_open_element(writer, config_element_session); if (ret) { @@ -247,28 +798,28 @@ int mi_lttng_session(struct mi_writer *writer, goto end; } - /* path */ + /* Path */ ret = mi_lttng_writer_write_element_string(writer, config_element_path, session->path); if (ret) { goto end; } - /* enabled ? */ - ret = mi_lttng_writer_write_element_unsigned_int(writer, + /* Enabled ? */ + ret = mi_lttng_writer_write_element_bool(writer, config_element_enabled, session->enabled); if (ret) { goto end; } - /* snapshot mode */ + /* Snapshot mode */ ret = mi_lttng_writer_write_element_unsigned_int(writer, config_element_snapshot_mode, session->snapshot_mode); if (ret) { goto end; } - /* live timer interval in usec */ + /* Live timer interval in usec */ ret = mi_lttng_writer_write_element_unsigned_int(writer, config_element_live_timer_interval, session->live_timer_interval); @@ -284,3 +835,1513 @@ end: return ret; } + +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; +} + +LTTNG_HIDDEN +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_trackers); +} + +LTTNG_HIDDEN +int mi_lttng_pid_tracker_open(struct mi_writer *writer) +{ + int ret; + + /* Open element pid_tracker */ + ret = mi_lttng_writer_open_element(writer, config_element_pid_tracker); + if (ret) { + goto end; + } + + /* Open targets element */ + ret = mi_lttng_targets_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_targets_open(struct mi_writer *writer) +{ + return mi_lttng_writer_open_element(writer, + config_element_targets); +} + +LTTNG_HIDDEN +int mi_lttng_pid_target(struct mi_writer *writer, pid_t pid, int is_open) +{ + int ret; + + ret = mi_lttng_writer_open_element(writer, + config_element_target_pid); + if (ret) { + goto end; + } + + /* Writing pid number + * Special case for element all on track untrack command + * All pid is represented as wildcard * + */ + if ((int) pid == -1) { + ret = mi_lttng_writer_write_element_string(writer, + config_element_pid, + mi_lttng_element_track_untrack_all_wildcard); + } else { + ret = mi_lttng_writer_write_element_signed_int(writer, + config_element_pid, (int) pid); + } + 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; +}