Commit | Line | Data |
---|---|---|
42f8feff MK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2015 Ericsson | |
3 | * | |
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 | |
8 | * | |
9 | * Contributors: | |
10 | * Matthew Khouzam - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.tracecompass.internal.ctf.core.trace; | |
14 | ||
15 | import java.util.List; | |
16 | ||
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; | |
42 | ||
43 | /** | |
44 | * Packet reader with a fixed bit buffer, should be the fast and easily | |
45 | * parallelizable one. | |
46 | */ | |
47 | @NonNullByDefault | |
48 | public final class CTFPacketReader implements IPacketReader, IDefinitionScope { | |
49 | ||
50 | private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() { | |
51 | ||
52 | @Override | |
53 | public @Nullable IDefinition lookupDefinition(@Nullable String lookupPath) { | |
54 | return null; | |
55 | } | |
56 | ||
57 | @Override | |
58 | public @Nullable ILexicalScope getScopePath() { | |
59 | return null; | |
60 | } | |
61 | }; | |
62 | ||
63 | private final BitBuffer fInput; | |
64 | private final ICTFPacketDescriptor fPacketContext; | |
32ea78ed | 65 | private final List<@Nullable IEventDeclaration> fDeclarations; |
42f8feff MK |
66 | private boolean fHasLost; |
67 | private long fLastTimestamp; | |
68 | private @Nullable final IDeclaration fStreamEventHeaderDecl; | |
69 | ||
70 | private @Nullable final StructDeclaration fStreamContext; | |
71 | ||
72 | private @Nullable final ICompositeDefinition fTracePacketHeader; | |
73 | ||
74 | private @Nullable final IDefinitionScope fPacketScope; | |
75 | ||
76 | private @Nullable ICompositeDefinition fEventHeader; | |
77 | ||
78 | /** | |
79 | * Constructor | |
80 | * | |
81 | * @param input | |
82 | * input {@link BitBuffer} | |
83 | * @param packetContext | |
84 | * packet_context where we get info like lost events and cpu_id | |
85 | * @param declarations | |
86 | * event declarations for this packet reader | |
87 | * @param eventHeaderDeclaration | |
88 | * event header declaration, what to read before any given event, | |
89 | * to find it's id | |
90 | * @param streamContext | |
91 | * the context declaration | |
92 | * @param packetHeader | |
93 | * the header with the magic numbers and such | |
94 | * @param packetScope | |
95 | * the scope of the packetHeader | |
96 | */ | |
32ea78ed | 97 | public CTFPacketReader(BitBuffer input, ICTFPacketDescriptor packetContext, List<@Nullable IEventDeclaration> declarations, @Nullable IDeclaration eventHeaderDeclaration, @Nullable StructDeclaration streamContext, @Nullable ICompositeDefinition packetHeader, |
42f8feff MK |
98 | IDefinitionScope packetScope) { |
99 | fInput = input; | |
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; | |
108 | } | |
109 | ||
110 | @Override | |
111 | public int getCPU() { | |
112 | return (int) fPacketContext.getTargetId(); | |
113 | } | |
114 | ||
115 | @Override | |
116 | public boolean hasMoreEvents() { | |
f450c256 | 117 | return fHasLost || (fInput.position() < fPacketContext.getContentSizeBits()); |
42f8feff MK |
118 | } |
119 | ||
120 | @Override | |
121 | public EventDefinition readNextEvent() throws CTFException { | |
122 | int eventID = (int) IEventDeclaration.UNSET_EVENT_ID; | |
123 | final long posStart = fInput.position(); | |
124 | /* | |
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. | |
127 | */ | |
f450c256 | 128 | if (fHasLost && (posStart >= fPacketContext.getContentSizeBits())) { |
42f8feff MK |
129 | fHasLost = false; |
130 | return createLostEvent(fPacketContext); | |
131 | } | |
132 | ||
133 | fEventHeader = null; | |
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$ | |
139 | fEventHeader = ehd; | |
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$ | |
151 | } | |
152 | /* Check for the variant v. */ | |
153 | IDefinition variantDef = structEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$ | |
154 | if (variantDef instanceof VariantDefinition) { | |
155 | ||
156 | /* Get the variant current field */ | |
157 | StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField(); | |
158 | ||
159 | /* | |
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. | |
162 | */ | |
163 | IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$ | |
164 | if (vIdDef instanceof IntegerDefinition) { | |
165 | simpleIdDef = (SimpleDatatypeDefinition) vIdDef; | |
166 | } | |
167 | ||
168 | } | |
169 | if (simpleIdDef != null) { | |
170 | eventID = simpleIdDef.getIntegerValue().intValue(); | |
171 | } | |
172 | } | |
173 | /* Single event type in a trace */ | |
174 | if (eventID == IEventDeclaration.UNSET_EVENT_ID && fDeclarations.size() == 1) { | |
175 | eventID = 0; | |
176 | } | |
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$ | |
181 | } | |
182 | EventDeclaration declaration = (EventDeclaration) eventDeclaration; | |
183 | EventDefinition eventDef = declaration.createDefinition(fStreamContext, fPacketContext, fTracePacketHeader, fEventHeader, fInput, fLastTimestamp); | |
184 | fLastTimestamp = eventDef.getTimestamp(); | |
185 | /* | |
186 | * Set the event timestamp using the timestamp calculated by | |
187 | * updateTimestamp. | |
188 | */ | |
189 | ||
190 | if (posStart == fInput.position()) { | |
191 | throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$ | |
192 | } | |
193 | ||
194 | return eventDef; | |
195 | } | |
196 | ||
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$ | |
204 | } | |
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$ | |
208 | } | |
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, | |
217 | cpu, | |
218 | lostEventsTimestamp, | |
219 | null, | |
220 | null, | |
221 | null, | |
222 | null, | |
223 | new StructDefinition( | |
224 | lostFields, | |
225 | this, "fields", //$NON-NLS-1$ | |
6b8f960d MK |
226 | fields), |
227 | fPacketContext); | |
42f8feff MK |
228 | } |
229 | ||
230 | @Override | |
231 | public ILexicalScope getScopePath() { | |
232 | return ILexicalScope.PACKET; | |
233 | } | |
234 | ||
235 | @Override | |
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); | |
241 | } | |
242 | return null; | |
243 | } | |
244 | ||
245 | @Override | |
246 | public ICTFPacketDescriptor getCurrentPacket() { | |
247 | return fPacketContext; | |
248 | } | |
249 | ||
250 | /** | |
251 | * TODO: remove when API is reworked a bit. | |
252 | */ | |
253 | @Override | |
254 | public @Nullable ICompositeDefinition getCurrentPacketEventHeader() { | |
255 | return fEventHeader; | |
256 | } | |
257 | ||
258 | } |