From 215d5cc6d06a6bcfe7bb6234c4a6e4b43b49c0d0 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Wed, 3 Dec 2025 23:50:16 -0500 Subject: [PATCH 1/3] ctf2: add missing types Change-Id: Ied093d7edf0e7de76e0dc637699711cf0653dc6b Signed-off-by: Matthew Khouzam --- .../internal/ctf/core/utils/JsonMetadataStrings.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java index 6af764f398..54369405d9 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java @@ -43,6 +43,17 @@ private JsonMetadataStrings() { */ public static final String FRAGMENT_FIELD_ALIAS = "field-class-alias"; //$NON-NLS-1$ + /** + * The field class + */ + public static final String FIELD_CLASS = "field-class"; //$NON-NLS-1$ + + /** + * The name of the fragment + */ + public static final String NAME = "name"; //$NON-NLS-1$ + + /** * Type string for a CTF2 clock class fragment */ From 4882775b30ed3ea666bfd1b8d59a6e77b77ed5d7 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Wed, 3 Dec 2025 23:50:31 -0500 Subject: [PATCH 2/3] ctf: make an alias cache to auto-expand ctf2 aliases Change-Id: I62cc5e26645ea1d2bd2150af99d5aeb878061e1f Signed-off-by: Matthew Khouzam --- .../tracecompass/ctf/core/trace/Metadata.java | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java index add9c2f9a4..91429d8f9b 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java @@ -35,7 +35,9 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -73,6 +75,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; /** @@ -247,30 +252,42 @@ private static ICTFMetadataNode parseJsonToTree(String json) throws CTFException Gson gson = builder.create(); String[] jsonBlocks = json.split("\u001e"); //$NON-NLS-1$ + Map metadata = new HashMap<>(); + + // Second pass: expand string references and parse for (int i = 1; i < jsonBlocks.length; i++) { + JsonElement element = JsonParser.parseString(jsonBlocks[i]); + if (element.isJsonObject()) { + JsonObject obj = element.getAsJsonObject(); + expandAliases(obj, metadata); + if (obj.has(JsonMetadataStrings.TYPE) && obj.get(JsonMetadataStrings.TYPE).getAsString().equals(JsonMetadataStrings.FRAGMENT_FIELD_ALIAS)) { + metadata.put(obj.get(JsonMetadataStrings.NAME).getAsString(), obj.get(JsonMetadataStrings.FIELD_CLASS).getAsJsonObject()); + } + } + ICTFMetadataNode fragment; try { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], CTFJsonMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, CTFJsonMetadataNode.class)); } catch (JsonSyntaxException e) { throw new CTFException("Trace cannot be parsed as CTF2"); //$NON-NLS-1$ } String type = fragment.getType(); if (type.equals(JsonMetadataStrings.FRAGMENT_PREAMBLE)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonPreambleMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonPreambleMetadataNode.class)); } else if (type.equals(JsonMetadataStrings.FRAGMENT_TRACE)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonTraceMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonTraceMetadataNode.class)); } else if (type.equals(JsonMetadataStrings.FRAGMENT_CLOCK)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonClockMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonClockMetadataNode.class)); } else if (type.equals(JsonMetadataStrings.FRAGMENT_EVENT_RECORD)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonEventRecordMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonEventRecordMetadataNode.class)); } else if (type.equals(JsonMetadataStrings.FRAGMENT_DATA_STREAM)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonDataStreamMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonDataStreamMetadataNode.class)); if (!jsonBlocks[i].contains("id:")) { //$NON-NLS-1$ ((JsonDataStreamMetadataNode) fragment).setId(-1); } } else if (type.equals(JsonMetadataStrings.FRAGMENT_FIELD_ALIAS)) { - fragment = Objects.requireNonNull(gson.fromJson(jsonBlocks[i], JsonFieldClassAliasMetadataNode.class)); + fragment = Objects.requireNonNull(gson.fromJson(element, JsonFieldClassAliasMetadataNode.class)); } ((CTFJsonMetadataNode) fragment).initialize(); @@ -281,6 +298,23 @@ private static ICTFMetadataNode parseJsonToTree(String json) throws CTFException return root; } + private static void expandAliases(JsonObject obj, Map metadata) { + for (String key : obj.keySet()) { + JsonElement value = obj.get(key); + if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString() && metadata.containsKey(value.getAsString())) { + obj.add(key, metadata.get(value.getAsString())); + } else if (value.isJsonObject()) { + expandAliases(value.getAsJsonObject(), metadata); + } else if (value.isJsonArray()) { + for (JsonElement elem : value.getAsJsonArray()) { + if (elem.isJsonObject()) { + expandAliases(elem.getAsJsonObject(), metadata); + } + } + } + } + } + /** * Checks the version of the CTF trace by reading the first JSON fragment if * it is a CTF2 fragment it updates the major of the trace From b347e64549cd779a0ef46c06b4b933a20a1371b6 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Thu, 4 Dec 2025 00:01:20 -0500 Subject: [PATCH 3/3] ctf: fix variants can have integer selectors Change-Id: Ie8752173c78caf0d0f5cef3cb1a5d2aa58c1e8d8 Signed-off-by: Matthew Khouzam --- .../metadata/tsdl/variant/VariantParser.java | 19 ++++++++++++------- .../ctf/core/utils/JsonMetadataStrings.java | 5 +++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java index 81dd29fcee..d35010dc8d 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java @@ -22,6 +22,7 @@ import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope; import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; +import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration; import org.eclipse.tracecompass.ctf.core.trace.CTFTrace; import org.eclipse.tracecompass.ctf.parser.CTFParser; @@ -266,7 +267,7 @@ public VariantDeclaration parse(ICTFMetadataNode variant, ICommonTreeParserParam if (variant instanceof JsonStructureFieldMemberMetadataNode) { JsonObject fieldClass = ((JsonStructureFieldMemberMetadataNode) variant).getFieldClass().getAsJsonObject(); if (fieldClass.has(SELECTOR_FIELD_LOCATION)) { - JsonArray location = fieldClass.get(SELECTOR_FIELD_LOCATION).getAsJsonArray(); + JsonArray location = (fieldClass.get(SELECTOR_FIELD_LOCATION).getAsJsonObject().get(JsonMetadataStrings.PATH)).getAsJsonArray(); variantTag = location.get(location.size() - 1).getAsString(); hasTag = true; } @@ -361,13 +362,17 @@ public VariantDeclaration parse(ICTFMetadataNode variant, ICommonTreeParserParam if (decl == null) { throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$ } - if (!(decl instanceof EnumDeclaration)) { - throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$ - } - EnumDeclaration tagDecl = (EnumDeclaration) decl; - if (!intersects(tagDecl.getLabels(), variantDeclaration.getFields().keySet())) { - throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$ + if (decl instanceof EnumDeclaration) { + EnumDeclaration tagDecl = (EnumDeclaration) decl; + if (!intersects(tagDecl.getLabels(), variantDeclaration.getFields().keySet())) { + throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$ + } + } else if (decl instanceof IntegerDeclaration) { + // do nothing + } else { + throw new ParseException("Variant tag must be an enum: " + variantTag);//$NON-NLS-1$ } + } return variantDeclaration; diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java index 54369405d9..a60efc3008 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/utils/JsonMetadataStrings.java @@ -173,6 +173,11 @@ private JsonMetadataStrings() { */ public static final String VARIANT = "variant"; //$NON-NLS-1$ + /** + * Type string for a structure field class + */ + public static final String PATH = "path"; //$NON-NLS-1$ + /** * Type string for a structure field class */