+static
+int print_tabs(struct lttng_session *session, size_t nesting)
+{
+ size_t i;
+
+ for (i = 0; i < nesting; i++) {
+ int ret;
+
+ ret = lttng_metadata_printf(session, " ");
+ if (ret) {
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_struct_type_statedump(struct lttng_session *session,
+ const struct lttng_type *type,
+ size_t nesting)
+{
+ int ret;
+ uint32_t i, nr_fields;
+
+ ret = print_tabs(session, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "struct {\n");
+ if (ret)
+ return ret;
+ nr_fields = type->u._struct.nr_fields;
+ for (i = 0; i < nr_fields; i++) {
+ const struct lttng_event_field *iter_field;
+
+ iter_field = &type->u._struct.fields[i];
+ ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+ if (ret)
+ return ret;
+ }
+ ret = print_tabs(session, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "}");
+ return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_struct_statedump(struct lttng_session *session,
+ const struct lttng_event_field *field,
+ size_t nesting)
+{
+ int ret;
+
+ ret = _lttng_struct_type_statedump(session,
+ &field->type, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "_%s;\n",
+ field->name);
+ return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_variant_type_statedump(struct lttng_session *session,
+ const struct lttng_type *type,
+ size_t nesting)
+{
+ int ret;
+ uint32_t i, nr_choices;
+
+ ret = print_tabs(session, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "variant <_%s> {\n",
+ type->u.variant.tag_name);
+ if (ret)
+ return ret;
+ nr_choices = type->u.variant.nr_choices;
+ for (i = 0; i < nr_choices; i++) {
+ const struct lttng_event_field *iter_field;
+
+ iter_field = &type->u.variant.choices[i];
+ ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+ if (ret)
+ return ret;
+ }
+ ret = print_tabs(session, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "}");
+ return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_variant_statedump(struct lttng_session *session,
+ const struct lttng_event_field *field,
+ size_t nesting)
+{
+ int ret;
+
+ ret = _lttng_variant_type_statedump(session,
+ &field->type, nesting);
+ if (ret)
+ return ret;
+ ret = lttng_metadata_printf(session,
+ "_%s;\n",
+ field->name);
+ return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_array_compound_statedump(struct lttng_session *session,
+ const struct lttng_event_field *field,
+ size_t nesting)
+{
+ int ret;
+ const struct lttng_type *elem_type;
+
+ /* Only array of structures and variants are currently supported. */
+ elem_type = field->type.u.array_compound.elem_type;
+ switch (elem_type->atype) {
+ case atype_struct:
+ ret = _lttng_struct_type_statedump(session, elem_type, nesting);
+ if (ret)
+ return ret;
+ break;
+ case atype_variant:
+ ret = _lttng_variant_type_statedump(session, elem_type, nesting);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = lttng_metadata_printf(session,
+ " _%s[%u];\n",
+ field->name,
+ field->type.u.array_compound.length);
+ return ret;
+}
+
+/*
+ * Must be called with sessions_mutex held.
+ */
+static
+int _lttng_sequence_compound_statedump(struct lttng_session *session,
+ const struct lttng_event_field *field,
+ size_t nesting)
+{
+ int ret;
+ const char *length_name;
+ const struct lttng_type *elem_type;
+
+ length_name = field->type.u.sequence_compound.length_name;
+
+ /* Only array of structures and variants are currently supported. */
+ elem_type = field->type.u.sequence_compound.elem_type;
+ switch (elem_type->atype) {
+ case atype_struct:
+ ret = _lttng_struct_type_statedump(session, elem_type, nesting);
+ if (ret)
+ return ret;
+ break;
+ case atype_variant:
+ ret = _lttng_variant_type_statedump(session, elem_type, nesting);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = lttng_metadata_printf(session,
+ " _%s[ _%s ];\n",
+ field->name,
+ length_name);
+ return ret;
+}
+