+ 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;
+ }