| /******************************************************************************* |
| * Copyright (c) 2011-2014 Ericsson, Ecole Polytechnique de Montreal and others |
| * |
| * All rights reserved. This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: Matthew Khouzam - Initial API and implementation |
| * Contributors: Simon Marchi - Initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.internal.ctf.core.event; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration; |
| import org.eclipse.tracecompass.ctf.core.event.IEventDefinition; |
| import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; |
| import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope; |
| import org.eclipse.tracecompass.ctf.core.event.scope.LexicalScope; |
| import org.eclipse.tracecompass.ctf.core.event.types.Definition; |
| import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition; |
| import org.eclipse.tracecompass.ctf.core.event.types.IDefinition; |
| import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; |
| import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition; |
| import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor; |
| |
| /** |
| * Representation of a particular instance of an event. |
| */ |
| public final class EventDefinition implements IDefinitionScope, IEventDefinition { |
| |
| // ------------------------------------------------------------------------ |
| // Attributes |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * The corresponding event declaration. |
| */ |
| private final IEventDeclaration fDeclaration; |
| |
| /** |
| * The timestamp of the current event. |
| */ |
| private final long fTimestamp; |
| |
| private final ICompositeDefinition fEventHeaderDefinition; |
| |
| /** |
| * The event context structure definition. |
| */ |
| private final ICompositeDefinition fEventContext; |
| |
| private final ICompositeDefinition fStreamContext; |
| |
| private final ICompositeDefinition fPacketContext; |
| |
| /** |
| * The event fields structure definition. |
| */ |
| private final ICompositeDefinition fFields; |
| |
| /** |
| * The current cpu, could be @link {@link IPacketHeader#UNKNOWN_CPU} |
| */ |
| private final int fCpu; |
| |
| private final @NonNull Map<String, Object> fPacketAttributes; |
| |
| // ------------------------------------------------------------------------ |
| // Constructors |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Constructs an event definition. |
| * |
| * @param declaration |
| * The corresponding event declaration |
| * @param cpu |
| * The cpu source of the event. You can use UNKNOWN_CPU if it is |
| * not known. |
| * @param timestamp |
| * event timestamp |
| * @param eventHeaderDefinition |
| * The event header definition, can be null if there is no header |
| * definition |
| * @param eventContext |
| * The event context |
| * @param packetContext |
| * the packet context (the one with content size, not magic |
| * number) |
| * @param streamContext |
| * the stream context |
| * @param fields |
| * The event fields |
| * @param packetDescriptor |
| * descriptor of the packet containing this event |
| * @since 2.0 |
| */ |
| public EventDefinition(IEventDeclaration declaration, |
| int cpu, |
| long timestamp, |
| ICompositeDefinition eventHeaderDefinition, |
| ICompositeDefinition streamContext, |
| ICompositeDefinition eventContext, |
| ICompositeDefinition packetContext, |
| ICompositeDefinition fields, |
| @Nullable ICTFPacketDescriptor packetDescriptor) { |
| fDeclaration = declaration; |
| fEventHeaderDefinition = eventHeaderDefinition; |
| fCpu = cpu; |
| fTimestamp = timestamp; |
| fFields = fields; |
| fEventContext = eventContext; |
| fPacketContext = packetContext; |
| fStreamContext = streamContext; |
| fPacketAttributes = packetDescriptor != null ? packetDescriptor.getAttributes() : Collections.emptyMap(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Getters/Setters/Predicates |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public ILexicalScope getScopePath() { |
| String eventName = fDeclaration.getName(); |
| if (eventName == null) { |
| return null; |
| } |
| ILexicalScope myScope = ILexicalScope.EVENT.getChild(eventName); |
| if (myScope == null) { |
| myScope = new LexicalScope(ILexicalScope.EVENT, eventName); |
| } |
| return myScope; |
| } |
| |
| @Override |
| public IEventDeclaration getDeclaration() { |
| return fDeclaration; |
| } |
| |
| @Override |
| public ICompositeDefinition getEventHeader() { |
| return fEventHeaderDefinition; |
| } |
| |
| @Override |
| public ICompositeDefinition getFields() { |
| return fFields; |
| } |
| |
| @Override |
| public ICompositeDefinition getEventContext() { |
| return fEventContext; |
| } |
| |
| @Override |
| public ICompositeDefinition getStreamContext() { |
| return fStreamContext; |
| } |
| |
| @Override |
| public ICompositeDefinition getContext() { |
| |
| /* Most common case so far */ |
| if (fStreamContext == null) { |
| return fEventContext; |
| } |
| |
| /* streamContext is not null, but the context of the event is null */ |
| if (fEventContext == null) { |
| return fStreamContext; |
| } |
| |
| // TODO: cache if this is a performance issue |
| |
| /* The stream context and event context are assigned. */ |
| StructDeclaration mergedDeclaration = new StructDeclaration(1); |
| |
| List<Definition> fieldValues = new ArrayList<>(); |
| |
| /* Add fields from the stream */ |
| List<@NonNull String> fieldNames = fStreamContext.getFieldNames(); |
| for (String fieldName : fieldNames) { |
| Definition definition = fStreamContext.getDefinition(fieldName); |
| mergedDeclaration.addField(fieldName, definition.getDeclaration()); |
| fieldValues.add(definition); |
| } |
| |
| /* |
| * Add fields from the event context, overwrite the stream ones if |
| * needed. |
| */ |
| for (String fieldName : fEventContext.getFieldNames()) { |
| Definition definition = fEventContext.getDefinition(fieldName); |
| mergedDeclaration.addField(fieldName, definition.getDeclaration()); |
| if (fieldNames.contains(fieldName)) { |
| fieldValues.set((fieldNames.indexOf(fieldName)), definition); |
| } else { |
| fieldValues.add(definition); |
| } |
| } |
| return new StructDefinition(mergedDeclaration, this, "context", //$NON-NLS-1$ |
| fieldValues.toArray(new Definition[fieldValues.size()])); |
| } |
| |
| @Override |
| public ICompositeDefinition getPacketContext() { |
| return fPacketContext; |
| } |
| |
| @Override |
| public int getCPU() { |
| return fCpu; |
| } |
| |
| @Override |
| public long getTimestamp() { |
| return fTimestamp; |
| } |
| |
| @Override |
| public Map<String, Object> getPacketAttributes() { |
| return fPacketAttributes; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Operations |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public IDefinition lookupDefinition(String lookupPath) { |
| if (lookupPath.equals("context")) { //$NON-NLS-1$ |
| return fEventContext; |
| } else if (lookupPath.equals("fields")) { //$NON-NLS-1$ |
| return fFields; |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public String toString() { |
| Iterable<String> list; |
| StringBuilder retString = new StringBuilder(); |
| final String cr = System.getProperty("line.separator");//$NON-NLS-1$ |
| |
| retString.append("Event type: ").append(fDeclaration.getName()).append(cr); //$NON-NLS-1$ |
| retString.append("Timestamp: ").append(Long.toString(fTimestamp)).append(cr); //$NON-NLS-1$ |
| |
| if (fEventContext != null) { |
| list = fEventContext.getFieldNames(); |
| |
| for (String field : list) { |
| retString.append(field).append(" : ").append(fEventContext.getDefinition(field).toString()).append(cr); //$NON-NLS-1$ |
| } |
| } |
| |
| if (fFields != null) { |
| list = fFields.getFieldNames(); |
| |
| for (String field : list) { |
| retString.append(field).append(" : ").append(fFields.getDefinition(field).toString()).append(cr); //$NON-NLS-1$ |
| } |
| } |
| |
| return retString.toString(); |
| } |
| |
| } |