1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.ctf
.core
.trace
;
15 import java
.util
.List
;
17 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
18 import org
.eclipse
.jdt
.annotation
.Nullable
;
19 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
20 import org
.eclipse
.tracecompass
.ctf
.core
.CTFStrings
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.event
.EventDefinition
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.event
.IEventDeclaration
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.LostEventDeclaration
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.ILexicalScope
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.ICompositeDefinition
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDeclaration
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IEventHeaderDeclaration
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDeclaration
;
32 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
33 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.SimpleDatatypeDefinition
;
34 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDeclaration
;
35 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDefinition
;
36 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.VariantDefinition
;
37 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFIOException
;
38 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.ICTFPacketDescriptor
;
39 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.IPacketReader
;
40 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.EventDeclaration
;
41 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.types
.composite
.EventHeaderDefinition
;
44 * Packet reader with a fixed bit buffer, should be the fast and easily
48 public final class CTFPacketReader
implements IPacketReader
, IDefinitionScope
{
50 private static final IDefinitionScope EVENT_HEADER_SCOPE
= new IDefinitionScope() {
53 public @Nullable IDefinition
lookupDefinition(@Nullable String lookupPath
) {
58 public @Nullable ILexicalScope
getScopePath() {
63 private final BitBuffer fInput
;
64 private final ICTFPacketDescriptor fPacketContext
;
65 private final List
<@Nullable IEventDeclaration
> fDeclarations
;
66 private boolean fHasLost
;
67 private long fLastTimestamp
;
68 private @Nullable final IDeclaration fStreamEventHeaderDecl
;
70 private @Nullable final StructDeclaration fStreamContext
;
72 private @Nullable final ICompositeDefinition fTracePacketHeader
;
74 private @Nullable final IDefinitionScope fPacketScope
;
76 private @Nullable ICompositeDefinition fEventHeader
;
82 * input {@link BitBuffer}
83 * @param packetContext
84 * packet_context where we get info like lost events and cpu_id
86 * event declarations for this packet reader
87 * @param eventHeaderDeclaration
88 * event header declaration, what to read before any given event,
90 * @param streamContext
91 * the context declaration
93 * the header with the magic numbers and such
95 * the scope of the packetHeader
97 public CTFPacketReader(BitBuffer input
, ICTFPacketDescriptor packetContext
, List
<@Nullable IEventDeclaration
> declarations
, @Nullable IDeclaration eventHeaderDeclaration
, @Nullable StructDeclaration streamContext
, @Nullable ICompositeDefinition packetHeader
,
98 IDefinitionScope packetScope
) {
100 fPacketContext
= packetContext
;
101 fDeclarations
= declarations
;
102 fPacketScope
= packetScope
;
103 fHasLost
= fPacketContext
.getLostEvents() != 0;
104 fLastTimestamp
= fPacketContext
.getTimestampBegin();
105 fStreamEventHeaderDecl
= eventHeaderDeclaration
;
106 fStreamContext
= streamContext
;
107 fTracePacketHeader
= packetHeader
;
111 public int getCPU() {
112 return (int) fPacketContext
.getTargetId();
116 public boolean hasMoreEvents() {
117 return fHasLost
|| (fInput
.position() < fPacketContext
.getContentSizeBits());
121 public EventDefinition
readNextEvent() throws CTFException
{
122 int eventID
= (int) IEventDeclaration
.UNSET_EVENT_ID
;
123 final long posStart
= fInput
.position();
125 * Return the Lost Event after all other events in this packet. We need
126 * to check if the bytebuffer is at the beginning too.
128 if (fHasLost
&& (posStart
>= fPacketContext
.getContentSizeBits())) {
130 return createLostEvent(fPacketContext
);
134 /* Read the stream event header. */
135 final IDeclaration streamEventHeaderDecl
= fStreamEventHeaderDecl
;
136 if (streamEventHeaderDecl
instanceof IEventHeaderDeclaration
) {
137 IEventHeaderDeclaration eventHeaderDeclaration
= (IEventHeaderDeclaration
) streamEventHeaderDecl
;
138 EventHeaderDefinition ehd
= (EventHeaderDefinition
) eventHeaderDeclaration
.createDefinition(EVENT_HEADER_SCOPE
, "", fInput
); //$NON-NLS-1$
140 eventID
= ehd
.getId();
141 } else if (streamEventHeaderDecl
instanceof StructDeclaration
) {
142 StructDefinition structEventHeaderDef
= ((StructDeclaration
) streamEventHeaderDecl
).createDefinition(EVENT_HEADER_SCOPE
, ILexicalScope
.EVENT_HEADER
, fInput
);
143 fEventHeader
= structEventHeaderDef
;
144 /* Check for the event id. */
145 IDefinition idDef
= structEventHeaderDef
.lookupDefinition("id"); //$NON-NLS-1$
146 SimpleDatatypeDefinition simpleIdDef
= null;
147 if (idDef
instanceof SimpleDatatypeDefinition
) {
148 simpleIdDef
= ((SimpleDatatypeDefinition
) idDef
);
149 } else if (idDef
!= null) {
150 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
152 /* Check for the variant v. */
153 IDefinition variantDef
= structEventHeaderDef
.lookupDefinition("v"); //$NON-NLS-1$
154 if (variantDef
instanceof VariantDefinition
) {
156 /* Get the variant current field */
157 StructDefinition variantCurrentField
= (StructDefinition
) ((VariantDefinition
) variantDef
).getCurrentField();
160 * Try to get the id field in the current field of the variant.
161 * If it is present, it overrides the previously read event id.
163 IDefinition vIdDef
= variantCurrentField
.lookupDefinition("id"); //$NON-NLS-1$
164 if (vIdDef
instanceof IntegerDefinition
) {
165 simpleIdDef
= (SimpleDatatypeDefinition
) vIdDef
;
169 if (simpleIdDef
!= null) {
170 eventID
= simpleIdDef
.getIntegerValue().intValue();
173 /* Single event type in a trace */
174 if (eventID
== IEventDeclaration
.UNSET_EVENT_ID
&& fDeclarations
.size() == 1) {
177 /* Get the right event definition using the event id. */
178 IEventDeclaration eventDeclaration
= fDeclarations
.get(eventID
);
179 if (!(eventDeclaration
instanceof EventDeclaration
)) {
180 throw new CTFIOException("Incorrect event id : " + eventID
); //$NON-NLS-1$
182 EventDeclaration declaration
= (EventDeclaration
) eventDeclaration
;
183 EventDefinition eventDef
= declaration
.createDefinition(fStreamContext
, fPacketContext
, fTracePacketHeader
, fEventHeader
, fInput
, fLastTimestamp
);
184 fLastTimestamp
= eventDef
.getTimestamp();
186 * Set the event timestamp using the timestamp calculated by
190 if (posStart
== fInput
.position()) {
191 throw new CTFIOException("Empty event not allowed, event: " + eventDef
.getDeclaration().getName()); //$NON-NLS-1$
197 private EventDefinition
createLostEvent(final ICTFPacketDescriptor currentPacket
) {
198 IEventDeclaration lostEventDeclaration
= LostEventDeclaration
.INSTANCE
;
199 StructDeclaration lostFields
= lostEventDeclaration
.getFields();
200 // this is a hard coded map, we know it's not null
201 IntegerDeclaration lostFieldsDecl
= (IntegerDeclaration
) lostFields
.getField(CTFStrings
.LOST_EVENTS_FIELD
);
202 if (lostFieldsDecl
== null) {
203 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
205 IntegerDeclaration lostEventsDurationDecl
= (IntegerDeclaration
) lostFields
.getField(CTFStrings
.LOST_EVENTS_DURATION
);
206 if (lostEventsDurationDecl
== null) {
207 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
209 long lostEventsTimestamp
= fLastTimestamp
;
210 long lostEventsDuration
= currentPacket
.getTimestampEnd() - lostEventsTimestamp
;
211 IntegerDefinition lostDurationDef
= new IntegerDefinition(lostFieldsDecl
, null, CTFStrings
.LOST_EVENTS_DURATION
, lostEventsDuration
);
212 IntegerDefinition lostCountDef
= new IntegerDefinition(lostEventsDurationDecl
, null, CTFStrings
.LOST_EVENTS_FIELD
, fPacketContext
.getLostEvents());
213 IntegerDefinition
[] fields
= new IntegerDefinition
[] { lostCountDef
, lostDurationDef
};
214 int cpu
= (int) fPacketContext
.getTargetId();
215 return new EventDefinition(
216 lostEventDeclaration
,
223 new StructDefinition(
225 this, "fields", //$NON-NLS-1$
231 public ILexicalScope
getScopePath() {
232 return ILexicalScope
.PACKET
;
236 public @Nullable IDefinition
lookupDefinition(@Nullable String lookupPath
) {
237 if (ILexicalScope
.TRACE_PACKET_HEADER
.getPath().equals(lookupPath
)) {
238 return fTracePacketHeader
;
239 } else if (ILexicalScope
.STREAM_PACKET_CONTEXT
.getPath().equals(lookupPath
) && fPacketScope
!= null) {
240 return fPacketScope
.lookupDefinition(lookupPath
);
246 public ICTFPacketDescriptor
getCurrentPacket() {
247 return fPacketContext
;
251 * TODO: remove when API is reworked a bit.
254 public @Nullable ICompositeDefinition
getCurrentPacketEventHeader() {