ctf: Introduce IPacketReader
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 27 Aug 2015 02:32:24 +0000 (22:32 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Fri, 20 Nov 2015 22:37:15 +0000 (17:37 -0500)
Introduce the IPacketReader api to allow better decoupling between the
streaminputreader and the packet reader. This allows for more packet
reader types in the future, such as an InMemoryPacketReader for streamed
in RAM traces.

The IPacketReader is currently implemented by 2 classes:
    * a NullPacketReader, if there is no data to read
    * a CTFPacketReader, the typical packet reader

The CTFPacketReader is quite different from the CTFStreamPacketReader. The
SPR holds on to a FileChannel and maps segments as it needs. This results in
a fast but complex sliding window like reader. On the other hand, the
CTFPacketReader will only read one packet of a stream, a new one needs to
be created for each packet. This makes it wrap a single BitBuffer. As
FileChannels are resources but Bit(Byte)Buffers are not, this means a
CTFPacketReader is NOT autoclosable.

It should be noted that ByteBuffers can hold onto a system file handle. They
are released on GC. Also, ByteBuffers as they have their handle, will not
require the fileChannel to be opened all the time, so resources can be
dynamically closed when running low on file handles.

This patch also fixes some bugs in the tests relating to uninitialized traces
and lost event locations that were hidden due to "event.equals" not working as
well as it should.

The reason this patch does two things at the same time is that the interface
required a major re-write of the packet reader. This resulted in several bugs
being highlighted and fixed. To fix them in a separate patch before would
be very time consuming, and fixing them after would mean deliberately writing
a buggy packet reader to fix it in a subsequent patch.

This change will allow the following changes down the road:
    * In memory ctf reading (network streams)
    * Encrypted ctf stream reading
    * Compressed ctf stream reading
    * Multi-threaded stream reading
    * A power set of the previous elements

Change-Id: Id45b69bb0dac7a1f74f50cd732cd92064595f737
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/53284
Reviewed-by: Hudson CI
18 files changed:
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/EventDefinition.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStream.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInput.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java [deleted file]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputReader.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTrace.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTraceReader.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/ICTFPacketDescriptor.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/IPacketReader.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFPacketReader.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/NullPacketReader.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/StreamInputPacketIndexEntry.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/StreamInputReaderTimestampComparator.java
ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/src/org/eclipse/tracecompass/tmf/ctf/core/tests/event/CtfTmfEventTest.java
ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/src/org/eclipse/tracecompass/tmf/ctf/core/tests/event/CtfTmfLostEventStatisticsTest.java
ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/src/org/eclipse/tracecompass/tmf/ctf/core/tests/event/CtfTmfLostEventsTest.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/piecharts/TmfPieChartViewer.java

index 2e0e177003d0ce9235f829b256d4bf14efdef8cc..68cb58948b19b87bc2cc336faff226f34b5a8cf6 100644 (file)
@@ -74,7 +74,7 @@ public final class EventDefinition implements IDefinitionScope {
     private final ICompositeDefinition fFields;
 
     /**
-     * The cpu number of the event, can be UNKNOWN
+     * The current cpu, could be @link {@link IPacketHeader#UNKNOWN_CPU}
      */
     private final int fCpu;
 
@@ -98,7 +98,7 @@ public final class EventDefinition implements IDefinitionScope {
      * @param eventContext
      *            The event context
      * @param packetContext
-     *            the packet context
+     *            the packet context (the one with content size, not magic number)
      * @param streamContext
      *            the stream context
      * @param fields
index b0fb0e54fc19456b5c9f515747d1574a8f5de6ca..dd94b0bfb3860b67031da74e55c38236ebd0292a 100644 (file)
@@ -14,12 +14,14 @@ package org.eclipse.tracecompass.ctf.core.trace;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
@@ -224,15 +226,10 @@ public class CTFStream {
      * Get all the event declarations in this stream.
      *
      * @return The event declarations for this stream
+     * @since 2.0
      */
-    public @NonNull Collection<@NonNull IEventDeclaration> getEventDeclarations() {
-        List<@NonNull IEventDeclaration> retVal = new ArrayList<>();
-        for (IEventDeclaration eventDeclaration : fEvents) {
-            if (eventDeclaration != null) {
-                retVal.add(eventDeclaration);
-            }
-        }
-        return retVal;
+    public @NonNull List<IEventDeclaration> getEventDeclarations() {
+        return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
     }
 
     /**
index 5c708e943d3239ec3d2f893feb2bd74628c3e339..7c62cfb1b2179daa529b03c34f0a7b6af9d8bc9c 100644 (file)
@@ -367,7 +367,7 @@ public class CTFStreamInput implements IDefinitionScope {
             BitBuffer bitBuffer) throws CTFException {
         ICTFPacketDescriptor packetIndex;
         StructDefinition streamPacketContextDef = fStreamPacketContextDecl.createDefinition(this, ILexicalScope.STREAM_PACKET_CONTEXT, bitBuffer);
-        packetIndex = new StreamInputPacketIndexEntry(dataOffsetBits, streamPacketContextDef, fileSizeBytes, fLostSoFar);
+        packetIndex = new StreamInputPacketIndexEntry(dataOffsetBits, streamPacketContextDef, fileSizeBytes, fLostSoFar, bitBuffer.position());
         fLostSoFar = packetIndex.getLostEvents() + fLostSoFar;
         setTimestampEnd(packetIndex.getTimestampEnd());
         return packetIndex;
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputPacketReader.java
deleted file mode 100644 (file)
index 55d98d6..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2015 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 v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Matthew Khouzam - Initial API and implementation
- *   Simon Marchi - Initial API and implementation
- *   Patrick Tasse - Bug 470754 - Incorrect time range in CTF Lost Event
- *******************************************************************************/
-package org.eclipse.tracecompass.ctf.core.trace;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel.MapMode;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.ctf.core.CTFException;
-import org.eclipse.tracecompass.ctf.core.CTFStrings;
-import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
-import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
-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.IDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
-import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
-import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
-import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
-import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
-import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
-
-/**
- * CTF trace packet reader. Reads the events of a packet of a trace file.
- *
- * @author Matthew Khouzam
- * @author Simon Marchi
- */
-public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
-
-    // ------------------------------------------------------------------------
-    // Attributes
-    // ------------------------------------------------------------------------
-
-    private static final int BITS_PER_BYTE = Byte.SIZE;
-
-    private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() {
-
-        @Override
-        public IDefinition lookupDefinition(String lookupPath) {
-            return null;
-        }
-
-        @Override
-        public ILexicalScope getScopePath() {
-            return null;
-        }
-    };
-
-    /** BitBuffer used to read the trace file. */
-    @Nullable
-    private BitBuffer fBitBuffer;
-
-    /** StreamInputReader that uses this StreamInputPacketReader. */
-    private final CTFStreamInputReader fStreamInputReader;
-
-    /** Trace packet header. */
-    private final StructDeclaration fTracePacketHeaderDecl;
-
-    /** Stream packet context definition. */
-    private final StructDeclaration fStreamPacketContextDecl;
-
-    /** Stream event header definition. */
-    private final IDeclaration fStreamEventHeaderDecl;
-
-    /** Stream event context definition. */
-    private final StructDeclaration fStreamEventContextDecl;
-
-    private ICompositeDefinition fCurrentTracePacketHeaderDef;
-    private ICompositeDefinition fCurrentStreamEventHeaderDef;
-    private ICompositeDefinition fCurrentStreamPacketContextDef;
-    /** Reference to the index entry of the current packet. */
-    private ICTFPacketDescriptor fCurrentPacket = null;
-
-    /**
-     * Last timestamp recorded.
-     *
-     * Needed to calculate the complete timestamp values for the events with
-     * compact headers.
-     */
-    private long fLastTimestamp = 0;
-
-    /** CPU id of current packet. */
-    private int fCurrentCpu = 0;
-
-    private int fLostEventsInThisPacket;
-
-    private boolean fHasLost = false;
-
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Constructs a StreamInputPacketReader.
-     *
-     * @param streamInputReader
-     *            The StreamInputReader to which this packet reader belongs to.
-     */
-    public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
-        fStreamInputReader = streamInputReader;
-
-        /* Set the BitBuffer's byte order. */
-        ByteBuffer allocateDirect = ByteBuffer.allocateDirect(0);
-        if (allocateDirect == null) {
-            throw new IllegalStateException("Unable to allocate 0 bytes!"); //$NON-NLS-1$
-        }
-        fBitBuffer = new BitBuffer(allocateDirect);
-
-        final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
-        fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
-        fStreamPacketContextDecl = currentStream.getPacketContextDecl();
-        fStreamEventHeaderDecl = currentStream.getEventHeaderDeclaration();
-        fStreamEventContextDecl = currentStream.getEventContextDecl();
-    }
-
-    /**
-     * Get the event context defintiion
-     *
-     * @param input
-     *            the bitbuffer to read from
-     * @return an context definition, can be null
-     * @throws CTFException
-     *             out of bounds exception or such
-     */
-    public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFException {
-        return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_EVENT_CONTEXT, input);
-    }
-
-    /**
-     * Get the packet context defintiion
-     *
-     * @param input
-     *            the bitbuffer to read from
-     * @return an context definition, can be null
-     * @throws CTFException
-     *             out of bounds exception or such
-     */
-    public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFException {
-        return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_PACKET_CONTEXT, input);
-    }
-
-    /**
-     * Get the event header defintiion
-     *
-     * @param input
-     *            the bitbuffer to read from
-     * @return an header definition, can be null
-     * @throws CTFException
-     *             out of bounds exception or such
-     */
-    public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFException {
-        return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), ILexicalScope.TRACE_PACKET_HEADER, input);
-    }
-
-    /**
-     * Dispose the StreamInputPacketReader
-     */
-    @Override
-    public void close() {
-        fBitBuffer = null;
-    }
-
-    // ------------------------------------------------------------------------
-    // Getters/Setters/Predicates
-    // ------------------------------------------------------------------------
-
-    /**
-     * Gets the current packet
-     *
-     * @return the current packet
-     */
-    ICTFPacketDescriptor getCurrentPacket() {
-        return fCurrentPacket;
-    }
-
-    /**
-     * Gets the CPU (core) number
-     *
-     * @return the CPU (core) number
-     */
-    public int getCPU() {
-        return fCurrentCpu;
-    }
-
-    @Override
-    public LexicalScope getScopePath() {
-        return ILexicalScope.PACKET;
-    }
-
-    // ------------------------------------------------------------------------
-    // Operations
-    // ------------------------------------------------------------------------
-
-    @NonNull
-    private ByteBuffer getByteBufferAt(long position, long size) throws CTFException, IOException {
-        ByteBuffer map = SafeMappedByteBuffer.map(fStreamInputReader.getFc(), MapMode.READ_ONLY, position, size);
-        if (map == null) {
-            throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
-        }
-        return map;
-    }
-
-    /**
-     * Changes the current packet to the given one.
-     *
-     * @param currentPacket
-     *            The index entry of the packet to switch to.
-     * @throws CTFException
-     *             If we get an error reading the packet
-     * @since 1.0
-     */
-    public void setCurrentPacket(ICTFPacketDescriptor currentPacket) throws CTFException {
-        fCurrentPacket = currentPacket;
-        fHasLost = false;
-
-        if (fCurrentPacket != null) {
-            /*
-             * Change the map of the BitBuffer.
-             */
-            ByteBuffer bb = null;
-            try {
-                bb = getByteBufferAt(fCurrentPacket.getOffsetBytes(), (fCurrentPacket.getPacketSizeBits() + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
-            } catch (IOException e) {
-                throw new CTFIOException(e.getMessage(), e);
-            }
-
-            BitBuffer bitBuffer = new BitBuffer(bb);
-            fBitBuffer = bitBuffer;
-            /*
-             * Read trace packet header.
-             */
-            if (fTracePacketHeaderDecl != null) {
-                fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
-            }
-
-            /*
-             * Read stream packet context.
-             */
-            if (fStreamPacketContextDecl != null) {
-                fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
-
-                /* Read CPU ID */
-                if (getCurrentPacket().getTarget() != null) {
-                    fCurrentCpu = (int) getCurrentPacket().getTargetId();
-                }
-
-                /* Read number of lost events */
-                fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
-                if (fLostEventsInThisPacket != 0) {
-                    fHasLost = true;
-                }
-            }
-
-            /*
-             * Use the timestamp begin of the packet as the reference for the
-             * timestamp reconstitution.
-             */
-            fLastTimestamp = Math.max(currentPacket.getTimestampBegin(), 0);
-        } else {
-            fBitBuffer = null;
-            fLastTimestamp = 0;
-        }
-    }
-
-    /**
-     * Returns whether it is possible to read any more events from this packet.
-     *
-     * @return True if it is possible to read any more events from this packet.
-     */
-    public boolean hasMoreEvents() {
-        BitBuffer bitBuffer = fBitBuffer;
-        ICTFPacketDescriptor currentPacket = fCurrentPacket;
-        if (currentPacket != null && bitBuffer != null) {
-            return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
-        }
-        return false;
-    }
-
-    /**
-     * Reads the next event of the packet into the right event definition.
-     *
-     * @return The event definition containing the event data that was just
-     *         read.
-     * @throws CTFException
-     *             If there was a problem reading the trace
-     */
-    public EventDefinition readNextEvent() throws CTFException {
-        /* Default values for those fields */
-        // compromise since we cannot have 64 bit addressing of arrays yet.
-        int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
-        final BitBuffer currentBitBuffer = fBitBuffer;
-        final ICTFPacketDescriptor currentPacket = fCurrentPacket;
-        if (currentBitBuffer == null || currentPacket == null) {
-            return null;
-        }
-        final long posStart = currentBitBuffer.position();
-        /*
-         * Return the Lost Event after all other events in this packet.
-         */
-        if (fHasLost && posStart >= currentPacket.getContentSizeBits()) {
-            fHasLost = false;
-            IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
-            StructDeclaration lostFields = lostEventDeclaration.getFields();
-            // this is a hard coded map, we know it's not null
-            IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
-            if (lostFieldsDecl == null)
-            {
-                throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
-            }
-            IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
-            if (lostEventsDurationDecl == null) {
-                throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
-            }
-            long lostEventsTimestamp = fLastTimestamp;
-            long lostEventsDuration = currentPacket.getTimestampEnd() - lostEventsTimestamp;
-            IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, lostEventsDuration);
-            IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
-            IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
-            return new EventDefinition(
-                    lostEventDeclaration,
-                    fStreamInputReader.getCPU(),
-                    lostEventsTimestamp,
-                    null,
-                    null,
-                    null,
-                    null,
-                    new StructDefinition(
-                            lostFields,
-                            this, "fields", //$NON-NLS-1$
-                            fields
-                    ));
-
-        }
-
-        /* Read the stream event header. */
-        if (fStreamEventHeaderDecl != null) {
-            if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
-                fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$
-                EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
-                eventID = ehd.getId();
-            } else {
-                fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer);
-                StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef;
-                /* Check for the event id. */
-                IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
-                SimpleDatatypeDefinition simpleIdDef = null;
-                if (idDef instanceof SimpleDatatypeDefinition) {
-                    simpleIdDef = ((SimpleDatatypeDefinition) idDef);
-                } else if (idDef != null) {
-                    throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
-                }
-                /* Check for the variant v. */
-                IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
-                if (variantDef instanceof VariantDefinition) {
-
-                    /* Get the variant current field */
-                    StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
-
-                    /*
-                     * Try to get the id field in the current field of the
-                     * variant. If it is present, it overrides the previously
-                     * read event id.
-                     */
-                    IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
-                    if (vIdDef instanceof IntegerDefinition) {
-                        simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
-                    }
-
-                }
-                if (simpleIdDef != null) {
-                    eventID = simpleIdDef.getIntegerValue().intValue();
-                }
-            }
-        }
-        /* Get the right event definition using the event id. */
-        EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
-        if (eventDeclaration == null) {
-            throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
-        }
-        EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, fLastTimestamp);
-        fLastTimestamp = eventDef.getTimestamp();
-        /*
-         * Set the event timestamp using the timestamp calculated by
-         * updateTimestamp.
-         */
-
-        if (posStart == currentBitBuffer.position()) {
-            throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
-        }
-
-        return eventDef;
-    }
-
-    @Override
-    public Definition lookupDefinition(String lookupPath) {
-        if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
-            return (Definition) fCurrentStreamPacketContextDef;
-        }
-        if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
-            return (Definition) fCurrentTracePacketHeaderDef;
-        }
-        return null;
-    }
-
-
-    /**
-     * Get stream event header
-     *
-     * @return the stream event header
-     */
-    public ICompositeDefinition getStreamEventHeaderDefinition() {
-        return fCurrentStreamEventHeaderDef;
-    }
-
-    /**
-     * Get the current packet event header
-     *
-     * @return the current packet event header
-     */
-    public StructDefinition getCurrentPacketEventHeader() {
-        if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
-            return (StructDefinition) fCurrentTracePacketHeaderDef;
-        }
-        return null;
-    }
-}
index 8faf38c45f58c256a0f4b16a9eb7c6100f0aa1ba..251a0ccfa02b29d0cb3faa9640109f0d611efeed 100644 (file)
@@ -16,8 +16,11 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
 import java.nio.file.StandardOpenOption;
+import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -25,10 +28,14 @@ import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
 import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.internal.ctf.core.Activator;
-
-import com.google.common.collect.ImmutableList;
+import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFPacketReader;
+import org.eclipse.tracecompass.internal.ctf.core.trace.NullPacketReader;
 
 /**
  * A CTF trace event reader. Reads the events of a trace file.
@@ -40,6 +47,8 @@ import com.google.common.collect.ImmutableList;
 @NonNullByDefault
 public class CTFStreamInputReader implements AutoCloseable {
 
+    private static final int BITS_PER_BYTE = Byte.SIZE;
+
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
@@ -56,7 +65,7 @@ public class CTFStreamInputReader implements AutoCloseable {
     /**
      * The packet reader used to read packets from this trace file.
      */
-    private final CTFStreamInputPacketReader fPacketReader;
+    private IPacketReader fPacketReader;
 
     /**
      * Iterator on the packet index
@@ -96,7 +105,6 @@ public class CTFStreamInputReader implements AutoCloseable {
             throw new CTFIOException(e);
         }
         try {
-            fPacketReader = new CTFStreamInputPacketReader(this);
             /*
              * Get the iterator on the packet index.
              */
@@ -104,7 +112,16 @@ public class CTFStreamInputReader implements AutoCloseable {
             /*
              * Make first packet the current one.
              */
-            goToNextPacket();
+            // did we already index the packet?
+            if (getPacketSize() < (fPacketIndex + 1)) {
+                // go to the next packet if there is one, index it at the same
+                // time
+                if (fStreamInput.addPacketHeaderIndex()) {
+                    fPacketIndex = getPacketSize() - 1;
+                }
+            }
+            ICTFPacketDescriptor packet = getPacket();
+            fPacketReader = getCurrentPacketReader(packet);
         } catch (Exception e) {
             try {
                 close();
@@ -115,6 +132,49 @@ public class CTFStreamInputReader implements AutoCloseable {
         }
     }
 
+    private IPacketReader getCurrentPacketReader(@Nullable ICTFPacketDescriptor packet) throws CTFException {
+        IPacketReader ctfPacketReader = NullPacketReader.INSTANCE;
+        if (packet != null) {
+            long size = packet.getContentSizeBits();
+            if (size < 0) {
+                throw new CTFIOException("Cannot have negative sized buffers."); //$NON-NLS-1$
+            }
+            BitBuffer bitBuffer = new BitBuffer(getByteBufferAt(packet.getOffsetBits(), size));
+            bitBuffer.position(packet.getPayloadStartBits());
+            IDeclaration eventHeaderDeclaration = getStreamInput().getStream().getEventHeaderDeclaration();
+            CTFTrace trace = getStreamInput().getStream().getTrace();
+            StructDefinition packetHeaderDef = checkNotNull(trace.getPacketHeaderDef());
+            ctfPacketReader = new CTFPacketReader(bitBuffer, packet, getEventDeclarations(), eventHeaderDeclaration, getStreamEventContextDecl(), packetHeaderDef, trace);
+        }
+        return ctfPacketReader;
+    }
+
+    /**
+     * Get a bytebuffer map of the file
+     *
+     * @param position
+     *            start offset in bits
+     * @param size
+     *            size of the map in bits, use caution
+     * @return a byte buffer
+     * @throws CTFException
+     *             if the map failed in its allocation
+     *
+     * @since 2.0
+     */
+    public ByteBuffer getByteBufferAt(long position, long size) throws CTFException {
+        ByteBuffer map;
+        try {
+            map = SafeMappedByteBuffer.map(fFileChannel, MapMode.READ_ONLY, position / BITS_PER_BYTE, (size + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
+        } catch (IOException e) {
+            throw new CTFIOException(e.getMessage(), e);
+        }
+        if (map == null) {
+            throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
+        }
+        return map;
+    }
+
     /**
      * Dispose the StreamInputReader, closes the file channel and its packet
      * reader
@@ -127,7 +187,7 @@ public class CTFStreamInputReader implements AutoCloseable {
         if (fFileChannel != null) {
             fFileChannel.close();
         }
-        fPacketReader.close();
+        fPacketReader = NullPacketReader.INSTANCE;
     }
 
     // ------------------------------------------------------------------------
@@ -193,9 +253,10 @@ public class CTFStreamInputReader implements AutoCloseable {
      * Gets the event definition set for this StreamInput
      *
      * @return Unmodifiable set with the event definitions
+     * @since 2.0
      */
-    public Iterable<IEventDeclaration> getEventDeclarations() {
-        return checkNotNull(ImmutableList.copyOf(fStreamInput.getStream().getEventDeclarations()));
+    public List<IEventDeclaration> getEventDeclarations() {
+        return fStreamInput.getStream().getEventDeclarations();
     }
 
     /**
@@ -269,18 +330,19 @@ public class CTFStreamInputReader implements AutoCloseable {
     private void goToNextPacket() throws CTFException {
         fPacketIndex++;
         // did we already index the packet?
-        if (getPacketSize() >= (fPacketIndex + 1)) {
-            fPacketReader.setCurrentPacket(getPacket());
-        } else {
+        while (getPacketSize() < (fPacketIndex + 1)) {
             // go to the next packet if there is one, index it at the same time
             if (fStreamInput.addPacketHeaderIndex()) {
                 fPacketIndex = getPacketSize() - 1;
-                fPacketReader.setCurrentPacket(getPacket());
             } else {
-                // out of packets
-                fPacketReader.setCurrentPacket(null);
+                fPacketReader = NullPacketReader.INSTANCE;
+                return;
             }
+
         }
+        ICTFPacketDescriptor packet = getPacket();
+        fPacketReader = getCurrentPacketReader(packet);
+
     }
 
     /**
@@ -382,7 +444,7 @@ public class CTFStreamInputReader implements AutoCloseable {
         /*
          * Go to last indexed packet
          */
-        fPacketReader.setCurrentPacket(getPacket());
+        fPacketReader = getCurrentPacketReader(getPacket());
 
         /*
          * Keep going until you cannot
@@ -397,7 +459,7 @@ public class CTFStreamInputReader implements AutoCloseable {
          */
         for (int pos = lastPacketIndex; pos > 0; pos--) {
             fPacketIndex = pos;
-            fPacketReader.setCurrentPacket(getPacket());
+            fPacketReader = getCurrentPacketReader(getPacket());
 
             if (fPacketReader.hasMoreEvents()) {
                 break;
@@ -443,19 +505,12 @@ public class CTFStreamInputReader implements AutoCloseable {
     }
 
     /**
-     * Get the file channel wrapped by this reader
+     * Get the current packet reader
      *
-     * @return the file channel
-     */
-    @Nullable
-    FileChannel getFc() {
-        return fFileChannel;
-    }
-
-    /**
      * @return the packetReader
+     * @since 2.0
      */
-    public CTFStreamInputPacketReader getPacketReader() {
+    public IPacketReader getCurrentPacketReader() {
         return fPacketReader;
     }
 
index 2ef8fec142e60aa8f98e41a5c995974657660443..dab024292bb38e1a1085bee1c6a83ee1b2c945eb 100644 (file)
@@ -477,13 +477,14 @@ public class CTFTrace implements IDefinitionScope {
             /* Shouldn't happen at this stage if every other check passed */
             throw new CTFException(e);
         }
-        if (fPacketHeaderDef != null) {
-            validateMagicNumber(fPacketHeaderDef);
+        final StructDefinition packetHeaderDef = getPacketHeaderDef();
+        if (packetHeaderDef != null) {
+            validateMagicNumber(packetHeaderDef);
 
-            validateUUID(fPacketHeaderDef);
+            validateUUID(packetHeaderDef);
 
             /* Read the stream ID */
-            IDefinition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
+            IDefinition streamIDDef = packetHeaderDef.lookupDefinition(MetadataStrings.STREAM_ID);
 
             if (streamIDDef instanceof IntegerDefinition) {
                 /* This doubles as a null check */
@@ -556,7 +557,7 @@ public class CTFTrace implements IDefinitionScope {
     @Override
     public Definition lookupDefinition(String lookupPath) {
         if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
-            return fPacketHeaderDef;
+            return getPacketHeaderDef();
         }
         return null;
     }
@@ -824,6 +825,17 @@ public class CTFTrace implements IDefinitionScope {
     public DeclarationScope getScope() {
         return fScope;
     }
+
+    /**
+     * Gets the packet header definition (UUID, magic number and such)
+     *
+     * @return the packet header definition
+     *
+     * @since 2.0
+     */
+    public StructDefinition getPacketHeaderDef() {
+        return fPacketHeaderDef;
+    }
 }
 
 class MetadataFileFilter implements FileFilter {
index d6eed173ed329e050786f68e3923744a04e52c5e..805c7a9a41a8ad5ba55cf9185ddc0d2df28e92aa 100644 (file)
@@ -29,9 +29,6 @@ import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
 import org.eclipse.tracecompass.internal.ctf.core.Activator;
 import org.eclipse.tracecompass.internal.ctf.core.trace.StreamInputReaderTimestampComparator;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-
 /**
  * A CTF trace reader. Reads the events of a trace.
  *
@@ -116,11 +113,8 @@ public class CTFTraceReader implements AutoCloseable {
          */
         fStartTime = 0;
         if (hasMoreEvents()) {
-            EventDefinition currentEvent = getTopStream().getCurrentEvent();
-            if (currentEvent != null) {
-                fStartTime = currentEvent.getTimestamp();
-                setEndTime(fStartTime);
-            }
+            fStartTime = checkNotNull(getTopStream().getCurrentEvent()).getTimestamp();
+            setEndTime(fStartTime);
         }
     }
 
@@ -254,6 +248,7 @@ public class CTFTraceReader implements AutoCloseable {
                  */
                 CTFStreamInputReader streamInputReader = new CTFStreamInputReader(checkNotNull(streamInput));
 
+
                 /*
                  * Add it to the group.
                  */
@@ -280,11 +275,12 @@ public class CTFTraceReader implements AutoCloseable {
      * @return the iterable of the stream input readers
      */
     public Iterable<IEventDeclaration> getEventDeclarations() {
-        ImmutableSet.Builder<IEventDeclaration> builder = new Builder<>();
+        Set<IEventDeclaration> retSet = new HashSet<>();
         for (CTFStreamInputReader sir : fStreamInputReaders) {
-            builder.addAll(sir.getEventDeclarations());
+            retSet.addAll(sir.getEventDeclarations());
         }
-        return builder.build();
+        retSet.remove(null);
+        return retSet;
     }
 
     /**
index 504638a44a487738d88bb199d760e4d61c176308..649c5f5600d4637b1a1dd0cfd1af6ee36d4f83d5 100644 (file)
@@ -104,4 +104,12 @@ public interface ICTFPacketDescriptor {
      */
     long getOffsetBytes();
 
+    /**
+     * Get the offset where the events start and the packet header ends
+     *
+     * @return the offset in the file of the end of the packet header
+     * @since 2.0
+     */
+    long getPayloadStartBits();
+
 }
\ No newline at end of file
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/IPacketReader.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/IPacketReader.java
new file mode 100644 (file)
index 0000000..165566d
--- /dev/null
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.ctf.core.trace;
+
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
+
+/**
+ * Packet reader interface, allows for more flexible packet readers. A packet
+ * reader must be able to do one thing only: read a ctf packet.
+ *
+ * In order to do that, it will have access to the packet and can then iterate
+ * over the packet with two main functions {@link #readNextEvent()} and
+ * {@link #hasMoreEvents()}. The packet reader must also have a notion of
+ * whether a given packet has an assigned CPU or not, which will be given
+ * by @link {@link #getCPU()}, as well as the event header, defined in
+ * {@link #getCurrentPacketEventHeader()}. The packet description in the reader
+ * can be obtained by calling {@link #getCurrentPacket()}
+ *
+ * @author Matthew Khouzam
+ *
+ * @since 2.0
+ */
+public interface IPacketReader {
+
+    /**
+     * The value of a cpu if it is unknown to the packet reader
+     */
+    int UNKNOWN_CPU = -1;
+
+    /**
+     * Gets the CPU (core) number
+     *
+     * @return the CPU (core) number
+     */
+    int getCPU();
+
+    /**
+     * Returns whether it is possible to read any more events from this packet.
+     *
+     * @return True if it is possible to read any more events from this packet.
+     */
+    boolean hasMoreEvents();
+
+    /**
+     * Reads the next event of the packet into the right event definition.
+     *
+     * @return The event definition containing the event data that was just
+     *         read.
+     * @throws CTFException
+     *             If there was a problem reading the trace
+     */
+    EventDefinition readNextEvent() throws CTFException;
+
+    /**
+     * Get the packet being read
+     *
+     * @return the packet being read
+     */
+    ICTFPacketDescriptor getCurrentPacket();
+
+    /**
+     * Get the current event header definition
+     *
+     * @return the current event header definition
+     */
+    ICompositeDefinition getCurrentPacketEventHeader();
+
+}
\ No newline at end of file
index 08f678e52715d74b352e56d6af8dac800ca4874c..cf8bdaa6bb4c5ef2a191b07a1ff90a4715695093 100644 (file)
@@ -33,6 +33,7 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.ctf.core.trace.CTFIOException;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
 
 /**
@@ -89,8 +90,12 @@ public class EventDeclaration implements IEventDeclaration {
     /**
      * Creates an instance of EventDefinition corresponding to this declaration.
      *
-     * @param streamInputReader
-     *            The StreamInputReader for which this definition is created.
+     * @param streamEventContextDecl
+     *            event context
+     * @param packetDescriptor
+     *            current packet
+     * @param packetContext
+     *            packet context
      * @param eventHeaderDef
      *            The event header definition
      * @param input
@@ -102,17 +107,17 @@ public class EventDeclaration implements IEventDeclaration {
      *             As a bitbuffer is used to read, it could have wrapped
      *             IOExceptions.
      */
-    public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, ICompositeDefinition eventHeaderDef, @NonNull BitBuffer input, long prevTimestamp) throws CTFException {
-        StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl();
+    public EventDefinition createDefinition(StructDeclaration streamEventContextDecl, ICTFPacketDescriptor packetDescriptor, ICompositeDefinition packetContext, ICompositeDefinition eventHeaderDef, @NonNull BitBuffer input, long prevTimestamp)
+            throws CTFException {
         StructDefinition streamEventContext = streamEventContextDecl != null ? streamEventContextDecl.createDefinition(fStream.getTrace(), ILexicalScope.STREAM_EVENT_CONTEXT, input) : null;
-        ICompositeDefinition packetContext = streamInputReader.getPacketReader().getCurrentPacketEventHeader();
         StructDefinition eventContext = fContext != null ? fContext.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.CONTEXT, input) : null;
         StructDefinition eventPayload = fFields != null ? fFields.createFieldDefinition(eventHeaderDef, fStream.getTrace(), ILexicalScope.FIELDS, input) : null;
         long timestamp = calculateTimestamp(eventHeaderDef, prevTimestamp, eventPayload, eventContext);
 
+        int cpu = (int) packetDescriptor.getTargetId();
         return new EventDefinition(
                 this,
-                streamInputReader.getCPU(),
+                cpu,
                 timestamp,
                 eventHeaderDef,
                 streamEventContext,
@@ -151,7 +156,7 @@ public class EventDeclaration implements IEventDeclaration {
     public EventDefinition createDefinition(CTFStreamInputReader streamInputReader, @NonNull BitBuffer input, long timestamp) throws CTFException {
         StructDeclaration streamEventContextDecl = streamInputReader.getStreamEventContextDecl();
         StructDefinition streamEventContext = streamEventContextDecl != null ? streamEventContextDecl.createDefinition(fStream.getTrace(), ILexicalScope.STREAM_EVENT_CONTEXT, input) : null;
-        ICompositeDefinition packetContext = streamInputReader.getPacketReader().getCurrentPacketEventHeader();
+        ICompositeDefinition packetContext = streamInputReader.getCurrentPacketReader().getCurrentPacketEventHeader();
         StructDefinition eventContext = fContext != null ? fContext.createDefinition(fStream.getTrace(), ILexicalScope.CONTEXT, input) : null;
         StructDefinition eventPayload = fFields != null ? fFields.createDefinition(fStream.getTrace(), ILexicalScope.FIELDS, input) : null;
 
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFPacketReader.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFPacketReader.java
new file mode 100644 (file)
index 0000000..b66233b
--- /dev/null
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.trace;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.CTFStrings;
+import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
+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.types.ICompositeDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
+import org.eclipse.tracecompass.ctf.core.trace.CTFIOException;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
+import org.eclipse.tracecompass.ctf.core.trace.IPacketReader;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
+
+/**
+ * Packet reader with a fixed bit buffer, should be the fast and easily
+ * parallelizable one.
+ */
+@NonNullByDefault
+public final class CTFPacketReader implements IPacketReader, IDefinitionScope {
+
+    private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() {
+
+        @Override
+        public @Nullable IDefinition lookupDefinition(@Nullable String lookupPath) {
+            return null;
+        }
+
+        @Override
+        public @Nullable ILexicalScope getScopePath() {
+            return null;
+        }
+    };
+
+    private final BitBuffer fInput;
+    private final ICTFPacketDescriptor fPacketContext;
+    private final List<IEventDeclaration> fDeclarations;
+    private boolean fHasLost;
+    private long fLastTimestamp;
+    private @Nullable final IDeclaration fStreamEventHeaderDecl;
+
+    private @Nullable final StructDeclaration fStreamContext;
+
+    private @Nullable final ICompositeDefinition fTracePacketHeader;
+
+    private @Nullable final IDefinitionScope fPacketScope;
+
+    private @Nullable ICompositeDefinition fEventHeader;
+
+    /**
+     * Constructor
+     *
+     * @param input
+     *            input {@link BitBuffer}
+     * @param packetContext
+     *            packet_context where we get info like lost events and cpu_id
+     * @param declarations
+     *            event declarations for this packet reader
+     * @param eventHeaderDeclaration
+     *            event header declaration, what to read before any given event,
+     *            to find it's id
+     * @param streamContext
+     *            the context declaration
+     * @param packetHeader
+     *            the header with the magic numbers and such
+     * @param packetScope
+     *            the scope of the packetHeader
+     */
+    public CTFPacketReader(BitBuffer input, ICTFPacketDescriptor packetContext, List<IEventDeclaration> declarations, @Nullable IDeclaration eventHeaderDeclaration, @Nullable StructDeclaration streamContext, ICompositeDefinition packetHeader,
+            IDefinitionScope packetScope) {
+        fInput = input;
+        fPacketContext = packetContext;
+        fDeclarations = declarations;
+        fPacketScope = packetScope;
+        fHasLost = fPacketContext.getLostEvents() != 0;
+        fLastTimestamp = fPacketContext.getTimestampBegin();
+        fStreamEventHeaderDecl = eventHeaderDeclaration;
+        fStreamContext = streamContext;
+        fTracePacketHeader = packetHeader;
+    }
+
+    @Override
+    public int getCPU() {
+        return (int) fPacketContext.getTargetId();
+    }
+
+    @Override
+    public boolean hasMoreEvents() {
+        return fInput.position() < fPacketContext.getContentSizeBits();
+    }
+
+    @Override
+    public EventDefinition readNextEvent() throws CTFException {
+        int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
+        final long posStart = fInput.position();
+        /*
+         * Return the Lost Event after all other events in this packet. We need
+         * to check if the bytebuffer is at the beginning too.
+         */
+        if (fHasLost && (posStart == fPacketContext.getPayloadStartBits())) {
+            fHasLost = false;
+            return createLostEvent(fPacketContext);
+        }
+
+        fEventHeader = null;
+        /* Read the stream event header. */
+        final IDeclaration streamEventHeaderDecl = fStreamEventHeaderDecl;
+        if (streamEventHeaderDecl instanceof IEventHeaderDeclaration) {
+            IEventHeaderDeclaration eventHeaderDeclaration = (IEventHeaderDeclaration) streamEventHeaderDecl;
+            EventHeaderDefinition ehd = (EventHeaderDefinition) eventHeaderDeclaration.createDefinition(EVENT_HEADER_SCOPE, "", fInput); //$NON-NLS-1$
+            fEventHeader = ehd;
+            eventID = ehd.getId();
+        } else if (streamEventHeaderDecl instanceof StructDeclaration) {
+            StructDefinition structEventHeaderDef = ((StructDeclaration) streamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, fInput);
+            fEventHeader = structEventHeaderDef;
+            /* Check for the event id. */
+            IDefinition idDef = structEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
+            SimpleDatatypeDefinition simpleIdDef = null;
+            if (idDef instanceof SimpleDatatypeDefinition) {
+                simpleIdDef = ((SimpleDatatypeDefinition) idDef);
+            } else if (idDef != null) {
+                throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
+            }
+            /* Check for the variant v. */
+            IDefinition variantDef = structEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
+            if (variantDef instanceof VariantDefinition) {
+
+                /* Get the variant current field */
+                StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
+
+                /*
+                 * Try to get the id field in the current field of the variant.
+                 * If it is present, it overrides the previously read event id.
+                 */
+                IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
+                if (vIdDef instanceof IntegerDefinition) {
+                    simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
+                }
+
+            }
+            if (simpleIdDef != null) {
+                eventID = simpleIdDef.getIntegerValue().intValue();
+            }
+        }
+        /* Single event type in a trace */
+        if (eventID == IEventDeclaration.UNSET_EVENT_ID && fDeclarations.size() == 1) {
+            eventID = 0;
+        }
+        /* Get the right event definition using the event id. */
+        IEventDeclaration eventDeclaration = fDeclarations.get(eventID);
+        if (!(eventDeclaration instanceof EventDeclaration)) {
+            throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
+        }
+        EventDeclaration declaration = (EventDeclaration) eventDeclaration;
+        EventDefinition eventDef = declaration.createDefinition(fStreamContext, fPacketContext, fTracePacketHeader, fEventHeader, fInput, fLastTimestamp);
+        fLastTimestamp = eventDef.getTimestamp();
+        /*
+         * Set the event timestamp using the timestamp calculated by
+         * updateTimestamp.
+         */
+
+        if (posStart == fInput.position()) {
+            throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
+        }
+
+        return eventDef;
+    }
+
+    private EventDefinition createLostEvent(final ICTFPacketDescriptor currentPacket) {
+        IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
+        StructDeclaration lostFields = lostEventDeclaration.getFields();
+        // this is a hard coded map, we know it's not null
+        IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
+        if (lostFieldsDecl == null) {
+            throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
+        }
+        IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
+        if (lostEventsDurationDecl == null) {
+            throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
+        }
+        long lostEventsTimestamp = fLastTimestamp;
+        long lostEventsDuration = currentPacket.getTimestampEnd() - lostEventsTimestamp;
+        IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, lostEventsDuration);
+        IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fPacketContext.getLostEvents());
+        IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
+        int cpu = (int) fPacketContext.getTargetId();
+        return new EventDefinition(
+                lostEventDeclaration,
+                cpu,
+                lostEventsTimestamp,
+                null,
+                null,
+                null,
+                null,
+                new StructDefinition(
+                        lostFields,
+                        this, "fields", //$NON-NLS-1$
+                        fields));
+    }
+
+    @Override
+    public ILexicalScope getScopePath() {
+        return ILexicalScope.PACKET;
+    }
+
+    @Override
+    public @Nullable IDefinition lookupDefinition(@Nullable String lookupPath) {
+        if (ILexicalScope.TRACE_PACKET_HEADER.getPath().equals(lookupPath)) {
+            return fTracePacketHeader;
+        } else if (ILexicalScope.STREAM_PACKET_CONTEXT.getPath().equals(lookupPath) && fPacketScope != null) {
+            return fPacketScope.lookupDefinition(lookupPath);
+        }
+        return null;
+    }
+
+    @Override
+    public ICTFPacketDescriptor getCurrentPacket() {
+        return fPacketContext;
+    }
+
+    /**
+     * TODO: remove when API is reworked a bit.
+     */
+    @Override
+    public @Nullable ICompositeDefinition getCurrentPacketEventHeader() {
+        return fEventHeader;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/NullPacketReader.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/NullPacketReader.java
new file mode 100644 (file)
index 0000000..9325a48
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.trace;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
+import org.eclipse.tracecompass.ctf.core.trace.IPacketReader;
+
+/**
+ * Null packet reader, used for unset packets
+ */
+@NonNullByDefault
+public final class NullPacketReader implements IPacketReader {
+
+    /**
+     * Instance of a null packet reader
+     */
+    public static final NullPacketReader INSTANCE = new NullPacketReader();
+
+    private NullPacketReader() { }
+
+    @Override
+    public int getCPU() {
+        return UNKNOWN_CPU;
+    }
+
+    @Override
+    public boolean hasMoreEvents() {
+        return false;
+    }
+
+    @Override
+    public @Nullable EventDefinition readNextEvent() throws CTFException {
+        return null;
+    }
+
+    @Override
+    public @Nullable ICTFPacketDescriptor getCurrentPacket() {
+        return null;
+    }
+
+    @Override
+    public @Nullable ICompositeDefinition getCurrentPacketEventHeader() {
+        return null;
+    }
+}
index 165679ef6fea476eeb31b98951cb227f02ccfe46..c5593c2056f33c37f1397c8ec727859442d68211 100644 (file)
@@ -26,6 +26,7 @@ import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
 import org.eclipse.tracecompass.ctf.core.event.types.StringDefinition;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
+import org.eclipse.tracecompass.ctf.core.trace.IPacketReader;
 
 /**
  * <b><u>StreamInputPacketIndexEntry</u></b>
@@ -36,8 +37,6 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
 
     private static final Pattern NUMBER_PATTERN = Pattern.compile("\\D*(\\d+)"); //$NON-NLS-1$
 
-    private static final int UNKNOWN = -1;
-
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
@@ -88,6 +87,8 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
      */
     private final Map<String, Object> fAttributes = new HashMap<>();
 
+    private final long fEndPacketHeaderBits;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -99,6 +100,8 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
      *            offset in the file for the start of data in bits
      * @param fileSizeBytes
      *            number of bytes in a file
+     *
+     * TODO: Remove
      */
 
     public StreamInputPacketIndexEntry(long dataOffsetBits, long fileSizeBytes) {
@@ -111,6 +114,7 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
         fTargetID = 0;
         fTimestampBegin = 0;
         fTimestampEnd = Long.MAX_VALUE;
+        fEndPacketHeaderBits = dataOffsetBits;
     }
 
     /**
@@ -124,8 +128,29 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
      *            number of bytes in a file
      * @param lostSoFar
      *            number of lost events so far
+     *
+     * TODO: Remove
      */
     public StreamInputPacketIndexEntry(long dataOffsetBits, StructDefinition streamPacketContextDef, long fileSizeBytes, long lostSoFar) {
+        this(dataOffsetBits, streamPacketContextDef, fileSizeBytes, lostSoFar, dataOffsetBits);
+    }
+
+    /**
+     * full Constructor
+     *
+     * @param dataOffsetBits
+     *            offset in the file for the start of data in bits
+     * @param streamPacketContextDef
+     *            packet context
+     * @param fileSizeBytes
+     *            number of bytes in a file
+     * @param lostSoFar
+     *            number of lost events so far
+     * @param endPacketHeaderBits
+     *            end of packet headers
+     */
+    public StreamInputPacketIndexEntry(long dataOffsetBits, StructDefinition streamPacketContextDef, long fileSizeBytes, long lostSoFar, long endPacketHeaderBits) {
+        fEndPacketHeaderBits = endPacketHeaderBits;
         for (String field : streamPacketContextDef.getDeclaration().getFieldsList()) {
             IDefinition id = streamPacketContextDef.lookupDefinition(field);
             if (id instanceof IntegerDefinition) {
@@ -204,7 +229,7 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
 
         public Target() {
             string = null;
-            number = UNKNOWN;
+            number = IPacketReader.UNKNOWN_CPU;
         }
     }
 
@@ -313,4 +338,9 @@ public class StreamInputPacketIndexEntry implements ICTFPacketDescriptor {
     public long getOffsetBytes() {
         return fOffsetBytes;
     }
+
+    @Override
+    public long getPayloadStartBits() {
+        return fEndPacketHeaderBits;
+    }
 }
index 47ce93e4741826d98cf1f700ed1d4be8930408de..3e60759068c4e3e077906053371c13d3ae61141d 100644 (file)
@@ -40,8 +40,8 @@ public class StreamInputReaderTimestampComparator implements
 
     /**
      * @throws NullPointerException
-     *             If any {@link CTFStreamInputReader} parameter is null, of if any
-     *             of them does not contain a current event.
+     *             If any {@link CTFStreamInputReader} parameter is null, of if
+     *             any of them does not contain a current event.
      */
     @Override
     public int compare(CTFStreamInputReader a, CTFStreamInputReader b) {
index 517b6de16912f932ec48f8a5beb44aa077715d5d..ce98f7e058bd267883f874dce2c40625eddfbeac 100644 (file)
@@ -43,8 +43,18 @@ import org.junit.Test;
  */
 public class CtfTmfEventTest {
 
+    private static final String VALID_FIELD = "ret";
+
     private static final @NonNull CtfTestTrace testTrace = CtfTestTrace.KERNEL;
 
+    /**
+     * <pre>
+     * babeltrace output :
+     * [11:24:42.440133097] (+?.?????????) sys_socketcall: { cpu_id = 1 }, { call = 17, args = 0xB7555F30 }
+     * [11:24:42.440137077] (+0.000003980) exit_syscall: { cpu_id = 1 }, { ret = 4132 }
+     * </pre>
+     */
+
     private static CtfTmfEvent nullEvent;
     private CtfTmfEvent fixture;
 
@@ -102,8 +112,7 @@ public class CtfTmfEventTest {
      */
     @Test
     public void testGetFieldValue() {
-        String fieldName = "pid";
-        ITmfEventField result = fixture.getContent().getField(fieldName);
+        ITmfEventField result = fixture.getContent().getField(VALID_FIELD);
 
         assertNotNull(result);
         assertNotNull(result.getValue());
@@ -124,11 +133,11 @@ public class CtfTmfEventTest {
     @Test
     public void testGetSubFieldValue() {
         /* Field exists */
-        String[] names = { "pid" };
+        String[] names = { VALID_FIELD };
         assertNotNull(fixture.getContent().getField(names));
 
         /* First field exists, not the second */
-        String[] names2 = { "pid", "abcd" };
+        String[] names2 = { VALID_FIELD, "abcd" };
         assertNull(fixture.getContent().getField(names2));
 
         /* Both field do not exist */
@@ -163,7 +172,7 @@ public class CtfTmfEventTest {
 
         assertEquals("channel0_1", reference);
         assertEquals(1, cpu);
-        assertEquals("lttng_statedump_vm_map", type.toString());
+        assertEquals("exit_syscall", type.toString());
     }
 
     /**
@@ -185,7 +194,7 @@ public class CtfTmfEventTest {
     @Test
     public void testToString() {
         String s = fixture.getContent().toString();
-        assertEquals("pid=1922, start=0xb73ea000, end=0xb73ec000, flags=0x8000075, inode=917738, pgoff=0", s);
+        assertEquals("ret=4132", s);
     }
 
     /**
index 0cfedc29709129360501e28e8eadc8adc501d146..fd4b642c75d594ba3192faa3259d1c665d6f1935 100644 (file)
@@ -157,6 +157,6 @@ public class CtfTmfLostEventStatisticsTest {
         Map<String, Long> eventsInRange = fStats.getEventTypesInRange(rangeStart, rangeEnd);
         Long lostEventsInRange = eventsInRange.get(CTFStrings.LOST_EVENT_NAME);
         assertNotNull(lostEventsInRange);
-        assertEquals(365752L, lostEventsInRange.longValue());
+        assertEquals(363494L, lostEventsInRange.longValue());
     }
 }
index dc04ed68bfc56140b98db1cbe5465896a1d92110..96a0295766379acb2df8c6db760febb21b4db952 100644 (file)
@@ -129,23 +129,13 @@ public class CtfTmfLostEventsTest {
      */
     @Test
     public void testFirstLostEvent() {
-        final long rank = 190;
-        final ITmfTimestamp start = new TmfNanoTimestamp(1376592664828900165L);
-        final ITmfTimestamp end   = new TmfNanoTimestamp(1376592664829403076L);
+        final long rank = 152;
+        final long startTime = 1376592664828848222L;
+        final ITmfTimestamp start = new TmfNanoTimestamp(startTime);
+        final ITmfTimestamp end = new TmfNanoTimestamp(startTime + 554854L);
         final long nbLost = 859;
 
-        final CtfTmfEvent ev = getOneEventTime(start);
-        /* Make sure seeking by rank yields the same event */
-        final CtfTmfEvent ev2 = getOneEventRank(rank);
-        assertEquals(ev, ev2);
-
-        assertTrue(ev instanceof ITmfLostEvent);
-        ITmfLostEvent event = (ITmfLostEvent) ev;
-
-        assertEquals(start, event.getTimestamp());
-        assertEquals(start, event.getTimeRange().getStartTime());
-        assertEquals(end, event.getTimeRange().getEndTime());
-        assertEquals(nbLost, event.getNbLostEvents());
+        validateLostEvent(rank, start, end, nbLost);
     }
 
     /**
@@ -153,11 +143,16 @@ public class CtfTmfLostEventsTest {
      */
     @Test
     public void testSecondLostEvent() {
-        final long rank = 229;
-        final ITmfTimestamp start = new TmfNanoTimestamp(1376592664829477058L);
-        final ITmfTimestamp end   = new TmfNanoTimestamp(1376592664829824514L);
+        final long rank = 191;
+        final long startTime = 1376592664829402521L;
+        final ITmfTimestamp start = new TmfNanoTimestamp(startTime);
+        final ITmfTimestamp end = new TmfNanoTimestamp(startTime + 421993L);
         final long nbLost = 488;
 
+        validateLostEvent(rank, start, end, nbLost);
+    }
+
+    private void validateLostEvent(final long rank, final @NonNull ITmfTimestamp start, final ITmfTimestamp end, final long nbLost) {
         final CtfTmfEvent ev = getOneEventTime(start);
         /* Make sure seeking by rank yields the same event */
         final CtfTmfEvent ev2 = getOneEventRank(rank);
@@ -178,8 +173,8 @@ public class CtfTmfLostEventsTest {
      */
     @Test
     public void testNormalEvent() {
-        final long rank = 200;
-        final ITmfTimestamp ts = new TmfNanoTimestamp(1376592664829425780L);
+        final long rank = 193;
+        final ITmfTimestamp ts = new TmfNanoTimestamp(1376592664829411423L);
 
         final CtfTmfEvent event = getOneEventTime(ts);
         /* Make sure seeking by rank yields the same event */
@@ -200,9 +195,9 @@ public class CtfTmfLostEventsTest {
         trace.setTimestampTransform(TimestampTransformFactory.createWithOffset(offset));
         trace.indexTrace(true);
 
-        final long rank = 190;
-        final ITmfTimestamp start = new TmfNanoTimestamp(1376592664828900165L + offset);
-        final ITmfTimestamp end   = new TmfNanoTimestamp(1376592664829403076L + offset);
+        final long rank = 152;
+        final ITmfTimestamp start = new TmfNanoTimestamp(1376592664828848222L + offset);
+        final ITmfTimestamp end = new TmfNanoTimestamp(1376592664828848222L + 554854L + offset);
         final long nbLost = 859;
 
         ITmfContext context = trace.seekEvent(rank);
@@ -273,7 +268,7 @@ public class CtfTmfLostEventsTest {
         public OneEventRequestPerTs(@NonNull ITmfTimestamp ts) {
             super(CtfTmfEvent.class,
                     new TmfTimeRange(ts, ts),
-                    0, ITmfEventRequest.ALL_DATA, ExecutionType.FOREGROUND);
+                    0, 1, ExecutionType.FOREGROUND);
         }
 
         @Override
index f4e608a6dee647f6db1aa871fd0e7d092776872f..e387bb9a198f44de4c166e411ca1531cc8b22905 100644 (file)
@@ -132,7 +132,7 @@ public class TmfPieChartViewer extends Composite {
      * Called by this class' constructor. Constructs the basic viewer containing
      * the charts, as well as their listeners
      */
-    private void initContent() {
+    private synchronized void initContent() {
         setLayout(new FillLayout());
 
         fGlobalPC = null;
This page took 0.046004 seconds and 5 git commands to generate.