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
.common
.core
.NonNullUtils
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.CTFStrings
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.event
.EventDefinition
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.IEventDeclaration
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.ILexicalScope
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.Definition
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.ICompositeDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IntegerDefinition
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDeclaration
;
32 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDefinition
;
33 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFIOException
;
34 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFStreamInputReader
;
35 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTrace
;
36 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.ICTFPacketDescriptor
;
37 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.types
.composite
.EventHeaderDefinition
;
38 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.trace
.CTFStream
;
41 * Representation of one type of event. A bit like "int" or "long" but for trace
44 public class EventDeclaration
implements IEventDeclaration
{
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
56 * Event context structure declaration
58 private StructDeclaration fContext
= null;
61 * Event fields structure declaration
63 private StructDeclaration fFields
= null;
66 * Stream to which belongs this event.
68 private @Nullable CTFStream fStream
= null;
71 * Loglevel of an event
73 private long fLogLevel
;
75 /** Map of this event type's custom CTF attributes */
76 private final Map
<String
, String
> fCustomAttributes
= new HashMap
<>();
78 private int fId
= (int) UNSET_EVENT_ID
;
80 // ------------------------------------------------------------------------
82 // ------------------------------------------------------------------------
85 * Default constructor. Use the setters afterwards to set the fields
88 public EventDeclaration() {
92 * Creates an instance of EventDefinition corresponding to this declaration.
94 * @param streamEventContextDecl
96 * @param packetDescriptor
98 * @param packetContext
100 * @param eventHeaderDef
101 * The event header definition
103 * the bitbuffer input source
104 * @param prevTimestamp
105 * The timestamp when the event was taken
106 * @return A new EventDefinition.
107 * @throws CTFException
108 * As a bitbuffer is used to read, it could have wrapped
111 public EventDefinition
createDefinition(StructDeclaration streamEventContextDecl
, ICTFPacketDescriptor packetDescriptor
, ICompositeDefinition packetContext
, ICompositeDefinition eventHeaderDef
, @NonNull BitBuffer input
, long prevTimestamp
)
112 throws CTFException
{
113 final CTFStream stream
= fStream
;
114 final CTFTrace trace
= stream
== null ?
null : stream
.getTrace();
115 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(trace
, ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
116 StructDefinition eventContext
= fContext
!= null ? fContext
.createFieldDefinition(eventHeaderDef
, trace
, ILexicalScope
.CONTEXT
, input
) : null;
117 StructDefinition eventPayload
= fFields
!= null ? fFields
.createFieldDefinition(eventHeaderDef
, trace
, ILexicalScope
.FIELDS
, input
) : null;
118 long timestamp
= calculateTimestamp(eventHeaderDef
, prevTimestamp
, eventPayload
, eventContext
);
120 int cpu
= (int) packetDescriptor
.getTargetId();
121 return new EventDefinition(
132 private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef
, long prevTimestamp
, StructDefinition eventPayload
, StructDefinition eventContext
) throws CTFIOException
{
134 Definition def
= null;
135 if (eventHeaderDef
instanceof EventHeaderDefinition
) {
136 EventHeaderDefinition eventHeaderDefinition
= (EventHeaderDefinition
) eventHeaderDef
;
137 timestamp
= calculateTimestamp(eventHeaderDefinition
.getTimestamp(), eventHeaderDefinition
.getTimestampLength(), prevTimestamp
);
138 def
= eventHeaderDefinition
;
139 } else if (eventHeaderDef
instanceof StructDefinition
) {
140 StructDefinition structDefinition
= (StructDefinition
) eventHeaderDef
;
141 def
= structDefinition
.lookupDefinition(CTFStrings
.TIMESTAMP
);
142 } else if (eventHeaderDef
!= null) {
143 throw new CTFIOException("Event header def is not a Struct or an Event Header"); //$NON-NLS-1$
145 if (def
== null && eventPayload
!= null) {
146 def
= eventPayload
.lookupDefinition(CTFStrings
.TIMESTAMP
);
148 if (def
== null && eventContext
!= null) {
149 def
= eventContext
.lookupDefinition(CTFStrings
.TIMESTAMP
);
151 if (def
instanceof IntegerDefinition
) {
152 IntegerDefinition timestampDef
= (IntegerDefinition
) def
;
153 timestamp
= calculateTimestamp(timestampDef
, prevTimestamp
);
159 public EventDefinition
createDefinition(CTFStreamInputReader streamInputReader
, @NonNull BitBuffer input
, long timestamp
) throws CTFException
{
160 StructDeclaration streamEventContextDecl
= streamInputReader
.getStreamEventContextDecl();
161 final @Nullable CTFStream stream
= fStream
;
162 final CTFTrace trace
= stream
== null ?
null : stream
.getTrace();
163 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(trace
, ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
164 ICompositeDefinition packetContext
= streamInputReader
.getCurrentPacketReader().getCurrentPacketEventHeader();
165 StructDefinition eventContext
= fContext
!= null ? fContext
.createDefinition(trace
, ILexicalScope
.CONTEXT
, input
) : null;
166 StructDefinition eventPayload
= fFields
!= null ? fFields
.createDefinition(trace
, ILexicalScope
.FIELDS
, input
) : null;
168 // a bit lttng specific
169 // CTF doesn't require a timestamp,
170 // but it's passed to us
171 return new EventDefinition(
173 streamInputReader
.getCPU(),
182 // ------------------------------------------------------------------------
183 // Getters/Setters/Predicates
184 // ------------------------------------------------------------------------
187 * Sets a name for an event Declaration
192 public void setName(String name
) {
197 public String
getName() {
202 * Sets the context for an event declaration (see CTF specification)
205 * the context in structdeclaration format
207 public void setContext(StructDeclaration context
) {
212 * Sets the fields of an event declaration
215 * the fields in structdeclaration format
217 public void setFields(StructDeclaration fields
) {
222 public StructDeclaration
getFields() {
227 public StructDeclaration
getContext() {
232 * Sets the id of an event declaration
237 public void setId(long id
) {
238 if (id
< 0 || id
> Integer
.MAX_VALUE
) {
239 throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
245 public Long
getId() {
246 return Long
.valueOf(fId
);
250 * Faster get id assuming you have less than a billion event types
252 * @return the event id
259 * Sets the stream of an event declaration
264 public void setStream(CTFStream stream
) {
269 public CTFStream
getStream() {
274 * Is the name of the event declaration set
276 * @return is the name set?
278 public boolean nameIsSet() {
279 return fName
!= null;
285 * @return is the context set
287 public boolean contextIsSet() {
288 return fContext
!= null;
294 * @return Is the field set?
296 public boolean fieldsIsSet() {
297 return fFields
!= null;
303 * @return is the id set?
305 public boolean idIsSet() {
306 return (fId
!= UNSET_EVENT_ID
);
312 * @return is the stream set?
314 public boolean streamIsSet() {
315 return fStream
!= null;
319 public long getLogLevel() {
329 public void setLogLevel(long level
) {
334 public Set
<String
> getCustomAttributes() {
335 return fCustomAttributes
.keySet();
339 public String
getCustomAttribute(String key
) {
340 return fCustomAttributes
.get(key
);
344 * Sets a custom attribute value.
347 * the key of the attribute
349 * the value of the attribute
351 public void setCustomAttribute(String key
, String value
) {
352 fCustomAttributes
.put(key
, value
);
356 * Calculates the timestamp value of the event, possibly using the timestamp
357 * from the last event.
359 * @param timestampDef
360 * Integer definition of the timestamp.
361 * @return The calculated timestamp value.
363 private static long calculateTimestamp(IntegerDefinition timestampDef
, long lastTimestamp
) {
364 int len
= timestampDef
.getDeclaration().getLength();
365 final long value
= timestampDef
.getValue();
367 return calculateTimestamp(value
, len
, lastTimestamp
);
370 private static long calculateTimestamp(final long value
, int len
, long prevTimestamp
) {
373 long lastTimestamp
= prevTimestamp
;
375 * If the timestamp length is 64 bits, it is a full timestamp.
377 if (len
== Long
.SIZE
) {
378 lastTimestamp
= value
;
379 return lastTimestamp
;
383 * Bit mask to keep / remove all old / new bits.
385 majorasbitmask
= (1L << len
) - 1;
388 * If the new value is smaller than the corresponding bits of the last
389 * timestamp, we assume an overflow of the compact representation.
392 if (newval
< (lastTimestamp
& majorasbitmask
)) {
393 newval
= newval
+ (1L << len
);
396 /* Keep only the high bits of the old value */
397 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
399 /* Then add the low bits of the new value */
400 lastTimestamp
= lastTimestamp
+ newval
;
402 return lastTimestamp
;
405 // ------------------------------------------------------------------------
407 // ------------------------------------------------------------------------
410 public boolean equals(Object obj
) {
417 if (!(obj
instanceof EventDeclaration
)) {
420 EventDeclaration other
= (EventDeclaration
) obj
;
421 if (fId
!= (other
.fId
)) {
424 if (!NonNullUtils
.equalsNullable(fContext
, other
.fContext
)) {
427 if (!NonNullUtils
.equalsNullable(fFields
, other
.fFields
)) {
430 if (!NonNullUtils
.equalsNullable(fName
, other
.fName
)) {
433 if (!NonNullUtils
.equalsNullable(fStream
, 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 final CTFStream stream
= fStream
;
452 result
= (prime
* result
) + ((stream
== null) ?
0 : stream
.hashCode());
453 result
= (prime
* result
) + fCustomAttributes
.hashCode();