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(
133 private static long calculateTimestamp(@Nullable ICompositeDefinition eventHeaderDef
, long prevTimestamp
, StructDefinition eventPayload
, StructDefinition eventContext
) throws CTFIOException
{
135 Definition def
= null;
136 if (eventHeaderDef
instanceof EventHeaderDefinition
) {
137 EventHeaderDefinition eventHeaderDefinition
= (EventHeaderDefinition
) eventHeaderDef
;
138 timestamp
= calculateTimestamp(eventHeaderDefinition
.getTimestamp(), eventHeaderDefinition
.getTimestampLength(), prevTimestamp
);
139 def
= eventHeaderDefinition
;
140 } else if (eventHeaderDef
instanceof StructDefinition
) {
141 StructDefinition structDefinition
= (StructDefinition
) eventHeaderDef
;
142 def
= structDefinition
.lookupDefinition(CTFStrings
.TIMESTAMP
);
143 } else if (eventHeaderDef
!= null) {
144 throw new CTFIOException("Event header def is not a Struct or an Event Header"); //$NON-NLS-1$
146 if (def
== null && eventPayload
!= null) {
147 def
= eventPayload
.lookupDefinition(CTFStrings
.TIMESTAMP
);
149 if (def
== null && eventContext
!= null) {
150 def
= eventContext
.lookupDefinition(CTFStrings
.TIMESTAMP
);
152 if (def
instanceof IntegerDefinition
) {
153 IntegerDefinition timestampDef
= (IntegerDefinition
) def
;
154 timestamp
= calculateTimestamp(timestampDef
, prevTimestamp
);
160 public EventDefinition
createDefinition(CTFStreamInputReader streamInputReader
, @NonNull BitBuffer input
, long timestamp
) throws CTFException
{
161 StructDeclaration streamEventContextDecl
= streamInputReader
.getStreamEventContextDecl();
162 final @Nullable CTFStream stream
= fStream
;
163 final CTFTrace trace
= stream
== null ?
null : stream
.getTrace();
164 StructDefinition streamEventContext
= streamEventContextDecl
!= null ? streamEventContextDecl
.createDefinition(trace
, ILexicalScope
.STREAM_EVENT_CONTEXT
, input
) : null;
165 ICompositeDefinition packetContext
= streamInputReader
.getCurrentPacketReader().getCurrentPacketEventHeader();
166 StructDefinition eventContext
= fContext
!= null ? fContext
.createDefinition(trace
, ILexicalScope
.CONTEXT
, input
) : null;
167 StructDefinition eventPayload
= fFields
!= null ? fFields
.createDefinition(trace
, ILexicalScope
.FIELDS
, input
) : null;
169 // a bit lttng specific
170 // CTF doesn't require a timestamp,
171 // but it's passed to us
172 return new EventDefinition(
174 streamInputReader
.getCPU(),
181 streamInputReader
.getCurrentPacketReader().getCurrentPacket());
184 // ------------------------------------------------------------------------
185 // Getters/Setters/Predicates
186 // ------------------------------------------------------------------------
189 * Sets a name for an event Declaration
194 public void setName(String name
) {
199 public String
getName() {
204 * Sets the context for an event declaration (see CTF specification)
207 * the context in structdeclaration format
209 public void setContext(StructDeclaration context
) {
214 * Sets the fields of an event declaration
217 * the fields in structdeclaration format
219 public void setFields(StructDeclaration fields
) {
224 public StructDeclaration
getFields() {
229 public StructDeclaration
getContext() {
234 * Sets the id of an event declaration
239 public void setId(long id
) {
240 if (id
< 0 || id
> Integer
.MAX_VALUE
) {
241 throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
247 public Long
getId() {
248 return Long
.valueOf(fId
);
252 * Faster get id assuming you have less than a billion event types
254 * @return the event id
261 * Sets the stream of an event declaration
266 public void setStream(CTFStream stream
) {
271 public CTFStream
getStream() {
276 * Is the name of the event declaration set
278 * @return is the name set?
280 public boolean nameIsSet() {
281 return fName
!= null;
287 * @return is the context set
289 public boolean contextIsSet() {
290 return fContext
!= null;
296 * @return Is the field set?
298 public boolean fieldsIsSet() {
299 return fFields
!= null;
305 * @return is the id set?
307 public boolean idIsSet() {
308 return (fId
!= UNSET_EVENT_ID
);
314 * @return is the stream set?
316 public boolean streamIsSet() {
317 return fStream
!= null;
321 public long getLogLevel() {
331 public void setLogLevel(long level
) {
336 public Set
<String
> getCustomAttributes() {
337 return fCustomAttributes
.keySet();
341 public String
getCustomAttribute(String key
) {
342 return fCustomAttributes
.get(key
);
346 * Sets a custom attribute value.
349 * the key of the attribute
351 * the value of the attribute
353 public void setCustomAttribute(String key
, String value
) {
354 fCustomAttributes
.put(key
, value
);
358 * Calculates the timestamp value of the event, possibly using the timestamp
359 * from the last event.
361 * @param timestampDef
362 * Integer definition of the timestamp.
363 * @return The calculated timestamp value.
365 private static long calculateTimestamp(IntegerDefinition timestampDef
, long lastTimestamp
) {
366 int len
= timestampDef
.getDeclaration().getLength();
367 final long value
= timestampDef
.getValue();
369 return calculateTimestamp(value
, len
, lastTimestamp
);
372 private static long calculateTimestamp(final long value
, int len
, long prevTimestamp
) {
375 long lastTimestamp
= prevTimestamp
;
377 * If the timestamp length is 64 bits, it is a full timestamp.
379 if (len
== Long
.SIZE
) {
380 lastTimestamp
= value
;
381 return lastTimestamp
;
385 * Bit mask to keep / remove all old / new bits.
387 majorasbitmask
= (1L << len
) - 1;
390 * If the new value is smaller than the corresponding bits of the last
391 * timestamp, we assume an overflow of the compact representation.
394 if (newval
< (lastTimestamp
& majorasbitmask
)) {
395 newval
= newval
+ (1L << len
);
398 /* Keep only the high bits of the old value */
399 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
401 /* Then add the low bits of the new value */
402 lastTimestamp
= lastTimestamp
+ newval
;
404 return lastTimestamp
;
407 // ------------------------------------------------------------------------
409 // ------------------------------------------------------------------------
412 public boolean equals(Object obj
) {
419 if (!(obj
instanceof EventDeclaration
)) {
422 EventDeclaration other
= (EventDeclaration
) obj
;
423 if (fId
!= (other
.fId
)) {
426 if (!NonNullUtils
.equalsNullable(fContext
, other
.fContext
)) {
429 if (!NonNullUtils
.equalsNullable(fFields
, other
.fFields
)) {
432 if (!NonNullUtils
.equalsNullable(fName
, other
.fName
)) {
435 if (!NonNullUtils
.equalsNullable(fStream
, other
.fStream
)) {
438 if (!fCustomAttributes
.equals(other
.fCustomAttributes
)) {
445 public int hashCode() {
446 final int prime
= 31;
448 result
= (prime
* result
)
449 + ((fContext
== null) ?
0 : fContext
.hashCode());
450 result
= (prime
* result
) + ((fFields
== null) ?
0 : fFields
.hashCode());
451 result
= (prime
* result
) + fId
;
452 result
= (prime
* result
) + ((fName
== null) ?
0 : fName
.hashCode());
453 final CTFStream stream
= fStream
;
454 result
= (prime
* result
) + ((stream
== null) ?
0 : stream
.hashCode());
455 result
= (prime
* result
) + fCustomAttributes
.hashCode();