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
.TmfNanoTimestamp
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
41 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.CtfConstants
;
42 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.CtfTmfTrace
;
45 * A wrapper class around CTF's Event Definition/Declaration that maps all types
46 * of Declaration to native Java types.
48 * @author Alexandre Montplaisir
51 public class CtfTmfEvent
extends TmfEvent
52 implements ITmfModelLookup
, ITmfCustomAttributes
{
54 // ------------------------------------------------------------------------
56 // ------------------------------------------------------------------------
58 private static final String EMPTY_CTF_EVENT_NAME
= "Empty CTF event"; //$NON-NLS-1$
60 // ------------------------------------------------------------------------
62 // Not part of this event's "definition", but used to populate lazy-loaded
64 // ------------------------------------------------------------------------
66 private final @Nullable IEventDeclaration fEventDeclaration
;
67 private final IEventDefinition fEvent
;
69 // ------------------------------------------------------------------------
71 // ------------------------------------------------------------------------
73 /* Fields that are introduced by and part of this event's definition. */
74 private final int fSourceCpu
;
75 private final String fChannel
;
78 * Field to override {@link TmfEvent#getName()}, to bypass the type-getting
80 private final String fEventName
;
82 /** Lazy-loaded field containing the event's payload */
83 private transient @Nullable ITmfEventField fContent
;
85 /** Lazy-loaded field for the type, overriding TmfEvent's field */
86 private transient @Nullable CtfTmfEventType fEventType
;
88 private final @Nullable ICTFStream fStream
;
89 private final Map
<String
, Object
> fPacketAttributes
;
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
96 * Constructor, used by {@link CtfTmfEventFactory#createEvent}.
98 * Only subclasses should call this. It is imperative that the subclass also
99 * has a constructor with the EXACT same parameter signature, because the
100 * factory will look for a constructor with the same arguments.
103 * The trace to which this event belongs
105 * The rank of the event
109 * The CTF channel of this event
113 * The event declaration
114 * @param eventDefinition
115 * The event definition
118 protected CtfTmfEvent(CtfTmfTrace trace
,
120 TmfNanoTimestamp timestamp
,
123 IEventDeclaration declaration
,
124 IEventDefinition eventDefinition
) {
129 * Event type. We don't use TmfEvent's field here, we
130 * re-implement getType().
134 * Content handled with a lazy-loaded field re-implemented in
139 fEventDeclaration
= declaration
;
141 fEventName
= checkNotNull(declaration
.getName());
142 fEvent
= eventDefinition
;
144 fStream
= fEvent
.getDeclaration().getStream();
145 fPacketAttributes
= eventDefinition
.getPacketAttributes();
149 * Inner constructor to create "null" events. Don't use this directly in
150 * normal usage, use {@link CtfTmfEventFactory#getNullEvent(CtfTmfTrace)} to
151 * get an instance of an empty event.
153 * There is no need to give higher visibility to this method than package
157 * The trace associated with this event
159 CtfTmfEvent(CtfTmfTrace trace
) {
161 ITmfContext
.UNKNOWN_RANK
,
162 new TmfNanoTimestamp(-1),
164 new TmfEventField("", null, new CtfTmfEventField
[0])); //$NON-NLS-1$
166 fEventName
= EMPTY_CTF_EVENT_NAME
;
167 fEventDeclaration
= null;
168 fEvent
= NullEventDefinition
.INSTANCE
;
169 fChannel
= ""; //$NON-NLS-1$
171 fPacketAttributes
= Collections
.EMPTY_MAP
;
175 * Default constructor. Do not use directly, but it needs to be present
176 * because it's used in extension points, and the framework will use this
177 * constructor to get the class type.
179 * @deprecated Should not be called by normal code
182 public CtfTmfEvent() {
185 fEventName
= EMPTY_CTF_EVENT_NAME
;
186 fEventDeclaration
= null;
187 fEvent
= NullEventDefinition
.INSTANCE
;
188 fChannel
= ""; //$NON-NLS-1$
190 fPacketAttributes
= Collections
.EMPTY_MAP
;
193 // ------------------------------------------------------------------------
194 // Getters/Setters/Predicates
195 // ------------------------------------------------------------------------
198 * Gets the cpu core the event was recorded on.
200 * @return The cpu id for a given source. In lttng it's from CPUINFO
202 public int getCPU() {
207 * Return the CTF trace's channel from which this event originates.
209 * @return The event's channel
212 public String
getChannel() {
217 * Return this event's reference.
219 * @return The event's reference
220 * @deprecated This method was replaced by {@link #getChannel()}.
223 public String
getReference() {
230 * @return the stream ID or -1 if the stream is null
233 public long getStreamId() {
234 ICTFStream stream
= fStream
;
235 if (stream
== null) {
238 return stream
.getId();
241 // ------------------------------------------------------------------------
243 // ------------------------------------------------------------------------
246 public CtfTmfTrace
getTrace() {
248 * Should be of the right type, since we take a CtfTmfTrace at the
251 return (CtfTmfTrace
) super.getTrace();
255 public synchronized ITmfEventType
getType() {
256 CtfTmfEventType type
= fEventType
;
258 type
= new CtfTmfEventType(fEventName
, getContent());
261 * Register the event type in the owning trace, but only if there is
264 getTrace().registerEventType(type
);
271 public String
getName() {
276 public synchronized ITmfEventField
getContent() {
277 ITmfEventField content
= fContent
;
278 if (content
== null) {
279 content
= new TmfEventField(
280 ITmfEventField
.ROOT_FIELD_ID
, null, parseFields(fEvent
));
287 * Extract the field information from the structDefinition haze-inducing
288 * mess, and put them into something ITmfEventField can cope with.
290 private static CtfTmfEventField
[] parseFields(IEventDefinition eventDef
) {
291 List
<CtfTmfEventField
> fields
= new ArrayList
<>();
293 ICompositeDefinition structFields
= eventDef
.getFields();
294 if (structFields
!= null) {
295 if (structFields
.getFieldNames() != null) {
296 for (String fn
: structFields
.getFieldNames()) {
297 fields
.add(CtfTmfEventField
.parseField((IDefinition
) structFields
.getDefinition(fn
), fn
));
301 /* Add context information as CtfTmfEventField */
302 ICompositeDefinition structContext
= eventDef
.getContext();
303 if (structContext
!= null) {
304 for (String contextName
: structContext
.getFieldNames()) {
305 /* Prefix field name */
306 String curContextName
= CtfConstants
.CONTEXT_FIELD_PREFIX
+ contextName
;
307 fields
.add(CtfTmfEventField
.parseField((IDefinition
) structContext
.getDefinition(contextName
), curContextName
));
311 return fields
.toArray(new @NonNull CtfTmfEventField
[fields
.size()]);
314 // ------------------------------------------------------------------------
315 // ITmfCustomAttributes
316 // ------------------------------------------------------------------------
319 public Set
<String
> listCustomAttributes() {
320 IEventDeclaration declaration
= fEventDeclaration
;
321 if (declaration
== null) {
322 return new HashSet
<>();
324 return declaration
.getCustomAttributes();
328 public @Nullable String
getCustomAttribute(@Nullable String name
) {
329 IEventDeclaration declaration
= fEventDeclaration
;
330 if (declaration
== null) {
333 return declaration
.getCustomAttribute(name
);
337 public @Nullable String
getModelUri() {
338 return getCustomAttribute(CtfConstants
.MODEL_URI_KEY
);
342 * Gets the packet attributes. The result is an instance of one of the
343 * following classes: <code>Entry<String, Long></code>, <code>Long</code>,
344 * <code>String</code> or <code>Double</code>. The map contains pairs of key
345 * and values where the key and value can never be null.
347 * @return gets the packet attributes
350 public Map
<String
, Object
> getPacketAttributes() {
351 return fPacketAttributes
;
354 // ------------------------------------------------------------------------
356 // ------------------------------------------------------------------------
359 public int hashCode() {
360 final int prime
= 31;
361 int result
= super.hashCode();
362 result
= prime
* result
+ getCPU();
363 result
= prime
* result
+ getChannel().hashCode();
368 public boolean equals(@Nullable Object obj
) {
369 if (!super.equals(obj
)) {
372 /* super.equals() checks that the classes are the same */
373 CtfTmfEvent other
= checkNotNull((CtfTmfEvent
) obj
);
374 if (getCPU() != other
.getCPU()) {
377 if (!getChannel().equals(other
.getChannel())) {