1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson
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
10 * Alexandre Montplaisir - Initial API and implementation
11 * Bernd Hufmann - Updated for source and model lookup interfaces
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Collections
;
20 import java
.util
.HashSet
;
21 import java
.util
.List
;
25 import org
.eclipse
.jdt
.annotation
.NonNull
;
26 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
27 import org
.eclipse
.jdt
.annotation
.Nullable
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.event
.IEventDeclaration
;
29 import org
.eclipse
.tracecompass
.ctf
.core
.event
.IEventDefinition
;
30 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.ICompositeDefinition
;
31 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.IDefinition
;
32 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.ICTFStream
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfCustomAttributes
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventType
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEvent
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventField
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.event
.lookup
.ITmfModelLookup
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
42 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.CtfConstants
;
43 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.CtfTmfTrace
;
46 * A wrapper class around CTF's Event Definition/Declaration that maps all types
47 * of Declaration to native Java types.
49 * @author Alexandre Montplaisir
52 public class CtfTmfEvent
extends TmfEvent
53 implements ITmfModelLookup
, ITmfCustomAttributes
{
55 // ------------------------------------------------------------------------
57 // ------------------------------------------------------------------------
59 private static final String EMPTY_CTF_EVENT_NAME
= "Empty CTF event"; //$NON-NLS-1$
61 // ------------------------------------------------------------------------
63 // Not part of this event's "definition", but used to populate lazy-loaded
65 // ------------------------------------------------------------------------
67 private final @Nullable IEventDeclaration fEventDeclaration
;
68 private final IEventDefinition fEvent
;
70 // ------------------------------------------------------------------------
72 // ------------------------------------------------------------------------
74 /* Fields that are introduced by and part of this event's definition. */
75 private final int fSourceCpu
;
76 private final String fChannel
;
79 * Field to override {@link TmfEvent#getName()}, to bypass the type-getting
81 private final String fEventName
;
83 /** Lazy-loaded field containing the event's payload */
84 private transient @Nullable ITmfEventField fContent
;
86 /** Lazy-loaded field for the type, overriding TmfEvent's field */
87 private transient @Nullable CtfTmfEventType fEventType
;
89 private final @Nullable ICTFStream fStream
;
90 private final Map
<String
, Object
> fPacketAttributes
;
92 // ------------------------------------------------------------------------
94 // ------------------------------------------------------------------------
97 * Constructor, used by {@link CtfTmfEventFactory#createEvent}.
99 * Only subclasses should call this. It is imperative that the subclass also
100 * has a constructor with the EXACT same parameter signature, because the
101 * factory will look for a constructor with the same arguments.
104 * The trace to which this event belongs
106 * The rank of the event
110 * The CTF channel of this event
114 * The event declaration
115 * @param eventDefinition
116 * The event definition
119 protected CtfTmfEvent(CtfTmfTrace trace
,
121 ITmfTimestamp timestamp
,
124 IEventDeclaration declaration
,
125 IEventDefinition eventDefinition
) {
130 * Event type. We don't use TmfEvent's field here, we
131 * re-implement getType().
135 * Content handled with a lazy-loaded field re-implemented in
140 fEventDeclaration
= declaration
;
142 fEventName
= checkNotNull(declaration
.getName());
143 fEvent
= eventDefinition
;
145 fStream
= fEvent
.getDeclaration().getStream();
146 fPacketAttributes
= eventDefinition
.getPacketAttributes();
150 * Inner constructor to create "null" events. Don't use this directly in
151 * normal usage, use {@link CtfTmfEventFactory#getNullEvent(CtfTmfTrace)} to
152 * get an instance of an empty event.
154 * There is no need to give higher visibility to this method than package
158 * The trace associated with this event
160 CtfTmfEvent(CtfTmfTrace trace
) {
162 ITmfContext
.UNKNOWN_RANK
,
163 TmfTimestamp
.fromNanos(-1),
165 new TmfEventField("", null, new CtfTmfEventField
[0])); //$NON-NLS-1$
167 fEventName
= EMPTY_CTF_EVENT_NAME
;
168 fEventDeclaration
= null;
169 fEvent
= NullEventDefinition
.INSTANCE
;
170 fChannel
= ""; //$NON-NLS-1$
172 fPacketAttributes
= Collections
.EMPTY_MAP
;
176 * Default constructor. Do not use directly, but it needs to be present
177 * because it's used in extension points, and the framework will use this
178 * constructor to get the class type.
180 * @deprecated Should not be called by normal code
183 public CtfTmfEvent() {
186 fEventName
= EMPTY_CTF_EVENT_NAME
;
187 fEventDeclaration
= null;
188 fEvent
= NullEventDefinition
.INSTANCE
;
189 fChannel
= ""; //$NON-NLS-1$
191 fPacketAttributes
= Collections
.EMPTY_MAP
;
194 // ------------------------------------------------------------------------
195 // Getters/Setters/Predicates
196 // ------------------------------------------------------------------------
199 * Gets the cpu core the event was recorded on.
201 * @return The cpu id for a given source. In lttng it's from CPUINFO
203 public int getCPU() {
208 * Return the CTF trace's channel from which this event originates.
210 * @return The event's channel
213 public String
getChannel() {
218 * Return this event's reference.
220 * @return The event's reference
221 * @deprecated This method was replaced by {@link #getChannel()}.
224 public String
getReference() {
231 * @return the stream ID or -1 if the stream is null
234 public long getStreamId() {
235 ICTFStream stream
= fStream
;
236 if (stream
== null) {
239 return stream
.getId();
242 // ------------------------------------------------------------------------
244 // ------------------------------------------------------------------------
247 public CtfTmfTrace
getTrace() {
249 * Should be of the right type, since we take a CtfTmfTrace at the
252 return (CtfTmfTrace
) super.getTrace();
256 public synchronized ITmfEventType
getType() {
257 CtfTmfEventType type
= fEventType
;
259 type
= new CtfTmfEventType(fEventName
, getContent());
262 * Register the event type in the owning trace, but only if there is
265 getTrace().registerEventType(type
);
272 public String
getName() {
277 public synchronized ITmfEventField
getContent() {
278 ITmfEventField content
= fContent
;
279 if (content
== null) {
280 content
= new TmfEventField(
281 ITmfEventField
.ROOT_FIELD_ID
, null, parseFields(fEvent
));
288 * Extract the field information from the structDefinition haze-inducing
289 * mess, and put them into something ITmfEventField can cope with.
291 private static CtfTmfEventField
[] parseFields(IEventDefinition eventDef
) {
292 List
<CtfTmfEventField
> fields
= new ArrayList
<>();
294 ICompositeDefinition structFields
= eventDef
.getFields();
295 if (structFields
!= null) {
296 if (structFields
.getFieldNames() != null) {
297 for (String fn
: structFields
.getFieldNames()) {
298 fields
.add(CtfTmfEventField
.parseField((IDefinition
) structFields
.getDefinition(fn
), fn
));
302 /* Add context information as CtfTmfEventField */
303 ICompositeDefinition structContext
= eventDef
.getContext();
304 if (structContext
!= null) {
305 for (String contextName
: structContext
.getFieldNames()) {
306 /* Prefix field name */
307 String curContextName
= CtfConstants
.CONTEXT_FIELD_PREFIX
+ contextName
;
308 fields
.add(CtfTmfEventField
.parseField((IDefinition
) structContext
.getDefinition(contextName
), curContextName
));
312 return fields
.toArray(new @NonNull CtfTmfEventField
[fields
.size()]);
315 // ------------------------------------------------------------------------
316 // ITmfCustomAttributes
317 // ------------------------------------------------------------------------
320 public Set
<String
> listCustomAttributes() {
321 IEventDeclaration declaration
= fEventDeclaration
;
322 if (declaration
== null) {
323 return new HashSet
<>();
325 return declaration
.getCustomAttributes();
329 public @Nullable String
getCustomAttribute(@Nullable String name
) {
330 IEventDeclaration declaration
= fEventDeclaration
;
331 if (declaration
== null) {
334 return declaration
.getCustomAttribute(name
);
338 public @Nullable String
getModelUri() {
339 return getCustomAttribute(CtfConstants
.MODEL_URI_KEY
);
343 * Gets the packet attributes. The result is an instance of one of the
344 * following classes: <code>Entry<String, Long></code>, <code>Long</code>,
345 * <code>String</code> or <code>Double</code>. The map contains pairs of key
346 * and values where the key and value can never be null.
348 * @return gets the packet attributes
351 public Map
<String
, Object
> getPacketAttributes() {
352 return fPacketAttributes
;
355 // ------------------------------------------------------------------------
357 // ------------------------------------------------------------------------
360 public int hashCode() {
361 final int prime
= 31;
362 int result
= super.hashCode();
363 result
= prime
* result
+ getCPU();
364 result
= prime
* result
+ getChannel().hashCode();
369 public boolean equals(@Nullable Object obj
) {
370 if (!super.equals(obj
)) {
373 /* super.equals() checks that the classes are the same */
374 CtfTmfEvent other
= checkNotNull((CtfTmfEvent
) obj
);
375 if (getCPU() != other
.getCPU()) {
378 if (!getChannel().equals(other
.getChannel())) {