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
.HashMap
;
18 import java
.util
.regex
.Matcher
;
19 import java
.util
.regex
.Pattern
;
21 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.CTFStrings
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.EnumDefinition
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.FloatDefinition
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDefinition
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.SimpleDatatypeDefinition
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StringDefinition
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.ICTFPacketDescriptor
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.IPacketReader
;
34 * <b><u>StreamInputPacketIndexEntry</u></b>
36 * Represents an entry in the index of event packets.
38 public class StreamInputPacketIndexEntry
implements ICTFPacketDescriptor
{
40 private static final Pattern NUMBER_PATTERN
= Pattern
.compile("\\D*(\\d+)"); //$NON-NLS-1$
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
47 * Position of the start of the packet header in the file, in bits
49 private final long fOffsetBits
;
52 * Position of the start of the packet header in the file, in bytes
54 private final long fOffsetBytes
;
57 * Packet size, in bits
59 private final long fPacketSizeBits
;
62 * Content size, in bits
64 private final long fContentSizeBits
;
69 private final long fTimestampBegin
;
74 private final long fTimestampEnd
;
77 * How many lost events are there?
79 private final long fLostEvents
;
82 * Which target is being traced
84 private final String fTarget
;
85 private final long fTargetID
;
88 * Attributes of this index entry
90 private final Map
<String
, Object
> fAttributes
= new HashMap
<>();
92 private final long fEndPacketHeaderBits
;
94 // ------------------------------------------------------------------------
96 // ------------------------------------------------------------------------
99 * Constructs an index entry.
101 * @param dataOffsetBits
102 * offset in the file for the start of data in bits
103 * @param fileSizeBytes
104 * number of bytes in a file
109 public StreamInputPacketIndexEntry(long dataOffsetBits
, long fileSizeBytes
) {
110 fContentSizeBits
= (fileSizeBytes
* Byte
.SIZE
);
111 fPacketSizeBits
= (fileSizeBytes
* Byte
.SIZE
);
112 fOffsetBits
= dataOffsetBits
;
113 fOffsetBytes
= dataOffsetBits
/ Byte
.SIZE
;
115 fTarget
= ""; //$NON-NLS-1$
118 fTimestampEnd
= Long
.MAX_VALUE
;
119 fEndPacketHeaderBits
= dataOffsetBits
;
125 * @param dataOffsetBits
126 * offset in the file for the start of data in bits
127 * @param streamPacketContextDef
129 * @param fileSizeBytes
130 * number of bytes in a file
132 * number of lost events so far
136 public StreamInputPacketIndexEntry(long dataOffsetBits
, StructDefinition streamPacketContextDef
, long fileSizeBytes
, long lostSoFar
) {
137 this(dataOffsetBits
, streamPacketContextDef
, fileSizeBytes
, lostSoFar
, dataOffsetBits
);
143 * @param dataOffsetBits
144 * offset in the file for the start of data in bits
145 * @param streamPacketContextDef
147 * @param fileSizeBytes
148 * number of bytes in a file
150 * number of lost events so far
151 * @param endPacketHeaderBits
152 * end of packet headers
154 public StreamInputPacketIndexEntry(long dataOffsetBits
, StructDefinition streamPacketContextDef
, long fileSizeBytes
, long lostSoFar
, long endPacketHeaderBits
) {
155 fEndPacketHeaderBits
= endPacketHeaderBits
;
156 for (String field
: streamPacketContextDef
.getDeclaration().getFieldsList()) {
157 IDefinition id
= streamPacketContextDef
.lookupDefinition(field
);
158 if (id
instanceof IntegerDefinition
) {
159 fAttributes
.put(field
, ((IntegerDefinition
) id
).getValue());
160 } else if (id
instanceof FloatDefinition
) {
161 fAttributes
.put(field
, ((FloatDefinition
) id
).getValue());
162 } else if (id
instanceof EnumDefinition
) {
163 final EnumDefinition enumDec
= (EnumDefinition
) id
;
164 fAttributes
.put(field
, new AbstractMap
.SimpleImmutableEntry
<>(
165 NonNullUtils
.checkNotNull(enumDec
.getStringValue()),
166 NonNullUtils
.checkNotNull(enumDec
.getIntegerValue())));
167 } else if (id
instanceof StringDefinition
) {
168 fAttributes
.put(field
, ((StringDefinition
) id
).getValue());
172 fContentSizeBits
= computeContentSize(fileSizeBytes
);
173 fPacketSizeBits
= computePacketSize(fileSizeBytes
);
174 fTimestampBegin
= computeTsBegin();
175 fTimestampEnd
= computeTsEnd();
176 fOffsetBits
= dataOffsetBits
;
177 fOffsetBytes
= dataOffsetBits
/ Byte
.SIZE
;
180 Target target
= lookupTarget(streamPacketContextDef
);
181 fTarget
= target
.string
;
182 fTargetID
= target
.number
;
183 fLostEvents
= computeLostEvents(lostSoFar
);
186 private Long
getPacketSize() {
187 return (Long
) fAttributes
.get(CTFStrings
.PACKET_SIZE
);
190 private long computeContentSize(long fileSizeBytes
) {
191 Long contentSize
= (Long
) fAttributes
.get(CTFStrings
.CONTENT_SIZE
);
192 /* Read the content size in bits */
193 if (contentSize
!= null) {
194 return contentSize
.longValue();
196 Long packetSize
= getPacketSize();
197 if (packetSize
!= null) {
198 return packetSize
.longValue();
200 return fileSizeBytes
* Byte
.SIZE
;
203 private long computePacketSize(long fileSizeBytes
) {
204 Long packetSize
= getPacketSize();
205 /* Read the packet size in bits */
206 if (packetSize
!= null) {
207 return packetSize
.longValue();
209 long contentSizeBits
= computeContentSize(fileSizeBytes
);
210 if (contentSizeBits
!= 0) {
211 return contentSizeBits
;
213 return fileSizeBytes
* Byte
.SIZE
;
216 private long computeTsBegin() {
217 Long tsBegin
= (Long
) fAttributes
.get(CTFStrings
.TIMESTAMP_BEGIN
);
218 /* Read the begin timestamp */
219 if (tsBegin
!= null) {
220 return tsBegin
.longValue();
225 private long computeTsEnd() {
226 Long tsEnd
= (Long
) fAttributes
.get(CTFStrings
.TIMESTAMP_END
);
227 /* Read the end timestamp */
229 // check if tsEnd == unsigned long max value
231 return Long
.MAX_VALUE
;
233 return tsEnd
.longValue();
235 return Long
.MAX_VALUE
;
238 private long computeLostEvents(long lostSoFar
) {
239 Long lostEvents
= (Long
) fAttributes
.get(CTFStrings
.EVENTS_DISCARDED
);
240 if (lostEvents
!= null) {
241 return lostEvents
- lostSoFar
;
246 private static class Target
{
247 public String string
;
252 number
= IPacketReader
.UNKNOWN_CPU
;
256 private Target
lookupTarget(StructDefinition streamPacketContextDef
) {
257 Target ret
= new Target();
258 boolean hasDevice
= fAttributes
.containsKey(CTFStrings
.DEVICE
);
260 IDefinition def
= streamPacketContextDef
.lookupDefinition(CTFStrings
.DEVICE
);
261 if (def
instanceof SimpleDatatypeDefinition
) {
262 SimpleDatatypeDefinition simpleDefinition
= (SimpleDatatypeDefinition
) def
;
263 ret
.string
= simpleDefinition
.getStringValue();
264 ret
.number
= simpleDefinition
.getIntegerValue();
265 } else if (def
instanceof StringDefinition
) {
266 StringDefinition stringDefinition
= (StringDefinition
) def
;
267 ret
.string
= stringDefinition
.getValue();
268 final Matcher matcher
= NUMBER_PATTERN
.matcher(ret
.string
);
269 if (matcher
.matches()) {
270 String number
= matcher
.group(1);
271 ret
.number
= Integer
.parseInt(number
);
275 Long cpuId
= (Long
) fAttributes
.get(CTFStrings
.CPU_ID
);
277 ret
.string
= ("CPU" + cpuId
.toString()); //$NON-NLS-1$
284 // ------------------------------------------------------------------------
286 // ------------------------------------------------------------------------
289 public boolean includes(long ts
) {
290 return (ts
>= fTimestampBegin
) && (ts
<= fTimestampEnd
);
294 public String
toString() {
295 return "StreamInputPacketIndexEntry [offsetBits=" + fOffsetBits
//$NON-NLS-1$
296 + ", timestampBegin=" + fTimestampBegin
+ ", timestampEnd=" //$NON-NLS-1$ //$NON-NLS-2$
297 + fTimestampEnd
+ "]"; //$NON-NLS-1$
300 // ------------------------------------------------------------------------
301 // Getters and Setters
302 // ------------------------------------------------------------------------
305 public long getOffsetBits() {
310 public long getPacketSizeBits() {
311 return fPacketSizeBits
;
315 public long getContentSizeBits() {
316 return fContentSizeBits
;
320 public long getTimestampBegin() {
321 return fTimestampBegin
;
325 public long getTimestampEnd() {
326 return fTimestampEnd
;
330 public long getLostEvents() {
335 * Add an attribute to this index entry
338 * The name of the attribute
340 * The value to insert
342 public void addAttribute(String field
, Object value
) {
343 fAttributes
.put(field
, value
);
347 public Object
lookupAttribute(String field
) {
348 return fAttributes
.get(field
);
352 public String
getTarget() {
357 public long getTargetId() {
362 public long getOffsetBytes() {
367 public long getPayloadStartBits() {
368 return fEndPacketHeaderBits
;