1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal and others
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
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.ctf
.core
.trace
;
15 import java
.util
.AbstractMap
;
16 import java
.util
.Collections
;
18 import java
.util
.regex
.Matcher
;
19 import java
.util
.regex
.Pattern
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.CTFStrings
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.EnumDefinition
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.FloatDefinition
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDefinition
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.SimpleDatatypeDefinition
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StringDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDefinition
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.ICTFPacketDescriptor
;
32 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.IPacketReader
;
34 import com
.google
.common
.collect
.ImmutableMap
;
35 import com
.google
.common
.collect
.ImmutableMap
.Builder
;
38 * <b><u>StreamInputPacketIndexEntry</u></b>
40 * Represents an entry in the index of event packets.
42 public class StreamInputPacketIndexEntry
implements ICTFPacketDescriptor
{
44 private static final Pattern NUMBER_PATTERN
= Pattern
.compile("\\D*(\\d+)"); //$NON-NLS-1$
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
51 * Position of the start of the packet header in the file, in bits
53 private final long fOffsetBits
;
56 * Position of the start of the packet header in the file, in bytes
58 private final long fOffsetBytes
;
61 * Packet size, in bits
63 private final long fPacketSizeBits
;
66 * Content size, in bits
68 private final long fContentSizeBits
;
73 private final long fTimestampBegin
;
78 private final long fTimestampEnd
;
81 * How many lost events are there?
83 private final long fLostEvents
;
86 * Which target is being traced
88 private final String fTarget
;
89 private final long fTargetID
;
92 * Attributes of this index entry
94 private final @NonNull Map
<String
, Object
> fAttributes
;
96 private final long fEndPacketHeaderBits
;
98 // ------------------------------------------------------------------------
100 // ------------------------------------------------------------------------
103 * Constructs an index entry.
105 * @param dataOffsetBits
106 * offset in the file for the start of data in bits
107 * @param fileSizeBytes
108 * number of bytes in a file
113 public StreamInputPacketIndexEntry(long dataOffsetBits
, long fileSizeBytes
) {
114 fAttributes
= Collections
.EMPTY_MAP
;
115 fContentSizeBits
= (fileSizeBytes
* Byte
.SIZE
);
116 fPacketSizeBits
= (fileSizeBytes
* Byte
.SIZE
);
117 fOffsetBits
= dataOffsetBits
;
118 fOffsetBytes
= dataOffsetBits
/ Byte
.SIZE
;
120 fTarget
= ""; //$NON-NLS-1$
123 fTimestampEnd
= Long
.MAX_VALUE
;
124 fEndPacketHeaderBits
= dataOffsetBits
;
130 * @param dataOffsetBits
131 * offset in the file for the start of data in bits
132 * @param streamPacketContextDef
134 * @param fileSizeBytes
135 * number of bytes in a file
137 * number of lost events so far
141 public StreamInputPacketIndexEntry(long dataOffsetBits
, StructDefinition streamPacketContextDef
, long fileSizeBytes
, long lostSoFar
) {
142 this(dataOffsetBits
, streamPacketContextDef
, fileSizeBytes
, lostSoFar
, dataOffsetBits
);
148 * @param dataOffsetBits
149 * offset in the file for the start of data in bits
150 * @param streamPacketContextDef
152 * @param fileSizeBytes
153 * number of bytes in a file
155 * number of lost events so far
156 * @param endPacketHeaderBits
157 * end of packet headers
159 public StreamInputPacketIndexEntry(long dataOffsetBits
, StructDefinition streamPacketContextDef
, long fileSizeBytes
, long lostSoFar
, long endPacketHeaderBits
) {
160 fEndPacketHeaderBits
= endPacketHeaderBits
;
161 fAttributes
= computeAttributeMap(streamPacketContextDef
);
162 fContentSizeBits
= computeContentSize(fileSizeBytes
);
163 fPacketSizeBits
= computePacketSize(fileSizeBytes
);
164 fTimestampBegin
= computeTsBegin();
165 fTimestampEnd
= computeTsEnd();
166 fOffsetBits
= dataOffsetBits
;
167 fOffsetBytes
= dataOffsetBits
/ Byte
.SIZE
;
170 Target target
= lookupTarget(streamPacketContextDef
);
171 fTarget
= target
.string
;
172 fTargetID
= target
.number
;
173 fLostEvents
= computeLostEvents(lostSoFar
);
176 private static @NonNull Map
<String
, Object
> computeAttributeMap(StructDefinition streamPacketContextDef
) {
177 Builder
<String
, Object
> attributeBuilder
= ImmutableMap
.<String
, Object
> builder();
178 for (String field
: streamPacketContextDef
.getDeclaration().getFieldsList()) {
179 IDefinition id
= streamPacketContextDef
.lookupDefinition(field
);
180 if (id
instanceof IntegerDefinition
) {
181 attributeBuilder
.put(field
, ((IntegerDefinition
) id
).getValue());
182 } else if (id
instanceof FloatDefinition
) {
183 attributeBuilder
.put(field
, ((FloatDefinition
) id
).getValue());
184 } else if (id
instanceof EnumDefinition
) {
185 final EnumDefinition enumDec
= (EnumDefinition
) id
;
186 attributeBuilder
.put(field
, new AbstractMap
.SimpleImmutableEntry
<>(
187 NonNullUtils
.checkNotNull(enumDec
.getStringValue()),
188 NonNullUtils
.checkNotNull(enumDec
.getIntegerValue())));
189 } else if (id
instanceof StringDefinition
) {
190 attributeBuilder
.put(field
, ((StringDefinition
) id
).getValue());
193 return attributeBuilder
.build();
196 private Long
getPacketSize() {
197 return (Long
) fAttributes
.get(CTFStrings
.PACKET_SIZE
);
200 private long computeContentSize(long fileSizeBytes
) {
201 Long contentSize
= (Long
) fAttributes
.get(CTFStrings
.CONTENT_SIZE
);
202 /* Read the content size in bits */
203 if (contentSize
!= null) {
204 return contentSize
.longValue();
206 Long packetSize
= getPacketSize();
207 if (packetSize
!= null) {
208 return packetSize
.longValue();
210 return fileSizeBytes
* Byte
.SIZE
;
213 private long computePacketSize(long fileSizeBytes
) {
214 Long packetSize
= getPacketSize();
215 /* Read the packet size in bits */
216 if (packetSize
!= null) {
217 return packetSize
.longValue();
219 long contentSizeBits
= computeContentSize(fileSizeBytes
);
220 if (contentSizeBits
!= 0) {
221 return contentSizeBits
;
223 return fileSizeBytes
* Byte
.SIZE
;
226 private long computeTsBegin() {
227 Long tsBegin
= (Long
) fAttributes
.get(CTFStrings
.TIMESTAMP_BEGIN
);
228 /* Read the begin timestamp */
229 if (tsBegin
!= null) {
230 return tsBegin
.longValue();
235 private long computeTsEnd() {
236 Long tsEnd
= (Long
) fAttributes
.get(CTFStrings
.TIMESTAMP_END
);
237 /* Read the end timestamp */
239 // check if tsEnd == unsigned long max value
241 return Long
.MAX_VALUE
;
243 return tsEnd
.longValue();
245 return Long
.MAX_VALUE
;
248 private long computeLostEvents(long lostSoFar
) {
249 Long lostEvents
= (Long
) fAttributes
.get(CTFStrings
.EVENTS_DISCARDED
);
250 if (lostEvents
!= null) {
251 return lostEvents
- lostSoFar
;
256 private static class Target
{
257 public String string
;
262 number
= IPacketReader
.UNKNOWN_CPU
;
266 private Target
lookupTarget(StructDefinition streamPacketContextDef
) {
267 Target ret
= new Target();
268 boolean hasDevice
= fAttributes
.containsKey(CTFStrings
.DEVICE
);
270 IDefinition def
= streamPacketContextDef
.lookupDefinition(CTFStrings
.DEVICE
);
271 if (def
instanceof SimpleDatatypeDefinition
) {
272 SimpleDatatypeDefinition simpleDefinition
= (SimpleDatatypeDefinition
) def
;
273 ret
.string
= simpleDefinition
.getStringValue();
274 ret
.number
= simpleDefinition
.getIntegerValue();
275 } else if (def
instanceof StringDefinition
) {
276 StringDefinition stringDefinition
= (StringDefinition
) def
;
277 ret
.string
= stringDefinition
.getValue();
278 final Matcher matcher
= NUMBER_PATTERN
.matcher(ret
.string
);
279 if (matcher
.matches()) {
280 String number
= matcher
.group(1);
281 ret
.number
= Integer
.parseInt(number
);
285 Long cpuId
= (Long
) fAttributes
.get(CTFStrings
.CPU_ID
);
287 ret
.string
= ("CPU" + cpuId
.toString()); //$NON-NLS-1$
294 // ------------------------------------------------------------------------
296 // ------------------------------------------------------------------------
299 public boolean includes(long ts
) {
300 return (ts
>= fTimestampBegin
) && (ts
<= fTimestampEnd
);
304 public String
toString() {
305 return "StreamInputPacketIndexEntry [offsetBits=" + fOffsetBits
//$NON-NLS-1$
306 + ", timestampBegin=" + fTimestampBegin
+ ", timestampEnd=" //$NON-NLS-1$ //$NON-NLS-2$
307 + fTimestampEnd
+ "]"; //$NON-NLS-1$
310 // ------------------------------------------------------------------------
311 // Getters and Setters
312 // ------------------------------------------------------------------------
315 public long getOffsetBits() {
320 public long getPacketSizeBits() {
321 return fPacketSizeBits
;
325 public long getContentSizeBits() {
326 return fContentSizeBits
;
330 public long getTimestampBegin() {
331 return fTimestampBegin
;
335 public long getTimestampEnd() {
336 return fTimestampEnd
;
340 public long getLostEvents() {
345 public Map
<String
, Object
> getAttributes() {
350 public String
getTarget() {
355 public long getTargetId() {
360 public long getOffsetBytes() {
365 public long getPayloadStartBits() {
366 return fEndPacketHeaderBits
;