From 94c255ef493dfc2d7d0081f156a0d673618826f1 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Wed, 8 Jul 2015 14:56:34 -0400 Subject: [PATCH] ctf: make dynamic scopes work with definitions [bug 470846] Change-Id: I0838fb9f17ceab856f3009bdf340185b24e82f28 Signed-off-by: Matthew Khouzam Reviewed-on: https://git.eclipse.org/r/51546 Reviewed-by: Patrick Tasse Tested-by: Patrick Tasse Reviewed-by: Hudson CI --- .../ctf/core/event/EventDefinition.java | 46 ++++++++ .../core/event/types/StructDeclaration.java | 103 +++++++++++++++++- .../core/event/types/StructDefinition.java | 2 +- .../trace/CTFStreamInputPacketReader.java | 22 +++- .../ctf/core/event/EventDeclaration.java | 37 +++++++ .../ctf/core/event/metadata/IOStructGen.java | 43 ++++---- 6 files changed, 225 insertions(+), 28 deletions(-) diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/EventDefinition.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/EventDefinition.java index aa75dd6388..2e0a3d3520 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/EventDefinition.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/EventDefinition.java @@ -52,6 +52,8 @@ public final class EventDefinition implements IDefinitionScope { */ private final long fTimestamp; + private final ICompositeDefinition fEventHeaderDefinition; + /** * The event context structure definition. */ @@ -101,7 +103,41 @@ public final class EventDefinition implements IDefinitionScope { ICompositeDefinition eventContext, ICompositeDefinition packetContext, ICompositeDefinition fields) { + this(declaration, streamInputReader, timestamp, null, streamContext, + eventContext, packetContext, fields); + } + + /** + * Constructs an event definition. + * + * @param declaration + * The corresponding event declaration + * @param streamInputReader + * The SIR from where this EventDef was read + * @param timestamp + * event timestamp + * @param eventHeaderDefinition + * the event header definition, can be null + * @param eventContext + * The event context + * @param packetContext + * the packet context + * @param streamContext + * the stream context + * @param fields + * The event fields + * @since 1.1 + */ + public EventDefinition(IEventDeclaration declaration, + CTFStreamInputReader streamInputReader, + long timestamp, + ICompositeDefinition eventHeaderDefinition, + ICompositeDefinition streamContext, + ICompositeDefinition eventContext, + ICompositeDefinition packetContext, + ICompositeDefinition fields) { fDeclaration = declaration; + fEventHeaderDefinition = eventHeaderDefinition; fStreamInputReader = streamInputReader; fTimestamp = timestamp; fFields = fields; @@ -139,6 +175,16 @@ public final class EventDefinition implements IDefinitionScope { return fDeclaration; } + /** + * Get the event header + * + * @return the event header + * @since 1.1 + */ + public ICompositeDefinition getEventHeader() { + return fEventHeaderDefinition; + } + /** * Gets the fields of a definition * diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDeclaration.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDeclaration.java index 90f6efc67e..f45323d8af 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDeclaration.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDeclaration.java @@ -20,6 +20,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.regex.Pattern; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -145,7 +146,14 @@ public class StructDeclaration extends Declaration { String fieldName, BitBuffer input) throws CTFException { alignRead(input); final Definition[] myFields = new Definition[fFieldMap.size()]; - StructDefinition structDefinition = new StructDefinition(this, definitionScope, fieldName, myFields); + StructDefinition structDefinition = null; + if (definitionScope == null) { + InternalDef localDefinitionScope = new InternalDef(null, null); + structDefinition = new StructDefinition(this, localDefinitionScope, fieldName, myFields); + localDefinitionScope.setDefinition(structDefinition); + } else { + structDefinition = new StructDefinition(this, definitionScope, fieldName, myFields); + } fillStruct(input, myFields, structDefinition); return structDefinition; } @@ -171,7 +179,7 @@ public class StructDeclaration extends Declaration { alignRead(input); final Definition[] myFields = new Definition[fFieldMap.size()]; - StructDefinition structDefinition = new StructDefinition(this,definitionScope, + StructDefinition structDefinition = new StructDefinition(this, definitionScope, fieldScope, fieldScope.getName(), checkNotNull(fFieldMap.keySet()), myFields); fillStruct(input, myFields, structDefinition); return structDefinition; @@ -200,6 +208,95 @@ public class StructDeclaration extends Declaration { } } + /** + * Special constructor for fields + * + * @param eventHeaderDef + * the event header, used for scopes + * @param definitionScope + * the definition scope, in this case, the trace + * @param fields + * event fields + * @param input + * the input {@link BitBuffer} + * @return the fields definition + * @throws CTFException + * something went wrong + * @since 1.1 + */ + public StructDefinition createFieldDefinition(ICompositeDefinition eventHeaderDef, IDefinitionScope definitionScope, ILexicalScope fields, @NonNull BitBuffer input) throws CTFException { + alignRead(input); + final Definition[] myFields = new Definition[fFieldMap.size()]; + IDefinitionScope merged = definitionScope; + if (eventHeaderDef != null) { + merged = new InternalDef(definitionScope, eventHeaderDef); + } + StructDefinition structDefinition = new StructDefinition(this, merged, + fields, fields.getName(), checkNotNull(fFieldMap.keySet()), myFields); + if (merged instanceof InternalDef) { + InternalDef internalDef = (InternalDef) merged; + internalDef.setDefinition(structDefinition); + } + fillStruct(input, myFields, structDefinition); + return structDefinition; + } + + private static final Pattern EVENT_HEADER = Pattern.compile(ILexicalScope.EVENT_HEADER.getPath().replaceAll("\\.", "\\\\.") + "\\."); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + + private class InternalDef implements IDefinitionScope { + + private final ICompositeDefinition fEventHeaderDef; + private final IDefinitionScope fTraceDef; + private StructDefinition fDefinition; + + public InternalDef(IDefinitionScope definitionScope, ICompositeDefinition eventHeaderDef) { + fTraceDef = definitionScope; + fEventHeaderDef = eventHeaderDef; + } + + @Override + public ILexicalScope getScopePath() { + return ILexicalScope.EVENT; + } + + @Override + public IDefinition lookupDefinition(String lookupPath) { + IDefinition lookupDefinition = null; + if (fTraceDef != null) { + lookupDefinition = fTraceDef.lookupDefinition(lookupPath); + } + if (lookupDefinition == null) { + if (fEventHeaderDef != null) { + String[] paths = EVENT_HEADER.split(lookupPath); + if (paths.length > 1) { + String[] childLookup = paths[1].split("\\."); //$NON-NLS-1$ + return getRecursiveDef(fEventHeaderDef.getDefinition(childLookup[0]), childLookup, 1); + } + if (fDefinition != null) { + return fDefinition.lookupDefinition(lookupPath); + } + } + } + return lookupDefinition; + } + + private IDefinition getRecursiveDef(Definition definition, String[] childLookup, int i) { + if (i == childLookup.length) { + return definition; + } + if (definition instanceof ICompositeDefinition) { + ICompositeDefinition compositeDefinition = (ICompositeDefinition) definition; + return getRecursiveDef(compositeDefinition.getDefinition(childLookup[i]), childLookup, i + 1); + } + return null; + } + + public void setDefinition(StructDefinition definition) { + fDefinition = definition; + } + + } + @Override public String toString() { /* Only used for debugging */ @@ -252,7 +349,7 @@ public class StructDeclaration extends Declaration { List otherDecs = new ArrayList<>(); otherDecs.addAll(other.fFieldMap.values()); - //check fields in order + // check fields in order for (int i = 0; i < fFieldMap.size(); i++) { if ((!localFieldNames.get(i).equals(otherFieldNames.get(i))) || (!otherDecs.get(i).equals(localDecs.get(i)))) { diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDefinition.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDefinition.java index a3bbd14eda..c70eb47477 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDefinition.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/StructDefinition.java @@ -156,7 +156,7 @@ public final class StructDefinition extends ScopedDefinition implements IComposi if (val != -1) { return fDefinitions[val]; } - return null; + return (Definition) getDefinitionScope().lookupDefinition(lookupPath); } @Override diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java index 4b9fdccf55..d073d90ce3 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java @@ -40,6 +40,7 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition; import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition; import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer; +import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration; import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition; /** @@ -56,6 +57,19 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab private static final int BITS_PER_BYTE = Byte.SIZE; + private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() { + + @Override + public IDefinition lookupDefinition(String lookupPath) { + return null; + } + + @Override + public ILexicalScope getScopePath() { + return null; + } + }; + /** BitBuffer used to read the trace file. */ @Nullable private BitBuffer fBitBuffer; @@ -344,12 +358,12 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab /* Read the stream event header. */ if (fStreamEventHeaderDecl != null) { if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) { - fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(null, "", currentBitBuffer); //$NON-NLS-1$ + fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$ EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef; eventID = ehd.getId(); timestamp = calculateTimestamp(ehd.getTimestamp(), ehd.getTimestampLength()); } else { - fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(null, ILexicalScope.EVENT_HEADER, currentBitBuffer); + fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer); StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef; /* Check for the event id. */ IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$ @@ -398,11 +412,11 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab } } /* Get the right event definition using the event id. */ - IEventDeclaration eventDeclaration = fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID); + EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID); if (eventDeclaration == null) { throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$ } - EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, currentBitBuffer, timestamp); + EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, timestamp); /* * Set the event timestamp using the timestamp calculated by diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java index 6167586ad3..9acb2b7d95 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java @@ -79,6 +79,43 @@ public class EventDeclaration implements IEventDeclaration { public EventDeclaration() { } + /** + * Creates an instance of EventDefinition corresponding to this declaration. + * + * @param streamInputReader + * The StreamInputReader for which this definition is created. + * @param eventHeaderDef + * The event header definition + * @param input + * the bitbuffer input source + * @param timestamp + * The timestamp when the event was taken + * @return A new EventDefinition. + * @throws CTFException + * As a bitbuffer is used to read, it could have wrapped + * IOExceptions. + */ + public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, ICompositeDefinition eventHeaderDef, @NonNull BitBuffer input, long timestamp) throws CTFException { + StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl(); + StructDefinition streamEventContext = streamEventContextDecl != null ? streamEventContextDecl.createDefinition(fStream.getTrace(), ILexicalScope.STREAM_EVENT_CONTEXT, input) : null; + ICompositeDefinition packetContext = streamInputReader.getPacketReader().getCurrentPacketEventHeader(); + StructDefinition eventContext = fContext != null ? fContext.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.CONTEXT, input) : null; + StructDefinition eventPayload = fFields != null ? fFields.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.FIELDS, input) : null; + + // a bit lttng specific + // CTF doesn't require a timestamp, + // but it's passed to us + return new EventDefinition( + this, + streamInputReader, + timestamp, + eventHeaderDef, + streamEventContext, + eventContext, + packetContext, + eventPayload); + } + @Override public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, @NonNull BitBuffer input, long timestamp) throws CTFException { StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl(); diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java index 957e65c030..ab2cb4770c 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java +++ b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java @@ -463,8 +463,7 @@ public class IOStructGen { throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$ } - IDeclaration packetHeaderDecl = parseTypeSpecifierList( - typeSpecifier, null); + IDeclaration packetHeaderDecl = parseTypeSpecifierList(typeSpecifier); if (!(packetHeaderDecl instanceof StructDeclaration)) { throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$ @@ -608,8 +607,7 @@ public class IOStructGen { throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$ } - IDeclaration eventHeaderDecl = parseTypeSpecifierList( - typeSpecifier, null); + IDeclaration eventHeaderDecl = parseTypeSpecifierList(typeSpecifier); DeclarationScope scope = getCurrentScope(); DeclarationScope eventHeaderScope = scope.lookupChildRecursive(MetadataStrings.STRUCT); if (eventHeaderScope == null) { @@ -638,8 +636,7 @@ public class IOStructGen { throw new ParseException("event.context expects a type specifier"); //$NON-NLS-1$ } - IDeclaration eventContextDecl = parseTypeSpecifierList( - typeSpecifier, null); + IDeclaration eventContextDecl = parseTypeSpecifierList(typeSpecifier); if (!(eventContextDecl instanceof StructDeclaration)) { throw new ParseException("event.context expects a struct"); //$NON-NLS-1$ @@ -657,8 +654,7 @@ public class IOStructGen { throw new ParseException("packet.context expects a type specifier"); //$NON-NLS-1$ } - IDeclaration packetContextDecl = parseTypeSpecifierList( - typeSpecifier, null); + IDeclaration packetContextDecl = parseTypeSpecifierList(typeSpecifier); if (!(packetContextDecl instanceof StructDeclaration)) { throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$ @@ -796,8 +792,7 @@ public class IOStructGen { throw new ParseException("context expects a type specifier"); //$NON-NLS-1$ } - IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier, - null); + IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier); if (!(contextDecl instanceof StructDeclaration)) { throw new ParseException("context expects a struct"); //$NON-NLS-1$ @@ -816,7 +811,7 @@ public class IOStructGen { } IDeclaration fieldsDecl; - fieldsDecl = parseTypeSpecifierList(typeSpecifier, null); + fieldsDecl = parseTypeSpecifierList(typeSpecifier); if (!(fieldsDecl instanceof StructDeclaration)) { throw new ParseException("fields expects a struct"); //$NON-NLS-1$ @@ -858,7 +853,7 @@ public class IOStructGen { parseTypealias(child); break; case CTFParser.TYPE_SPECIFIER_LIST: - parseTypeSpecifierList(child, null); + parseTypeSpecifierList(child); break; default: throw childTypeError(child); @@ -1121,7 +1116,7 @@ public class IOStructGen { * Parse the type specifier list, which is the "base" type. For example, * it would be int in int a[3][len]. */ - declaration = parseTypeSpecifierList(typeSpecifierList, pointers); + declaration = parseTypeSpecifierList(typeSpecifierList, pointers, identifier); /* * Each length subscript means that we must create a nested array or @@ -1212,9 +1207,7 @@ public class IOStructGen { private void registerType(IDeclaration declaration, String identifier) throws ParseException { final DeclarationScope currentScope = getCurrentScope(); - if (declaration instanceof StructDeclaration) { - currentScope.registerStruct(identifier, (StructDeclaration) declaration); - } else if (declaration instanceof EnumDeclaration) { + if (declaration instanceof EnumDeclaration) { currentScope.registerEnum(identifier, (EnumDeclaration) declaration); } else if (declaration instanceof VariantDeclaration) { currentScope.registerVariant(identifier, (VariantDeclaration) declaration); @@ -1300,6 +1293,10 @@ public class IOStructGen { } + private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList) throws ParseException { + return parseTypeSpecifierList(typeSpecifierList, null, null); + } + /** * Parses a type specifier list and returns the corresponding declaration. * @@ -1313,7 +1310,7 @@ public class IOStructGen { * creating the declaration. */ private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList, - List pointerList) throws ParseException { + List pointerList, CommonTree identifier) throws ParseException { IDeclaration declaration = null; /* @@ -1333,7 +1330,7 @@ public class IOStructGen { declaration = parseString(firstChild); break; case CTFParser.STRUCT: - declaration = parseStruct(firstChild); + declaration = parseStruct(firstChild, identifier); StructDeclaration structDeclaration = (StructDeclaration) declaration; IDeclaration idEnumDecl = structDeclaration.getFields().get("id"); //$NON-NLS-1$ if (idEnumDecl instanceof EnumDeclaration) { @@ -1627,7 +1624,7 @@ public class IOStructGen { * @return The corresponding struct declaration. * @throws ParseException */ - private StructDeclaration parseStruct(CommonTree struct) + private StructDeclaration parseStruct(CommonTree struct, CommonTree identifier) throws ParseException { List children = struct.getChildren(); @@ -1672,6 +1669,11 @@ public class IOStructGen { } } + if (!hasName && identifier != null) { + structName = identifier.getText(); + hasName = true; + } + /* * If a struct has just a body and no name (just like the song, * "A Struct With No Name" by America (sorry for that...)), it's a @@ -1764,6 +1766,7 @@ public class IOStructGen { break; case CTFParser.TYPEDEF: parseTypedef(declarationNode); + parseStructDeclaration(declarationNode, structDeclaration); break; case CTFParser.SV_DECLARATION: parseStructDeclaration(declarationNode, structDeclaration); @@ -2061,7 +2064,7 @@ public class IOStructGen { CommonTree typeSpecifierList = (CommonTree) enumContainerType.getChild(0); /* Parse it and get the corresponding declaration */ - IDeclaration decl = parseTypeSpecifierList(typeSpecifierList, null); + IDeclaration decl = parseTypeSpecifierList(typeSpecifierList); /* If is is an integer, return it, else throw an error */ if (decl instanceof IntegerDeclaration) { -- 2.34.1