1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 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
.event
;
15 import java
.util
.HashMap
;
19 import org
.eclipse
.jdt
.annotation
.NonNull
;
20 import org
.eclipse
.jdt
.annotation
.Nullable
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.CTFStrings
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.event
.EventDefinition
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.IEventDeclaration
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.ILexicalScope
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.Definition
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.ICompositeDefinition
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDeclaration
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDefinition
;
32 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFIOException
;
33 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFStream
;
34 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFStreamInputReader
;
35 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.types
.composite
.EventHeaderDefinition
;
38 * Representation of one type of event. A bit like "int" or "long" but for trace
41 public class EventDeclaration
implements IEventDeclaration
{
43 // ------------------------------------------------------------------------
45 // ------------------------------------------------------------------------
53 * Event context structure declaration
55 private StructDeclaration fContext
= null;
58 * Event fields structure declaration
60 private StructDeclaration fFields
= null;
63 * Stream to which belongs this event.
65 private CTFStream fStream
= null;
68 * Loglevel of an event
70 private long fLogLevel
;
72 /** Map of this event type's custom CTF attributes */
73 private final Map
<String
, String
> fCustomAttributes
= new HashMap
<>();
75 private int fId
= (int) UNSET_EVENT_ID
;
77 // ------------------------------------------------------------------------
79 // ------------------------------------------------------------------------
82 * Default constructor. Use the setters afterwards to set the fields
85 public EventDeclaration() {
89 * Creates an instance of EventDefinition corresponding to this declaration.
91 * @param streamInputReader
92 * The StreamInputReader for which this definition is created.
93 * @param eventHeaderDef
94 * The event header definition
96 * the bitbuffer input source
97 * @param prevTimestamp
98 * The timestamp when the event was taken
99 * @return A new EventDefinition.
100 * @throws CTFException
101 * As a bitbuffer is used to read, it could have wrapped
104 public EventDefinition
createDefinition(CTFStreamInputReader streamInputReader
, ICompositeDefinition eventHeaderDef
, @NonNull BitBuffer input
, long prevTimestamp
) throws CTFException
{
105 StructDeclaration streamEventContextDecl
= streamInputReader
.getStreamEventContextDecl();
106 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(fStream
.getTrace(), ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
107 ICompositeDefinition packetContext
= streamInputReader
.getPacketReader().getCurrentPacketEventHeader();
108 StructDefinition eventContext
= fContext
!= null ? fContext
.createFieldDefinition(eventHeaderDef
, fStream
.getTrace(), ILexicalScope
.CONTEXT
, input
) : null;
109 StructDefinition eventPayload
= fFields
!= null ? fFields
.createFieldDefinition(eventHeaderDef
, fStream
.getTrace(), ILexicalScope
.FIELDS
, input
) : null;
110 long timestamp
= calculateTimestamp(eventHeaderDef
, prevTimestamp
, eventPayload
, eventContext
);
112 return new EventDefinition(
123 private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef
, long prevTimestamp
, StructDefinition eventPayload
, StructDefinition eventContext
) throws CTFIOException
{
125 Definition def
= null;
126 if (eventHeaderDef
instanceof EventHeaderDefinition
) {
127 EventHeaderDefinition eventHeaderDefinition
= (EventHeaderDefinition
) eventHeaderDef
;
128 timestamp
= calculateTimestamp(eventHeaderDefinition
.getTimestamp(), eventHeaderDefinition
.getTimestampLength(), prevTimestamp
);
129 def
= eventHeaderDefinition
;
130 } else if (eventHeaderDef
instanceof StructDefinition
) {
131 StructDefinition structDefinition
= (StructDefinition
) eventHeaderDef
;
132 def
= structDefinition
.lookupDefinition(CTFStrings
.TIMESTAMP
);
133 } else if (eventHeaderDef
!= null) {
134 throw new CTFIOException("Event header def is not a Struct or an Event Header"); //$NON-NLS-1$
136 if (def
== null && eventPayload
!= null) {
137 def
= eventPayload
.lookupDefinition(CTFStrings
.TIMESTAMP
);
139 if (def
== null && eventContext
!= null) {
140 def
= eventContext
.lookupDefinition(CTFStrings
.TIMESTAMP
);
142 if (def
instanceof IntegerDefinition
) {
143 IntegerDefinition timestampDef
= (IntegerDefinition
) def
;
144 timestamp
= calculateTimestamp(timestampDef
, prevTimestamp
);
150 public EventDefinition
createDefinition(CTFStreamInputReader streamInputReader
, @NonNull BitBuffer input
, long timestamp
) throws CTFException
{
151 StructDeclaration streamEventContextDecl
= streamInputReader
.getStreamEventContextDecl();
152 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(fStream
.getTrace(), ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
153 ICompositeDefinition packetContext
= streamInputReader
.getPacketReader().getCurrentPacketEventHeader();
154 StructDefinition eventContext
= fContext
!= null ? fContext
.createDefinition(fStream
.getTrace(), ILexicalScope
.CONTEXT
, input
) : null;
155 StructDefinition eventPayload
= fFields
!= null ? fFields
.createDefinition(fStream
.getTrace(), ILexicalScope
.FIELDS
, input
) : null;
157 // a bit lttng specific
158 // CTF doesn't require a timestamp,
159 // but it's passed to us
160 return new EventDefinition(
170 // ------------------------------------------------------------------------
171 // Getters/Setters/Predicates
172 // ------------------------------------------------------------------------
175 * Sets a name for an event Declaration
180 public void setName(String name
) {
185 public String
getName() {
190 * Sets the context for an event declaration (see CTF specification)
193 * the context in structdeclaration format
195 public void setContext(StructDeclaration context
) {
200 * Sets the fields of an event declaration
203 * the fields in structdeclaration format
205 public void setFields(StructDeclaration fields
) {
210 public StructDeclaration
getFields() {
215 public StructDeclaration
getContext() {
220 * Sets the id of an event declaration
225 public void setId(long id
) {
226 if (id
< 0 || id
> Integer
.MAX_VALUE
) {
227 throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
233 public Long
getId() {
234 return Long
.valueOf(fId
);
238 * Faster get id assuming you have less than a billion event types
240 * @return the event id
247 * Sets the stream of an event declaration
252 public void setStream(CTFStream stream
) {
257 public CTFStream
getStream() {
262 * Is the name of the event declaration set
264 * @return is the name set?
266 public boolean nameIsSet() {
267 return fName
!= null;
273 * @return is the context set
275 public boolean contextIsSet() {
276 return fContext
!= null;
282 * @return Is the field set?
284 public boolean fieldsIsSet() {
285 return fFields
!= null;
291 * @return is the id set?
293 public boolean idIsSet() {
294 return (fId
!= UNSET_EVENT_ID
);
300 * @return is the stream set?
302 public boolean streamIsSet() {
303 return fStream
!= null;
307 public long getLogLevel() {
317 public void setLogLevel(long level
) {
322 public Set
<String
> getCustomAttributes() {
323 return fCustomAttributes
.keySet();
327 public String
getCustomAttribute(String key
) {
328 return fCustomAttributes
.get(key
);
332 * Sets a custom attribute value.
335 * the key of the attribute
337 * the value of the attribute
339 public void setCustomAttribute(String key
, String value
) {
340 fCustomAttributes
.put(key
, value
);
344 * Calculates the timestamp value of the event, possibly using the timestamp
345 * from the last event.
347 * @param timestampDef
348 * Integer definition of the timestamp.
349 * @return The calculated timestamp value.
351 private static long calculateTimestamp(IntegerDefinition timestampDef
, long lastTimestamp
) {
352 int len
= timestampDef
.getDeclaration().getLength();
353 final long value
= timestampDef
.getValue();
355 return calculateTimestamp(value
, len
, lastTimestamp
);
358 private static long calculateTimestamp(final long value
, int len
, long prevTimestamp
) {
361 long lastTimestamp
= prevTimestamp
;
363 * If the timestamp length is 64 bits, it is a full timestamp.
365 if (len
== Long
.SIZE
) {
366 lastTimestamp
= value
;
367 return lastTimestamp
;
371 * Bit mask to keep / remove all old / new bits.
373 majorasbitmask
= (1L << len
) - 1;
376 * If the new value is smaller than the corresponding bits of the last
377 * timestamp, we assume an overflow of the compact representation.
380 if (newval
< (lastTimestamp
& majorasbitmask
)) {
381 newval
= newval
+ (1L << len
);
384 /* Keep only the high bits of the old value */
385 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
387 /* Then add the low bits of the new value */
388 lastTimestamp
= lastTimestamp
+ newval
;
390 return lastTimestamp
;
393 // ------------------------------------------------------------------------
395 // ------------------------------------------------------------------------
398 public boolean equals(Object obj
) {
405 if (!(obj
instanceof EventDeclaration
)) {
408 EventDeclaration other
= (EventDeclaration
) obj
;
409 if (fContext
== null) {
410 if (other
.fContext
!= null) {
413 } else if (!fContext
.equals(other
.fContext
)) {
416 if (fFields
== null) {
417 if (other
.fFields
!= null) {
420 } else if (!fFields
.equals(other
.fFields
)) {
423 if (fId
!= (other
.fId
)) {
427 if (other
.fName
!= null) {
430 } else if (!fName
.equals(other
.fName
)) {
433 if (fStream
== null) {
434 if (other
.fStream
!= null) {
437 } else if (!fStream
.equals(other
.fStream
)) {
440 if (!fCustomAttributes
.equals(other
.fCustomAttributes
)) {
447 public int hashCode() {
448 final int prime
= 31;
450 result
= (prime
* result
)
451 + ((fContext
== null) ?
0 : fContext
.hashCode());
452 result
= (prime
* result
) + ((fFields
== null) ?
0 : fFields
.hashCode());
453 result
= (prime
* result
) + fId
;
454 result
= (prime
* result
) + ((fName
== null) ?
0 : fName
.hashCode());
455 result
= (prime
* result
) + ((fStream
== null) ?
0 : fStream
.hashCode());
456 result
= (prime
* result
) + fCustomAttributes
.hashCode();