ctf: Introduce IPacketReader
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / internal / ctf / core / trace / CTFPacketReader.java
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;
65 private final List<IEventDeclaration> fDeclarations;
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 */
97 public CTFPacketReader(BitBuffer input, ICTFPacketDescriptor packetContext, List<IEventDeclaration> declarations, @Nullable IDeclaration eventHeaderDeclaration, @Nullable StructDeclaration streamContext, ICompositeDefinition packetHeader,
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() {
117 return fInput.position() < fPacketContext.getContentSizeBits();
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 */
128 if (fHasLost && (posStart == fPacketContext.getPayloadStartBits())) {
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$
226 fields));
227 }
228
229 @Override
230 public ILexicalScope getScopePath() {
231 return ILexicalScope.PACKET;
232 }
233
234 @Override
235 public @Nullable IDefinition lookupDefinition(@Nullable String lookupPath) {
236 if (ILexicalScope.TRACE_PACKET_HEADER.getPath().equals(lookupPath)) {
237 return fTracePacketHeader;
238 } else if (ILexicalScope.STREAM_PACKET_CONTEXT.getPath().equals(lookupPath) && fPacketScope != null) {
239 return fPacketScope.lookupDefinition(lookupPath);
240 }
241 return null;
242 }
243
244 @Override
245 public ICTFPacketDescriptor getCurrentPacket() {
246 return fPacketContext;
247 }
248
249 /**
250 * TODO: remove when API is reworked a bit.
251 */
252 @Override
253 public @Nullable ICompositeDefinition getCurrentPacketEventHeader() {
254 return fEventHeader;
255 }
256
257 }
This page took 0.0397 seconds and 5 git commands to generate.