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
);
112 return new EventDefinition(
123 private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef
, long prevTimestamp
, StructDefinition eventPayload
) 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 } else if (eventHeaderDef
instanceof StructDefinition
) {
130 StructDefinition structDefinition
= (StructDefinition
) eventHeaderDef
;
131 def
= structDefinition
.lookupDefinition(CTFStrings
.TIMESTAMP
);
132 } else if (eventHeaderDef
!= null) {
133 throw new CTFIOException("Event header def is not a Struct or an Event Header"); //$NON-NLS-1$
135 if (def
== null && eventPayload
!= null) {
136 def
= eventPayload
.lookupDefinition(CTFStrings
.TIMESTAMP
);
138 if (def
instanceof IntegerDefinition
) {
139 IntegerDefinition timestampDef
= (IntegerDefinition
) def
;
140 timestamp
= calculateTimestamp(timestampDef
, prevTimestamp
);
146 public EventDefinition
createDefinition(CTFStreamInputReader streamInputReader
, @NonNull BitBuffer input
, long timestamp
) throws CTFException
{
147 StructDeclaration streamEventContextDecl
= streamInputReader
.getStreamEventContextDecl();
148 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(fStream
.getTrace(), ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
149 ICompositeDefinition packetContext
= streamInputReader
.getPacketReader().getCurrentPacketEventHeader();
150 StructDefinition eventContext
= fContext
!= null ? fContext
.createDefinition(fStream
.getTrace(), ILexicalScope
.CONTEXT
, input
) : null;
151 StructDefinition eventPayload
= fFields
!= null ? fFields
.createDefinition(fStream
.getTrace(), ILexicalScope
.FIELDS
, input
) : null;
153 // a bit lttng specific
154 // CTF doesn't require a timestamp,
155 // but it's passed to us
156 return new EventDefinition(
166 // ------------------------------------------------------------------------
167 // Getters/Setters/Predicates
168 // ------------------------------------------------------------------------
171 * Sets a name for an event Declaration
176 public void setName(String name
) {
181 public String
getName() {
186 * Sets the context for an event declaration (see CTF specification)
189 * the context in structdeclaration format
191 public void setContext(StructDeclaration context
) {
196 * Sets the fields of an event declaration
199 * the fields in structdeclaration format
201 public void setFields(StructDeclaration fields
) {
206 public StructDeclaration
getFields() {
211 public StructDeclaration
getContext() {
216 * Sets the id of an event declaration
221 public void setId(long id
) {
222 if (id
< 0 || id
> Integer
.MAX_VALUE
) {
223 throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
229 public Long
getId() {
230 return Long
.valueOf(fId
);
234 * Faster get id assuming you have less than a billion event types
236 * @return the event id
243 * Sets the stream of an event declaration
248 public void setStream(CTFStream stream
) {
253 public CTFStream
getStream() {
258 * Is the name of the event declaration set
260 * @return is the name set?
262 public boolean nameIsSet() {
263 return fName
!= null;
269 * @return is the context set
271 public boolean contextIsSet() {
272 return fContext
!= null;
278 * @return Is the field set?
280 public boolean fieldsIsSet() {
281 return fFields
!= null;
287 * @return is the id set?
289 public boolean idIsSet() {
290 return (fId
!= UNSET_EVENT_ID
);
296 * @return is the stream set?
298 public boolean streamIsSet() {
299 return fStream
!= null;
303 public long getLogLevel() {
313 public void setLogLevel(long level
) {
318 public Set
<String
> getCustomAttributes() {
319 return fCustomAttributes
.keySet();
323 public String
getCustomAttribute(String key
) {
324 return fCustomAttributes
.get(key
);
328 * Sets a custom attribute value.
331 * the key of the attribute
333 * the value of the attribute
335 public void setCustomAttribute(String key
, String value
) {
336 fCustomAttributes
.put(key
, value
);
340 * Calculates the timestamp value of the event, possibly using the timestamp
341 * from the last event.
343 * @param timestampDef
344 * Integer definition of the timestamp.
345 * @return The calculated timestamp value.
347 private static long calculateTimestamp(IntegerDefinition timestampDef
, long lastTimestamp
) {
348 int len
= timestampDef
.getDeclaration().getLength();
349 final long value
= timestampDef
.getValue();
351 return calculateTimestamp(value
, len
, lastTimestamp
);
354 private static long calculateTimestamp(final long value
, int len
, long prevTimestamp
) {
357 long lastTimestamp
= prevTimestamp
;
359 * If the timestamp length is 64 bits, it is a full timestamp.
361 if (len
== Long
.SIZE
) {
362 lastTimestamp
= value
;
363 return lastTimestamp
;
367 * Bit mask to keep / remove all old / new bits.
369 majorasbitmask
= (1L << len
) - 1;
372 * If the new value is smaller than the corresponding bits of the last
373 * timestamp, we assume an overflow of the compact representation.
376 if (newval
< (lastTimestamp
& majorasbitmask
)) {
377 newval
= newval
+ (1L << len
);
380 /* Keep only the high bits of the old value */
381 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
383 /* Then add the low bits of the new value */
384 lastTimestamp
= lastTimestamp
+ newval
;
386 return lastTimestamp
;
389 // ------------------------------------------------------------------------
391 // ------------------------------------------------------------------------
394 public boolean equals(Object obj
) {
401 if (!(obj
instanceof EventDeclaration
)) {
404 EventDeclaration other
= (EventDeclaration
) obj
;
405 if (fContext
== null) {
406 if (other
.fContext
!= null) {
409 } else if (!fContext
.equals(other
.fContext
)) {
412 if (fFields
== null) {
413 if (other
.fFields
!= null) {
416 } else if (!fFields
.equals(other
.fFields
)) {
419 if (fId
!= (other
.fId
)) {
423 if (other
.fName
!= null) {
426 } else if (!fName
.equals(other
.fName
)) {
429 if (fStream
== null) {
430 if (other
.fStream
!= null) {
433 } else if (!fStream
.equals(other
.fStream
)) {
436 if (!fCustomAttributes
.equals(other
.fCustomAttributes
)) {
443 public int hashCode() {
444 final int prime
= 31;
446 result
= (prime
* result
)
447 + ((fContext
== null) ?
0 : fContext
.hashCode());
448 result
= (prime
* result
) + ((fFields
== null) ?
0 : fFields
.hashCode());
449 result
= (prime
* result
) + fId
;
450 result
= (prime
* result
) + ((fName
== null) ?
0 : fName
.hashCode());
451 result
= (prime
* result
) + ((fStream
== null) ?
0 : fStream
.hashCode());
452 result
= (prime
* result
) + fCustomAttributes
.hashCode();